v07i071: Public-domain MAKE

sources-request at mirror.UUCP sources-request at mirror.UUCP
Thu Dec 4 05:44:49 AEST 1986


Submitted by: caret at fairlight.oz
Mod.sources: Volume 7, Issue 71
Archive-name: make

[  This seems to be fairly complete for the V7 make.  People with
   source licenses will appreciate the appearance of this code.  --r$  ]

#!/bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If all goes well, you will see the message "No problems found."

# Exit status; set to 1 on "wc" errors or if would overwrite.
STATUS=0
# Contents:  README Makefile h.h check.c input.c macro.c main.c
#	make.c reader.c rules.c
 
echo x - README
if test -f README ; then
    echo README exists, putting output in $$README
    OUT=$$README
    STATUS=1
else
    OUT=README
fi
sed 's/^X//' > $OUT <<'@//E*O*F README//'
XFollowing is a repost of the public domain 'make' that I posted
Xto net.sources a couple of months ago.  I have fixed a few bugs, and
Xadded some more features, and the resulting changes amounted to
Xabout as much text as the whole program (hence the repost).

XFor those that missed the net.sources posting, this is a public domain
Xre-implementation of the UNIX make program.  There is no manual included;
Xfor documentation, refer to a UNIX manual, or the source.

XHere is a list of the changes made:

Xi)	If '-' (ignore) or '@' (silent) where used at the start
X	of a command, their effect was not turned off for the following
X	commands.
Xii)	A special target (.SUFFIXES, .PRECIOUS) or a rule (.c.o, .a.o),
X	if first in the file would be taken as the default target.
X	This resulted in error messages like "Don't know how to
X	make .c", because things like .SUFFIXES were being made.
X	This was further complicated by ---
Xiii)	Special target lines with no dependents (ie. .SUFFIXES:\n)
X	were not clearing out the existing dependents like
X	they should.
Xiv)	Default rules could not be redefined because of the error
X	checking for commands being defined twice.  Now you are
X	allowed to define a target beinging with '.', having
X	no dependents with commands.
Xv)	The -q option didn't do the time comparison correctly,
X	or clear the variable used to keep track of this.  Thus
X	it didn't work very well.
Xvi)	The syntax ${..} for macro's supported by UNIX make was
X	not supported.
Xvii)	There wuz a couple of spelling errors.
Xviii)	When make checked for implicit rules on targets without
X	a suffix, there were problems.  (Note: The ~ feature of
X	UNIX make wasn't and still isn't supported)
Xix)	The -n option did not print @ lines like it was supposed to.
Xx)	:: added.  (See UNIX manual)
Xxi)	$? added.  (see UNIX manual)
@//E*O*F README//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - Makefile
if test -f Makefile ; then
    echo Makefile exists, putting output in $$Makefile
    OUT=$$Makefile
    STATUS=1
else
    OUT=Makefile
fi
sed 's/^X//' > $OUT <<'@//E*O*F Makefile//'
X# Makefile for make!



XOBJS	=	check.o input.o macro.o main.o \
X		make.o reader.o rules.o

Xm:		$(OBJS)
X	cc -o m $(OBJS)

X$(OBJS):	h.h
@//E*O*F Makefile//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - h.h
if test -f h.h ; then
    echo h.h exists, putting output in $$h.h
    OUT=$$h.h
    STATUS=1
else
    OUT=h.h
fi
sed 's/^X//' > $OUT <<'@//E*O*F h.h//'
X/*
X *	Include header for make
X */


X#ifndef uchar
X#ifdef os9
X#define uchar		char
X#define void		int
X#define fputc		putc
X#else
X#define uchar		unsigned char
X#endif
X#endif

X#define bool		uchar
X#define time_t		long
X#define TRUE		(1)
X#define FALSE		(0)
X#define max(a,b)	((a)>(b)?(a):(b))

X#define DEFN1		"makefile"		/*  Default names  */
X#ifdef unix
X#define DEFN2		"Makefile"
X#endif
X#ifdef eon
X#define DEFN2		"Makefile"
X#endif
X/* os9 is case insensitive */

X#define LZ		(1024)			/*  Line size  */



X/*
X *	A name.  This represents a file, either to be made, or existant
X */

Xstruct name
X{
X	struct name *		n_next;		/* Next in the list of names */
X	char *			n_name;		/* Called */
X	struct line *		n_line;		/* Dependencies */
X	time_t			n_time;		/* Modify time of this name */
X	uchar			n_flag;		/* Info about the name */
X};

X#define N_MARK		0x01			/* For cycle check */
X#define N_DONE		0x02			/* Name looked at */
X#define N_TARG		0x04			/* Name is a target */
X#define N_PREC		0x08			/* Target is precious */
X#define N_DOUBLE	0x10			/* Double colon target */

X/*
X *	Definition of a target line.
X */
Xstruct	line
X{
X	struct line *		l_next;		/* Next line (for ::) */
X	struct depend *		l_dep;		/* Dependents for this line */
X	struct cmd *		l_cmd;		/* Commands for this line */
X};


X/*
X *	List of dependents for a line
X */
Xstruct	depend
X{
X	struct depend *		d_next;		/* Next dependent */
X	struct name *		d_name;		/* Name of dependent */
X};


X/*
X *	Commands for a line
X */
Xstruct	cmd
X{
X	struct cmd *		c_next;		/* Next command line */
X	char *			c_cmd;		/* Command line */
X};


X/*
X *	Macro storage
X */
Xstruct	macro
X{
X	struct macro *		m_next;		/* Next variable */
X	char *			m_name;		/* Called ... */
X	char *			m_val;		/* Its value */
X	uchar			m_flag;		/* Infinite loop check */
X};

Xextern char *		myname;
Xextern struct name	namehead;
Xextern struct macro *	macrohead;
Xextern struct name *	firstname;
Xextern bool		silent;
Xextern bool		ignore;
Xextern bool		rules;
Xextern bool		dotouch;
Xextern bool		quest;
Xextern bool		domake;
Xextern char		str1[];
Xextern char		str2[];
Xextern int		lineno;

Xchar *			fgets();
Xchar *			index();
Xchar *			rindex();
Xchar *			malloc();
Xextern int		errno;

