rh

Artifact Content
Login

Artifact 5665e10159a333665a1256585e99a3d0cb0635331b78f89e4ce06a1b9c5d49e8:


#!/usr/local/bin/perl --
#
# rcsid: $Id: makedep,v 1.1 1994/01/12 19:36:03 rick Exp $
#
#*********************************************************************#
#                                                                      
#  PERL SCRIPT:  makedep
#  AUTHOR:       Rick Ohnemus
#  ABSTRACT:
#
# This script generates the make dependencies for normal files and
# library files and writes them to the file specified on the command line.
#
# Options:
#	-a		output $(ARCH) in dependencies and compile lines
#	-c		output compile lines
#	-e exclusion	pattern to exclude from dependency list (may be
#			specified multiple times)
#	-l library	library name if doing dependencies for a library
#	-m makefile	makefile to modify
#	-o pp_options	preprocessor options
#	-p preprocessor	preprocessor to use instead of builtin
#	-r		replace entire contents of makefile
#	-s		separate dependencies from rest of file with
#			"### DO NOT DELETE THIS LINE - make depend needs it"
#	-t string	pattern to strip from object names (may be specified
#			multiple times)
#
# Other arguments (in order of command line use):
#	make variables and values
#		make macros to substitute in generated dependencies
#		variable=value
#	files to generate dependencies for
#
#*********************************************************************#
#

# Set default preprocessor.

$Preprocessor = "gcc -E";
#$Preprocessor = "cc -E";
#$Preprocessor = "/lib/cpp";

$Usage = "Usage: $0 [-acrs] [-e exclusion] [-t strip_string] [-l library] [-m makefile] [-o preprocessor_options] [-p preprocessor] [variable=value ...] file [...]\n";

# get switches and values

die $Usage unless &Getopts('ace&t&l:m:o:p:rs');

$Arch = defined($opt_a) ? 1 : 0;	# use $(ARCH) macro in output
$Cc = defined($opt_c) ? 1 : 0;		# output CC lines

