#!/usr/local/bin/perl

# makedepend
# a replacement for the standard makedepend that uses "cc -E" to actually
# preprocess the C source file, then parses its output to generate a
# dependency list.

# John M. Relph <relph@engr.sgi.com>, 12 April 1995
# Copyright 1995 John M. Relph

# see http://reality.sgi.com/employees/relph/src/makedepend.html
# for full usage documentation

# parse command line options
&Getopt('CDIafopsw');

# get -Ccc (C compiler and flags to use to compile)
$CC = ($opt_C ? $opt_C : "cc -E");

# get -fmakefile
if ($opt_f) {
    $Makefile = $opt_f;
}
else {
    $Makefile = "makefile";
    if (! (-e $Makefile && -w $Makefile)) {
	$Makefile = "Makefile";
    }

}
if (! (-e $Makefile && -w $Makefile)) {
    die "$0\: cannot open makefile \"$Makefile\"\n";
}

# get -sstring
$Delimiter = ($opt_s ? $opt_s : "# DO NOT DELETE THIS LINE -- make depend depends on it.");

# get -pobjprefix
$Prefix = ($opt_p ? $opt_p : "");

# get -oobjsuffix
$Suffix = ($opt_o ? $opt_o : ".o");

rename("$Makefile","$Makefile.bak")
    || die "$0\: cannot make backup \"$Makefile.bak\"\n";

# copy the existing makefile
open(MAKEIN,"<$Makefile.bak")
    || die "$0\: cannot read backup \"$Makefile.bak\"\n";

open(MAKEOUT,">$Makefile")
    || die "$0\: cannot create makefile \"$Makefile\"\n";

$found = 0;
while (<MAKEIN>) {
    chop;
    last if ($_ eq $Delimiter);
    print MAKEOUT "$_\n";
}

print MAKEOUT "$Delimiter\n";

if ($opt_a) {
    while (<MAKEIN>) {
	chop;
	print MAKEOUT "$_\n";
    }
}

close(MAKEIN);

while (@ARGV) {
    $_ = $ARGV[0];		# get object filename
    if (m/(.*)\.c/) {
	$Obj = "$Prefix$1$Suffix";
    }
    else {
	$Obj = "$Prefix$_$Suffix";
    }

    # Amulet-specific
    $Obj =~ s|$ENV{"AMULET_DIR"}|\$(AMULET_DIR)|g;
    
    print "$ARGV[0] => $Obj\n";

    %Includes = ();

    open(CPP,"$CC $opt_D $opt_I $opt_other $ARGV[0] | grep '^#' | ");
    while (<CPP>) {
	chop;
	if (m/^# [0-9]+ "(.+)"/) {
	    $Includes{$1} = $1;
	}
    }
    close(APP);

    foreach $file (sort keys(%Includes)) {
	if ($file =~ s|$ENV{"AMULET_DIR"}|\$(AMULET_DIR)|g # Amulet-specific
	    && $file ne $ARGV[0]) {
	    print MAKEOUT "$Obj: $file\n";
	}
    }

    shift(@ARGV);
}

close(MAKEOUT);

exit;

# taken from Getopt.pl
# modified to save -- args -- separately (as $opt_other)
# and to concatenate -I and -D switches
#
# $RCSfile: makedepend,v $$Revision: 1.1 $$Date: 1996/03/15 23:18:48 $
# Process single-character switches with switch clustering.  Pass one argument
# which is a string containing all switches that take an argument.  For each
# switch found, sets $opt_x (where x is the switch name) to the value of the
# argument, or 1 if no argument.  Switches which take an argument don't care
# whether there is a space between the switch and the argument.
# Usage:
#   do Getopt('oDI');  # -o, -D & -I take arg.  Sets opt_* as a side effect.

sub Getopt {
    local($argumentative) = @_;
    local($_,$first,$rest);
    local($[) = 0;

    while (@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
	($first,$rest) = ($1,$2);

	if ($first eq "-") {
	    shift(@ARGV);
	    while (@ARGV && ($ARGV[0] ne "--")) {
		if ($ARGV[0] eq "-o") {
		    shift(@ARGV); # skip outputfile
		}
		elsif ($ARGV[0] ne "-c") {
		    $opt_other = "$opt_other $ARGV[0]";
		}
		shift(@ARGV);
	    }
	    shift(@ARGV);
	}
	elsif ($first eq "I") {
	    if ($rest ne '') {
		shift(@ARGV);
	    }
	    else {
		shift(@ARGV);
		$rest = shift(@ARGV);
	    }
	    $opt_I = "$opt_I -I$rest";
	}
	elsif ($first eq "D") {
	    if ($rest ne '') {
		shift(@ARGV);
	    }
	    else {
		shift(@ARGV);
		$rest = shift(@ARGV);
	    }
	    $opt_D = "$opt_D -D$rest";
	}
	elsif (index($argumentative,$first) >= $[) {
	    if ($rest ne '') {
		shift(@ARGV);
	    }
	    else {
		shift(@ARGV);
		$rest = shift(@ARGV);
	    }
	    eval "\$opt_$first = \$rest;";
	}
	else {
	    eval "\$opt_$first = 1;";
	    if ($rest ne '') {
		$ARGV[0] = "-$rest";
	    }
	    else {
		shift(@ARGV);
	    }
	}
    }
}

1;