Xchar *			getmacro();
Xstruct macro *		setmacro();
Xvoid			input();
Xvoid			error();
Xvoid			fatal();
Xint			make();
Xstruct name *		newname();
Xstruct depend *		newdep();
Xstruct cmd *		newcmd();
Xvoid			newline();
Xchar *			suffix();
Xvoid			touch();
Xvoid			makerules();
Xchar *			gettok();
Xvoid			precious();
@//E*O*F h.h//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - check.c
if test -f check.c ; then
    echo check.c exists, putting output in $$check.c
    OUT=$$check.c
    STATUS=1
else
    OUT=check.c
fi
sed 's/^X//' > $OUT <<'@//E*O*F check.c//'
X/*
X *	Check structures for make.
X */

X#include <stdio.h>
X#include "h.h"


X/*
X *	Prints out the structures as defined in memory.  Good for check
X *	that you make file does what you want (and for debugging make).
X */
Xvoid
Xprt()
X{
X	register struct name *		np;
X	register struct depend *	dp;
X	register struct line *		lp;
X	register struct cmd *		cp;
X	register struct macro *		mp;


X	for (mp = macrohead; mp; mp = mp->m_next)
X		fprintf(stderr, "%s = %s\n", mp->m_name, mp->m_val);

X	fputc('\n', stderr);

X	for (np = namehead.n_next; np; np = np->n_next)
X	{
X		if (np->n_flag & N_DOUBLE)
X			fprintf(stderr, "%s::\n", np->n_name);
X		else
X			fprintf(stderr, "%s:\n", np->n_name);
X		if (np == firstname)
X			fprintf(stderr, "(MAIN NAME)\n");
X		for (lp = np->n_line; lp; lp = lp->l_next)
X		{
X			fputc(':', stderr);
X			for (dp = lp->l_dep; dp; dp = dp->d_next)
X				fprintf(stderr, " %s", dp->d_name->n_name);
X			fputc('\n', stderr);

X			for (cp = lp->l_cmd; cp; cp = cp->c_next)
X#ifdef os9
X				fprintf(stderr, "-   %s\n", cp->c_cmd);
X#else
X				fprintf(stderr, "-\t%s\n", cp->c_cmd);
X#endif
X			fputc('\n', stderr);
X		}
X		fputc('\n', stderr);
X	}
X}


X/*
X *	Recursive routine that does the actual checking.
X */
Xvoid
Xcheck(np)
Xstruct name *		np;
X{
X	register struct depend *	dp;
X	register struct line *		lp;


X	if (np->n_flag & N_MARK)
X		fatal("Circular dependency from %s", np->n_name);

X	np->n_flag |= N_MARK;

X	for (lp = np->n_line; lp; lp = lp->l_next)
X		for (dp = lp->l_dep; dp; dp = dp->d_next)
X			check(dp->d_name);

X	np->n_flag &= ~N_MARK;
X}


X/*
X *	Look for circular dependancies.
X *	ie.
X *		a: b
X *		b: a
X *	is a circular dep
X */
Xvoid
Xcirch()
X{
X	register struct name *	np;


X	for (np = namehead.n_next; np; np = np->n_next)
X		check(np);
X}


X/*
X *	Check the target .PRECIOUS, and mark its dependentd as precious
X */
Xvoid
Xprecious()
X{
X	register struct depend *	dp;
X	register struct line *		lp;
X	register struct name *		np;


X	if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG))
X		return;

X	for (lp = np->n_line; lp; lp = lp->l_next)
X		for (dp = lp->l_dep; dp; dp = dp->d_next)
X			dp->d_name->n_flag |= N_PREC;
X}
@//E*O*F check.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - input.c
if test -f input.c ; then
    echo input.c exists, putting output in $$input.c
    OUT=$$input.c
    STATUS=1
else
    OUT=input.c
fi
sed 's/^X//' > $OUT <<'@//E*O*F input.c//'
X/*
X *	Parse a makefile
X */


X#include <stdio.h>
X#include	<ctype.h>
X#include "h.h"


Xstruct name		namehead;
Xstruct name *		firstname;

Xchar 			str1[LZ];		/*  General store  */
Xchar			str2[LZ];


X/*
X *	Intern a name.  Return a pointer to the name struct
X */
Xstruct name *
Xnewname(name)
Xchar *			name;
X{
X	register struct name *	rp;
X	register struct name *	rrp;
X	register char *		cp;


X	for
X	(
X		rp = namehead.n_next, rrp = &namehead;
X		rp;
X		rp = rp->n_next, rrp = rrp->n_next
X	)
X		if (strcmp(name, rp->n_name) == 0)
X			return rp;

X	if ((rp = (struct name *)malloc(sizeof (struct name)))
X				== (struct name *)0)
X		fatal("No memory for name");
X	rrp->n_next = rp;
X	rp->n_next = (struct name *)0;
X	if ((cp = malloc(strlen(name)+1)) == (char *)0)
X		fatal("No memory for name");
X	strcpy(cp, name);
X	rp->n_name = cp;
X	rp->n_line = (struct line *)0;
X	rp->n_time = (time_t)0;
X	rp->n_flag = 0;

X	return rp;
X}


X/*
X *	Add a dependant to the end of the supplied list of dependants.
X *	Return the new head pointer for that list.
X */
Xstruct depend *
Xnewdep(np, dp)
Xstruct name *		np;
Xstruct depend *		dp;
X{
X	register struct depend *	rp;
X	register struct depend *	rrp;


X	if ((rp = (struct depend *)malloc(sizeof (struct depend)))
X				== (struct depend *)0)
X		fatal("No memory for dependant");
X	rp->d_next = (struct depend *)0;
X	rp->d_name = np;

X	if (dp == (struct depend *)0)
X		return rp;

X	for (rrp = dp; rrp->d_next; rrp = rrp->d_next)
X		;

X	rrp->d_next = rp;

X	return dp;
X}


X/*
X *	Add a command to the end of the supplied list of commands.
X *	Return the new head pointer for that list.
X */
Xstruct cmd *
Xnewcmd(str, cp)
Xchar *			str;
Xstruct cmd *		cp;
X{
X	register struct cmd *	rp;
X	register struct cmd *	rrp;
X	register char *		rcp;


X	if (rcp = rindex(str, '\n'))
X		*rcp = '\0';		/*  Loose newline  */

X	while (isspace(*str))
X		str++;

X	if (*str == '\0')		/*  If nothing left, the exit  */
X		return;

X	if ((rp = (struct cmd *)malloc(sizeof (struct cmd)))
X				== (struct cmd *)0)
X		fatal("No memory for command");
X	rp->c_next = (struct cmd *)0;
X	if ((rcp = malloc(strlen(str)+1)) == (char *)0)
X		fatal("No memory for command");
X	strcpy(rcp, str);
X	rp->c_cmd = rcp;

X	if (cp == (struct cmd *)0)
X		return rp;

X	for (rrp = cp; rrp->c_next; rrp = rrp->c_next)
X		;

X	rrp->c_next = rp;

X	return cp;
X}


