diff options
Diffstat (limited to '')
-rwxr-xr-x | scripts/unanon | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/scripts/unanon b/scripts/unanon new file mode 100755 index 0000000..5336825 --- /dev/null +++ b/scripts/unanon @@ -0,0 +1,50 @@ +#!/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); |