use List::MoreUtils qw(uniq);
sub gather_includes {
my ($dir) = @_;
my @rawincludes=`cd $dir;grep include *.h *.c`;
my %include=();
foreach $inc (@rawincludes) {
if ((my $a, my $b) = $inc =~ /(\S+):\s*#\s*include\s*\"(\S+)\"/) {
if (!exists $include{$a}) {
$include{$a} = [];
}
$b =~ s/(\S+)\.h/\$\($1_h\)/;
push @{ $include{$a} }, $b;
}
}
return %include;
}
sub read_makefile {
my ($dir, $file) = @_;
my %depend=();
my %vars=();
open(IN, "$dir/$file") or die "can't open $dir/$file";
LINE: while (<IN>) {
$_ =~ s/[\r\n]*$//;
my $line=$_;
while (substr($line,-1) eq "\\") {
my $nextline = <IN>;
$nextline =~ s/[\r\n]*$//;
substr($line,-1) = $nextline;
}
if ((my $f, my $deps) = $line =~ /^([A-Za-z0-9_\$\(\)\.]+)\s*:\s*(.*)/) {
next LINE if (@deps eq "");
my @deplist = split /\s+/, $deps;
if (!exists $depend{$f}) {
$depend{$f} = ();
}
push @{ $depend{$f} }, @deplist;
}
elsif ((my $var, $val) = $line =~ /^([A-Za-z0-9_]+)\s*=\s*(.*)/) {
next LINE if (@val eq "");
my @values = split /\s+/, $val;
if (!exists $vars{$var}) {
$vars{$var} = [];
}
push @{ $vars{$var} }, @values;
}
}
close(IN);
return (\%depend, \%vars);
}
sub check_vars
{
(my $include_ref, my $vars_ref) = @_;
my %include = %$include_ref;
my %vars = %$vars_ref;
VAR: foreach $var (sort keys %vars) {
next VAR if !((my $v) = $var =~ /(\w+)_h/);
my @inclist = ( "\$(GLSRC)$v.h" );
if (exists $include{"$v.h"}) {
push @inclist, @ { $include{"$v.h"} };
}
@inclist = uniq(sort @inclist);
@deplist = sort @ { $vars{$var} };
$a = shift @deplist;
$b = shift @inclist;
while (defined($a) || defined($b)) {
if (defined($a) && defined($b) && $a ne $b &&
($a =~ m/\$\(.*\)(\S+).h/) &&
($b =~ m/\$\(.*\)$1.h/))
{
print "$v.h: accepting $a ($b expected)\n";
$a = shift @deplist;
$b = shift @inclist;
}
elsif (defined($a) && ($a lt $b || !defined($b))) {
print "$v.h: extra dependency on $a\n";
$a = shift @deplist;
} elsif (defined($b) && ($a gt $b || !defined($a))) {
print "$v.h: missing dependency on $b\n";
$b = shift @inclist;
} else {
$a = shift @deplist;
$b = shift @inclist;
}
}
}
}
sub check_depend
{
(my $include_ref, my $depend_ref) = @_;
my %include = %$include_ref;
my %depend = %$depend_ref;
VAR: foreach $dep (sort keys %depend) {
if ((my $path,my $d) = $dep =~ /^(\S+?)([a-zA-Z0-9_]+)\.\$\(OBJ\)/) {
my @inclist = ( "\$(GLSRC)$d.c" );
if (exists $include{"$d.c"}) {
push @inclist, @ { $include{"$d.c"} };
}
@inclist = uniq(sort @inclist);
@deplist = sort @ { $depend{$dep} };
$a = shift @deplist;
$b = shift @inclist;
while (defined($a) || defined($b)) {
if (defined($a) && defined($b) && $a ne $b &&
($a =~ m/\$\(.*\)(\S+).h/) &&
($b =~ m/\$\(.*\)$1.h/))
{
print "$d.\$(OBJ): accepting $a ($b expected)\n";
$a = shift @deplist;
$b = shift @inclist;
}
elsif ($a eq "\$(AK)") {
$a = shift @deplist;
}
elsif ($a eq "STDDIRS") {
$a = shift @deplist;
}
elsif (defined($a) && ($a lt $b || !defined($b))) {
print "$d.\$(OBJ): extra dependency on $a\n";
$a = shift @deplist;
} elsif (defined($b) && ($a gt $b || !defined($a))) {
print "$d.\$(OBJ): missing dependency on $b\n";
$b = shift @inclist;
} else {
$a = shift @deplist;
$b = shift @inclist;
}
}
}
}
}
my %include, %depend, %vars;
my $depend_ref, $vars_ref;
%include = gather_includes("base");
($depend_ref, $vars_ref) = read_makefile("base", "lib.mak");
%depend = %$depend_ref;
%vars = %$vars_ref;
check_vars(\%include, \%vars);
check_depend(\%include, \%depend);