X/*
X *	Add a new 'line' of stuff to a target.  This check to see
X *	if commands already exist for the target.  If flag is set,
X *	the line is a double colon target.
X *
X *	Kludges:
X *	i)  If the new name begins with a '.', and there are no dependents,
X *	    then the target must cease to be a target.  This is for .SUFFIXES.
X *	ii) If the new name begins with a '.', with no dependents and has
X *	    commands, then replace the current commands.  This is for
X *	    redefining commands for a default rule.
X *	Neither of these free the space used by dependents or commands,
X *	since they could be used by another target.
X */
Xvoid
Xnewline(np, dp, cp, flag)
Xstruct name *		np;
Xstruct depend *		dp;
Xstruct cmd *		cp;
X{
X	bool			hascmds = FALSE;  /*  Target has commands  */
X	register struct line *	rp;
X	register struct line *	rrp;


X	/* Handle the .SUFFIXES case */
X	if (np->n_name[0] == '.' && !dp && !cp)
X	{
X		for (rp = np->n_line; rp; rp = rrp)
X		{
X			rrp = rp->l_next;
X			free(rp);
X		}
X		np->n_line = (struct line *)0;
X		np->n_flag &= ~N_TARG;
X		return;
X	}

X	/* This loop must happen since rrp is used later. */
X	for
X	(
X		rp = np->n_line, rrp = (struct line *)0;
X		rp;
X		rrp = rp, rp = rp->l_next
X	)
X		if (rp->l_cmd)
X			hascmds = TRUE;

X	if (hascmds && cp && !(np->n_flag & N_DOUBLE))
X		/* Handle the implicit rules redefinition case */
X		if (np->n_name[0] == '.' && dp == (struct depend *)0)
X		{
X			np->n_line->l_cmd = cp;
X			return;
X		}
X		else
X			error("Commands defined twice for target %s", np->n_name);
X	if (np->n_flag & N_TARG)
X		if (!(np->n_flag & N_DOUBLE) != !flag)		/* like xor */
X			error("Inconsistent rules for target %s", np->n_name);

X	if ((rp = (struct line *)malloc(sizeof (struct line)))
X				== (struct line *)0)
X		fatal("No memory for line");
X	rp->l_next = (struct line *)0;
X	rp->l_dep = dp;
X	rp->l_cmd = cp;

X	if (rrp)
X		rrp->l_next = rp;
X	else
X		np->n_line = rp;

X	np->n_flag |= N_TARG;
X	if (flag)
X		np->n_flag |= N_DOUBLE;
X}


X/*
X *	Parse input from the makefile, and construct a tree structure
X *	of it.
X */
Xvoid
Xinput(fd)
XFILE *			fd;
X{
X	char *			p;		/*  General  */
X	char *			q;
X	struct name *		np;
X	struct depend *		dp;
X	struct cmd *		cp;
X	bool			dbl;


X	if (getline(str1, fd))	/*  Read the first line  */
X		return;

X	for(;;)
X	{
X#ifdef os9
X		if (*str1 == ' ')	/*  Rules without targets  */
X#else
X		if (*str1 == '\t')	/*  Rules without targets  */
X#endif
X			error("Rules not allowed here");

X		p = str1;

X		while (isspace(*p))	/*  Find first target  */
X			p++;

X		while (((q = index(p, '=')) != (char *)0) &&
X		    (p != q) && (q[-1] == '\\'))	/*  Find value */
X		{
X			register char *		a;

X			a = q - 1;	/*  Del \ chr; move rest back  */
X			p = q;
X			while(*a++ = *q++)
X				;
X		}

X		if (q != (char *)0)
X		{
X			register char *		a;

X			*q++ = '\0';		/*  Separate name and val  */
X			while (isspace(*q))
X				q++;
X			if (p = rindex(q, '\n'))
X				*p = '\0';

X			p = str1;
X			if ((a = gettok(&p)) == (char *)0)
X				error("No macro name");

X			setmacro(a, q);

X			if (getline(str1, fd))
X				return;
X			continue;
X		}

X		expand(str1);
X		p = str1;

X		while (((q = index(p, ':')) != (char *)0) &&
X		    (p != q) && (q[-1] == '\\'))	/*  Find dependents  */
X		{
X			register char *		a;

X			a = q - 1;	/*  Del \ chr; move rest back  */
X			p = q;
X			while(*a++ = *q++)
X				;
X		}

X		if (q == (char *)0)
X			error("No targets provided");

X		*q++ = '\0';	/*  Separate targets and dependents  */

X		if (*q == ':')		/* Double colon */
X		{
X			dbl = 1;
X			q++;
X		}
X		else
X			dbl = 0;

X		for (dp = (struct depend *)0; ((p = gettok(&q)) != (char *)0);)
X					/*  get list of dep's */
X		{
X			np = newname(p);		/*  Intern name  */
X			dp = newdep(np, dp);		/*  Add to dep list */
X		}

X		*((q = str1) + strlen(str1) + 1) = '\0';
X			/*  Need two nulls for gettok (Remember separation)  */

X		cp = (struct cmd *)0;
X		if (getline(str2, fd) == FALSE)		/*  Get commands  */
X		{
X#ifdef os9
X			while (*str2 == ' ')
X#else
X			while (*str2 == '\t')
X#endif
X			{
X				cp = newcmd(&str2[0], cp);
X				if (getline(str2, fd))
X					break;
X			}
X		}

X		while ((p = gettok(&q)) != (char *)0)	/* Get list of targ's */
X		{
X			np = newname(p);		/*  Intern name  */
X			newline(np, dp, cp, dbl);
X			if (!firstname && p[0] != '.')
X				firstname = np;
X		}

X		if (feof(fd))				/*  EOF?  */
X			return;

X		strcpy(str1, str2);
X	}
X}
@//E*O*F input.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - macro.c
if test -f macro.c ; then
    echo macro.c exists, putting output in $$macro.c
    OUT=$$macro.c
    STATUS=1
else
    OUT=macro.c
