#! /usr/bin/perl -w use File::Find; use Getopt::Long; use strict; my %symbol_type_name = ( n => 'normal', t => 'typedef', e => 'enum', s => 'struct', u => 'union' ); sub pack_dump($$) { my ($dir, $ext) = @_; my %definitions; my @files; $ext = ".symtypes" unless defined $ext; find(sub ($) { /\Q$ext\E$/ && push @files, $File::Find::name}, $dir); map { s/^\Q$dir\E\/(.*)\Q$ext\E$/$1/ } @files; foreach my $file (sort @files) { print "/* $file.o */\n"; local *FD; open FD, "< $dir/$file$ext" or die "$dir/$file$ext: $!\n"; while (<FD>) { chomp; if (s/^override //) { print "override "; } if (/^(\S)#(\S+)\s*(.*)/) { my $sym = "$1#$2"; if (/^$sym\s+$symbol_type_name{$1}\s+$2\s+{\s+UNKNOWN\s+}\s*$/) { $_ = substr($sym, 0, 1) . "##" . substr($sym, 2); } else { if (exists $definitions{$sym} && $definitions{$sym} eq $3) { $_ = $sym; } else { $definitions{$sym} = $3; } } } print "$_\n"; } close FD; print "\n"; } } sub unpack_dump($$) { my ($dir, $ext) = @_; my %definitions; $ext = ".symref" unless defined $ext; while (<STDIN>) { next if /^$/; chomp; if (/^\/\* (.*)\.o \*\//) { close STDOUT; open STDOUT, "> $dir/$1$ext" or die "$dir/$1$ext: $!\n"; next; } if (s/^override //) { print "override "; } if (/^([^ ])#(#?)([^ ]+) *(.*)$/) { my $sym = "$1#$3"; if ($4 ne "") { unless (/\s+{\s+UNKNOWN\s+}\s*$/) { $definitions{$sym} = $4; } } elsif ($2 ne "") { $_ = "$sym $symbol_type_name{$1} $3 { UNKNOWN } "; } else { $_ = "$sym $definitions{$sym}"; } } print "$_\n"; } } my ($pack, $unpack, $ext); GetOptions("pack" => \$pack, "unpack" => \$unpack, "ext" => \$ext) && ($pack || $unpack) && @ARGV == 1 or die "USAGE:\t$0 [--ext extension] --pack {dir} > file\n" . "\t$0 [--ext extension] --unpack {dir} < file\n"; pack_dump($ARGV[0], $ext) if $pack; unpack_dump($ARGV[0], $ext) if $unpack;