#!/usr/bin/env perl # # Post-process files generated by protoc-c to remove anonymous unions. # Works on the generated files but probably little else. use warnings; use strict; sub unanon { my $hfile = shift; my $cfile = shift; my ($fh, $content); my %members; open $fh, "<", $hfile or die $!; local $/; # enable localized slurp mode $content = <$fh>; close $fh; # Detect and replace anonymous unions in .h file. # Assumes there is only one anonymous union in scope. while ($content =~ s/^(struct\s+(\w+)[^}]+)(union\s+{([^}]+)}\s*);/$1$3 u;/sm) { my $s = $2; my $u = $4; $u =~ s:/\*((?!\*/).)*\*/::sg; foreach (split(/\n+/, $u)) { if (/^.*\s+\**([^;]+);/) { $members{$1} = $s; } } } open $fh, ">", $hfile or die $!; print $fh $content; close $fh; # Replace anonymous union access in generated .c file. open $fh, "<", $cfile or die $!; $content = <$fh>; close $fh; while (my ($key, $val) = each %members) { # We only support access via offsetof() $content =~ s/offsetof\($val, $key\)/offsetof($val, u.$key)/g; } open $fh, ">", $cfile or die $!; print $fh $content; close $fh; } unanon(@ARGV);