fi
sed 's/^X//' > $OUT <<'@//E*O*F macro.c//'
X/*
X *	Macro control for make
X */


X#include "h.h"


Xstruct macro *		macrohead;


Xstruct macro *
Xgetmp(name)
Xchar *			name;
X{
X	register struct macro *	rp;

X	for (rp = macrohead; rp; rp = rp->m_next)
X		if (strcmp(name, rp->m_name) == 0)
X			return rp;
X	return (struct macro *)0;
X}


Xchar *
Xgetmacro(name)
Xchar *			name;
X{
X	struct macro *		mp;

X	if (mp = getmp(name))
X		return mp->m_val;
X	else
X		return "";
X}


Xstruct macro *
Xsetmacro(name, val)
Xchar *			name;
Xchar *			val;
X{
X	register struct macro *	rp;
X	register char *		cp;


X			/*  Replace macro definition if it exists  */
X	for (rp = macrohead; rp; rp = rp->m_next)
X		if (strcmp(name, rp->m_name) == 0)
X		{
X			free(rp->m_val);	/*  Free space from old  */
X			break;
X		}

X	if (!rp)		/*  If not defined, allocate space for new  */
X	{
X		if ((rp = (struct macro *)malloc(sizeof (struct macro)))
X					 == (struct macro *)0)
X			fatal("No memory for macro");

X		rp->m_next = macrohead;
X		macrohead = rp;
X		rp->m_flag = FALSE;

X		if ((cp = malloc(strlen(name)+1)) == (char *)0)
X			fatal("No memory for macro");
X		strcpy(cp, name);
X		rp->m_name = cp;
X	}

X	if ((cp = malloc(strlen(val)+1)) == (char *)0)
X		fatal("No memory for macro");
X	strcpy(cp, val);		/*  Copy in new value  */
X	rp->m_val = cp;

X	return rp;
X}


X/*
X *	Do the dirty work for expand
X */
Xvoid
Xdoexp(to, from, len, buf)
Xchar **			to;
Xchar *			from;
Xint *			len;
Xchar *			buf;
X{
X	register char *		rp;
X	register char *		p;
X	register char *		q;
X	register struct macro *	mp;


X	rp = from;
X	p = *to;
X	while (*rp)
X	{
X		if (*rp != '$')
X		{
X			*p++ = *rp++;
X			(*len)--;
X		}
X		else
X		{
X			q = buf;
X			if (*++rp == '{')
X				while (*++rp && *rp != '}')
X					*q++ = *rp;
X			else if (*rp == '(')
X				while (*++rp && *rp != ')')
X					*q++ = *rp;
X			else if (!*rp)
X			{
X				*p++ = '$';
X				break;
X			}
X			else
X				*q++ = *rp;
X			*q = '\0';
X			if (*rp)
X				rp++;
X			if (!(mp = getmp(buf)))
X				mp = setmacro(buf, "");
X			if (mp->m_flag)
X				fatal("Infinitely recursive macro %s", mp->m_name);
X			mp->m_flag = TRUE;
X			*to = p;
X			doexp(to, mp->m_val, len, buf);
X			p = *to;
X			mp->m_flag = FALSE;
X		}
X		if (*len <= 0)
X			error("Expanded line too line");
X	}
X	*p = '\0';
X	*to = p;
X}


X/*
X *	Expand any macros in str.
X */
Xvoid
Xexpand(str)
Xchar *		str;
X{
X	static char		a[LZ];
X	static char		b[LZ];
X	char *			p = str;
X	int			len = LZ-1;

X	strcpy(a, str);
X	doexp(&p, a, &len, b);
X}
@//E*O*F macro.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - main.c
if test -f main.c ; then
    echo main.c exists, putting output in $$main.c
    OUT=$$main.c
    STATUS=1
else
    OUT=main.c
fi
sed 's/^X//' > $OUT <<'@//E*O*F main.c//'
X/*
X *	make [-f makefile] [-ins] [target(s) ...]
X *
X *	(Better than EON mk but not quite as good as UNIX make)
X *
X *	-f makefile name
X *	-i ignore exit status
X *	-n Pretend to make
X *	-p Print all macros & targets
X *	-q Question up-to-dateness of target.  Return exit status 1 if not
X *	-r Don't not use inbuilt rules
X *	-s Make silently
X *	-t Touch files instead of making them
X *	-m Change memory requirements (EON only)
X */

X#include <stdio.h>
X#include "h.h"

X#ifdef unix
X#include <sys/errno.h>
X#endif
X#ifdef eon
X#include <sys/err.h>
X#endif
X#ifdef os9
X#include <errno.h>
X#endif


X#ifdef eon
X#define MEMSPACE	(16384)
X#endif


Xchar *			myname;
Xchar *			makefile;	/*  The make file  */
X#ifdef eon
Xunsigned		memspace = MEMSPACE;
X#endif

XFILE *			ifd;		/*  Input file desciptor  */
Xbool			domake = TRUE;	/*  Go through the motions option  */
Xbool			ignore = FALSE;	/*  Ignore exit status option  */
Xbool			silent = FALSE;	/*  Silent option  */
Xbool			print = FALSE;	/*  Print debuging information  */
Xbool			rules = TRUE;	/*  Use inbuilt rules  */
Xbool			dotouch = FALSE;/*  Touch files instead of making  */
Xbool			quest = FALSE;	/*  Question up-to-dateness of file  */


