#!/usr/bin/perl -w # see usage string for description use strict 'subs'; if (@ARGV == 0) { print(<<"EOF"); usage: $0 file1.d [file2.d [...]] Given a bunch of .d files after compilation is complete, this script yields dependencies where the dependee is *not* checked into CVS. This is then the dependencies which need to appear explicitly in Makefile.in. EOF exit(0); } for my $fname (@ARGV) { # open the file open(IN, "<$fname") or die("cannot open $fname: $!\n"); # dependency target is listed first my $line = ; if (!defined($line)) { # empty file, skip it } else { my ($target) = ($line =~ m/^([^:]+):/); die if (!$target); # now search for the command-less, prerequisite-less rules # where the dependees are listed while (defined($line = )) { my ($dependee) = ($line =~ m/^([^:]+):$/); if (!defined($dependee)) { # line is not of right form next; } if ($dependee =~ m,^\.\./,) { # it begins with "../", suggesting the file is in another # repository; I'll just assume cross-repository dependencies # don't need to influence the build order of the current # directory next; } # is this file checked into CVS? if (isCheckedIn($dependee)) { # no need to include this in the Makefile since the file # will always exist next; } # is the dependee something the Makefile would already # know about? for example, we don't need to explicitly # say that grampar.tab.o depends on grampar.tab.cc, because # the pattern rule which makes the former already includes # the dependency on the latter if (isPattern($target, ".o", $dependee, ".cc") || isPattern($target, ".ast.gen.o", $dependee, ".ast.gen.h") || isPattern($target, ".gr.gen.o", $dependee, ".gr.gen.h")) { # Makefile already knows next; } print("$target: $dependee\n"); } } close(IN) or die; } exit(0); # check whether a given file is checked in, by looking for it # in the CVS/Entries file sub isCheckedIn { my ($fname) = @_; # split into directory and file my ($dir, $file) = ($fname =~ m|^(.*)/([^/]+)$|); if (!defined($file)) { $dir = "."; $file = $fname; } # debugging #print("dir: $dir\n"); #print("file: $file\n"); # open the Entries file if (!open(ENTRIES, "<$dir/CVS/Entries")) { # the Entries file doesn't exist, so the file in question # is not checked in to CVS return 0; } # look for the file in question among the lines of Entries my $line; while (defined($line = )) { if ($line =~ m|^/$file/|) { # found the file, it's checked in close(ENTRIES) or die; return 1; } } close(ENTRIES) or die; # didn't find the file, it's not checked in return 0; } # check whether a target and dependee are related by being # the same base with two given extensions sub isPattern { my ($name1, $ext1, $name2, $ext2) = @_; # separate $name1 into a prefix and a suffix my $name1len = length($name1); my $ext1len = length($ext1); if ($name1len < $ext1len) { return 0; } my ($prefix1) = substr($name1, 0, $name1len - $ext1len); #print("prefix1: $prefix1\n"); # we have a match if the suffix matches $ext1, and if $name2 # is exactly the concatenation of $prefix1 and $ext2 return ($name1 eq "$prefix1$ext1") && ($name2 eq "$prefix1$ext2"); }