#!/mit/watchmaker/vaxbin/perl
        eval "exec /mit/watchmaker/vaxbin/perl -S $0 $*"
		if $running_under_some_shell;

# $Header: metaconfig.SH,v 2.0.1.1 88/08/05 00:27:27 lwall Exp $
#
# $Log:	metaconfig.SH,v $
# Revision 2.0.1.1  88/08/05  00:27:27  lwall
# patch1: now depends on perlpath
# 
# Revision 2.0  88/06/28  23:18:46  lwall
# Baseline.
# 

$MC='/mit/watchmaker/vaxsrc/dist/mcon';
$ENV{'MC'} = $MC;
chop($WD=`pwd`);
$ENV{'WD'} = $WD;

do 'getopt.pl';
do Getopt("");

++$opt_v if $opt_V;

unlink 'Wanted' unless $opt_w;

$NEWMANI = 'MANIFEST.new';
$MANI = 'MANIFEST';

do readpackage();

$ENV{'package'} = $package;

`mkdir .MT 2>&1` unless -d '.MT';

print "Locating units...\n" if $opt_v;
if (-d 'U') {
    chdir 'U';
    foreach $file (<*.U>) {
	push(@myUlist,"$WD/U/$file");
	$myUseen{$file} = 1;
    }
    chdir '..';
}

chdir "$MC/U" || die "Can't find $MC/U.\n";
foreach $file (<*.U>) {
    if ($myUseen{$file}) {
	print "    Your private U/$file overrides the public one.\n" if $opt_v;
    }
    else {
	push(@ARGV,$file);
    }
}
push(@ARGV,@myUlist);

if ($opt_V) {
    print "\t";
    $, = "\n\t";
    print @ARGV;
    $, = '';
    print "\n";
}

print "Extracting dependency lists from units...\n" if $opt_v;
$dependencies = ' ' x 10000;	# pre-extend
$dependencies = '';
open(INIT,">$WD/.MT/.Init.U")      || die "Can't create $WD/.MT/.Init.U\n";
open(CONF_H,">$WD/.MT/.Config_h.U") || die "Can't create $WD/.MT/.Config_h.U\n";
line: while (<>) {
    if (/^\?MAKE:[\w ]*:/) {
	s|^\?MAKE:\s*||;
	$dependencies .= $_;
	chop;
	s/:.*//;
	@ary = split(' ');
	$hold = join(' ',@ary);
	$unit = $ary[0];
	foreach $sym (@ary) {
	    if ($sym =~ /^([a-z]|Mcc|Log|Header)/) {
		$shmaster{"\$$sym"} = '#';
		push(@Master,"?$unit:$sym=''\n");
	    }
	}
	next line;
    }
    if (/^\?C:/) {
	s|^\?C:([A-Za-z_])|?H:?%1:/* $1|;
	s|^\?C:\.\s*$|?H:?%1: */\n|;
	s|^\?C:(.*)|?H:?%1: *$1|;
    }
    s/%\*/$hold/;
    s/%1/$unit/;
    $dependencies .= $_		if s|^\?MAKE:||;
    print INIT			if s|^\?INIT:||;
    print CONF_H		if s|^\?H:||;
}
print $dependencies if $opt_V;
print CONF_H "!GROK!THIS!\n";
close DEP;
close INIT;
close CONF_H;
close MASTER;

chdir $WD;