Xvoid
Xmain(argc, argv)
Xint			argc;
Xchar **			argv;
X{
X	register char *		p;		/*  For argument processing  */
X	int			estat = 0;	/*  For question  */
X	register struct name *	np;


X	myname = (argc-- < 1) ? "make" : *argv++;

X	while ((argc > 0) && (**argv == '-'))
X	{
X		argc--;		/*  One less to process  */
X		p = *argv++;	/*  Now processing this one  */

X		while (*++p != '\0')
X		{
X			switch(*p)
X			{
X			case 'f':	/*  Alternate file name  */
X				if (*++p == '\0')
X				{
X					if (argc-- <= 0)
X						usage();
X					p = *argv++;
X				}
X				makefile = p;
X				goto end_of_args;
X#ifdef eon
X			case 'm':	/*  Change space requirements  */
X				if (*++p == '\0')
X				{
X					if (argc-- <= 0)
X						usage();
X					p = *argv++;
X				}
X				memspace = atoi(p);
X				goto end_of_args;
X#endif
X			case 'n':	/*  Pretend mode  */
X				domake = FALSE;
X				break;
X			case 'i':	/*  Ignore fault mode  */
X				ignore = TRUE;
X				break;
X			case 's':	/*  Silent about commands  */
X				silent = TRUE;
X				break;
X			case 'p':
X				print = TRUE;
X				break;
X			case 'r':
X				rules = FALSE;
X				break;
X			case 't':
X				dotouch = TRUE;
X				break;
X			case 'q':
X				quest = TRUE;
X				break;
X			default:	/*  Wrong option  */
X				usage();
X			}
X		}
X	end_of_args:;
X	}

X#ifdef eon
X	if (initalloc(memspace) == 0xffff)  /*  Must get memory for alloc  */
X		fatal("Cannot initalloc memory");
X#endif

X	if (strcmp(makefile, "-") == 0)	/*  Can use stdin as makefile  */
X		ifd = stdin;
X	else
X		if (!makefile)		/*  If no file, then use default */
X		{
X			if ((ifd = fopen(DEFN1, "r")) == (FILE *)0)
X#ifdef eon
X				if (errno != ER_NOTF)
X					fatal("Can't open %s; error %02x", DEFN1, errno);
X#endif
X#ifdef unix
X				if (errno != ENOENT)
X					fatal("Can't open %s; error %02x", DEFN1, errno);
X#endif
X#ifndef os9
X			if ((ifd == (FILE *)0)
X				  && ((ifd = fopen(DEFN2, "r")) == (FILE *)0))
X				fatal("Can't open %s", DEFN2);
X#else
X				fatal("Can't open %s", DEFN1);
X#endif
X		}
X		else
X			if ((ifd = fopen(makefile, "r")) == (FILE *)0)
X				fatal("Can't open %s", makefile);

X	makerules();

X	setmacro("$", "$");

X	while (argc && (p = index(*argv, '=')))
X	{
X		char		c;

X		c = *p;
X		*p = '\0';
X		setmacro(*argv, p+1);
X		*p = c;

X		argv++;
X		argc--;
X	}

X	input(ifd);	/*  Input all the gunga  */
X	fclose(ifd);	/*  Finished with makefile  */
X	lineno = 0;	/*  Any calls to error now print no line number */

X	if (print)
X		prt();	/*  Print out structures  */

X	np = newname(".SILENT");
X	if (np->n_flag & N_TARG)
X		silent = TRUE;

X	np = newname(".IGNORE");
X	if (np->n_flag & N_TARG)
X		ignore = TRUE;

X	precious();

X	if (!firstname)
X		fatal("No targets defined");

X	circh();	/*  Check circles in target definitions  */

X	if (!argc)
X		estat = make(firstname, 0);
X	else while (argc--)
X	{
X		if (!print && !silent && strcmp(*argv, "love") == 0)
X			printf("Not war!\n");
X		estat |= make(newname(*argv++), 0);
X	}

X	if (quest)
X		exit(estat);
X	else
X		exit(0);
X}


Xusage()
X{
X	fprintf(stderr, "Usage: %s [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n", myname);
X	exit(1);
X}


Xvoid
Xfatal(msg, a1, a2, a3, a4, a5, a6)
Xchar	*msg;
X{
X	fprintf(stderr, "%s: ", myname);
X	fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
X	fputc('\n', stderr);
X	exit(1);
X}
@//E*O*F main.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - make.c
if test -f make.c ; then
    echo make.c exists, putting output in $$make.c
    OUT=$$make.c
    STATUS=1
else
    OUT=make.c
fi
sed 's/^X//' > $OUT <<'@//E*O*F make.c//'
X/*
X *	Do the actual making for make
X */

X#include <stdio.h>
X#ifdef unix
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/errno.h>
X#endif
X#ifdef eon
X#include <sys/stat.h>
X#include <sys/err.h>
X#endif
X#ifdef os9
X#include <time.h>
X#include <os9.h>
X#include <modes.h>
X#include <direct.h>
X#include <errno.h>
X#endif
X#include "h.h"



X/*
X *	Exec a shell that returns exit status correctly (/bin/esh).
X *	The standard EON shell returns the process number of the last
X *	async command, used by the debugger (ugg).
X *	[exec on eon is like a fork+exec on unix]
X */
Xint
Xdosh(string, shell)
Xchar *			string;
Xchar *			shell;
X{
X	int	number;

X#ifdef unix
X	return system(string);
X#endif
X#ifdef eon
X	return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
X		-1:	/* couldn't start the shell */
X		wait(number);	/* return its exit status */
X#endif
X#ifdef os9
X	int	status, pid;

X	strcat(string, "\n");
X	if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
X		return -1;		/* Couldn't start a shell */
X	do
X	{
X		if ((pid = wait(&status)) == -1)
X			return -1;	/* child already died!?!? */
X	} while (pid != number);

X	return status;
X#endif
X}


X/*
X *	Do commands to make a target
X */
Xvoid
Xdocmds1(np, lp)
Xstruct name *		np;
Xstruct line *		lp;
X{
X	bool			ssilent;
X	bool			signore;
X	int			estat;
X	register char *		q;
X	register char *		p;
X	char *			shell;
X	register struct cmd *	cp;


X	if (*(shell = getmacro("SHELL")) == '\0')
X#ifdef eon
X		shell = ":bin/esh";
X#endif
X#ifdef unix
X		shell = "/bin/sh";
X#endif
X#ifdef os9
X		shell = "shell";
X#endif

X	for (cp = lp->l_cmd; cp; cp = cp->c_next)
X	{
X		strcpy(str1, cp->c_cmd);
X		expand(str1);
X		q = str1;
X		ssilent = silent;
X		signore = ignore;
X		while ((*q == '@') || (*q == '-'))
X		{
X			if (*q == '@')	   /*  Specific silent  */
X				ssilent = TRUE;
X			else		   /*  Specific ignore  */
X				signore = TRUE;
X			q++;		   /*  Not part of the command  */
X		}

X		if (!domake)
X			ssilent = 0;

X		if (!ssilent)
X			fputs("    ", stdout);

X		for (p=q; *p; p++)
X		{
X			if (*p == '\n' && p[1] != '\0')
X			{
X				*p = ' ';
X				if (!ssilent)
X					fputs("\\\n", stdout);
X			}
X			else if (!ssilent)
X				putchar(*p);
X		}
X		if (!ssilent)
X			putchar('\n');

X		if (domake)
X		{			/*  Get the shell to execute it  */
X			if ((estat = dosh(q, shell)) != 0)
X			{
X				if (estat == -1)
X					fatal("Couldn't execute %s", shell);
X				else
X				{
X					printf("%s: Error code %d", myname, estat);
X					if (signore)
X						fputs(" (Ignored)\n", stdout);
X					else
X					{
X						putchar('\n');
X						if (!(np->n_flag & N_PREC))
X							if (unlink(np->n_name) == 0)
X								printf("%s: '%s' removed.\n", myname, np->n_name);
X						exit(estat);
X					}
X				}
X			}
X		}
X	}
X}


