[comp.sources.misc] v13i018: PD make V1.6

greggy@zebra.UUCP (Greg Yachuk) (06/03/90)

Posting-number: Volume 13, Issue 18
Submitted-by: greggy@zebra.UUCP (Greg Yachuk)
Archive-name: make1.6/part01

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  README MANIFEST decl.h make.c make.doc
# Wrapped by greggy@etude on Thu May 31 10:55:30 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(5819 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XMake Version 1.6					90-02-08
X
XThis is the source for a public domain version of make.  It is very
Xsimilar to the `make' provided on Sun systems.  It is compiled with
XMicrosoft C (5.1) and runs on PCDOS 3.3.  It also compiles and runs on
XBSD 4.2 Unix.
X
XMany thanks to Dr. T. Andrews (uunet!cdin-1!cdis-1!tanner)
X	       Arend van den Brug (arend@philmds@philnl@mcvax)
X	       Jeff Fried (jfried@informix.com)
X	       Brian Wilson (island!sun!grenada!dr_unix)
X	       Kirk Bailey (bailey@mist.cs.orst)
X
Xfor pointing out problems and improvements.
X
XI have included a makefile and a (rudimentary) default.mk for BSD Unix.
XUpdates, additions and corrections are welcomed.  The shar distribution
Xhas the filenames reversed from the ZOO distribution:
X
X	ZOO distribution		shar distribution
X	----------------------------    --------------------------
X	makefile	makefile.bsd	makefile.dos	makefile
X	default.mk	default.bsd	default.dos	default.mk
X
X
XI'm assuming that the ZOO is used on DOS and the shar on Unix.  If what
Xyou got is not appropriate, rename the appropriate files and make.  For
Xexample, if you got the DOS version on a Unix system:
X
X	mv makefile makefile.dos
X	mv makefile.bsd makefile
X	mv default.mk default.dos
X	mv default.bsd default.mk
X	make
X
XAlternatively, you can (probably) just use this following command:
X
X	make -r -f default.bsd -f makefile.bsd
X===========================================================================
XThis is version 1.6.  Here are the changes from 1.5 to 1.6:
X
X     accept and ignore the -b option for backwards compatibility.
X
X     accept and ignore the -- option for compatibility with SCO Xenix.
X
X     set up spawnvp() so that the wait() call works on non-BSD Unix.
X
X     translate "$$" to "$" when doing macro expansion.
X
X     set "$?" to the set of dependents younger than the current target.
X
X     support GnuMake's -W (What If) switch.
X
X     strip quotes from around arguments before spawning a command (DOS).
X
X     emulate inline-stdin redirection ("<<") on DOS by collecting the
X     following commands into a temporary file and placing the filename
X     on the command line.
X
X===========================================================================
XThere is a version 1.4 that was submitted to comp.binaries.ibm.pc by
XArend van den Brug.  I have incorporated many of the changes into my
Xversion and called it 1.5.  These are the changes from 1.3 to 1.5:
X
X     support the -k, -S and -q options (see make.man).
X
X     correctly support the $(MAKE) macro.
X
X     allow target lines to end with a semi-colon and a command.
X
X     corrected bugs when allocated strings are over-run.
X
X     added "*?[]()&" to the list of characters that force the use of the
X     shell on Unix.
X
X===========================================================================
XThese are the changes from 1.2 to 1.3:
X
X     don't append shell command lines when encountering multiple targets
X     of the same name.  if this is a *special* target (e.g.  .c.obj),
X     just override.  otherwise exit with an error.
X
X     flush output before executing the command, so the output comes out
X     in the right order when redirecting stdout to a file.
X
X     if a file is supposedly built, but does not exists, use current
X     time.
X
X     exit with an error if a target line does not have a ':'.
X
X     don't force a space after "include" in case TAB is used.
X
X     D and F modifiers for Directory and Filename of $@, $<, $*.
X
X     use a dependent file for an implicit rule, if possible.
X
X     allow Makefile as well as makefile, for Unix.
X
X     always print statements when using -n, even if they start with @.
X
X     backquote (`) will force use of a shell, in Unix.
X
X===========================================================================
XThese are the changes from 1.1 to 1.2:
X
X     ensure command line macros override makefile macros, even as
X     makefiles are being read in.
X
X     support time checks correctly on MSDOS directories.
X
X     use MAKEFLAGS macro, and set it up for subordinate makes.
X
X     import environment variables and support -e flag.
X
X     handle `-f -' (i.e.  makefile from stdin) correctly.
X
X     clean up some potential NULL pointer dereferences.
X
X     correct errors in handling nested makes.
X
X     modify tokenizing routine to correctly handle trailing separators.
X
X     the documentation has been re-written
X
X===========================================================================
XThese are the changes from 1.0 to 1.1:
X
X     modify prerequisite list handling to correctly allow a target to
X     appear on multiple target lines.
X
X
XThere is a short story which goes with this offering.  Sometime early in
X1988, someone (possibly Dan Grayson) posted copyrighted source for a
X`make' to Usenet.  I used it and modified it somewhat, and then lost my
Xhard disk.  Having found this program to be very useful, I set about
Xrewriting it from my recollection of the source that I had seen.  I have
Xasked Rahul (moderator of comp.binaries.ibm.pc) if he could trace the
Xoriginal submitter, and have also posted a note to the net in c.b.i.p.d,
Xtrying to locate this person.  So far, no trace has been found.  I
Xreally would like to show this source to him (and hopefully have him
Xagree that it is not the same as his).
X
XI have based my algorithms on this previous source code.  Algorithms are
Xnot copyrightable, so I feel that I have not infringed upon anyone's
Xrights.  Also, I have acted in good faith trying to trace this person.
XI hope that recipients of this code feel the same.  I am releasing this
Xinto the public domain.  You may do anything you wish with it, even
Xcopyright it yourself and try to sell it as your own.  Good luck, and
Xhave fun.
X
X	-greg
X
XGreg Yachuk		  Informix Software Inc., Menlo Park, CA 92025
Xgreggy@informix.com | {uunet,pyramid}!infmx!greggy	(415) 926-6300
END_OF_FILE
if test 5819 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(547 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X----------------------------------------------------------
X README                     1	
X MANIFEST                   1	This shipping list
X build.c                    2	
X decl.h                     1	
X default.mk                 2	
X default.msc                2	
X make.c                     1	
X make.doc                   1	
X make.h                     2	
X makefile                   2	
X makefile.msc               2	
X parse.c                    2	
X tstring.c                  2	
X tstring.h                  2	
END_OF_FILE
if test 547 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'decl.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'decl.h'\"
else
echo shar: Extracting \"'decl.h'\" \(2877 characters\)
sed "s/^X//" >'decl.h' <<'END_OF_FILE'
X/*
X * decl.h
X *
X * 88-10-01 v1.0	created by greg yachuk, placed in the public domain
X * 88-10-06 v1.1	changed prerequisite list handling
X * 88-11-11 v1.2	fixed some bugs and added environment variables
X * 89-07-12 v1.3	stop appending shell commands, and flush output
X * 89-08-01 v1.4 AB	lots of new options and code
X * 89-10-30 v1.5	-f -S -q options, took some changes from v1.4
X * 90-04-18 v1.6	-b -- -W options, emulate <<, non-BSD cleanup
X */
X
X#ifdef	__STDC__
Xextern int main(int argc, char **argv);
Xextern int make_args(int argc, char **argv);
Xextern char **grow_list(char **list, int *len);
Xextern FILE *fopenp(char *fname, char *type);
Xextern int make(char *targname, int worry);
Xextern int default_rule(char *targname, struct targnode * targetp, int worry, int mustbuild);
Xextern char *get_preqname(struct targnode * targp, char *suffix, char *basename);
Xextern int add_metas(char *basename, char *preqname, char *targname);
Xextern int split_meta(char *sym, char *name);
Xextern int touch_file(char *targname);
Xextern int display_prereq(char *targname, long targtime, char *preqname, long preqtime);
Xextern long file_time(char *fname, int built);
Xextern int usage(void);
Xextern int build(struct shellnode * *shellp);
Xextern char *shellinput(struct shellnode * **shellp, char *eof);
Xextern int new_make(char **argv);
Xextern int parse(FILE * fd);
Xextern int link_targs(struct targnode * *targs, struct filenode * *preqs, struct shellnode * *shells);
Xextern int add_macro(char *input, int scmd);
Xextern int add_symbol(char *name, char *value, int scmd);
Xextern struct symnode *get_symbol(char *name, int scmd);
Xextern struct symnode *dup_symbol(struct symnode * sp, char *svalue);
Xextern struct targnode *add_target(char *name);
Xextern struct targnode *hash_target(char *name, unsigned short *maskp);
Xextern struct filenode *add_file(char *name);
Xextern struct filenode *hash_file(char *name, unsigned short *maskp);
Xextern char **append_node(char **node, char **adds, int size);
Xextern struct shellnode *add_shell(char *input);
Xextern char *breakout(char *input);
X#else
Xextern int main();
Xextern int make_args();
Xextern char **grow_list();
Xextern FILE *fopenp();
Xextern int make();
Xextern int default_rule();
Xextern char *get_preqname();
Xextern int add_metas();
Xextern int split_meta();
Xextern int touch_file();
Xextern int display_prereq();
Xextern long file_time();
Xextern int usage();
Xextern int build();
Xextern char *shellinput();
Xextern int new_make();
Xextern int parse();
Xextern int link_targs();
Xextern int add_macro();
Xextern int add_symbol();
Xextern struct symnode *get_symbol();
Xextern struct symnode *dup_symbol();
Xextern struct targnode *add_target();
Xextern struct targnode *hash_target();
Xextern struct filenode *add_file();
Xextern struct filenode *hash_file();
Xextern char **append_node();
Xextern struct shellnode *add_shell();
Xextern char *breakout();
X#endif
END_OF_FILE
if test 2877 -ne `wc -c <'decl.h'`; then
    echo shar: \"'decl.h'\" unpacked with wrong size!
fi
# end of 'decl.h'
fi
if test -f 'make.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'make.c'\"
else
echo shar: Extracting \"'make.c'\" \(18624 characters\)
sed "s/^X//" >'make.c' <<'END_OF_FILE'
X/*
X * make.c	An imitation of the Unix MAKE facility
X *
X * 88-10-01 v1.0	created by greg yachuk, placed in the public domain
X * 88-10-06 v1.1	changed prerequisite list handling
X * 88-11-11 v1.2	fixed some bugs and added environment variables
X * 89-07-12 v1.3	stop appending shell commands, and flush output
X * 89-08-01 v1.4 AB	lots of new options and code
X * 89-10-30 v1.5	-f -S -q options, took some changes from v1.4
X * 90-04-18 v1.6	-b -- -W options, emulate <<, non-BSD cleanup
X */
X
X#include <stdio.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <time.h>
X#ifdef	MSDOS
X#include <stdlib.h>
X#endif
X
X#include "make.h"
X#include "tstring.h"
X#include "decl.h"
X
X
Xtargptr target_list = NULL;	/* list of target nodes */
Xfileptr file_list = NULL;	/* list of file nodes */
Xsymptr  symbol_list = NULL;	/* list of symbol nodes */
Xshellptr shell_list = NULL;	/* list of shell nodes */
X
Xchar  **shell_cmds = NULL;	/* commands which force a SHELL */
X
Xint     make_level = 0;		/* for counting new_make()'s */
X
Xtargptr first_targ = NULL;	/* first target, in case nothing explicit */
Xtargptr suffix_targ = NULL;	/* .SUFFIXES target pointer */
X
Xchar  **tlist = NULL;		/* command line targets */
Xchar  **flist = NULL;		/* command line make files */
Xchar  **mlist = NULL;		/* command line macros */
X
Xint     tmax = 0;		/* max size of tlist */
Xint     fmax = 0;		/* max size of flist */
Xint     mmax = 0;		/* max size of mlist */
X
Xoptnode opts;			/* all the options */
Xint     readdef = 1;		/* -r option */
Xint     dispcount = 0;		/* used for -D option */
X
Xlong    now;			/* time at startup */
Xchar   *makeflags;		/* value to update the MAKEFLAGS macro with */
X
X
Xmain(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X	int     i;
X	targptr targp;
X	int     mk;
X	symptr  symp;
X	char   *envp;
X	char  **envv;
X
X	/* initialize the various global lists */
X
X	opts.depend = 0;
X	dispcount = 0;
X
X	target_list = NULL;
X	file_list = NULL;
X	shell_list = NULL;
X	/* don't set symbol_list to NULL, or recursive makes won't work */
X
X	/* allocate space for command line targets, files and macros */
X
X	tlist = grow_list(NULL, &tmax);
X	flist = grow_list(NULL, &fmax);
X	mlist = grow_list(NULL, &mmax);
X
X	/* process MAKEFLAGS environment variable, first */
X
X	symp = get_symbol("MAKEFLAGS", 0);
X	if (symp->svalue != NULL)
X	{
X		/* chop up the MAKEFLAGS and feed them to to make_args() */
X
X		envp = tstrcpy(symp->svalue);
X		envv = tokenize(envp);
X		for (i = 0; envv[i] != NULL; i++);
X		make_args(i, envv);
X
X		/* free the vector of pointers, and the string itself, */
X		/* since you cannot have macros, targets or makefiles  */
X		/* in the MAKEFLAGS macro.                             */
X
X		tfree(envv);
X		tfree(envp);
X		tfree(makeflags);	/* ignore this, since we just read it */
X	}
X
X	make_args(--argc, ++argv);	/* process command line options */
X
X	add_macro(makeflags, 0);/* update the MAKEFLAGS macro */
X	tfree(makeflags);
X
X	/* add command line macros, so they DON'T get overridden */
X
X	for (i = 0; mlist[i] != NULL; i++)
X		add_macro(mlist[i], 1);
X
X	tfree(mlist);		/* all done with macros */
X
X	if (opts.query)		/* -q never executes anything */
X		opts.noexec = 1;
X
X	if (opts.noexec)
X		opts.touch = 0;	/* -n never touches */
X
X	if (dispcount > 1)	/* display `default.mk' on -DD */
X		opts.display = 1;
X
X	first_targ = NULL;	/* used in parse() */
X
X	if (readdef)		/* read in `default.mk' */
X		parse(fopenp(MAKEINI, "r"));
X
X	if (dispcount > 0)	/* display makefile's on -D */
X		opts.display = 1;
X
X	first_targ = NULL;	/* get first target in `makefile' */
X
X	/* parse the makefiles given on command line */
X	for (i = 0; flist[i] != NULL; i++)
X	{
X		parse(equal(flist[i], "-") ? fdopen(dup(fileno(stdin)), "r")
X		      : fopen(flist[i], "r"));
X	}
X
X	/* no makefiles specified, so use "makefile" or "Makefile" */
X	if (i == 0)
X	{
X		if (parse(fopen("makefile", "r")) == 0)
X		{
X#ifndef	MSDOS
X			parse(fopen("Makefile", "r"));
X#endif
X		}
X	}
X
X	tfree(flist);		/* all done with makefile's */
X
X	/* find the current value of the $(MAKE) macro */
X	symp = get_symbol("MAKE", 0);
X	opts.make = (symp->svalue == NULL) ? "make" : symp->svalue;
X
X	/* get list of commands which will force usage of SHELL */
X	symp = get_symbol("SHELLCMD", 0);
X	shell_cmds = (symp->svalue) ? tokenize(tstrcpy(symp->svalue)) : NULL;
X
X	if ((targp = get_target(".INIT")) != NULL)
X		build(targp->tshell);	/* process the .INIT rule */
X
X	mk = 0;
X
X	for (i = 0; tlist[i] != NULL; i++)
X	{
X		/* process command line arguments */
X		mk |= (make(tlist[i], 1) > 0) ? 1 : 0;
X	}
X
X	tfree(tlist);		/* all done with targets */
X
X	/* if no targets specified, make the first one */
X	if (i == 0 && first_targ)
X		mk |= (make(first_targ->tfile->fname, 1) > 0) ? 1 : 0;
X
X	if ((targp = get_target(".DONE")) != NULL)
X		build(targp->tshell);	/* process the .DONE rule */
X
X	/* all done with the shell commands, so clean up */
X	if (shell_cmds)
X	{
X		if (*shell_cmds)
X			tfree(*shell_cmds);
X		tfree(shell_cmds);
X	}
X
X	return (mk & opts.query);	/* not exit(); see new_make() */
X}
X
X
X/*
X * make_args	- process the command line arguments
X */
Xmake_args(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X	int     tlen;
X	int     flen;
X	int     mlen;
X	int     no_k = 0;	/* override the -k option */
X	char   *tmf;
X	int     addflag;
X	fileptr	fp;
X
X	now = time(NULL);	/* get current date & time */
X
X	makeflags = tstrcpy("MAKEFLAGS+=");
X
X	tlen = flen = mlen = 0;
X
X	for (; argc != 0; ++argv, --argc)
X	{
X		if (**argv != '-')
X		{
X			/* doesn't start with '-'; must be macro or target */
X
X			if (strchr(*argv, '='))
X			{	/* store as a macro */
X				if (mlen == mmax)
X					mlist = grow_list(mlist, &mmax);
X				mlist[mlen++] = *argv;
X			}
X			else
X			{	/* store as a target */
X				if (tlen == tmax)
X					tlist = grow_list(tlist, &tmax);
X				tlist[tlen++] = *argv;
X			}
X			continue;
X		}
X
X		/* must be an option */
X
X		tmf = tstrcat(makeflags, *argv);
X
X		while (*argv && *++*argv)
X		{
X			addflag = 1;	/* add to MAKEFLAGS */
X			switch (**argv)
X			{
X			case 'b':	/* backwards compatibility */
X			case '-':	/* SCO Xenix compatibility */
X				addflag = 0;	/* don't add to MAKEFLAGS */
X				break;
X
X			case 'd':	/* show dependencies */
X				addflag = 0;	/* don't add to MAKEFLAGS */
X				opts.depend++;
X				break;
X
X			case 'D':	/* display makefiles */
X				dispcount++;
X				break;
X
X			case 'e':	/* don't override environment */
X				opts.envirn = 1;
X				break;
X
X			case 'f':	/* new makefile name */
X				addflag = 0;	/* don't add to MAKEFLAGS */
X				if (argc < 2)
X					usage();
X				if (flen == fmax)
X					flist = grow_list(flist, &fmax);
X				++argv, --argc;
X				flist[flen++] = *argv;
X
X				*argv = NULL;
X				break;
X
X			case 'i':	/* ignore errors */
X				opts.ignore = 1;
X				break;
X
X			case 'k':	/* give up on current target on error */
X				opts.keepon = 1;
X				break;
X
X			case 'n':	/* don't execute commands */
X				opts.noexec = 1;
X				break;
X
X			case 'q':	/* question mode */
X				opts.query = 1;
X				break;
X
X			case 'r':	/* don't read default.mk */
X				readdef = 0;
X				break;
X
X			case 's':	/* don't echo commands */
X				opts.silent = 1;
X				break;
X
X			case 'S':	/* Undo -k option */
X				no_k = 1;
X				break;
X
X			case 't':	/* touch files, don't build */
X				opts.touch = 1;
X				break;
X
X			case 'W':	/* What-if file is touched? */
X				if (argc < 2)
X					usage();
X				++argv, --argc;
X				fp = add_file(*argv);
X				fp->ftime = now;
X
X				*argv = NULL;
X				break;
X
X			default:
X				usage();	/* never returns */
X			}
X		}
X
X		if (addflag)
X		{
X			tfree(makeflags);
X			makeflags = tstrcat(tmf, " ");
X		}
X
X		tfree(tmf);
X	}
X
X	/* terminate all lists with a NULL pointer */
X
X	tlist[tlen] = NULL;
X	flist[flen] = NULL;
X	mlist[mlen] = NULL;
X
X	/* check for -S over-riding -k option */
X	if (no_k)
X		opts.keepon = 0;
X
X	/* let the caller update the makeflags macro */
X}
X
X
X/*
X * grow_list	- expand the list of pointers by a factor of two
X */
Xchar  **grow_list(list, len)
Xchar  **list;
Xint    *len;
X{
X	int     l;
X
X	/* if list is NULL, start off with a default list */
X
X	if (list == NULL)
X		list = (char **) talloc(((l = 1) + 1) * sizeof(char *));
X	else
X	{
X		l = *len;	/* get current length */
X
X		list = (char **) trealloc((char *) list,
X					  ((l <<= 1) + 1) * sizeof(char *));
X	}
X
X	if (list == NULL)
X		terror(1, "too many options");
X
X	/* if we are initially allocating it, set first pointer to NULL */
X
X	if (l == 1)
X		*list = NULL;
X
X	*len = l;		/* update current length */
X	return (list);
X}
X
X
X/*
X * fopenp	- open file in current directory or along PATH
X */
XFILE   *fopenp(fname, type)
Xchar   *fname;
Xchar   *type;
X{
X	int     len;
X	char   *fpath;
X	FILE   *fd;
X	char   *path;
X	char   *tp;
X
X	/* try to open file relative to current directory */
X	if ((fd = fopen(fname, type)) != NULL)
X		return (fd);
X#ifndef	MSDOS
X	/* didn't work, try home directory */
X	if ((path = getenv("HOME")) != NULL)
X	{
X		fpath = talloc(strlen(path) + strlen(fname) + 2);
X
X		strcpy(fpath, path);
X		len = strlen(fpath) - 1;
X
X		/* make sure there is a separator between path and filename */
X
X		if (!strchr(FILE_SEPARATOR, fpath[len]))
X			fpath[++len] = '/';
X
X		strcpy(&fpath[len + 1], fname);	/* attach the filename */
X		fd = fopen(fpath, type);
X		tfree(fpath);
X
X		if (fd != NULL)
X			return (fd);
X	}
X#endif
X	/* didn't work, search along path */
X
X	if ((path = getenv("PATH")) == NULL)
X		return (NULL);
X
X	path = tstrcpy(path);	/* allocate string and copy */
X	fpath = talloc(strlen(path) + strlen(fname) + 2);
X
X	/* look for tokens separated by semi-colons (;) or colons (:) */
X
X	tp = token(path, PATH_SEPARATOR, NULL);
X	while (tp != NULL)
X	{
X		strcpy(fpath, tp);
X		len = strlen(fpath) - 1;
X
X		/* make sure there is a separator between path and filename */
X
X		if (!strchr(FILE_SEPARATOR, fpath[len]))
X			fpath[++len] = '/';
X
X		strcpy(&fpath[len + 1], fname);	/* attach the filename */
X		if ((fd = fopen(fpath, type)) != NULL)
X			break;
X
X		tp = token(NULL, PATH_SEPARATOR, NULL);
X	}
X
X	tfree(path);
X	tfree(fpath);
X
X	return (fd);
X}
X
X
X/*
X * make		- guts of the make command
X *		- make all pre-requisites, and if necessary, build target
X *
X *	returns	-1 target was already up to date w.r.t. pre-requisites
X *		 0 target has not been built
X *		 1 target is now built (and up to date)
X */
Xmake(targname, worry)
Xchar   *targname;
Xint     worry;			/* if set, it is an error to NOT build this */
X{
X	targptr targp;
X	fileptr *preqp;
X	int     mk;
X	fileptr filep;
X	long    targtime;
X	long    preqtime;
X	char   *dol_quest;
X	char   *dq;
X
X	mk = 0;
X
X	/* if recorded time of file is not default, we've already built it */
X	filep = get_file(targname);
X	if (filep && filep->ftime != MAXNEGTIME)
X		return (1);
X
X	targp = get_target(targname);	/* find the target node */
X	if (targp == NULL)
X		return (default_rule(targname, NULL, worry, 0));
X
X	/* keep actual time of current target */
X	targtime = file_time(targname, 0);
X
X	/* must build non-existant files, even with no pre-requisites */
X	preqtime = MAXNEGTIME + 1;
X
X	dol_quest = tstrcpy("");
X
X	/* make all pre-requisites */
X	preqp = targp->tpreq;
X	while (preqp && *preqp)
X	{
X		mk |= make((*preqp)->fname, worry);
X
X		/* keep track of newest pre-requisite */
X		if (preqtime < (*preqp)->ftime)
X			preqtime = (*preqp)->ftime;
X
X		if (targtime < (*preqp)->ftime)
X		{
X			dq = tstrcat(dol_quest, (*preqp)->fname);
X			tfree(dol_quest);
X			dol_quest = tstrcat(dq, " ");
X			tfree(dq);
X		}
X
X		/* display as necessary */
X		if (opts.depend > 1 ||
X		    (opts.depend && (*preqp)->ftime > targtime))
X		{
X			display_prereq(targname, targtime, (*preqp)->fname,
X				       (*preqp)->ftime);
X		}
X
X		++preqp;
X	}
X
X	add_symbol("?", dol_quest, 0);
X	tfree(dol_quest);
X
X	if (targp->tshell == NULL)	/* try default rules anyway */
X	{
X		if (default_rule(targname, targp, 0, preqtime > targtime))
X			return (1);
X		return (mk);
X	}
X	else
X	if (preqtime > targtime)
X	{
X		if (opts.touch)	/* won't be set when `noexec' */
X			touch_file(targname);
X		else
X		{
X			add_metas("", "", targname);
X			if (build(targp->tshell))
X				return (0);
X		}
X
X		targp->tfile->ftime = (opts.noexec) ? now
X			: file_time(targname, 1);
X		return (1);
X	}
X
X	targp->tfile->ftime = targtime;
X
X	return (mk);
X}
X
X
X/*
X * default_rule	- try the .SUFFIXES when we don't have an explicit target
X *		- if `worry' is set, it is an ERROR to NOT build this target
X *		- `mustbuild' is set if make() has out-of-date prereq's
X *		   but no explicit shell rules
X */
Xdefault_rule(targname, targetp, worry, mustbuild)
Xchar   *targname;
Xtargptr targetp;
Xint     worry;
Xint     mustbuild;
X{
X	targptr targp;
X	fileptr *preqp;
X	fileptr filep;
X	char   *ext;
X	char   *basename;
X	char   *preqname;
X	long    targtime;
X	long    preqtime;
X	int     built;
X	char    suffrule[80];
X
X	ext = strrchr(targname, '.');	/* find the extension */
X	if (ext == NULL)
X		ext = targname + strlen(targname);
X
X	basename = tstrncpy(targname, ext - targname);	/* find the base name */
X
X	targtime = file_time(targname, 0);
X
X	/* suffix_targ is used to (slightly) speed up this function */
X	preqp = suffix_targ ? suffix_targ->tpreq : NULL;
X	built = 0;
X
X	while (preqp && *preqp && !built)
X	{
X		/* look for a default rule from SUFFIX to `ext' */
X		strcat(strcpy(suffrule, (*preqp)->fname), ext);
X		targp = get_target(suffrule);	/* e.g. `.c.o' */
X
X		if (targp != NULL)
X		{
X			/* found a rule; see if file exists */
X			preqname = get_preqname(targetp, (*preqp)->fname,
X						basename);
X			preqtime = file_time(preqname, 0);
X
X			/*
X			 * don't bother recursive makes unless necessary e.g.
X			 * we have .c.o and .l.c, but also .l.o! we want to
X			 * use .l.o if a .c file does not exist 
X			 */
X			if (preqtime != MAXNEGTIME || mustbuild)
X				built = make(preqname, 0);
X
X			/* check if pre-req file exists and is newer */
X			preqtime = file_time(preqname, 0);
X			if (preqtime > targtime || (mustbuild && built))
X			{
X				if (opts.depend)
X				{
X					display_prereq(targname, targtime,
X						       preqname, preqtime);
X				}
X
X				if (opts.touch)	/* won't be set when `noexec' */
X					touch_file(targname);
X				else
X				{
X					add_metas(basename, preqname, targname);
X					if (build(targp->tshell))
X						return (0);
X				}
X				built = 1;
X			}
X			else
X			if (opts.depend > 1 && preqtime != MAXNEGTIME)
X			{
X				display_prereq(targname, targtime,
X					       preqname, preqtime);
X			}
X
X			tfree(preqname);
X		}
X
X		++preqp;	/* try next .SUFFIXES rule */
X	}
X
X	if (!built)
X	{
X		/* didn't find anything; try the default rule */
X		targp = get_target(".DEFAULT");
X		if (targp != NULL)
X		{
X			add_metas(basename, "", targname);
X			if (build(targp->tshell))
X				return (0);
X			built = 1;
X		}
X		else
X		if (targtime == MAXNEGTIME && worry)
X			terror(1, tstrcat("Don't know how to make ", targname));
X	}
X
X	tfree(basename);
X
X	/* record the current file time */
X	if ((filep = get_file(targname)) != NULL)
X	{
X		filep->ftime = (built == 1 && opts.noexec) ? now
X			: file_time(targname, 1);
X	}
X
X	return (built ? built : ((targtime == MAXNEGTIME) ? 0 : 1));
X}
X
X
X/*
X * get_preqname - find prerequisite name from target and prerequisite suffix
X */
Xchar   *get_preqname(targp, suffix, basename)
Xtargptr targp;
Xchar   *suffix;
Xchar   *basename;
X{
X	fileptr *preqp;
X	char   *preqf;
X	char   *basef;
X	int     i;
X
X	if (targp != NULL)
X	{
X		/* strip the directory name from the basename */
X		basef = tsplit(basename, FILE_SEPARATOR, NULL);
X
X		/* look through prerequisite list for file with right name */
X		for (preqp = targp->tpreq; preqp && *preqp; ++preqp)
X		{
X			/* split the pre-requisite into dir and filenames */
X			preqf = tsplit((*preqp)->fname, FILE_SEPARATOR, NULL);
X
X			/* see if the filename part matches the target */
X			for (i = 0; preqf[i] != '\0'; i++)
X			{
X				if (preqf[i] != basef[i])
X					break;
X			}
X
X			/* if we differed only on the suffix, we're okay */
X			if (strcmp(preqf + i, suffix) == 0)
X				return (tstrcpy((*preqp)->fname));
X		}
X#ifdef	ALL_PREQS
X		/* didn't find a matching basename + suffix in the preq-list. */
X		/* look through prerequisite list for file with right suffix. */
X		for (preqp = targp->tpreq; preqp && *preqp; ++preqp)
X		{
X			preqf = strrchr((*preqp)->fname, '.');
X			if (preqf == NULL)
X				continue;
X
X			/* take the first file which has right suffix */
X			if (strcmp(suffix, preqf) == 0)
X				return (tstrcpy((*preqp)->fname));
X		}
X#endif				/* ALL_PREQS */
X	}
X
X	/* didn't find one, so try forming one using basename + suffix */
X
X	return (tstrcat(basename, suffix));
X}
X
X
X/*
X * add_metas	- add symbols for $*, $< and $@
X */
Xadd_metas(basename, preqname, targname)
Xchar   *basename;
Xchar   *preqname;
Xchar   *targname;
X{
X	/* $* is the basename */
X	add_symbol("*", basename, 0);
X	split_meta("*", basename);
X
X	add_symbol("<", preqname, 0);
X	split_meta("<", preqname);
X
X	add_symbol("@", targname, 0);
X	split_meta("@", targname);
X}
X
X
X/*
X * split_meta -	split a metasymbol into Directory and File parts
X */
Xsplit_meta(sym, name)
Xchar   *sym;
Xchar   *name;
X{
X	char   *dname;
X	char   *dsym;
X	char   *fsym;
X
X	/* construct the macro names (e.g. $(*D), $(@F)) */
X	dsym = tstrcat(sym, "D");
X	fsym = tstrcat(sym, "F");
X
X	add_symbol(fsym, tsplit(name, FILE_SEPARATOR, &dname), 0);
X
X	if (dname == NULL)
X		add_symbol(dsym, ".", 0);
X	else
X	{
X		add_symbol(dsym, dname, 0);
X		tfree(dname);
X	}
X
X	tfree(dsym);
X	tfree(fsym);
X}
X
X
X/*
X * touch_file	- set the MODIFICATION time of the file to NOW
X */
Xtouch_file(targname)
Xchar   *targname;
X{
X	int     handle;
X#ifndef	MSDOS
X	time_t  timep[2];
X
X	time(&timep[0]);
X	timep[1] = timep[0];
X	handle = utime(targname, timep);
X#else
X	handle = utime(targname, NULL);
X#endif
X	fputs("touch ", stdout);
X	puts(targname);
X
X	if (handle == 0)
X		return;
X
X	/* create the file, if it did not exist */
X	if (errno == ENOENT)
X	{
X		handle = open(targname, O_CREAT | O_TRUNC, S_IWRITE);
X		if (handle != -1)
X		{
X			close(handle);
X			return;
X		}
X	}
X
X	perror("touch");
X	exit(1);
X}
X
Xdisplay_prereq(targname, targtime, preqname, preqtime)
Xchar   *targname;
Xlong    targtime;
Xchar   *preqname;
Xlong    preqtime;
X{
X#ifdef	MSDOS
X	char    chtime[10];
X
X	fputs(targname, stdout);
X	fputs(" (", stdout);
X	fputs(ltoa(targtime, chtime, 16), stdout);
X	fputs((targtime <= preqtime) ? ") older than " : ") newer than ", stdout);
X	fputs(preqname, stdout);
X	fputs(" (", stdout);
X	fputs(ltoa(preqtime, chtime, 16), stdout);
X	puts(")");
X#else
X	printf("%s (%08lx) %s than %s (%08lx)\n",
X	       targname, targtime,
X	       (targtime < preqtime) ? "older" : "newer",
X	       preqname, preqtime);
X#endif
X}
X
X
Xlong    file_time(fname, built)
Xchar   *fname;
Xint     built;
X{
X	struct stat sbuf;
X
X	/*
X	 * if the file is supposedly built, but still does not exists, just
X	 * fake it by returning the current time. 
X	 */
X	if (stat(fname, &sbuf) != 0)
X		return (built ? now : MAXNEGTIME);
X	return (sbuf.st_mtime);
X}
X
X
Xusage()
X{
X	puts("make [-f file] [-dDiknqrsStWb-] [target ...] [macro=value ...]");
X	exit(1);
X}
END_OF_FILE
if test 18624 -ne `wc -c <'make.c'`; then
    echo shar: \"'make.c'\" unpacked with wrong size!
fi
# end of 'make.c'
fi
if test -f 'make.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'make.doc'\"
else
echo shar: Extracting \"'make.doc'\" \(19978 characters\)
sed "s/^X//" >'make.doc' <<'END_OF_FILE'
XNAME
X     make - maintain, update, and reconstruct groups of programs
X
XSYNOPSIS
X     make [-f file] [-dDeiknqrsStWb-] [target...] [macro=value ...]
X
XDESCRIPTION
X     MAKE takes a file of dependencies (a 'makefile') and decides what
X     commands have to be executed to bring the files up to date.  These
X     commands are either executed directly from MAKE or written to the
X     standard output without executing them.
X
X     If no makefile is specified with a -f option, MAKE reads a file
X     named `makefile', if it exists.
X
X     If no target is specified on the command line, MAKE uses the first
X     target defined in the first makefile.
X
XOPTIONS
X     -f makefile
X         Use the description file `makefile'.  A - as the makefile
X         argument denotes the standard input.
X
X     -d  Display the reasons why MAKE chooses to rebuild a target.  All
X         dependencies which are newer are displayed
X
X     -dd Display the dependency checks in more detail.  Dependencies
X         which are older are displayed, as well as newer.
X
X     -D  Display the text of the makefiles as read in.
X
X     -DD Display the text of the makefiles and `default.mk'.
X
X     -e  Let environment variables override macro definitions from
X         makefiles.  Normally, makefile macros override environment
X         variables.  Command line macro definitions always override both
X         environment variables and makefile macros definitions.
X
X     -i  Ignore error codes returned by commands.  This is equivalent to
X         the special target .IGNORE:.
X
X     -k  When a nonzero error status is returned by a command, abandon
X         work on the current target, but continue with other branches
X         that do not depend on this target.
X
X     -n  No execution mode.  Print commands, but do not execute them.
X         Even lines beginning with an @ are printed.  However, if a
X         command line is an invocation of MAKE, that line is always
X         executed.
X
X     -q  Question mode.  MAKE returns a zero or non-zero status code,
X         depending on whether or not the target file is up to date.
X
X     -r  Do not read in the default file `default.mk'.
X
X     -s  Silent mode.  Do not print command lines before executing them.
X         This is equivalent to the special target .SILENT:.
X
X     -S  Undo the effect of the -k option.  Stop processing when a
X         non-zero exit status is returned by a command.
X
X     -t  Touch the target files, bringing them up to date, rather than
X         performing the rules to reconstruct them.
X
X     -W target
X         Perform the make as if this target has a modification time of
X         "right now".  This is the "What If?" option.
X
X     -b  This option is accepted and ignored.  It allows compatibility
X         with older makefiles (and scripts).
X
X     --  This option is accepted and ignored.  It allows compatibility
X         with SCO Xenix which requires -$(MAKEFLAGS).  This version of
X         make includes a '-' within $(MAKEFLAGS).
X
X     macro=value
X         Macro definition.  This definition remains fixed for the MAKE
X         invocation.  It overrides any regular definitions for the
X         specified macro within the makefiles and from the environment.
X         It is inherited by subordinate MAKE's but act as an environment
X         variable for these.  That is, depending on the -e setting, it
X         may be overridden by a makefile definition.
X
XUSAGE
X  Makefiles
X     The first makefile read is `default.mk', which can be located any-
X     where along the PATH.  It typically contains predefined macros and
X     implicit rules.  For non-DOS systems (e.g.  Unix), it is searched
X     for in the current directory, then in the users home directory, and
X     finally along the PATH.
X
X     The default name of the makefile is `makefile' in the current
X     directory.  If this file is not found on a non-DOS system, the file
X     `Makefile' is then used as the default.  Alternate makefiles can be
X     specified using one or more '-f' options on the command line.
X     Multiple '-f's act as the concatenation of all the makefiles in a
X     left-to-right order.
X
X     The makefile(s) may contain a mixture of comment lines, macro
X     definitions, include lines, and target lines.  Lines may be
X     continued across input lines by escaping the NEWLINE with a
X     backslash (\).
X
X     Anything after a "#" is considered to be a comment, and is stripped
X     from the line, including spaces immediately before the "#.  If the
X     "#" is inside a quoted string, it is not treated as a comment.
X     Completely blank lines are ignored.
X
X     An include line is used to include the text of another makefile.
X     It consists of the word "include" left justified, followed by
X     spaces, and followed by the name of the file that is to be included
X     at this line.  Macros in the name of the included file are expanded
X     before the file is included.  Include files may be nested.
X
X  Macros
X     Macros have the form `WORD = text and more text'.  The WORD need
X     not be uppercase, but this is an accepted standard.  Later lines
X     which contain $(WORD) or ${WORD} will have this replaced by `text
X     and more text'.  If the macro name is a single character, the
X     parentheses are optional.  Note that the expansion is done
X     recursively, so the body of a macro may contain other macro
X     invocations.
X
X	e.g.	FLINTSTONES = wilma and fred
X		RUBBLES = barney and betty
X		BEDROCK = $(FLINTSTONES) and $(RUBBLES)
X
X     `$(BEDROCK)' becomes `wilma and fred and barney and betty'
X
X     Also note that whitespace around the equal sign is not relevant
X     when defining a macro.  The following four macro definitions are
X     all equivalent:
X
X		MACRO = body
X		MACRO=  body
X		MACRO  =body
X		MACRO=body
X
X     Macros may be added to by using the `+=' notation.  Thus
X
X		FLINTSTONES += and pebbles and dino
X
X     would be (given the examples above) the same as
X
X		FLINTSTONES = wilma and fred and pebbles and dino
X
X  Special Macros
X     MAKE
X         This normally has the value "make".  Any line which invokes
X         MAKE temporarily overrides the -n option, just for the duration
X         of the one line.  This allows nested invocations of MAKE to be
X         tested with the -n option.
X
X     MAKEFLAGS
X         This macro has the set of options provided to MAKE as its
X         value.  If this is set as an environment variable, the set of
X         options is processed before any command line options.  This
X         macro may be explicitly passed to nested MAKEs, but it is also
X         available to these invocations as an environment variable.  The
X         -f and -d flags are not recorded in this macro.
X
X     SUFFIXES
X         This contains the default list of suffixes supplied to the
X         special target .SUFFIXES:.  It is not sufficient to simply
X         change this macro in order to change the .SUFFIXES: list.  That
X         target must be specified in your makefile.
X
X     SHELLCMD
X         This contains the default list of commands which are local to
X         the SHELL.  If a rule is an invocation of one of these
X         commands, a SHELL is automatically spawned to handle it.
X
X     $   This macro translates to a dollar sign.  Thus you can use "$$"
X         in the makefile to represent a single "$".
X
X     There are several dynamically maintained macros that are useful as
X     abbreviations within rules.  It is best not to define them
X     explicitly.
X
X     $*  The basename of the current target.
X
X     $<  The name of the current dependency file.
X
X     $@  The name of the current target.
X
X     $?  The names of dependents which are younger than the target.
X
X     The $< and $* macros are normally used for implicit rules.  They
X     may be unreliable when used within explicit target command lines.
X     These may be suffixed with D and F, to specify the Directory and
X     Filename components (e.g. ${*D}, ${@F}).  If there is no directory
X     in the name, "." is supplied.
X
X  Targets
X     A target entry in the makefile has the following format:
X
X	target ... : [dependency ...] [; rule]
X		[rule]
X		...
X
X     Any line which does not have leading whitespace (other than macro
X     definitions) is a `target' line.  Target lines consist of one or
X     more filenames (or macros which expand into same) called targets,
X     followed by a colon (:).  The ':' is followed by a list of
X     dependent files.  The dependency list may be terminated with a
X     semicolon (;) which may be followed by a rule or shell command.
X
X     Special allowance is made on MSDOS for the colons which are needed
X     to specify files on other drives, so for example, the following
X     will work as intended:
X
X		c:foo.bar : a:fee.ber
X
X     If a target is named in more than one target line, the dependencies
X     and rules are added to form the target's complete dependency list
X     and rule list.
X
X     The dependents are ones from which a target is constructed.  They
X     in turn may be targets of other dependents.  In general, for a
X     particular target file, each of its dependent files is `made', to
X     make sure that each is up to date with respect to it's dependents.
X
X     The modification time of the target is compared to the modification
X     times of each dependent file.  If the target is older, one or more
X     of the dependents have changed, so the target must be constructed.
X     Of course, this checking is done recursively, so that all
X     dependents of dependents of dependents of ...  are up to date.
X
X     To reconstruct a target, MAKE expands macros, strips off initial
X     whitespace, and either executes the rules directly, or passes each
X     to a shell or COMMAND.COM for execution.
X
X     For target lines, macros are expanded on input.  All other lines
X     have macro expansion delayed until absolutely required.
X
X  Special Targets
X     .DEFAULT:
X         The rule for this target is used to process a target when there
X         is no other entry for it, and no implicit rule for building it.
X         MAKE ignores all dependencies for this target.
X
X     .DONE:
X         This target and its dependencies are processed after all other
X         targets are built.
X
X     .IGNORE:
X         Non-zero error codes returned from commands are ignored.
X         Encountering this in a makefile is the same as specifying -i on
X         the command line.
X
X     .INIT:
X         This target and its dependencies are processed before any other
X         targets are processed.
X
X     .SILENT:
X         Commands are not echoed before executing them.  Encountering
X         this in a makefile is the same as specifying -s on the command
X         line.
X
X     .SUFFIXES:
X         The suffixes list for selecting implicit rules.  Specifying
X         this target with dependents adds these to the end of the
X         suffixes list.  Specifying it with no dependents clears the
X         list.  In order to add your own dependents to the head of the
X         list, you could enter:
X
X		.SUFFIXES:
X		.SUFFIXES:	.abc $(SUFFIXES)
X
X  Rules
X     A line in a makefile that starts with a TAB or SPACE is a shell
X     line or rule.  This line is associated with the most recently
X     preceding dependency line.  A sequence of these may be associated
X     with a single dependency line.  When a target is out of date with
X     respect to a dependent, the sequence of commands is executed.
X     Shell lines may have any combination of the following characters to
X     the left of the command:
X
X     @   will not echo the command line, except if -n is used.
X
X     -   MAKE will ignore the exit code of the command, i.e.  the
X         ERRORLEVEL of MSDOS.  Without this, MAKE terminates when a
X         nonzero exit code is returned.
X
X     +   MAKE will use a shell or COMMAND.COM to execute the command.
X
X     If the '+' is not attached to a shell line, but the command is a
X     DOS command or if redirection is used (<, |, >), the shell line is
X     passed to COMMAND.COM anyway.  For Unix, redirection, backquote (`)
X     parentheses and variables ($vname) force the use of a shell.
X
X     For DOS, inline stdin (<<) operator is emulated with a temporary
X     file.  That is, subsequent commands are written to a temporary
X     file, and the name of the temporary file is placed in the command
X     line.  For example, if you want to link a number of objects
X     together, you can have a rule such as
X
X         link $(OBJS),$(NAME),$(LDFLAGS),$(LIBS)
X
X     If the resulting command line (after expansion) is greater than
X     128, you can specify in the following manner.
X
X	link @<<END_OF_LINK
X		$(OBJS)
X		$(NAME)
X		$(LDFLAGS)
X		$(LIBS)
X	END_OF_LINK
X
X     The four lines between the tags (END_OF_LINK) are written to a
X     temporary file (e.g.  "\mk2"), and the command line is rewritten as
X     "link @\mk2".
X
X     The rules for redirection and tags are as follows:
X
X        1)  If the redirector (<<) is immediately followed by some text,
X            the text is used as the tag.  E.g.  "<<END_OF_LINK".
X
X        2)  If the redirector is not immediately followed by some text,
X            the next token is used as the tag.  E.g.  "<< END_OF_LINK".
X
X        3)  If the redirector is the last token on a line, there is no
X            tag.
X
X        4)  Lines immediately following the command are written to a
X            temporary file, until a line beginning with the tag is
X            encountered or until the end of the current set of rules.
X
X      The following are all equivalent.
X
X	link @<<		link @<<END_OF_LINK	link @<<END_OF_LINK
X		$(OBJS)			$(OBJS)			$(OBJS)
X		$(PROG)			$(PROG)			$(PROG)
X		$(LDFLAGS)		$(LDFLAGS)		$(LDFLAGS)
X		$(LIBS)			$(LIBS)			$(LIBS)
X				END_OF_LINK
X
X  Implicit Rules
X     Implicit rules are intimately tied to the .SUFFIXES: special
X     target.  Each entry in the .SUFFIXES defines an extension to a
X     filename which may be used to build another file.  The implicit
X     rules then define how to actually build one file from another.
X     These files are related, in that they must share a common basename,
X     but have different extensions.
X
X     If a file that is being made does not have an explicit target line,
X     an implicit rule is looked for.  Each entry in the .SUFFIXES: list
X     is combined with the extension of the target, to get the name of an
X     implicit target.  If this target exists, it gives the rules used to
X     transform a file with the dependent extension to the target file.
X     Any dependents of the implicit target are ignored.
X
X     In the following example, the .SUFFIXES: list is .c .y .l, and the
X     target file is fred.o which does not have a target line.  An
X     implicit rule target `.c.o' is constructed and searched for.  If it
X     does not exist, the next suffix is tried.  If the implicit rule
X     target does exist, MAKE looks for a file `fred.c'.  If this file
X     does not exist, the next extension is tried.  If `fred.c' does
X     exist, then the associated rules are executed to create fred.o from
X     fred.c, presumably invoking the C compiler.
X
X     If the next extension must be tried, MAKE reiterates the above with
X     target `.y.o' and a file named `fred.y', and potentially with
X     `.l.o' and `fred.l'.
X
X     If a file that is being made has an explicit target, but no rules,
X     a similar search is made for implicit rules.  Each entry in the
X     .SUFFIXES: list is combined with the extension of the target, to
X     get the name of an implicit target.  If such a target exists, then
X     the list of dependents is searched for a file with the correct
X     extension, and the implicit rules are invoked to create the target.
X
XEXAMPLES
X     This makefile says that pgm.exe depends on two files a.obj and
X     b.obj, and that they in turn depend on their corresponding source
X     files (a.c and b.c) along with the common file incl.h.
X
X	pgm.exe: a.obj b.obj
X		$(CC) a.obj b.obj -o $@
X
X	a.obj:	incl.h a.c
X		$(CC) -c a.c
X
X	b.obj:	incl.h b.c
X		$(CC) -c b.c
X
X     The following makefile uses implicit rules to express the same
X     dependencies.
X
X	pgm.exe: a.obj b.obj
X		$(CC) a.obj b.obj -o $@
X
X	a.obj b.obj: incl.h
X
X     This final makefile uses implicit rules to create targets with
X     dependencies in a different directory.  Note: this cannot be done
X     with standard Unix make.
X
X	pgm.exe: a.obj b.obj
X		$(CC) a.obj b.obj -o $@
X
X	a.obj:	incl.h ../a.c
X
X	b.obj:	incl.h ../b.c
X
XFILES
X     makefile            Current version(s) of make description file.
X     Makefile            Alternative to makefile, for Unix.
X     default.mk          Default file for user-defined targets, macros,
X                         and implicit rules.
X
XDIAGNOSTICS
X     MAKE returns an exit status of 1 when it halts as a result of an
X     error.  Otherwise it returns an exit status of 0.
X
X     Badly formed macro
X         A macro definition has been encountered which has incorrect
X         syntax.  Most likely, the name is missing.
X
X     cannot open file
X         The makefile indicated in an include directive was not found or
X         was not accessible.
X
X     Don't know how to make target
X         There is no makefile entry for target, none of MAKE's implicit
X         rules apply, and there is no .DEFAULT: rule.
X
X     Improper Macro.
X         An error has occurred during macro expansion.  The most likely
X         error is a missing closing bracket.
X
X     Macro too long (limit 100 chars):
X         A macro name is too long for the internal buffer.  Try shortening
X	 it to 100 characters or less.
X
X     rules must be after target
X         A makefile syntax error, where a line beginning with a SPACE or
X         TAB has been encountered before a target line.
X
X     too many options
X         MAKE has run out of allocated space while processing command
X         line options or a target list.
X
X     Too many rules defined for target
X	 A target occurs multiple times, and each time has rules.  A
X	 target may only have one set of rules.
X
X     Unexpected end of line seen
X         A target line without a colon has been encountered.
X
XAUTHOR
X     Greg Yachuk	  Informix Software Inc., Menlo Park, CA 92025
X     greggy@informix.com | {uunet,pyramid}!infmx!greggy	(415) 926-6300
X
X     Parts of this program are based on the work by Larry Campbell of
X     DEC, Mike Hickey of University of DC, and by Dan Grayson.
X
X     Some of this documentation is based on text written by Jeffrey
X     Spidle of Iowa State University and by Dan Grayson.
X
X     Some of the formatting of this documentation follows the example of
X     Sun Microsystems for their UNIX 4.2 Release.
X
XBUGS
X     The -n does not always correctly identify the targets which need to
X     be made.  It never misses required makes, but sometimes includes
X     unrequired makes.  It also incorrectly sets up the $?  macro in
X     these circumstances.  This does not happen during full execution.
X
X     MAKE allows spaces as well as TABs to introduce shell command
X     lines.
X
X     Target lines cannot use the double colon (::) syntax.
X
X     Once a dependency is made, MAKE assumes that the dependency file is
X     present for the remainder of the run.  If a rule subsequently
X     removes that file and future targets depend on it's existence,
X     unexpected errors may result.
X
X     Sometimes MAKE gets confused when searching for implicit rules, and
X     uses several rules instead of a single rule.  For example, the two
X     rules .c.o and .l.c may be used, rather than the more direct .l.o
X     rule.
X
X     If a number of command line flags are run together, and contains
X     either `f' or `d', the whole set of flags is dropped from
X     MAKEFLAGS.
X
X     The following flags are NOT supported:
X
X     -p  Print out the compete set of macro definitions and target
X         descriptions.
X
X     -P  Report dependencies recursively to show the entire dependency
X         hierarchy, without rebuilding any targets.
X
X     The following special targets are NOT supported:
X
X     .KEEP_STATE:
X     .MAKE_VERSION:
X     .PRECIOUS:
X     .SCCS_GET:
END_OF_FILE
if test 19978 -ne `wc -c <'make.doc'`; then
    echo shar: \"'make.doc'\" unpacked with wrong size!
fi
# end of 'make.doc'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0