#!/usr/bin/perl
#
# Usage:
#   gendep.pl core_modules... --- other_modules... > modules.dep
#
# This looks at the environment variable NM if present
#


$NM = $ENV{'NM'};
$NM = 'nm' unless (defined($NM));

#
# First, get the symbols from core modules
#
%core_syms = ();
$num_cores = 0;

while (defined($file = shift(@ARGV))) {
    last if ($file eq '---');

    $num_cores++;

    open(NM, '-|', "\Q$NM\E -D \Q$file\E")
	or die "$0: cannot run $NM on $file\n";

    while (defined($line = <NM>)) {
	chomp $line;
	if ($line =~ /^([0-9a-f]+) [ABCDGNRSTVW] (\S+)$/) {
	    $core_syms{$2}++;
	}
    }

    close(NM);
}

#
# Second, get the symbols from the auxilliary modules and their
# module list
#
%mod_syms = ();
%undefs   = ();
@mods     = ();

foreach $file (@ARGV) {
    next unless ($file =~ /^(.*\/|)([^\/]+)$/);
    $mod = $2;
    push(@mods, $mod);

    open(NM, '-|', "\Q$NM\E -D \Q$file\E")
	or die "$0: cannot run $NM on $file\n";
    
    $undefs{$mod} = [];

    while (defined($line = <NM>)) {
	chomp $line;
	if ($line =~ /^([0-9a-f]+)\s+[ABCDGNRSTVW]\s+(\S+)$/) {
	    $mod_syms{$2} = $mod unless (defined($mod_syms{$2}));
	} elsif ($line =~ /^\s+U\s+(\S+)$/) {
	    push(@{$undefs{$mod}}, $1);
	}
    }

    close(NM);
}

#
# Finally, resolve the dependencies.  This does not recurse; this assumes
# the parser of this file recurses itself.
# We may want to minimize the dependencies to save space, even.
#
$err = 0;

foreach $mod (@mods) {
    %deps = ();

    foreach $ud (@{$undefs{$mod}}) {
	if ($core_syms{$ud} == $num_cores) {
	    # Present in all cores
	} elsif (defined($mod_syms{$ud})) {
	    $deps{$mod_syms{$ud}}++;
	    # For debugging...
	    printf STDERR "%s needs %s because of %s\n",
		    $mod, $mod_syms{$ud}, $ud;
	} elsif ($core_syms{$ud} > 0) {
	    print STDERR "$0: module $mod needs $ud, which is only in some cores\n";
	    $err++;
	} else {
	    print STDERR "$0: module $mod needs $ud, which is not found\n";
	    $err++;
	}
    }

    @dmods = sort(keys(%deps));

    if (scalar(@dmods)) {
	print "$mod: ", join(' ', @dmods), "\n";
    }
}

exit $err ? 1 : 0;