Xdocmds(np)
Xstruct name *		np;
X{
X	register struct line *	lp;


X	for (lp = np->n_line; lp; lp = lp->l_next)
X		docmds1(np, lp);
X}


X#ifdef os9
X/*
X *	Some stuffing around to get the modified time of a file
X *	in an os9 file system
X */
Xgetmdate(fd, tbp)
Xstruct sgtbuf *		tbp;
X{
X	struct registers	regs;
X	static struct fildes	fdbuf;


X	regs.rg_a = fd;
X	regs.rg_b = SS_FD;
X	regs.rg_x = &fdbuf;
X	regs.rg_y = sizeof (fdbuf);

X	if (_os9(I_GETSTT, &regs) == -1)
X	{
X		errno = regs.rg_b & 0xff;
X		return -1;
X	}
X	if (tbp)
X	{
X		_strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
X		tbp->t_second = 0;	/* Files are only acurate to mins */
X	}
X	return 0;
X}


X/*
X *	Kludge routine to return an aproximation of how many
X *	seconds since 1980.  Dates will be in order, but will not
X *	be lineer
X */
Xtime_t
Xcnvtime(tbp)
Xstruct sgtbuf		*tbp;
X{
X	long			acc;


X	acc = tbp->t_year - 80;		/* Baseyear is 1980 */
X	acc = acc * 12 + tbp->t_month;
X	acc = acc * 31 + tbp->t_day;
X	acc = acc * 24 + tbp->t_hour;
X	acc = acc * 60 + tbp->t_minute;
X	acc = acc * 60 + tbp->t_second;

X	return acc;
X}


X/*
X *	Get the current time in the internal format
X */
Xtime(tp)
Xtime_t *		tp;
X{
X	struct sgtbuf		tbuf;


X	if (getime(&tbuf) < 0)
X		return -1;

X	if (tp)
X		*tp = cnvtime(&tbuf);

X	return 0;
X}
X#endif


X/*
X *	Get the modification time of a file.  If the first
X *	doesn't exist, it's modtime is set to 0.
X */
Xvoid
Xmodtime(np)
Xstruct name *		np;
X{
X#ifdef unix
X	struct stat		info;
X	int			fd;


X	if (stat(np->n_name, &info) < 0)
X	{
X		if (errno != ENOENT)
X			fatal("Can't open %s; error %d", np->n_name, errno);

X		np->n_time = 0L;
X	}
X	else
X		np->n_time = info.st_mtime;
X#endif
X#ifdef eon
X	struct stat		info;
X	int			fd;


X	if ((fd = open(np->n_name, 0)) < 0)
X	{
X		if (errno != ER_NOTF)
X			fatal("Can't open %s; error %02x", np->n_name, errno);

X		np->n_time = 0L;
X	}
X	else if (getstat(fd, &info) < 0)
X		fatal("Can't getstat %s; error %02x", np->n_name, errno);
X	else
X		np->n_time = info.st_mod;

X	close(fd);
X#endif
X#ifdef os9
X	struct sgtbuf		info;
X	int			fd;


X	if ((fd = open(np->n_name, 0)) < 0)
X	{
X		if (errno != E_PNNF)
X			fatal("Can't open %s; error %02x", np->n_name, errno);

X		np->n_time = 0L;
X	}
X	else if (getmdate(fd, &info) < 0)
X		fatal("Can't getstat %s; error %02x", np->n_name, errno);
X	else
X		np->n_time = cnvtime(&info);

X	close(fd);
X#endif
X}


X/*
X *	Update the mod time of a file to now.
X */
Xvoid
Xtouch(np)
Xstruct name *		np;
X{
X	char			c;
X	int			fd;


X	if (!domake || !silent)
X		printf("    touch(%s)\n", np->n_name);

X	if (domake)
X	{
X#ifdef unix
X		long		a[2];

X		a[0] = a[1] = time(0);
X		if (utime(np->n_name, &a[0]) < 0)
X			printf("%s: '%s' not touched - non-existant\n",
X					myname, np->n_name);
X#endif
X#ifdef eon
X		if ((fd = open(np->n_name, 0)) < 0)
X			printf("%s: '%s' not touched - non-existant\n",
X					myname, np->n_name);
X		else
X		{
X			uread(fd, &c, 1, 0);
X			uwrite(fd, &c, 1);
X		}
X		close(fd);
X#endif
X#ifdef os9
X		/*
X		 *	Strange that something almost as totally useless
X		 *	as this is easy to do in os9!
X		 */
X		if ((fd = open(np->n_name, S_IWRITE)) < 0)
X			printf("%s: '%s' not touched - non-existant\n",
X					myname, np->n_name);
X		close(fd);
X#endif
X	}
X}


X/*
X *	Recursive routine to make a target.
X */
Xint
Xmake(np, level)
Xstruct name *		np;
Xint			level;
X{
X	register struct depend *	dp;
X	register struct line *		lp;
X	register struct depend *	qdp;
X	time_t				dtime = 1;
X	bool				didsomething = 0;


X	if (np->n_flag & N_DONE)
X		return 0;

X	if (!np->n_time)
X		modtime(np);		/*  Gets modtime of this file  */

X	if (rules)
X	{
X		for (lp = np->n_line; lp; lp = lp->l_next)
X			if (lp->l_cmd)
X				break;
X		if (!lp)
X			dyndep(np);
X	}

X	if (!(np->n_flag & N_TARG) && np->n_time == 0L)
X		fatal("Don't know how to make %s", np->n_name);

X	for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next)
X	{
X		for (dp = lp->l_dep; dp; dp = dp->d_next)
X		{
X			make(dp->d_name, level+1);
X			if (np->n_time < dp->d_name->n_time)
X				qdp = newdep(dp->d_name, qdp);
X			dtime = max(dtime, dp->d_name->n_time);
X		}
X		if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime))
X		{
X			make1(np, lp, qdp);	/* free()'s qdp */
X			dtime = 1;
X			qdp = (struct depend *)0;
X			didsomething++;
X		}
X	}

