#!/usr/local/bin/perl require 'getopts.pl'; $files="files"; %have=(); %missing=(); %name=(); %func=(); &Getopts('Ff:'); &load_file("files"); foreach $file (@ARGV) { &do_nm($file); } if (defined($opt_f)) { %a=(); $r=&list_files($opt_f,"",*a); if ($opt_F) { foreach (sort split(/\n/,$r)) { print "$_\n"; } } else { print $r; } } else { for (sort keys %have) { print "$_:$have{$_}\n"; } } sub list_files { local($f,$o,*done)=@_; local($a,$_,$ff,$ret); return if $f =~ /^\s*$/; $done{$f}=1; $ret.=$f."\n" if $opt_F; foreach (split(/ /,$have{$f})) { $ret.="$o$f:$_\n" unless $opt_F; } foreach (split(/ /,$missing{$f})) { $ff=$func{$_}; next if defined($done{$ff}); $ret.=&list_files($ff,$o." "); } $ret; } sub do_nm { local($file)=@_; local($fname)=""; open(IN,"nm $file|") || die "unable to run 'nm $file|':$!\n"; while () { chop; next if /^\s*$/; if (/^(.*)\.o:\s*$/) { $fname="$1.c"; next; } ($type,$name)=/^.{8} (.) (.+)/; # print "$fname $type $name\n"; if ($type eq "T") { $have{$fname}.="$name "; $func{$name}=$fname; } elsif ($type eq "U") { $missing{$fname}.="$name "; } } close(IN); } sub load_file { local($file)=@_; open(IN,"<$files") || die "unable to open $files:$!\n"; while () { chop; next if /^\s*$/; ($n)=/\/([^\/\s]+)\s+/; ($fn)=/^(\S+)\s/; # print "$n - $fn\n"; if (defined($name{$n})) { print "$n already exists\n"; } else { $name{$n}=$fn; } } close(IN); @name=%name; }