#!/usr/npac/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;
	}