X	np->n_flag |= N_DONE;

X	if (quest)
X	{
X		long		t;

X		t = np->n_time;
X		time(&np->n_time);
X		return t < dtime;
X	}
X	else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE))
X	{
X		make1(np, (struct line *)0, qdp);	/* free()'s qdp */
X		time(&np->n_time);
X	}
X	else if (level == 0 && !didsomething)
X		printf("%s: '%s' is up to date\n", myname, np->n_name);
X	return 0;
X}


Xmake1(np, lp, qdp)
Xregister struct depend *	qdp;
Xstruct line *			lp;
Xstruct name *			np;
X{
X	register struct depend *	dp;


X	if (dotouch)
X		touch(np);
X	else
X	{
X		strcpy(str1, "");
X		for (dp = qdp; dp; dp = qdp)
X		{
X			if (strlen(str1))
X				strcat(str1, " ");
X			strcat(str1, dp->d_name->n_name);
X			qdp = dp->d_next;
X			free(dp);
X		}
X		setmacro("?", str1);
X		setmacro("@", np->n_name);
X		if (lp)		/* lp set if doing a :: rule */
X			docmds1(np, lp);
X		else
X			docmds(np);
X	}
X}
@//E*O*F make.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - reader.c
if test -f reader.c ; then
    echo reader.c exists, putting output in $$reader.c
    OUT=$$reader.c
    STATUS=1
else
    OUT=reader.c
fi
sed 's/^X//' > $OUT <<'@//E*O*F reader.c//'
X/*
X *	Read in makefile
X */


X#include <stdio.h>
X#include	<ctype.h>
X#include "h.h"


Xint			lineno;


X/*
X *	Syntax error handler.  Print message, with line number, and exits.
X */
Xvoid
Xerror(msg, a1, a2, a3)
Xchar *			msg;
X{
X	fprintf(stderr, "%s: ", myname);
X	fprintf(stderr, msg, a1, a2, a3);
X	if (lineno)
X		fprintf(stderr, " near line %d", lineno);
X	fputc('\n', stderr);
X	exit(1);
X}


X/*
X *	Read a line into the supplied string of length LZ.  Remove
X *	comments, ignore blank lines. Deal with	quoted (\) #, and
X *	quoted newlines.  If EOF return TRUE.
X */
Xbool
Xgetline(str, fd)
Xchar *		str;
XFILE *		fd;
X{
X	register char *		p;
X	char *			q;
X	int			pos = 0;


X	for (;;)
X	{
X		if (fgets(str+pos, LZ-pos, fd) == (char *)0)
X			return TRUE;		/*  EOF  */

X		lineno++;

X		if ((p = index(str+pos, '\n')) == (char *)0)
X			error("Line too long");

X		if (p[-1] == '\\')
X		{
X			p[-1] = '\n';
X			pos = p - str;
X			continue;
X		}

X		p = str;
X		while (((q = index(p, '#')) != (char *)0) &&
X		    (p != q) && (q[-1] == '\\'))
X		{
X			char	*a;

X			a = q - 1;	/*  Del \ chr; move rest back  */
X			p = q;
X			while (*a++ = *q++)
X				;
X		}
X		if (q != (char *)0)
X		{
X			q[0] = '\n';
X			q[1] = '\0';
X		}

X		p = str;
X		while (isspace(*p))	/*  Checking for blank  */
X			p++;

X		if (*p != '\0')
X			return FALSE;
X		pos = 0;
X	}
X}


X/*
X *	Get a word from the current line, surounded by white space.
X *	return a pointer to it. String returned has no white spaces
X *	in it.
X */
Xchar *
Xgettok(ptr)
Xchar	**ptr;
X{
X	register char *		p;


X	while (isspace(**ptr))	/*  Skip spaces  */
X		(*ptr)++;

X	if (**ptr == '\0')	/*  Nothing after spaces  */
X		return NULL;

X	p = *ptr;		/*  word starts here  */

X	while ((**ptr != '\0') && (!isspace(**ptr)))
X		(*ptr)++;	/*  Find end of word  */

X	*(*ptr)++ = '\0';	/*  Terminate it  */

X	return(p);
X}
@//E*O*F reader.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo x - rules.c
if test -f rules.c ; then
    echo rules.c exists, putting output in $$rules.c
    OUT=$$rules.c
    STATUS=1
else
    OUT=rules.c
fi
sed 's/^X//' > $OUT <<'@//E*O*F rules.c//'
X/*
X *	Control of the implicit suffix rules
X */


X#include "h.h"


X/*
X *	Return a pointer to the suffix of a name
X */
Xchar *
Xsuffix(name)
Xchar *			name;
X{
X	return rindex(name, '.');
X}


X/*
X *	Dynamic dependency.  This routine applies the suffis rules
X *	to try and find a source and a set of rules for a missing
X *	target.  If found, np is made into a target with the implicit
X *	source name, and rules.  Returns TRUE if np was made into
X *	a target.
X */
Xbool
Xdyndep(np)
Xstruct name *		np;
X{
X	register char *		p;
X	register char *		q;
X	register char *		suff;		/*  Old suffix  */
X	register char *		basename;	/*  Name without suffix  */
X	struct name *		op;		/*  New dependent  */
X	struct name *		sp;		/*  Suffix  */
X	struct line *		lp;
X	struct depend *		dp;
X	char *			newsuff;


X	p = str1;
X	q = np->n_name;
X	if (!(suff = suffix(q)))
X		return FALSE;		/* No suffix */
X	while (q < suff)
X		*p++ = *q++;
X	*p = '\0';
X	basename = setmacro("*", str1)->m_val;

X	if (!((sp = newname(".SUFFIXES"))->n_flag & N_TARG))
X		return FALSE;

X	for (lp = sp->n_line; lp; lp = lp->l_next)
X		for (dp = lp->l_dep; dp; dp = dp->d_next)
X		{
X			newsuff = dp->d_name->n_name;
X			if (strlen(suff)+strlen(newsuff)+1 >= LZ)
X				fatal("Suffix rule too long");
X			p = str1;
X			q = newsuff;
X			while (*p++ = *q++)
X				;
X			p--;
X			q = suff;
X			while (*p++ = *q++)
X				;
X			sp = newname(str1);
X			if (sp->n_flag & N_TARG)
X			{
X				p = str1;
X				q = basename;
X				if (strlen(basename) + strlen(newsuff)+1 >= LZ)
X					fatal("Implicit name too long");
X				while (*p++ = *q++)
X					;
X				p--;
X				q = newsuff;
X				while (*p++ = *q++)
X					;
X				op = newname(str1);
X				if (!op->n_time)
X					modtime(op);
X				if (op->n_time)
X				{
X					dp = newdep(op, 0);
X					newline(np, dp, sp->n_line->l_cmd, 0);
X					setmacro("<", op->n_name);
X					return TRUE;
X				}
X			}
X		}
X	return FALSE;
X}


X/*
X *	Make the default rules
X */
Xvoid
Xmakerules()
X{
X	struct cmd *		cp;
X	struct name *		np;
X	struct depend *		dp;


X#ifdef eon
X	setmacro("BDSCC", "asm");
X	/*	setmacro("BDSCFLAGS", "");	*/
X	cp = newcmd("$(BDSCC) $(BDSCFLAGS) -n $<", 0);
X	np = newname(".c.o");
X	newline(np, 0, cp, 0);

X	setmacro("CC", "c");
X	setmacro("CFLAGS", "-O");
X	cp = newcmd("$(CC) $(CFLAGS) -c $<", 0);
X	np = newname(".c.obj");
X	newline(np, 0, cp, 0);

X	setmacro("M80", "asm -n");
X	/*	setmacro("M80FLAGS", "");	*/
X	cp = newcmd("$(M80) $(M80FLAGS) $<", 0);
X	np = newname(".mac.o");
X	newline(np, 0, cp, 0);

X	setmacro("AS", "zas");
X	/*	setmacro("ASFLAGS", "");	*/
X	cp = newcmd("$(ZAS) $(ASFLAGS) -o $@ $<", 0);
X	np = newname(".as.obj");
X	newline(np, 0, cp, 0);

X	np = newname(".as");
X	dp = newdep(np, 0);
X	np = newname(".obj");
X	dp = newdep(np, dp);
X	np = newname(".c");
X	dp = newdep(np, dp);
X	np = newname(".o");
X	dp = newdep(np, dp);
X	np = newname(".mac");
X	dp = newdep(np, dp);
X	np = newname(".SUFFIXES");
X	newline(np, dp, 0, 0);
X#endif

X/*
X *	Some of the UNIX implicit rules
X */
X#ifdef unix
X	setmacro("CC", "cc");
X	setmacro("CFLAGS", "-O");
X	cp = newcmd("$(CC) $(CFLAGS) -c $<", 0);
X	np = newname(".c.o");
X	newline(np, 0, cp, 0);

X	setmacro("AS", "as");
X	cp = newcmd("$(AS) -o $@ $<", 0);
X	np = newname(".s.o");
X	newline(np, 0, cp, 0);

X	setmacro("YACC", "yacc");
X	/*	setmacro("YFLAGS", "");	*/
X	cp = newcmd("$(YACC) $(YFLAGS) $<", 0);
X	cp = newcmd("mv y.tab.c $@", cp);
X	np = newname(".y.c");
X	newline(np, 0, cp, 0);

X	cp = newcmd("$(YACC) $(YFLAGS) $<", 0);
X	cp = newcmd("$(CC) $(CFLAGS) -c y.tab.c", cp);
X	cp = newcmd("rm y.tab.c", cp);
X	cp = newcmd("mv y.tab.o $@", cp);
X	np = newname(".y.o");
X	newline(np, 0, cp, 0);

X	np = newname(".s");
X	dp = newdep(np, 0);
X	np = newname(".o");
X	dp = newdep(np, dp);
X	np = newname(".c");
X	dp = newdep(np, dp);
X	np = newname(".y");
X	dp = newdep(np, dp);
X	np = newname(".SUFFIXES");
X	newline(np, dp, 0, 0);
X#endif
X#ifdef os9
X/*
X *	Fairlight use an enhanced version of the C sub-system.
X *	They have a specialised macro pre-processor.
X */
X	setmacro("CC", "cc");
X	setmacro("CFLAGS", "-z");
X	cp = newcmd("$(CC) $(CFLAGS) -r $<", 0);

X	np = newname(".c.r");
X	newline(np, 0, cp, 0);
X	np = newname(".ca.r");
X	newline(np, 0, cp, 0);
X	np = newname(".a.r");
X	newline(np, 0, cp, 0);
X	np = newname(".o.r");
X	newline(np, 0, cp, 0);
X	np = newname(".mc.r");
X	newline(np, 0, cp, 0);
X	np = newname(".mca.r");
X	newline(np, 0, cp, 0);
X	np = newname(".ma.r");
X	newline(np, 0, cp, 0);
X	np = newname(".mo.r");
X	newline(np, 0, cp, 0);

X	np = newname(".r");
X	dp = newdep(np, 0);
X	np = newname(".mc");
X	dp = newdep(np, dp);
X	np = newname(".mca");
X	dp = newdep(np, dp);
X	np = newname(".c");
X	dp = newdep(np, dp);
X	np = newname(".ca");
X	dp = newdep(np, dp);
X	np = newname(".ma");
X	dp = newdep(np, dp);
X	np = newname(".mo");
X	dp = newdep(np, dp);
X	np = newname(".o");
X	dp = newdep(np, dp);
X	np = newname(".a");
X	dp = newdep(np, dp);
X	np = newname(".SUFFIXES");
X	newline(np, dp, 0, 0);
X#endif
X}
@//E*O*F rules.c//
chmod u=rw,g=rw,o=rw $OUT
 
echo Inspecting for damage in transit...
temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      38     313    1803 README
      11      22     134 Makefile
     130     414    2457 h.h
     115     316    2100 check.c
     340    1124    6577 input.c
     156     396    2366 macro.c
     222     683    4336 main.c
     452    1202    7682 make.c
     116     318    1795 reader.c
     234     740    4819 rules.c
    1814    5528   34069 total
!!!
wc  README Makefile h.h check.c input.c macro.c main.c make.c reader.c rules.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if test -s $dtemp ; then
    echo "Ouch [diff of wc output]:"
    cat $dtemp
    STATUS=1
elif test $STATUS = 0 ; then
    echo "No problems found."
else
    echo "WARNING -- PROBLEMS WERE FOUND..."
fi
exit $STATUS



More information about the Mod.sources mailing list