| #!/usr/bin/perl |
| |
| # Check that the various config.sh-clones have (at least) all the |
| # same symbols as the top-level config_h.SH so that the (potentially) |
| # needed symbols are not lagging after how Configure thinks the world |
| # is laid out. |
| # |
| # VMS is probably not handled properly here, due to their own |
| # rather elaborate DCL scripting. |
| # |
| |
| use strict; |
| use warnings; |
| use autodie; |
| |
| sub usage |
| { |
| my $err = shift and select STDERR; |
| print "usage: $0 [--list] [--regen] [--default=value]\n"; |
| exit $err; |
| } # usage |
| |
| use Getopt::Long; |
| my $opt_l = 0; |
| my $opt_r = 0; |
| my $default; |
| my $tap = 0; |
| my $test; |
| GetOptions ( |
| "help|?" => sub { usage (0); }, |
| "l|list!" => \$opt_l, |
| "regen" => \$opt_r, |
| "default=s" => \$default, |
| "tap" => \$tap, |
| ) or usage (1); |
| |
| require 'regen/regen_lib.pl' if $opt_r; |
| |
| my $MASTER_CFG = "config_h.SH"; |
| # Inclusive bounds on the main part of the file, $section == 1 below: |
| my $first = qr/^Author=/; |
| my $last = qr/^zip=/; |
| |
| my @CFG = ( |
| # we check from MANIFEST whether they are expected to be present. |
| # We can't base our check on $], because that's the version of the |
| # perl that we are running, not the version of the source tree. |
| "Cross/config.sh-arm-linux", |
| "epoc/config.sh", |
| "NetWare/config.wc", |
| "symbian/config.sh", |
| "uconfig.sh", |
| "uconfig64.sh", |
| "plan9/config_sh.sample", |
| "win32/config.gc", |
| "win32/config.gc64", |
| "win32/config.gc64nox", |
| "win32/config.vc", |
| "win32/config.vc64", |
| "win32/config.ce", |
| "configure.com", |
| "Porting/config.sh", |
| ); |
| |
| my @MASTER_CFG; |
| { |
| my %seen; |
| open my $fh, '<', $MASTER_CFG; |
| while (<$fh>) { |
| while (/[^\\]\$([a-z]\w+)/g) { |
| my $v = $1; |
| next if $v =~ /^(CONFIG_H|CONFIG_SH)$/; |
| $seen{$v}++; |
| } |
| } |
| close $fh; |
| @MASTER_CFG = sort keys %seen; |
| } |
| |
| my %MANIFEST; |
| |
| { |
| open my $fh, '<', 'MANIFEST'; |
| while (<$fh>) { |
| $MANIFEST{$1}++ if /^(.+?)\t/; |
| } |
| close $fh; |
| } |
| |
| printf "1..%d\n", 2 * @CFG if $tap; |
| |
| for my $cfg (sort @CFG) { |
| unless (exists $MANIFEST{$cfg}) { |
| print STDERR "[skipping not-expected '$cfg']\n"; |
| next; |
| } |
| my %cfg; |
| my $section = 0; |
| my @lines; |
| |
| open my $fh, '<', $cfg; |
| |
| if ($cfg eq 'configure.com') { |
| ++$cfg{startperl}; # Cheat. |
| |
| while (<$fh>) { |
| next if /^\#/ || /^\s*$/ || /^\:/; |
| s/(\s*!.*|\s*)$//; # remove trailing comments or whitespace |
| ++$cfg{$1} if /^\$\s+WC "(\w+)='(?:.*)'"$/; |
| } |
| } else { |
| while (<$fh>) { |
| if ($_ =~ $first) { |
| die "$cfg:$.:section=$section:$_" unless $section == 0; |
| $section = 1; |
| } |
| push @{$lines[$section]}, $_; |
| next if /^\#/ || /^\s*$/ || /^\:/; |
| if ($_ =~ $last) { |
| die "$cfg:$.:section=$section:$_" unless $section == 1; |
| $section = 2; |
| } |
| # foo='bar' |
| # foo=bar |
| # (optionally with a trailing comment) |
| if (/^(\w+)=(?:'.*'|[^'].*)(?: #.*)?$/) { |
| ++$cfg{$1}; |
| } else { |
| warn "$cfg:$.:$_"; |
| } |
| } |
| } |
| close $fh; |
| |
| ++$test; |
| my $missing; |
| if ($cfg eq 'configure.com') { |
| print "ok $test # skip $cfg doesn't need to be sorted\n" |
| if $tap; |
| } elsif (join("", @{$lines[1]}) eq join("", sort @{$lines[1]})) { |
| print "ok $test - $cfg sorted\n" |
| if $tap; |
| } elsif ($tap) { |
| print "not ok $test - $cfg is not sorted\n"; |
| } elsif ($opt_r || $opt_l) { |
| # A reference to an empty array is true, hence this flags the |
| # file for later attention by --regen and --list, even if |
| # nothing is missing. Actual sort and output are done later. |
| $missing = []; |
| } else { |
| print "$cfg: unsorted\n" |
| } |
| |
| for my $v (@MASTER_CFG) { |
| # This only creates a reference in $missing if something is missing: |
| push @$missing, $v unless exists $cfg{$v}; |
| } |
| |
| ++$test; |
| if ($missing) { |
| if ($tap) { |
| print "not ok $test - $cfg missing keys @$missing\n"; |
| } elsif ($opt_l) { |
| # print the name once, however many problems |
| print "$cfg\n"; |
| } elsif ($opt_r && $cfg ne 'configure.com') { |
| if (defined $default) { |
| push @{$lines[1]}, map {"$_='$default'\n"} @$missing; |
| } else { |
| print "$cfg: missing '$_', use --default to add it\n" |
| foreach @$missing; |
| } |
| |
| @{$lines[1]} = sort @{$lines[1]}; |
| my $fh = open_new($cfg); |
| print $fh @{$_} foreach @lines; |
| close_and_rename($fh); |
| } else { |
| print "$cfg: missing '$_'\n" foreach @$missing; |
| } |
| } elsif ($tap) { |
| print "ok $test - $cfg has no missing keys\n"; |
| } |
| } |