#!@PERL@ -w # -*- perl -*- # The process has two steps # (1) # Travers all the files (with some filtering) over /usr/pkgsrc # pick up referenced -> referer relation and store them to %HASH # (multiple files are concatinated by ';' ) # (2) # read input (usually named 'commonbump'), and expand one line into # replacement referer lines, which are referenced -> referer relation. use strict; use Getopt::Std; use File::Find; my(%HASH); # referenced -> referer relation hash, referer is delimitted by ; my($PKGSRCDIR); # /usr/pkgsrc path, usually /usr/pkgsrc my($TABLE) = 'commonbump'; # name of file, list-of-files to process my(@TABLE); # contents of file above my($debug) = 0; my($prefix) ; # A part of path, top to pkgsrc, typically /usr/pkgsrc my($common_bump) = 0; # count, not used for now (yet) my(%opts); our(@ARGV); my ($FILE) = __FILE__; $FILE =~ s,.*/([^/]+),$1,; # pick leafname from __FILE__ my($replaced) = 'commonbump.replaced'; my($my_name) = $0; $my_name =~ s#(.*)/##; sub usage() { print < referenced relation, then internally keeps (opposite) referenced -> referer relation table. (2) Read another file, named '$TABLE' or other name with -T, which usually lists Makefile.common or *common.mk files to expand. (3) Now expands those list in '$TABLE' into list of Makefiles by referenced -> refer relation. By default, it outputs to the file '$replaced' (currently the name is fixed). Synopsys: $my_name [-a ] [-h] [-p pkgsrc_directory] [-T list_file] Where: -a Check all, disregard to -T option. If "# used by" is included or not. -h Show this help -p directory pkgsrc directory to process (default $PKGSRCDIR) -T the filename containing list of files (default commonbump) See Also: revbump(1) for how to use it. HELP } # get value of variable by using make show-var sub show_var($$){ my($varname) = shift; my($pkgdir) = shift; my($value); #chdir $pkgdir; open(MAKE, '-|', "cd $PKGSRCDIR/$pkgdir ; make show-var VARNAME=$varname"); $value = ; close(MAKE); chomp($value); if ($value =~ /know how to make/ ) { print STDERR $value, '(', $pkgdir,')',"\n";} return $value } sub GenerateHash ($$) { my ($pkgsrc) = shift; my ($prefix) = shift; # ---------------------------------------------------------------- my ($wanted_closure) = sub () { my $dir = $File::Find::dir ; my $fname = "$File::Find::dir/$_" ; # skip these directories and files ( as files including something ) if ($dir =~ m|CVS$| ) {$File::Find::prune = 1; return;} if ($dir =~ m|mk$| ) {$File::Find::prune = 1; return;} if ($dir =~ m|work$| ) {$File::Find::prune = 1; return;} if ($dir =~ m|patches$| ) {$File::Find::prune = 1; return;} if ($dir =~ m|files$| ) {$File::Find::prune = 1; return;} if ($dir =~ m|bootstrap$| ) {$File::Find::prune = 1; return;} if ($dir =~ m|pkgsrc/[^/]$| ) {$File::Find::prune = 1; return;} if ($dir =~ m|x11-links| ) {$File::Find::prune = 1; return;} if ($_ =~ m|^\.\#| ) { return;} if ($_ =~ m|~$| ) { return;} if ($_ =~ m|buildlink3.mk$| ) { return;} if ($_ =~ m|builtin.mk$| ) { return;} my($shortname) = $fname; $shortname =~ s|$prefix/||; my($shortdir) = $dir; $shortdir =~ s|$prefix/||; # pick only Makefile.* and .mk ( as files including something ) if ($_ =~ m|Makefile| || $_ =~ m|\.mk$| ) { print STDERR __LINE__, ' ', $fname,' ', `pwd`, "\n" if $debug; open(FNAME, $fname) || print STDERR __LINE__, " Problem opening file $fname:$!\n"; my ($included) = ''; while (){ # now starts finding included file # pick .include "../../ if ( m|^\.\s*include\s+\"\.\./\.\./(.*)\"| ) { $included = $1;} # pick ".include "Makefile" etc (without leading ../../), this needs to add package dir. if ( m|^\.\s*include\s+\"(.*)\"| ) { next;} # including the same directory stuff, doesn't matter if ( m|^\.\s*include\s+\"(.*)\"| ) { $included = $prefix .'/'. $1;} if ( $included =~ m|/mk/| ) { next;} # it is include line but for mk, skip this line if ( $included =~ m|version.mk| ) { next;} if ( $included =~ m|tests/| ) { next;} if ( $included =~ m|options.mk| ) { next;} if ( $included =~ m|enigmail.mk| ) { next;} $included =~ s,\$\{.CURDIR},$shortname,; if ($included =~ /\$\{([^}]+)}/ ) { my($varname) = $1; my($value) = show_var($varname, $shortdir); $included =~ s/\$\{[^}]+}/$value/; if ($value eq '') { print STDERR $FILE, ': ', __LINE__, ' Value ${', $varname, '} is empty at ', $shortdir, "\n"; } } print STDERR __LINE__ , ' ', $shortname, ' -> ', $included,': ',$_ ,"\n" if $debug; if ( $included eq '') { next;} # not include line, look at next line print STDERR __LINE__ , ' ', $shortname, ' -> ', $included,"\n" if $debug; if ( ! $HASH{$included} ) { $HASH{$included} = $shortname; } else { my(@registered) = split ';', $HASH{$included}; if (grep (/^$shortname$/, @registered) == 0 ) { $HASH{$included} .= ';'. $shortname; } } } # end while close(FNAME); } # if of (major process) ... starting with: if ($_ =~ m|Makefile| || }; # end of my ($wanted_closure) = sub () { # ---------------------------------------------------------------- find($wanted_closure, $pkgsrc); } # Table is assumed to contain list of files to process, set up it in @TABLE here. sub ReadTable($) { my ($table) = shift; if ($table eq '-') { @TABLE = <>; } else { open(TABLE, $table) || print STDERR "Problem reading file $table: $!\n"; @TABLE = ; close(TABLE); } } sub ShowResults() { open(REPLACED, "> $replaced") || die "problem open to write: $replaced: $!\n"; foreach my $file (@TABLE) { chomp($file); if ($file =~ /^\s*$/ ) { next; } # Skip empty line, in case if ($HASH{$file} && # To avoid 'Use of uninitialized value in split at ..' grep ($file, $HASH{$file}) > 0) { # referer found ( separated with ';') my(@list) = split ';', $HASH{$file}; foreach my $i (0..$#list) { print REPLACED "$list[$i]\n"; # write the list into REPLACED handle } } } } # check the pkgsrc tree is healthy or not sub CheckPkgsrcTree($){ my ($pkgsrc) = shift; if (! -d $pkgsrc || ! -d "$pkgsrc/doc" || ! -d "$pkgsrc/mk") { print STDERR "Invalid pkgsrc directory $pkgsrc\n"; exit 1; } } # if -a option is applied, not using @TABLE, but scan whole thing. sub CheckAll() { foreach my $i (sort keys %HASH) { # for all the referenced if ($i =~ /buildlink3.mk/ ) { next;} # First collect the line of '# used by .*' open (REFERENCED, $i) || print ' *** ', __LINE__, " Unable to open $i $!\n"; my (@referer) = {}; while(){ if (/\# used by (.*)/) { push (@referer, $1);} } close(REFERENCED); my $number = 0; foreach my $referer (@referer) { $number += grep $referer, $HASH{$i}; } $#referer++; # conpensate -1 -> 0, 0 -> 1 etc if ($#referer < $number) { print $#referer . ' ? ' . $number .' .. ', $i,' <- ', $HASH{$i}, ' ... <', "\n";} if ($#referer > $number) { print $#referer . ' ? ' . $number .' .. ', $i,' <- ', $HASH{$i}, ' ... >', "\n";} } } sub main() { my($check_all) = 0; my($prefix); $PKGSRCDIR = $ENV{PKGSRCDIR}; if (! $PKGSRCDIR) { $PKGSRCDIR = "/usr/pkgsrc"; } getopts('ahp:T:', \%opts); if ($opts{'a'}) { $check_all = 1; } if ($opts{'h'}) { usage(); exit 0;} if ($opts{'p'}) { $PKGSRCDIR = $opts{'p'};} if ($opts{'T'}) { $TABLE = $opts{'T'};} $prefix = $PKGSRCDIR; $prefix =~ s|.*/pkgsrc/(.*)|$1|; CheckPkgsrcTree($PKGSRCDIR); GenerateHash($PKGSRCDIR, $prefix); ReadTable($TABLE); if ($check_all) { CheckAll(); } else { ShowResults();} } main(); exit; __END__