# things to exclude from dependencies
if (defined(@opt_e)) {
    if ($#opt_e == $[) {
	$Exclude = "($opt_e[$[])";
    }
    else {
	for ($i = $[; $i <= $#opt_e; ++$i) {
	    $Exclude .= "($opt_e[$i])|";
	}
	chop($Exclude);		# remove trailing '|'
    }
}

# things to strip from object names
if (defined(@opt_t)) {
    if ($#opt_t == $[) {
	$Strips = "($opt_t[$[])";
    }
    else {
	for ($i = $[; $i <= $#opt_t; ++$i) {
	    $Strips .= "($opt_t[$i])|";
	}
	chop($Strips);		# remove trailing '|'
    }
}

$Library = $opt_l if (defined($opt_l));	# do library depenedencies
$Makefile = defined($opt_m) ? $opt_m : 'Makefile';	# makefile to modify
$PPOptions = defined($opt_o) ? $opt_o : '';	# preprocessor options
$Preprocessor = $opt_p if (defined($opt_p));	# preprocessor
$Replace = defined($opt_r) ? 1 : 0;	# replace contents of makefile
$Separate = defined($opt_s) ? 1 : 0;	# output separation line

undef($opt_a);
undef($opt_c);
undef(@opt_e);
undef($opt_l);
undef($opt_m);
undef($opt_o);
undef($opt_p);
undef($opt_r);
undef($opt_s);
undef(@opt_t);

# Is the makefile readable?
die "$0: $Makefile: $!\n" if (! -r $Makefile);

# Check for invalid preprocessor options
@PpOpts = split(' ', $PPOptions);
@PpOpts = grep(!/^-[BCDIMPRU]/o, @PpOpts);
die "$0: invalid preprocessor options: @PpOpts\n" if ($#PpOpts >= 0);
undef(@PpOpts);

# Make associative arrays for all make variables from the command line
# and anything else (hopefully source files)

%Vmap = ();
for (@ARGV) {
    if (/(\w.*)=(.+)/o) {
	$Vmap{$2} = $1;
    }
    else {
	push(@Sources, $_);
    }
}

# Sort the macros in reverse length order (longest first)
@Vkeys = sort { length($b) <=> length($a) } keys(%Vmap);

die "$Usage" unless $#Sources >= 0;	# need at least 1 source file

# are all of the source files readable?
$badfiles = 0;
for (@Sources) {
    if (! -r $_) {
	warn "$0: $_: $!\n";
	++$badfiles;
    }
}
exit(1) if $badfiles;	# exit if 1 or more source files is not readable

# Create temporary output file name and set signal handlers to remove
# the temporary file.

$TempFile = "$Makefile.new.$$";

$SIG{'INT'} = 'cleanup';
$SIG{'QUIT'} = 'cleanup';
$SIG{'HUP'} = 'cleanup';

# open the output file

open(OUTPUT, "> $TempFile") || die "can't open temp file - $!\n";
select(OUTPUT);

# copy the contents of the makefile if replacement wasn't specified

if (!$Replace) {
    open(INPUT, "< $Makefile") || die "can't open $Makefile - $!\n";

    # If separation was requested then copy the make file until the
    # separation line or end of file is found. If separation was not
    # requested then just copy the contents of the makefile.

    if ($Separate) {
	while (<INPUT>) {
	    /^### DO NOT DELETE THIS LINE/o && last;
	    print;
	}
	print "### DO NOT DELETE THIS LINE - make depend needs it\n\n";
    }
    else {
	while (<INPUT>) {
	    print;
	}
    }

    # don't need the original makefile any more
    close(INPUT) || die "can't close $Makefile -$!\n";
}

# Output the dependencies for the library itself if doing a library.

if (defined($Library)) {
    local($Temp);

    for (@Sources) {
	print "$Library: $_\n";
    }
    for (@Sources) {
	$Temp = $_;
	$Temp =~ s/\.c/.o/o;
	print "$Library: $Library($Temp)\n";
    }
    print "\tranlib $Library\n\t-chmod 664 $Library\n\n";
}

# output the dependencies for each source file

$badfiles = 0;
foreach $src (@Sources) {

    # get dependencies
    open(CPP, "$Preprocessor $PPOptions $src|")
	|| die "'$Preprocessor' for $src failed: $!\n";

    %incfiles = ();
    while (<CPP>) {
	$incfiles{$filename}++ if (($filename) = /^# +\d+ +"(.*)"/o);
    }
    close(CPP);

    @dependencies = sort keys(%incfiles);

    # do make variable substitution
    if ($#Vkeys >= 0) {
	for (@dependencies) {
	    foreach $key (@Vkeys) {
		s/$key/\$($Vmap{$key})/;
	    }
	}
    }

    if (defined($Exclude)) {
	@dependencies = grep(!/$Exclude/, @dependencies);
    }

    if ($#dependencies < 0) {
	print STDERR "$0: no dependencies for $src\n";
	++$badfiles;
	next;
    }

    $Object = $src;
    $Object =~ s/\.c/\.o/o;

    if (defined($Strips)) {
	$Object =~ s/$Strips//g;
    }

    # print dependencies and compiler line to makefile
    if (defined($Library)) {
	for (@dependencies) {
	    print "$Library($Object): $_\n";
	}
	if ($Cc) {
	    print "\t\$(CC) \$(CFLAGS) -c $src";
	    if ($Arch) {
		print " -o \$(ARCH)/$Object";
	    }
	    print "\n\tar rv $Library $Object\n";
	    print "\tranlib $Library\n";
	}
    }
    else {
	if ($Arch) {
	    for (@dependencies) {
		print '$(ARCH)/', "$Object: $_\n";
	    }
	    $Cc && print "\t" , '$(CC) $(CFLAGS) -c ' , "$src", ' -o $@', "\n";
	}
	else {
	    for (@dependencies) {
		print "$Object: $_\n";
	    }
	    $Cc && print "\t" , '$(CC) $(CFLAGS) -c ' , "$src\n";
	}
    }
    print "\n";
}

if ($badfiles) {
    unlink $TempFile;
    exit 1;
}

rename($Makefile, "$Makefile.BAK")
    || die "can't rename $Makefile to $Makefile.BAK - $!\n";

rename("$TempFile", $Makefile)
    || die "can't rename $TempFile to $Makefile - $!\n";

exit 0;


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

    @args = split( / */o, $argumentative );

    while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/o) {
	($first,$rest) = ($1,$2);
	$pos = index($argumentative,$first);
	if($pos >= $[) {
	    if($args[$pos+1] eq ':') {
		shift(@ARGV);
		if($rest eq '') {
		    ++$errs unless @ARGV;
		    $rest = shift(@ARGV);
		}
		eval "\$opt_$first = \$rest;";
	    }
	    elsif($args[$pos+1] eq '&') {
		shift(@ARGV);
		if($rest eq '') {
		    ++$errs unless @ARGV;
		    $rest = shift(@ARGV);
		}
		eval "push(\@opt_$first, \$rest);";
	    }
	    else {
		eval "\$opt_$first = 1";
		if($rest eq '') {
		    shift(@ARGV);
		}
		else {
		    $ARGV[0] = "-$rest";
		}
	    }
	}
	else {
	    print STDERR "Unknown option: $first\n";
	    ++$errs;
	    if($rest ne '') {
		$ARGV[0] = "-$rest";
	    }
	    else {
		shift(@ARGV);
	    }
	}
    }
    $errs == 0;
}


sub cleanup {
    unlink $TempFile;
    exit 0;
}


# Local Variables:
# mode: perl
# End: