#!/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 (<IN>) | |
{ | |
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 (<IN>) | |
{ | |
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; | |
} | |