unless (-f 'Wanted') {
    print "Building a Wanted file...\n" if $opt_v;
    open(WANTED,"| sort | uniq >Wanted") || die "Can't create Wanted.\n";
    unless (-f $NEWMANI) {
	do manifake();
	die "No $NEWMANI--can't build a Wanted file.\n" unless -f $NEWMANI;
    }

    print "    Extracting filenames (*.[chy] and *.SH) from $NEWMANI...\n"
      if $opt_v;
    open(NEWMANI,$NEWMANI) || die "Can't open $NEWMANI";
    while (<NEWMANI>) {
	($file) = split(' ');
	next if $file eq 'config.h.SH';
	push(@SHlist,$file) if $file =~ /\.SH$/;
	push(@clist,$file) if $file =~ /\.[chy]$/;
    }

    print "    Extracting symbols from Config_h.U...\n" if $opt_v;
    if (-f 'U/Config_h.U') {
	@ARGV = ('U/Config_h.U', '.MT/.Config_h.U');
    }
    else {
	@ARGV = ("$MC/U/Config_h.U", '.MT/.Config_h.U');
    }
    while (<>) {
	next unless /^\?\w*:#.*\$/;
	s|^[^#]*#||;
	if (s|^\$(\w+)\s*(\w+).*\$(\w+).*$|$2 $1\n$2 $3|) {
	    $cmaster{$2} = '#';
	    $cwanted{$2} = "$1\n$3";
	}
	elsif (s|^\$(\w+)\s*(\w+).*$|$2 $1|) {
	    $cmaster{$2} = '#';
	    $cwanted{$2} = $1;
	}
	elsif (s|^define\s*(\w+).*\$(\w+).*$|$1 $2|) {
	    $cmaster{$1} = '#';
	    $cwanted{$1} = $2;
	}
    }

    # Now we are a little clever, and build a loop to eval so that we don't
    # have to recompile our patterns on every file.  We also use "study" since
    # we are searching the same string for many different things.  Hauls!

    unless ($#clist < 0) {
	print "    Scanning .c and .h files for symbols...\n" if $opt_v;
	$search = "while (<>) {study;\n";	# init loop over ARGV
	foreach $key (keys(cmaster)) {
	    $search .= "\$cmaster{'$key'}++ if /\\b$key\\b/;\n";
	}
	$search .= "}\n";			# terminate loop
	@ARGV = @clist;
	$/ = "\001";	# swallow each file whole (delete if memory is limited)
	eval $search;
	$/ = "\n";
	while (($key,$value) = each(cmaster)) {
	    if ($value ne '#') {
		print WANTED $cwanted{$key}, "\n";
	    }
	}
    }

    print "    Scanning .SH files for symbols...\n" if $opt_v;
    close WANTED;
    open(WANTED,"| sort | uniq >>Wanted") || die "Can't create Wanted.\n";
    $search = "while (<>) {study;\n";
    foreach $key (keys(shmaster)) {
	$search .= "\$shmaster{'$key'}++ if /\\$key\\b/;\n";
    }
    $search .= "}\n";
    @ARGV = @SHlist;
    $/ = "\001";		# (delete if memory is limited)
    eval $search;
    $/ = "\n";
#    while (<>) {
#	@ary = split(/[^\w\$]+/);
#	for (@ary) {
#	    $shmaster{$_}++ if $shmaster{$_};	# assuming most don't match
#	}
#    }
    while (($key,$value) = each(shmaster)) {
	if ($value ne '#') {
	    $key =~ s/^\$//;
	    print WANTED $key, "\n";
	}
    }
}
close WANTED;

die "No desirable symbols found--aborting.\n" unless -s 'Wanted';

print "Building private make file...\n" if $opt_v;
$/ = "\001";			# change record separtor to nonexistent char
open(WANTED,"Wanted") || die "Can't reopen Wanted.\n";
$_ = <WANTED>;			# slurp whole file;
$/ = "\n";
y/\n/ /;
open(MAKEFILE,">.MT/.Makefile") || die "Can't create .MT/.Makefile.\n";
print MAKEFILE "W = $_\n";
print MAKEFILE $dependencies;
close MAKEFILE;

print "Determining the correct order for the units...\n" if $opt_v;
chdir '.MT' || die "Can't chdir to .MT";
open(MAKE, "make -n -f .Makefile|") || die "Can't run make";
while (<MAKE>) {
    print "\t$_" if $opt_V;
    if (/^pick/) {
	($pick,$cmd,$symbol,$unit) = split(' ');
	$symwanted{$symbol}++;
	unless ($unitseen{$unit}++) {
	    push(@cmdwanted,"$cmd $unit");
	    $symwanted{$unit}++;
	}
    }
    else {
	chop;
	system;
    }
}
close MAKE;

print "Creating Configure...\n" if $opt_v;
open(CONFIGURE,">$WD/Configure") || die "Can't create Configure.\n";
open(CONF_H,">$WD/config.h.SH") || die "Can't create config.h.SH.\n";
for (@cmdwanted) {
    ($cmd,$unit) = split;
    $dir = ($myUseen{$unit} ? $WD : $MC);
    $unit .= '.U';
    if (m|/|) {
	$file = $unit;			# they must know what they're doing
    }
    elsif ($myUseen{$unit}) {
	$file = "$WD/U/$unit";		# they MIGHT know what they're doing
    }
    else {
	$file = "$MC/U/$unit";		# normal case
    }
    die "Can't open $file" unless open(UNIT,$file);
    print "\t$cmd $file\n" if $opt_V;
    if ($cmd eq 'add') {
	while (<UNIT>) {
	    print CONFIGURE unless /^\?/;
	}
    }
    elsif ($cmd eq 'weed') {
	while (<UNIT>) {
	    if (/^\?(\w+):/) {
		s/^\?\w+:// if $symwanted{$1};
	    }
	    print CONFIGURE unless /^\?/;
	}
    }
    elsif ($cmd eq 'add.package') {
	while (<UNIT>) {
	    s/PACKAGENAME/$package/g;
	    print CONFIGURE unless /^\?/;
	}
    }
    elsif ($cmd eq 'add.Null') {
	for (@Master) {
	    if (/^\?(\w+):/) {
		s/^\?\w+:// if $symwanted{$1};
	    }
	    print CONFIGURE unless /^\?/;
	}
	while (<UNIT>) {
	    print CONFIGURE unless /^\?/;
	}
	print CONFIGURE "CONFIG=''\n";
    }
    elsif ($cmd eq 'add.Config_sh') {
	while (<UNIT>) {
	    print CONFIGURE unless /^\?/;
	}
	for (@Master) {
	    if (/^\?(\w+):/) {
		s/^\?\w+:// if $symwanted{$1};
	    }
	    s/^(\w+)=''/$1='\$$1'/;
	    print CONFIGURE unless /^\?/;
	}
	print CONFIGURE "CONFIG=true\nEOT\n\n";
    }
    elsif ($cmd eq 'c_h_weed') {
	while (<UNIT>) {
	    if (/^\?(\w+):/) {
		s/^\?\w+:// if $symwanted{$1};
	    }
	    print CONF_H unless /^\?/;
	}
    }
    else {
	die "Unrecognized command from .Makefile: $cmd\n";
    }
    close UNIT;
}
close CONFIGURE;
close CONF_H;

chdir $WD || die "Can't cd back to $WD\n";
`chmod +x Configure`;

if (-f 'config.h.SH') {
    open(NEWMANI,$NEWMANI);
    $/ = "\001";
    $_ = <NEWMANI>;
    $/ = "\n";
    close NEWMANI;
    unless (/config\.h\.SH/) {
	print "Adding config.h.SH to your $NEWMANI file...\n" if $opt_v;
	`echo "config.h.SH	Produces config.h." >>$NEWMANI`;
    }
}
if ($opt_V) {
    print "Leaving subdirectory .MT unremoved so you can peruse it.\n";
}
else {
    `rm -rf .MT 2>&1`;
}
print "Done.\n" if $opt_v;

sub readpackage {
    if (! -f '.package') {
        if (-f '../.package' || -f '../../.package') {
            die "Run in top level directory only.\n";
        }
        else {
            die "No .package file!  Run packinit.\n";
        }
    }
    open(package,'.package');
    while (<package>) {
        next if /^:/;
        next if /^#/;
        if (($var,$val) = /^\s*(\w+)=(.*)/) {
            $val = "\"$val\"" unless $val =~ /^['"]/;
            eval "\$$var = $val;";
        }
    }
    close package;
}

sub manifake {
    # make MANIFEST and MANIFEST.new say the same thing
    if (! -f $NEWMANI) {
        if (-f $MANI) {
            open(IN,$MANI) || die "Can't open $MANI";
            open(OUT,">$NEWMANI") || die "Can't create $NEWMANI";
            while (<IN>) {
                next if 1 .. /---/;
                s/(\s+)[0-9]*\s*/$1/;
            }
            close IN; close OUT;
        }
        else {
die "You need to make a MANIFEST.new file, with names and descriptions.\n";
        }
    }
}
