Path: uunet!husc6!rutgers!clyde!cbosgd!mandrill!hal!ncoast!allbery
From: ljz@fxgrp.UUCP (Lloyd Zusman)
Newsgroups: comp.sources.misc
Subject: "mkmf" makefile maker (2 of 2)
Message-ID: <6904@ncoast.UUCP>
Date: 26 Dec 87 02:40:23 GMT
Sender: allbery@ncoast.UUCP
Lines: 2997
Approved: allbery@ncoast.UUCP
X-Archive: comp.sources.misc/mkmf/2

I hope I am posting this to the right person.  I assume you are
the moderator of comp.sources.misc.

In a recent posting I mentioned a program called "mkmf" which
makes makefiles.  Lots of people have sent me mail requesting
this software, so here it is.  In the aforementioned posting,
I said this program is "netware", but apparently it has not
been posted on the net (???).  It is, however, definitely in
the public domain.

It comes in two pieces.  Here is part 2.

Enjoy.

 Lloyd Zusman
 Master Byte Software
 Los Gatos, California	    	    	Internet:   fxgrp!ljz@ames.arpa
 "We take things well in hand."	    	UUCP:	    ...!ames!fxgrp!ljz

#--------------------------Cut Here--------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before the "#! /bin/sh" line,
# then unpack it by saving it in a file and typing "sh file."
#
# Wrapped by Lloyd Zusman (ljz) at fxgrp on Tue Dec 22 12:53:36 1987
#
# unpacks with default permissions
#
# Contents : src/editmf.c src/getcwp.c src/getproject.c src/hash.c
#	src/iolin.c src/macro.c src/misc.c src/mustfopen.c src/optpath.c
#	src/pathcat.c src/pathhead.c src/pperror.c src/rule.c src/slappend.c
#	src/slinit.c src/slsort.c src/strpcpy.c src/strsav.c src/suffix.c
#	src/usage.c src/warn.c src/warn2.c src/warns.c src/Mkmf.h
#	src/defaultrul.h src/defaultsfx.h src/dlist.h src/getarg.h src/hash.h
#	src/macro.h src/null.h src/path.h src/rule.h src/sccsid.h src/slist.h
#	src/spms.h src/suffix.h src/system.h src/target.h src/yesno.h
#	src/oMakefile x.Makefile/t.Makefile x.Makefile/Makefile
#	x.Makefile/l.Makefile x.Makefile/p.Makefile
#
if `test ! -d src`
then
  mkdir src
  echo "mkdir src"
fi
if `test ! -s src/editmf.c`
then
echo "x - src/editmf.c"
sed 's/^X//' > src/editmf.c << '@\End\of\File\'
X/* $Header: editmf.c,v 1.4 85/05/02 07:51:40 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <ctype.h>
X#include <signal.h>
X#include <stdio.h>
X#include "Mkmf.h"
X#include "dlist.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "slist.h"
X#include "system.h"
X#include "yesno.h"
X
Xstatic char *Mftemp;			/* temporary makefile */
X
X/*
X * editmf() replaces macro definitions within a makefile.
X */
Xvoid
Xeditmf(mfname, mfpath)
X	char *mfname;			/* makefile name */
X	char *mfpath;			/* makefile template pathname */
X{
X	register char *bp;		/* buffer pointer */
X	extern char IOBUF[];		/* I/O buffer line */
X	extern int DEPEND;		/* dependency analysis? */
X	extern SLIST *EXTLIST;		/* external header file name list */
X	extern SLIST *HEADLIST;		/* header file name list */
X	extern SLIST *LIBLIST;		/* library pathname list */
X	extern SLIST *SRCLIST;		/* source file name list */
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	char *findmacro();		/* is the line a macro definition? */
X	char *getlin();			/* get a line from input stream */
X	char *mktemp();			/* make file name */
X	char mnam[MACRONAMSIZE];	/* macro name buffer */
X	DLIST *dlp;			/* dependency list */
X	DLIST *mkdepend();		/* generate object-include file deps */
X	FILE *ifp;			/* input stream */
X	FILE *mustfopen();		/* must open file or die */
X	FILE *ofp;			/* output stream */
X	HASHBLK *htb;			/* hash table block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int cleanup();			/* remove temporary makefile and exit */
X	void dlprint();			/* print dependency list */
X	void purgcontinue();		/* get rid of continuation lines */
X	void putmacro();		/* put macro defs from table */
X	void putlin();			/* put a makefile line */
X	void putobjmacro();		/* put object file name macro def */
X	void putslmacro();		/* put macro defs from linked list */
X
X	ifp = mustfopen(mfpath, "r");
X	Mftemp = mktemp("mkmfXXXXXX");
X
X	signal(SIGHUP, cleanup);
X	signal(SIGINT, cleanup);
X	signal(SIGQUIT, cleanup);
X
X	ofp = mustfopen(Mftemp, "w");
X	if (DEPEND)
X		{
X		dlp = mkdepend();
X		}
X
X	while (getlin(ifp) != NULL)
X		{
X		if (DEPEND && EQUAL(IOBUF, DEPENDMARK))
X			break;
X		for (bp = IOBUF; *bp == ' '; bp++)
X			continue;
X		if (isalnum(*bp) && findmacro(mnam, bp) != NULL)
X			{
X			if ((htb = htlookup(mnam, MDEFTABLE)) != NULL)
X				{
X				if (htb->h_val == VREADWRITE)
X					{
X					putmacro(htb->h_def, ofp);
X					purgcontinue(ifp);
X					}
X				else	{
X					putlin(ofp);
X					}
X				}
X			else if (EQUAL(mnam, MHEADERS))
X				{
X				putslmacro(HEADLIST, ofp);
X				purgcontinue(ifp);
X				}
X			else if (EQUAL(mnam, MOBJECTS))
X				{
X				putobjmacro(ofp);
X				purgcontinue(ifp);
X				}
X			else if (EQUAL(mnam, MSOURCE))
X				{
X				putslmacro(SRCLIST, ofp);
X				purgcontinue(ifp);
X				}
X			else if (EQUAL(mnam, MEXTERNALS))
X				{
X				if (DEPEND)
X					{
X					putslmacro(EXTLIST, ofp);
X					purgcontinue(ifp);
X					}
X				else	{
X					putlin(ofp);
X					}
X				}
X			else if (EQUAL(mnam, MLIBLIST) && LIBLIST != NULL)
X				{
X				putslmacro(LIBLIST, ofp);
X				purgcontinue(ifp);
X				}
X			else	{
X				putlin(ofp);
X				}
X			}
X		else	{
X			putlin(ofp);
X			}
X		}
X	fclose(ifp);
X	if (DEPEND)
X		{
X		dlprint(dlp, ofp);
X		}
X	fclose(ofp);
X
X	signal(SIGHUP, SIG_IGN);
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X
X	RENAME(Mftemp, mfname);
X}
X
X
X
X/*
X * cleanup() removes the temporary makefile and dependency file, and
X * calls exit(1).
X */
Xcleanup()
X{
X	signal(SIGHUP, cleanup);
X	signal(SIGINT, cleanup);
X	signal(SIGQUIT, cleanup);
X
X	unlink(Mftemp);
X	exit(1);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/editmf.c"
fi
if `test ! -s src/getcwp.c`
then
echo "x - src/getcwp.c"
sed 's/^X//' > src/getcwp.c << '@\End\of\File\'
X/* $Header: getcwp.c,v 1.1 85/03/14 16:58:54 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * getcwp() returns the pathname of the current working project. If the
X * PROJECT environment variable is undefined or a null string, null is
X * returned.
X */
X#include "null.h"
X
Xchar *
Xgetcwp()
X{
X	extern char *_PROJECT;		/* project root directory pathname */
X	void getproject();		/* get PROJECT environment variable */
X
X	if (_PROJECT == NULL)
X		getproject();
X	return(_PROJECT);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/getcwp.c"
fi
if `test ! -s src/getproject.c`
then
echo "x - src/getproject.c"
sed 's/^X//' > src/getproject.c << '@\End\of\File\'
X/* $Header: getproject.c,v 1.1 85/03/14 16:59:01 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * getproject() saves the contents of the PROJECT environment variable.
X * If the PROJECT variable is undefined or a null string, null is returned.
X */
X#include "null.h"
X
Xchar *_PROJECT = NULL;			/* project root directory pathname */
X
Xvoid
Xgetproject()
X{
X	register char *pv;		/* ptr to start of PROJECT variable */
X	char *getenv();			/* get environment variable */
X	char *strsav();			/* save a string somewhere */
X
X	if ((pv = getenv("PROJECT")) != NULL && *pv != '\0')
X		_PROJECT = strsav(pv);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/getproject.c"
fi
if `test ! -s src/hash.c`
then
echo "x - src/hash.c"
sed 's/^X//' > src/hash.c << '@\End\of\File\'
X/* $Header: hash.c,v 1.1 85/03/14 15:38:16 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include "null.h"
X#include "hash.h"
X#include "macro.h"
X
X/*
X * hthash() returns a hash value for string, s.
X */
Xhthash(s, hash)
X	register char *s;		/* string */
X	HASH *hash;			/* hash table */
X{
X	register int hashval;		/* hash value for string */
X
X	for (hashval = 0; *s != '\0'; s++)
X		hashval += *s;
X	return(hashval % hash->hashsiz);
X}
X
X
X
X/*
X * htinit() returns a pointer to a new hash table, or a null pointer if
X * out of memory.
X */
XHASH *
Xhtinit(hashsiz)
X	unsigned int hashsiz;		/* hash table size */
X{
X	char *malloc();			/* allocate memory */
X	char *calloc();			/* allocate and zero memory */
X	HASH *ht;			/* pointer to hash table struct */
X	HASHBLK **pt;			/* pointer to hash pointer table */
X
X	if ((ht = (HASH *) malloc(sizeof(HASH))) == NULL ||
X	    (pt = (HASHBLK **) calloc(hashsiz, sizeof(HASHBLK *))) == NULL)
X		{
X		warn("out of memory");
X		return(NULL);
X		}
X	ht->hashtab = pt;
X	ht->hashsiz = hashsiz;
X	return(ht);
X}
X
X
X
X/*
X * htinstall() installs a new entry in a hash table if it doesn't already
X * exist. If it does, the old definition and value is superseded. Returns
X * a pointer to the entry, or null if out of memory.
X */
XHASHBLK *
Xhtinstall(key, def, val, hash)
X	char *key;			/* key for hash table entry */
X	char *def;			/* definition string */
X	int val;			/* integer value */
X	HASH *hash;			/* hash table */
X{
X	char *malloc();			/* memory allocator */
X	char *strsav();			/* save string somewhere */
X	HASHBLK *htb;			/* hash table entry block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int hashval;			/* hash value for key */
X	int hthash();			/* calculate hash value */
X
X	if ((htb = htlookup(key, hash)) == NULL)
X		{			/* not found */
X		if ((htb = (HASHBLK *) malloc(sizeof(HASHBLK))) == NULL)
X			return(NULL);
X		if ((htb->h_key = strsav(key)) == NULL)
X			return(NULL);
X		hashval = hthash(key, hash);
X		htb->h_next = (hash->hashtab)[hashval];
X		(hash->hashtab)[hashval] = htb;
X		htb->h_sub = NULL;
X		htb->h_tag = NULL;
X		}
X	else	{			/* found */
X		free(htb->h_def);	/* free previous definition */
X		}
X	if ((htb->h_def = strsav(def)) == NULL)
X		return(NULL);
X	htb->h_val = val;
X	return(htb);
X}
X
X
X
X/*
X * htlookup() returns a pointer to a hash table entry if found, otherwise null.
X */
XHASHBLK *
Xhtlookup(key, hash)
X	char *key;			/* key for hash table entry */
X	HASH *hash;			/* hash table */
X{
X	HASHBLK *htb;			/* hash table entry block */
X	int hthash();			/* calculate hash value */
X
X	for (htb = (hash->hashtab)[hthash(key, hash)]; htb != NULL; htb = htb->h_next)
X		if (EQUAL(htb->h_key, key))
X			return(htb);	/* found */
X	return(NULL);			/* not found */
X}
X
X
X
X/*
X * htrm() removes a hash table entry. If key is null, the entire hash
X * table is removed.
X */
Xvoid
Xhtrm(key, hash)
X	char *key;			/* key for hash table entry */
X	HASH *hash;			/* hash table */
X{
X	HASHBLK *htbrm();		/* remove hash table block */
X	HASHBLK *htc;			/* first hash table block in chain */
X	int hashval;			/* hash value for key */
X	int hthash();			/* compute hash value */
X	int i;				/* hash table index */
X
X	if (key == NULL)
X		{
X		for (i = 0; i < hash->hashsiz; i++)
X			if ((htc = (hash->hashtab)[i]) != NULL)
X				htc = htbrm(key, htc);
X		free((char *) hash);
X		}
X	else	{
X		hashval = hthash(key, hash);
X		if ((htc = (hash->hashtab)[hashval]) != NULL)
X			(hash->hashtab)[hashval] = htbrm(key, htc);
X		}
X}
X
X
X
X/*
X * htbrm() removes a hash table block identified by key. If key is null, the
X * entire chain is removed. Returns a pointer to the first block in the chain.
X */
XHASHBLK *
Xhtbrm(key, htc)
X	char *key;			/* key string */
X	HASHBLK *htc;			/* hash table block chain */
X{
X	HASHBLK *curblk;		/* current list block */
X	HASHBLK *nxtblk;		/* next list block */
X	HASHBLK *prvblk;		/* previous list block */
X
X	if (key == NULL)
X		while (htc != NULL)
X			{
X			nxtblk = htc->h_next;
X			free(htc->h_key);
X			free(htc->h_def);
X			free((char *) htc);
X			htc = nxtblk;
X			}
X	else	{
X		/* first block is a special case */
X		if (EQUAL(htc->h_key, key))
X			{
X			nxtblk = htc->h_next;
X			free(htc->h_key);
X			free(htc->h_def);
X			free((char *) htc);
X			htc = nxtblk;
X			}
X		else	{
X			/* remainder of list */
X			prvblk = htc;
X			curblk = htc->h_next;
X			while (curblk != NULL)
X				if (EQUAL(curblk->h_key, key))
X					{
X					prvblk->h_next = curblk->h_next;
X					free(curblk->h_key);
X					free(curblk->h_def);
X					free((char *) curblk);
X					curblk = prvblk->h_next;
X					break;
X					}
X				else	{
X					prvblk = curblk;
X					curblk = curblk->h_next;
X					}
X			}
X		}
X	return(htc);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/hash.c"
fi
if `test ! -s src/iolin.c`
then
echo "x - src/iolin.c"
sed 's/^X//' > src/iolin.c << '@\End\of\File\'
X/* $Header: iolin.c,v 1.1 85/03/14 15:38:25 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <stdio.h>
X#include "yesno.h"
X
Xchar IOBUF[BUFSIZ];			/* I/O line buffer */
Xshort CONTINUE;				/* does the line continue? */
X
X/*
X * getlin() stores a line from input stream in IOBUF. The string is terminated
X * by a newline character which is replaced by a null character. getlin()
X * returns IOBUF, or null pointer upon end of file.
X */
Xchar *
Xgetlin(stream)
X	register FILE *stream;		/* input stream */
X{
X	register int c;			/* current character */
X	register char *iop;		/* IOBUF pointer */
X
X	iop = IOBUF;
X	while ((c = getc(stream)) != '\n' && c != EOF)
X		*iop++ = c;
X	if (c == EOF && iop == IOBUF)
X		return(NULL);
X	if (iop != IOBUF && iop[-1] == '\\')
X		{
X		iop[-1] = '\0';
X		CONTINUE = YES;
X		}
X	else	{
X		iop[0] = '\0';
X		CONTINUE = NO;
X		}
X	return(IOBUF);
X}
X
X
X
X/*
X * purgcontinue() eats up continuation lines from an input stream.
X */
Xvoid
Xpurgcontinue(stream)
X	register FILE *stream;		/* input stream */
X{
X	register int c;			/* current character */
X	register int lastc;		/* previous character */
X
X	if (CONTINUE == YES)
X		{
X		for (;;)
X			{
X			while ((c = getc(stream)) != '\n' && c != EOF)
X				lastc = c;
X			if (c == EOF || (c == '\n' && lastc != '\\'))
X				break;
X			}
X		CONTINUE = NO;
X		}
X}
X
X
X
X/*
X * putlin() writes IOBUF to stream and appends a newline character. If
X * IOBUF holds a CONTINUE line, a `\' precedes the newline.
X */
Xvoid
Xputlin(stream)
X	register FILE *stream;		/* output stream */
X{
X	register int c;			/* current character */
X	register char *iop;		/* IOBUF pointer */
X
X	iop = IOBUF;
X	while (c = *iop++)
X		putc(c, stream);
X	if (CONTINUE == YES)
X		putc('\\', stream);
X	putc('\n', stream);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/iolin.c"
fi
if `test ! -s src/macro.c`
then
echo "x - src/macro.c"
sed 's/^X//' > src/macro.c << '@\End\of\File\'
X/* $Header: macro.c,v 1.3 85/05/02 07:53:52 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <ctype.h>
X#include <stdio.h>
X#include "Mkmf.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "slist.h"
X#include "yesno.h"
X
Xextern char IOBUF[];			/* I/O buffer line */
X
X/*
X * findmacro() searchs a line for a macro definition. Returns the name,
X * or null if not found.
X */
Xchar *
Xfindmacro(macroname, bp)
X	char *macroname;		/* macro name receiving buffer */
X	register char *bp;		/* buffer pointer */
X{
X	register char *mp;		/* macro name pointer */
X
X	mp = macroname;
X	while(isalnum(*bp))
X		*mp++ = *bp++;
X	*mp = '\0';
X	while(*bp == ' ' || *bp == '\t')
X		bp++;
X	if (*bp != '=')
X		return(NULL);
X	return(macroname);
X}
X	
X
X
X/*
X * getmacro() loads the body of a macro definition into mdefbuf and returns
X * a pointer to mdefbuf. If the macro definition continues on more than
X * one line further lines are fetched from the input stream.
X */
Xchar *
Xgetmacro(mdefbuf, stream)
X	char *mdefbuf;			/* receiving macro definition buffer */
X	FILE *stream;			/* input stream */
X{
X	extern short CONTINUE;		/* does the line continue? */
X	char *getlin();			/* get a line from input stream */
X	register char *bp;		/* buffer pointer */
X	register char *mp;		/* macro definition buffer pointer */
X
X	bp = IOBUF;
X	mp = mdefbuf;
X	while (*bp++ != '=')
X		continue;
X	if (WHITESPACE(*bp))
X		bp++;
X	while (*bp != '\0')
X		*mp++ = *bp++;
X	while (CONTINUE == YES)
X		{
X		*mp++ = ' ';
X		if (getlin(stream) == NULL)
X			break;
X		bp = IOBUF;
X		while (*bp != '\0')
X			*mp++ = *bp++;
X		}
X	*mp = '\0';
X	return(mdefbuf);
X}
X
X
X
X/*
X * putmacro() prints a macro definition from the macro definition table.
X */
Xvoid
Xputmacro(macrovalue, stream)
X	char *macrovalue;		/* value of macro definition */
X	register FILE *stream;		/* output stream */
X{
X	register char *iop;		/* IOBUF pointer */
X	register int c;			/* current character */
X
X	iop = IOBUF;
X	while ((c = *iop++) != '=')
X		putc(c, stream);
X	fprintf(stream, "= %s\n", macrovalue);
X}
X
X
X
X/*
X * putobjmacro() derives and prints object file names from the SRCLIST list.
X */
Xvoid
Xputobjmacro(stream)
X	register FILE *stream;		/* output stream */
X{
X	extern SLIST *SRCLIST;		/* source file name list */
X	register char *iop;		/* IOBUF pointer */
X	register int c;			/* current character */
X	char *rindex();			/* find last occurrence of character */
X	char *suffix;			/* suffix pointer */
X	HASHBLK *lookupinclude();	/* look up include name in hash table */
X	int cnt = 0;			/* number of object filenames printed */
X	int lookuptypeofinclude();	/* look up the brand of include */
X	int type;			/* file type */
X	SLBLK *lbp;			/* list block pointer */
X	void putobj();			/* print object file name */
X
X	iop = IOBUF;
X	while ((c = *iop++) != '=')
X		putc(c, stream);
X	putc('=', stream);
X	for (lbp = SRCLIST->head; lbp != NULL; lbp = lbp->next)
X		{
X		suffix = rindex(lbp->key, '.');
X		type = lookuptypeofinclude(++suffix);
X		if (lookupinclude(lbp->key, type) == NULL)
X			{
X			cnt += 1;
X			if (cnt == 1)
X				{
X				putc(' ', stream);
X				putobj(lbp->key, stream);
X				}
X			else	{
X				fprintf(stream, " \\\n\t\t");
X				putobj(lbp->key, stream);
X				}
X			}
X		}
X	putc('\n', stream);
X}
X
X
X
X/*
X * putslmacro() copies a macro definition from a list.
X */
Xvoid
Xputslmacro(slist, stream)
X	SLIST *slist;			/* singly-linked macro def list */
X	register FILE *stream;		/* output stream */
X{
X	register char *iop;		/* IOBUF pointer */
X	register int c;			/* current character */
X	SLBLK *lbp;			/* list block pointer */
X
X	iop = IOBUF;
X	while ((c = *iop++) != '=')
X		putc(c, stream);
X	putc('=', stream);
X	if (SLNUM(slist) > 0)
X		{
X		lbp = slist->head;
X		fprintf(stream, " %s", lbp->key);
X		}
X	if (SLNUM(slist) > 1)
X		for (lbp = lbp->next; lbp != NULL; lbp = lbp->next)
X			fprintf(stream, " \\\n\t\t%s", lbp->key);
X	putc('\n', stream);
X}
X
X
X
X/*
X * storemacro() stores a macro definition in the macro definition table.
X * Returns integer YES if a macro definition (macro=definition), otherwise
X * NO. exit(1) is called if out of memory.
X */
Xstoremacro(macdef)
X	char *macdef;			/* macro definition string */
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	register int i;			/* macro value index */
X	register int j;			/* macro name index */
X	HASHBLK *htinstall();		/* install hash table entry */
X
X	for (i = 0; macdef[i] != '='; i++)
X		if (macdef[i] == '\0')
X			return(NO);
X	
X	/* removing trailing blanks and tabs from end of macro name */
X	for (j = i; j > 0; j--)
X		if (!WHITESPACE(macdef[j-1]))
X			break;
X	macdef[j] = '\0';
X
X	/* remove leading blanks and tabs from macro value */
X	for (i++; WHITESPACE(macdef[i]); i++)
X		continue;
X	if (htinstall(macdef, macdef+i, VREADWRITE, MDEFTABLE) == NULL)
X		exit(1);
X	return(YES);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/macro.c"
fi
if `test ! -s src/misc.c`
then
echo "x - src/misc.c"
sed 's/^X//' > src/misc.c << '@\End\of\File\'
X/* $Header: misc.c,v 1.6 85/06/27 08:15:57 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <ctype.h>
X#include <stdio.h>
X#include "Mkmf.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "path.h"
X#include "target.h"
X#include "spms.h"
X#include "suffix.h"
X#include "system.h"
X#include "yesno.h"
X
X/*
X * answer() installs a line from stdin in the macro definition table.
X * exit(1) is called if EOF, error, or out of memory.
X */
Xvoid
Xanswer(mdefkey, mdefval)
X	char *mdefkey;			/* macro definition key */
X	int mdefval;			/* macro definition value */
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	char answerbuf[ANSWERBUFSIZE];	/* answer from stdin */
X	char *gets();			/* get a line from stdin */
X	HASHBLK *htinstall();		/* install hash table entry */
X
X	if (gets(answerbuf) == NULL)
X		exit(1);
X	if (*answerbuf != '\0')
X		if (htinstall(mdefkey, answerbuf, mdefval, MDEFTABLE) == NULL)
X			exit(1);
X}
X
X
X
X/*
X * fastcopy() copies file to stream fp. Returns integer YES if successful,
X * otherwise NO.
X */
Xfastcopy(filename, ofp)
X	char *filename;			/* file to be copied */
X	register FILE *ofp;		/* output stream */
X{
X	register int ifd;		/* input file descriptor */
X	register int n;			/* byte count */
X	char buf[BUFSIZ];		/* I/O buffer */
X
X	if ((ifd = OPEN(filename, 0, 0644)) == -1)
X		{
X		pperror("");
X		return(NO);
X		}
X	while ((n = read(ifd, buf, BUFSIZ)) > 0)
X		write(fileno(ofp), buf, n);
X	close(ifd);
X	return(YES);
X}
X
X
X
X/*
X * findmf() locates the makefile to be edited. The type of makefile
X * is returned in target. The pathname to the makefile is returned
X * in mfpath. Returns YES if makefile or makefile template can be
X * opened, otherwise NO.
X */
Xfindmf(mfname, mfpath, target)
X	char *mfname;			/* name of target makefile */
X	char *mfpath;			/* path to target makefile */
X	TARGET *target;			/* type of makefile target */
X{
X	extern int CFLAG;		/* makefile creation message */
X	char *strcpy();			/* string copy */
X	int readmf();			/* read makefile */
X	int targettype;			/* type of makefile requested */
X	void findmftemplate();		/* find makefile template */
X
X	targettype = target->type;
X	if (FILEXIST(mfname))
X		{
X		if (!FILEWRITE(mfname))
X			{
X			pperror(mfname);
X			target->type = VERROR;
X			return(NO);
X			}
X		if (readmf(mfname, target) == VERROR)
X			return(NO);
X		if (targettype == VUNKNOWN || targettype == target->type)
X			{
X			strcpy(mfpath, mfname);
X			return(YES);
X			}
X		}
X	target->type = (targettype == VLIBRARY) ? VLIBRARY : VPROGRAM;
X	findmftemplate(mfpath, target);
X	if (readmf(mfpath, target) == VERROR)
X		return(NO);
X	else if (CFLAG == YES)
X		warn2("creating %s from template %s", mfname, mfpath);
X	return(YES);
X}
X
X
X
X/*
X * findmftemplate() returns the pathname of a makefile template in mfpath.
X */
Xvoid
Xfindmftemplate(mfpath, target)
X	char *mfpath;			/* path to target makefile */
X	TARGET *target;			/* type of makefile target */
X{
X	extern char *L_MAKEFILE;	/* library makefile template */
X	extern char *P_MAKEFILE;	/* program makefile template */
X	char *cwp;			/* current project pathname pointer */
X	char *getcwp();			/* get current project pathname */
X	char *pathcat();		/* pathname concatenation */
X	char *strcpy();			/* string copy */
X
X	cwp = getcwp();
X	if (target->type == VPROGRAM)
X		{
X		if (*P_MAKEFILE == _RDIRC)
X			strcpy(mfpath, P_MAKEFILE);
X		else if (cwp == NULL ||
X			 !FILEXIST(pathcat(mfpath, pathcat(mfpath, cwp, "lib"), P_MAKEFILE)))
X			pathcat(mfpath, SPMSLIB, P_MAKEFILE);
X		}
X	else if (target->type == VLIBRARY)
X		{
X		if (*L_MAKEFILE == _RDIRC)
X			strcpy(mfpath, L_MAKEFILE);
X		else if (cwp == NULL ||
X			 !FILEXIST(pathcat(mfpath, pathcat(mfpath, cwp, "lib"), L_MAKEFILE)))
X			pathcat(mfpath, SPMSLIB, L_MAKEFILE);
X		}
X	else
X		warn("unknown template request");
X}
X
X
X
X/*
X * gettoken() copies the next token from token buffer to token. Returns a
X * pointer to the first character after the token, or null upon reaching
X * the end of the token buffer.
X */
Xchar *
Xgettoken(token, tp)
X	register char *token;		/* receiving token */
X	register char *tp;		/* token buffer pointer */
X{
X	while (isspace(*tp) && *tp != '\0')
X		tp++;
X	if (*tp == '\0')
X		{
X		*token = '\0';
X		return(NULL);
X		}
X	while (!isspace(*tp) && *tp != '\0')
X		*token++ = *tp++;
X	*token = '\0';
X	return(tp);
X}
X
X
X
X/*
X * putobj() converts a source file name to an object file name and then
X * writes the file name to stream.
X */
Xvoid
Xputobj(s, stream)
X	register char *s;		/* source file name */
X	register FILE *stream;		/* output stream */
X{
X	extern char OBJSFX[];		/* object file name suffix */
X	register char *dot;		/* pointer to suffix */
X	char *rindex();			/* last occurrence of character */
X
X	dot = rindex(s, '.');
X	while (s != dot)
X		putc(*s++, stream);
X	fprintf(stream, "%s", OBJSFX);
X}
X
X
X
X/*
X * readmf() reads a makefile and loads CFLAGS, FFLAGS, and SUFFIX definitions
X * into the macro definition table if they do not already exist. Returns
X * integer VLIBRARY, VPROGRAM, or VUNKNOWN according to the type of makefile,
X * or VERROR if cannot open makefile.
X */
Xreadmf(mfname, target)
X	char *mfname;			/* name of makefile */
X	TARGET *target;			/* type of makefile target */
X{
X	register char *bp;		/* buffer pointer */
X	extern char IOBUF[];		/* I/O buffer line */
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	char *findmacro();		/* is the line a macro definition? */
X	char *findrule();		/* is the line a rule definition? */
X	char *getlin();			/* get a line from input stream */
X	char *getmacro();		/* get macro def from input stream */
X	char macrodef[MACRODEFSIZE];	/* macro definition buffer */
X	char macroname[MACRONAMSIZE];	/* macro name buffer */
X	char rulename[2*SUFFIXSIZE+3];	/* transformation rule name */
X	FILE *fopen();			/* open file */
X	FILE *fp;			/* file pointer */
X	HASHBLK *htinstall();		/* install hash table entry */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int storerule();		/* store transformation rule */
X
X	target->type = target->dest = VUNKNOWN;
X	if ((fp = fopen(mfname, "r")) == NULL)
X		{
X		pperror(mfname);
X		target->type = VERROR;
X		return(target->type);
X		}
X	while (getlin(fp) != NULL)
X		{
X		if (EQUAL(IOBUF, DEPENDMARK))
X			break;
X		for (bp = IOBUF; *bp == ' '; bp++)
X			continue;
X		if (isalnum(*bp) && findmacro(macroname, bp) != NULL)
X			{
X			if (EQUAL(macroname, MPROGRAM))
X				{
X				target->type = VPROGRAM;
X				continue;
X				}
X			else if (EQUAL(macroname, MLIBRARY))
X				{
X				target->type = VLIBRARY;
X				continue;
X				}
X			else if (EQUAL(macroname, MDESTDIR))
X				{
X				target->dest = VDESTDIR;
X				continue;
X				}
X
X			/* does macro definition already exist? */
X			if (htlookup(macroname, MDEFTABLE) != NULL)
X				continue;
X
X			if (EQUAL(macroname, MCFLAGS) ||
X			    EQUAL(macroname, MFFLAGS) ||
X			    EQUAL(macroname, MPFLAGS) ||
X			    EQUAL(macroname, MSUFFIX))
X				{
X				if (htinstall(macroname, getmacro(macrodef, fp),
X					      VREADONLY, MDEFTABLE) == NULL)
X					{
X					fclose(fp);
X					return(NO);
X					}
X				}
X			}
X		else if (*bp == '.' && findrule(rulename, bp) != NULL)
X			{
X			if (storerule(rulename) == NO)
X				{
X				fclose(fp);
X				return(NO);
X				}
X			}
X		}
X	fclose(fp);
X	return(target->type);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/misc.c"
fi
if `test ! -s src/mustfopen.c`
then
echo "x - src/mustfopen.c"
sed 's/^X//' > src/mustfopen.c << '@\End\of\File\'
X/* $Header: mustfopen.c,v 1.2 85/03/17 12:51:04 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * mustfopen() opens a file in the manner of fopen(3). However, if the file
X * cannot be accessed, exit(1) is called.
X */
X#include <stdio.h>
X
Xextern char *PGN;		/* program name */
X
XFILE *
Xmustfopen(filename,mode)
X	char *filename;
X	char *mode;
X{
X	FILE *stream;			/* file stream */
X
X	if ((stream = fopen(filename,mode)) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "can't open %s\n",filename);
X		exit(1);
X		}
X	return(stream);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/mustfopen.c"
fi
if `test ! -s src/optpath.c`
then
echo "x - src/optpath.c"
sed 's/^X//' > src/optpath.c << '@\End\of\File\'
X/* $Header: optpath.c,v 1.2 85/05/06 13:32:05 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * optpath() condenses a pathname by eliminating adjacent separator
X * characters, and current and parent directory names. If optpath()
X * encounters a parent directory, it backtracks to eliminate the
X * previous directory. If the beginning of the pathname is reached
X * during backtracking, then if the pathname is absolute, the parent
X * directory is purged, otherwise it is shifted to the beginning of
X * pathname. Special care is taken not to clobber a shifted parent
X * by using a guard pointer. Returns pathname.
X */
X#include "path.h"
X
X#define absolute_path	(*pathname == _RDIRC)
X
Xstatic char parentdir[] = PARENTDIR;	/* parent directory name */
X
Xchar *
Xoptpath(pathname)
X	register char *pathname;	/* pathname to be optimized */
X{
X	register char *bp;		/* back pathname pointer */
X	register char *fp;		/* forward pathname pointer */
X	register char *up;		/* pathname update guard pointer */
X	char p1;			/* 1st parent directory character */
X	char p2;			/* 2nd parent directory character */
X
X	p1 = parentdir[0];
X	p2 = parentdir[1];
X
X	bp = fp = up = pathname;
X
X	/* elimination of initial "./" causes no harmful side-effects */
X	if (fp[0] == _CDIRC && fp[1] == _PSC) fp += 2;
X
X	while (*fp != '\0')
X		if (fp[0] == _PSC)
X			if (fp[1] == _PSC || fp[1] == '\0')
X				fp += 1;	/* "//" or trailing `/' */
X			else if (fp[1]==_CDIRC && (fp[2]==_PSC || fp[2]=='\0'))
X				fp += 2;	/* `.' */
X			else if ((fp[1] == p1 && fp[2] == p2) &&
X				 (fp[3] == _PSC || fp[3] == '\0'))
X				{	/* ".." (don't backtrack over a "..") */
X				if (absolute_path || 
X				   (bp > up && bp-2 < pathname) ||
X				   (bp > up && (bp[-2] != p1 || bp[-1] != p2)))
X					{
X					while (bp > up && *--bp != _PSC)
X						continue;
X					}
X				else	{
X					/* don't clobber separator character */
X					if (bp[0] == _PSC) bp++;
X					bp[0] = fp[1];
X					bp[1] = fp[2];
X					bp[2] = fp[3];
X					up = bp += 2;
X					}
X				fp += 3;
X				}
X			else	{
X				*bp++ = *fp++;
X				}
X		else	{
X			*bp++ = *fp++;
X			}
X	if (bp == pathname && *pathname != '\0')
X		*bp++ = (absolute_path) ? _RDIRC : _CDIRC;
X	*bp = '\0';
X	return(pathname);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/optpath.c"
fi
if `test ! -s src/pathcat.c`
then
echo "x - src/pathcat.c"
sed 's/^X//' > src/pathcat.c << '@\End\of\File\'
X/* $Header: pathcat.c,v 1.2 85/03/17 15:23:03 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * pathcat() concatenates path components p1 and p2 into character buffer
X * p1_p2. Returns p1_p2.
X */
X#include <stdio.h>
X#include "path.h"
X
Xextern char *PGN;			/* program name */
X
Xchar *
Xpathcat(p1_p2, p1, p2)
X	register char *p1;
X	register char *p2;
X	register char *p1_p2;
X{
X	register int plen;		/* maximum pathname length */
X	char *sp1_p2;			/* start of p1_p2 */
X
X	sp1_p2 = p1_p2;
X	for (plen = PATHSIZE; plen > 0; plen--, p1_p2++, p1++)
X		if ((*p1_p2 = *p1) == '\0')
X			break;
X	if (*p2 != '\0' && plen > 0)
X		{
X		if (p1_p2 != sp1_p2 && p1_p2[-1] != _PSC)
X			{
X			*p1_p2++ = _PSC;
X			plen--;
X			}
X		for (; plen > 0; plen--, p1_p2++, p2++)
X			if ((*p1_p2 = *p2) == '\0')
X				break;
X		}
X	if (plen == 0)
X		{
X		*--p1_p2 = '\0';
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "pathname too long\n");
X		}
X	return(sp1_p2);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/pathcat.c"
fi
if `test ! -s src/pathhead.c`
then
echo "x - src/pathhead.c"
sed 's/^X//' > src/pathhead.c << '@\End\of\File\'
X/* $Header: pathhead.c,v 1.2 85/03/08 17:21:50 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * pathhead() removes tail of pathname and returns pathname. The tail is
X * defined as that part of the pathname after the last separator.
X */
X#include "null.h"
X#include "path.h"
X
Xchar *
Xpathhead(pathname)
X	register char *pathname;
X{
X	register char *ls;		/* last separator character */
X	register char *p;		/* pathname pointer */
X
X	ls = NULL;
X	for (p = pathname; *p != '\0'; p++)
X		if (*p == _PSC)
X			ls = p;
X	if (ls != NULL) *ls = '\0';
X	return(pathname);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/pathhead.c"
fi
if `test ! -s src/pperror.c`
then
echo "x - src/pperror.c"
sed 's/^X//' > src/pperror.c << '@\End\of\File\'
X/* $Header: pperror.c,v 1.1 85/03/14 17:00:12 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * pperror() writes a system error message to standard error output,
X * preceded by the name of the program and message.
X */
X#include <stdio.h>
X
Xpperror(message)
X	char *message;			/* error message */
X{
X	extern char *PGN;		/* program name */
X
X	fprintf(stderr, "%s: ", PGN);
X	perror(message);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/pperror.c"
fi
if `test ! -s src/rule.c`
then
echo "x - src/rule.c"
sed 's/^X//' > src/rule.c << '@\End\of\File\'
X/* $Header: rule.c,v 1.2 85/05/16 12:49:56 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include "Mkmf.h"
X#include "null.h"
X#include "rule.h"
X#include "slist.h"
X#include "suffix.h"
X#include "system.h"
X#include "yesno.h"
X
X#define MAXNAMLEN	255
X
Xstatic RULEBLK *Ruletab[RULETABSIZE];	/* rules table */
Xstatic SLIST *Rulelist = NULL;		/* transformation rule list */
X
X/*
X * buildruletable() converts a list of transformation rules into a hash table
X * for fast lookup. Returns YES if successful, otherwise NO.
X */
Xbuildruletable()
X{
X	extern char *DEFRULE[];		/* default preprocessor rules */
X	int i;				/* default rule list counter */
X	int instalrule();		/* instale rule in hash table */
X	SLBLK *rblk;			/* singly-linked rulename block */
X
X	/* process default rules */
X	for (i = 0; DEFRULE[i] != NULL; i++)
X		{
X		if (instalrule(DEFRULE[i]) == NO)
X			{
X			warn("out of memory");
X			return(NO);
X			}
X		}
X
X	/* process rules found in makefile */
X	if (Rulelist != NULL)
X		{
X		for (rblk = Rulelist->head; rblk != NULL; rblk = rblk->next)
X			{
X			if (instalrule(rblk->key) == NO)
X				{
X				warn("out of memory");
X				return(NO);
X				}
X			}
X		}
X	return(YES);
X}
X
X
X
X/*
X * findrule() searchs a line for a transformation rule. Returns the
X * name of the transformation rule, or NULL if not found.
X */
Xchar *
Xfindrule(rulename, bp)
X	char *rulename;			/* transformation rule buffer */
X	register char *bp;		/* I/O buffer pointer */
X{ 
X	register char *rp;		/* rule name pointer */
X	int dotcount = 0;		/* number of '.'s in rule */
X
X	for (rp = rulename; *bp != ':' && *bp != ' ' && *bp != '\t'; rp++, bp++)
X		{
X		if ((*rp = *bp) == '.')
X			dotcount++;
X		}
X	*rp = '\0';
X
X	/* eat up white space between rule and ':' */
X	if (*bp != ':')
X		{
X		while (*bp == ' ' || *bp == '\t')
X			bp++;
X		if (*bp != ':')
X			return(NULL);
X		}
X
X	return((dotcount == 2) ? rulename : NULL);
X}
X
X
X
X/*
X * instalrule() installs a source transformation rule in the rule lookup
X * table. The rule table consists of a set of singly-linked lists, indexed
X * by the first character of the suffix of the target file. The index of
X * the target file is used by lookuprule() to find out the name of the file
X * from which it was derived. Returns YES if successful, otherwise NO.
X */
Xinstalrule(rule)
X	char *rule;			/* rule to be installed in Rule table */
X{
X	char *malloc();			/* memory allocator */
X	char *rindex();			/* find last occurrence of character */
X	char *strsav();			/* save a string somewhere */
X	char *target;			/* target suffix */
X	int lookupsfx();		/* get suffix type */
X	int ruleindex;			/* index into rule table */
X	RULEBLK *rblk;			/* rule list block */
X
X	target = rindex(rule, '.') + 1;
X	if (lookupsfx(target) == SFXSRC)
X		{
X		ruleindex = target[0];
X		if ((rblk = (RULEBLK *) malloc(sizeof(RULEBLK))) == NULL)
X			return(NO);
X		if ((rblk->r_rule = strsav(rule)) == NULL)
X			return(NO);
X		rblk->r_next = Ruletab[ruleindex];
X		Ruletab[ruleindex] = rblk;
X		}
X	return(YES);
X}
X
X
X
X/*
X * lookuprule() applies successive transformation rules to filename, and
X * checks to see if the file exists. Returns YES if filename exists,
X * otherwise NO.
X */
Xlookuprule(target, source)
X	char *target;			/* name of (transformed) file */
X	char *source;			/* name of source file */
X{
X	register char *r;		/* rule pointer */
X	register char *s;		/* source buffer pointer */
X	char *rindex();			/* find last occurrence of character */
X	char *sourcesuffix;		/* source file suffix */
X	char *strcpy();			/* string copy */
X	char *rulesuffix;		/* target suffix in each rule */
X	char *targetsuffix;		/* transformed file suffix string */
X	int ruleindex;			/* index into rule table */
X	int strcmp();			/* string comparison */
X	RULEBLK *rblk;			/* rule list block */
X
X	if ((targetsuffix = rindex(target, '.')) == NULL)
X		return(NO);
X	ruleindex = targetsuffix[1];
X	if (Ruletab[ruleindex] != NULL)
X		{
X		strcpy(source, target);
X		sourcesuffix = rindex(source, '.');
X		for (rblk=Ruletab[ruleindex]; rblk != NULL; rblk=rblk->r_next)
X			{
X			rulesuffix = rindex(rblk->r_rule, '.');
X			if (strcmp(rulesuffix, targetsuffix) == 0)
X				{
X				r = rblk->r_rule;
X				s = sourcesuffix;
X				while (*++s = *++r)
X					if (*s == '.')
X						{
X						*s = '\0';
X						break;
X						}
X				if (FILEXIST(source))
X					return(YES);
X				}
X			}
X		}
X	return(NO);
X}
X
X
X
X/*
X * storerule() appends a transformation rule to the end of a singly-linked
X * list. Returns integer NO if out of memory, otherwise YES.
X */
Xstorerule(rulename)
X	char *rulename;			/* transformation rule name */
X{
X	char *slappend();		/* append rule to list */
X	SLIST *slinit();		/* initialize transformation list */
X
X	if (Rulelist == NULL)
X		Rulelist = slinit();
X	if (slappend(rulename, Rulelist) == NULL)
X		return(NO);
X	return(YES);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/rule.c"
fi
if `test ! -s src/slappend.c`
then
echo "x - src/slappend.c"
sed 's/^X//' > src/slappend.c << '@\End\of\File\'
X/* $Header: slappend.c,v 1.2 85/03/18 13:18:28 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * slappend() saves a null-terminated key string somewhere and inserts a
X * pointer to the key at the tail of list slist. Returns a pointer to
X * the somewhere, or a null pointer if out of memory.
X */
X#include <stdio.h>
X#include "macro.h"
X#include "null.h"
X#include "slist.h"
X
Xextern char *PGN;			/* program name */
X
Xchar *
Xslappend(key, slist)
X	char *key;			/* key string */
X	SLIST *slist;			/* pointer to list head block */
X{
X	char *malloc();			/* memory allocator */
X	char *strcpy();			/* string copy */
X	int strlen();			/* string length */
X	SLBLK *slbptr;			/* pointer to list block */
X	unsigned int klen;		/* key length */
X
X	if (slist == NULL)
X		return(NULL);
X	klen = strlen(key);
X	slist->maxkey = MAX(slist->maxkey, klen);
X	if ((slbptr = (SLBLK *) malloc(sizeof(SLBLK))) == NULL ||
X	    (slbptr->key = malloc(klen+1)) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "out of memory\n");
X		return(NULL);
X		}
X	strcpy(slbptr->key, key);
X	slbptr->next = NULL;
X	if (slist->tail == NULL)
X		slist->head = slist->tail = slbptr;
X	else
X		slist->tail = slist->tail->next = slbptr;
X	slist->nk++;
X	return(slbptr->key);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/slappend.c"
fi
if `test ! -s src/slinit.c`
then
echo "x - src/slinit.c"
sed 's/^X//' > src/slinit.c << '@\End\of\File\'
X/* $Header: slinit.c,v 1.2 85/03/18 13:18:52 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * slinit() returns a pointer to the head block of a new list, or null
X * pointer if out of memory.
X */
X#include <stdio.h>
X#include "null.h"
X#include "slist.h"
X
Xextern char *PGN;			/* program name */
X
XSLIST *
Xslinit()
X{
X	char *malloc();			/* memory allocator */
X	SLIST *slist;			/* pointer to list head block */
X
X	if ((slist = (SLIST *) malloc(sizeof(SLIST))) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "out of memory\n");
X		return(NULL);
X		}
X	slist->nk = 0;
X	slist->maxkey = 0;
X	slist->head = slist->curblk = slist->tail = NULL;
X	return(slist);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/slinit.c"
fi
if `test ! -s src/slsort.c`
then
echo "x - src/slsort.c"
sed 's/^X//' > src/slsort.c << '@\End\of\File\'
X/* $Header: slsort.c,v 1.2 85/03/18 13:19:42 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * slsort() sorts list slist according to comparison function compar().
X * compar() is to be called with two arguments and must return an integer
X * greater than, equal to, or less than 0, depending on the lexicographic
X * relationship between the two arguments. Returns integer YES if
X * successful, otherwise NO if out of memory.
X */
X#include <stdio.h>
X#include "null.h"
X#include "slist.h"
X#include "yesno.h"
X
Xextern char *PGN;			/* program name */
X
Xstatic int (*sscmp)();			/* string compare function */
X
Xslsort(compar, slist)
X	int (*compar)();		/* compare two strings */
X	SLIST *slist;			/* pointer to list head block */
X{
X	char **kp;			/* pointer to key pointer array */
X	char *malloc();			/* memory allocator */
X	char **skp;			/* ptr to start of key ptr array */
X	int comparb();			/* compare 2 list blocks */
X	SLBLK *curblk;			/* current list block */
X
X	if (slist->nk <= 0)
X		return(YES);
X	else if ((skp = (char **) malloc((unsigned)slist->nk*sizeof(char *))) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "out of memory\n");
X		return(NO);
X		}
X	for (kp = skp, curblk = slist->head; curblk != NULL; kp++, curblk = curblk->next)
X		*kp = curblk->key;
X
X	sscmp = compar;
X	qsort((char *) skp, slist->nk, sizeof(char *), comparb);
X
X	for (kp = skp, curblk = slist->head; curblk != NULL; kp++, curblk = curblk->next)
X		curblk->key = *kp;
X	
X	free((char *) skp);
X	return(YES);
X}
X
X
X
X/*
X * comparb() compares key strings in 2 list blocks. Returns whatever
X * sscmp() returns. sscmp() is a string compare function.
X */
Xstatic int
Xcomparb(s1, s2)
X	char **s1;			/* string pointer */
X	char **s2;			/* string pointer */
X{
X	return(sscmp(*s1, *s2));
X}
@\End\of\File\
else
  echo "shar: Will not over write src/slsort.c"
fi
if `test ! -s src/strpcpy.c`
then
echo "x - src/strpcpy.c"
sed 's/^X//' > src/strpcpy.c << '@\End\of\File\'
X/* $Header: strpcpy.c,v 1.1 85/03/14 17:00:27 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * strpcpy() copies string s2 to s1 and returns a pointer to the
X * next character after s1.
X */
Xchar *
Xstrpcpy(s1, s2)
X	register char *s1;
X	register char *s2;
X{
X	while (*s1++ = *s2++)
X		continue;
X	return(--s1);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/strpcpy.c"
fi
if `test ! -s src/strsav.c`
then
echo "x - src/strsav.c"
sed 's/^X//' > src/strsav.c << '@\End\of\File\'
X/* $Header: strsav.c,v 1.1 85/03/14 17:00:30 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * strsav() saves a string somewhere and returns a pointer to the somewhere.
X * Returns NULL on error.
X */
X#include "null.h"
X
Xchar *
Xstrsav(s)
X	char *s;
X{
X	char *sptr;			/* somewhere string pointer */
X	char *malloc();			/* memory allocator */
X	char *strcpy();			/* string copy */
X	int strlen();			/* string length */
X
X	if ((sptr = malloc((unsigned)(strlen(s)+1))) == NULL)
X		return(NULL);
X	return(strcpy(sptr, s));
X}
@\End\of\File\
else
  echo "shar: Will not over write src/strsav.c"
fi
if `test ! -s src/suffix.c`
then
echo "x - src/suffix.c"
sed 's/^X//' > src/suffix.c << '@\End\of\File\'
X/* $Header: suffix.c,v 1.2 85/03/21 10:19:36 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <stdio.h>
X#include "Mkmf.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "suffix.h"
X#include "yesno.h"
X
Xstatic int SFX1[SFXTABSIZE];		/* single character suffixes */
Xstatic int INC1[SFXTABSIZE];		/* include file types for 1 char sfx */
Xstatic SFXBLK *SFX2[SFXTABSIZE];	/* 2+ character suffixes */
X
X/*
X * buildsfxtable() converts a suffix list into a hash table for fast lookup.
X * Returns YES if successful, otherwise NO.
X */
Xbuildsfxtable()
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	extern SUFFIX DEFSFX[];		/* default suffix list */
X	HASHBLK *htb;			/* hash table block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int i;				/* suffix list counter */
X	int installsfx();		/* install suffix in hash table */
X	int sfxbuftotable();		/* feed suffixes to installsfx() */
X
X	/* default suffix list */
X	for (i = 0; DEFSFX[i].suffix != NULL; i++)
X		if (installsfx(DEFSFX[i].suffix, DEFSFX[i].sfxtyp,
X		    DEFSFX[i].inctyp) == NO)
X			return(NO);
X	
X	/* supplementary suffix definitions */
X	if ((htb = htlookup(MSUFFIX, MDEFTABLE)) != NULL)
X		{
X		if (sfxbuftotable(htb->h_def) == NO)
X			return(NO);
X		}
X	return(YES);
X}
X
X
X
X/*
X * installsfx() installs a suffix in one of two suffix tables: SFX1 for
X * one character suffixes, and SFX2 for two or more character suffixes.
X * For a suffix that already exists, only its type and corresponding
X * included file type is updated. Returns integer YES if successful,
X * otherwise NO.
X */
Xinstallsfx(suffix, sfxtyp, inctyp)
X	char *suffix;			/* suffix string */
X	int sfxtyp;			/* suffix type */
X	int inctyp;			/* include file type */
X{
X	char *malloc();			/* memory allocator */
X	char *strsav();			/* save a string somewhere */
X	int sfxindex;			/* index into suffix tables */
X	SFXBLK *sfxblk;			/* suffix list block */
X
X	if (*suffix == '.')
X		suffix++;
X	sfxindex = suffix[0];
X	if (suffix[0] == '\0' || suffix[1] == '\0')
X		{
X		SFX1[sfxindex] = sfxtyp;	/* 0 or 1 character suffix */
X		INC1[sfxindex] = inctyp;
X		}
X	else	{				/* 2+ character suffix */
X		if ((sfxblk = (SFXBLK *) malloc(sizeof(SFXBLK))) == NULL)
X			return(NO);
X		if ((sfxblk->sfx.suffix = strsav(suffix)) == NULL)
X			return(NO);
X		sfxblk->sfx.sfxtyp = sfxtyp;
X		sfxblk->sfx.inctyp = inctyp;
X		sfxblk->next = SFX2[sfxindex];
X		SFX2[sfxindex] = sfxblk;
X		}
X	return(YES);
X}
X
X
X
X/*
X * lookuptypeofinclude() returns the include file type for suffix, or 0 if
X * unknown suffix.
X */
Xlookuptypeofinclude(suffix)
X	char *suffix;			/* suffix string */
X{
X	SFXBLK *sfxblk;			/* suffix block pointer */
X
X	if (suffix[0] == '\0' || suffix[1] == '\0')
X		return(INC1[*suffix]);		/* 0 or 1 char suffix */
X						/* 2+ character suffix */
X	for (sfxblk = SFX2[*suffix]; sfxblk != NULL; sfxblk = sfxblk->next)
X		if (EQUAL(suffix, sfxblk->sfx.suffix))
X			return(sfxblk->sfx.inctyp);
X	return(0);
X}
X
X
X
X/*
X * lookupsfx() returns the suffix type, or 0 if unknown suffix.
X */
Xlookupsfx(suffix)
X	char *suffix;			/* suffix string */
X{
X	SFXBLK *sfxblk;			/* suffix block pointer */
X
X	if (suffix[0] == '\0' || suffix[1] == '\0')
X		return(SFX1[*suffix]);		/* 0 or 1 char suffix */
X						/* 2+ character suffix */
X	for (sfxblk = SFX2[*suffix]; sfxblk != NULL; sfxblk = sfxblk->next)
X		if (EQUAL(suffix, sfxblk->sfx.suffix))
X			return(sfxblk->sfx.sfxtyp);
X	return(0);
X}
X
X
X
X/*
X * sfxbuftotable() parses a buffer containing suffixes and presents them
X * to installsfx() for installation into the appropriate hash table.
X * The suffix type may be altered by attaching a modifier :suffixtype.
X *	:h	--> header file type
X *	:o	--> object file type
X *	:s	--> source file type (default)
X *	:x	--> executable file type
X *	:	--> unknown file type
X * The include file type may be altered by attaching an additional
X * modifier includetype.
X *	C	--> C source code
X *	F	--> Fortran, Ratfor, Efl source code
X *	P	--> Pascal source code
X * If the suffix is object file type, the OBJSFX default object suffix
X * is modified accordingly. Returns YES if successful, otherwise NO.
X */
Xsfxbuftotable(sfxbuf)
X	char *sfxbuf;			/* buffer conatining suffixes */
X{
X	extern char OBJSFX[];		/* object file name suffix */
X	char *gettoken();		/* get next token */
X	char *rindex();			/* find last occurrence of character */
X	char *sfxtyp;			/* suffix type */
X	char *strcpy();			/* string copy */
X	char suffix[SUFFIXSIZE+2];	/* suffix + modifier */
X	int installsfx();		/* install suffix in hash table */
X
X	while ((sfxbuf = gettoken(suffix, sfxbuf)) != NULL)
X		if ((sfxtyp = rindex(suffix, ':')) == NULL)
X			{
X			if (installsfx(suffix, SFXSRC, INCLUDE_NONE) == NO)
X				return(NO);
X			}
X		else	{
X			*sfxtyp = '\0';
X			if (installsfx(suffix, sfxtyp[1], sfxtyp[2]) == NO)
X				return(NO);
X			if (sfxtyp[1] == SFXOBJ)
X				strcpy(OBJSFX, suffix);
X			}
X	return(YES);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/suffix.c"
fi
if `test ! -s src/usage.c`
then
echo "x - src/usage.c"
sed 's/^X//' > src/usage.c << '@\End\of\File\'
X/* $Header: usage.c,v 1.2 85/03/27 07:24:08 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * usage() places a usage error message on the standard error
X * output stream stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xusage(m)
X	char *m;			/* usage error message */
X{
X	fprintf(stderr, "usage: ");
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s ", PGN);
X	fprintf(stderr, "%s\n", m);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/usage.c"
fi
if `test ! -s src/warn.c`
then
echo "x - src/warn.c"
sed 's/^X//' > src/warn.c << '@\End\of\File\'
X/* $Header: warn.c,v 1.2 85/03/25 12:36:56 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * warn() places an error message on the standard error output stream
X * stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xwarn(m)
X	char *m;			/* warning message */
X{
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s: ", PGN);
X	fprintf(stderr, "%s\n", m);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/warn.c"
fi
if `test ! -s src/warn2.c`
then
echo "x - src/warn2.c"
sed 's/^X//' > src/warn2.c << '@\End\of\File\'
X/* $Header: warn2.c,v 1.1 85/04/01 17:20:41 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * warn2() places an error message and 2 string arguments on the
X * standard error output stream stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xwarn2(m, s1, s2)
X	char *m;			/* warning message */
X	char *s1;			/* string argument */
X	char *s2;			/* string argument */
X{
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s: ", PGN);
X	fprintf(stderr, m, s1, s2);
X	fprintf(stderr, "\n");
X}
@\End\of\File\
else
  echo "shar: Will not over write src/warn2.c"
fi
if `test ! -s src/warns.c`
then
echo "x - src/warns.c"
sed 's/^X//' > src/warns.c << '@\End\of\File\'
X/* $Header: warns.c,v 1.1 85/03/25 11:29:43 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * warns() places an error message and a string argument on the
X * standard error output stream stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xwarns(m, s)
X	char *m;			/* warning message */
X	char *s;			/* string argument */
X{
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s: ", PGN);
X	fprintf(stderr, m, s);
X	fprintf(stderr, "\n");
X}
@\End\of\File\
else
  echo "shar: Will not over write src/warns.c"
fi
if `test ! -s src/Mkmf.h`
then
echo "x - src/Mkmf.h"
sed 's/^X//' > src/Mkmf.h << '@\End\of\File\'
X/* $Header: Mkmf.h,v 1.4 85/04/23 16:43:00 nicklin Exp $ */
X
X/*
X * Mkmf definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Buffer sizes
X */
X#define ANSWERBUFSIZE		256	/* interactive answer buffer size */
X#define INCLUDETABLESIZE	1021	/* include file table size */
X#define MACRODEFSIZE		1024	/* macro definition body size */
X#define MACRONAMSIZE		32	/* macro definition name size */
X#define MDEFTABLESIZE		127	/* macro definition table size */
X#define RULETABSIZE		256	/* rule table size */
X#define SFXTABSIZE		256	/* suffix table size */
X#define SUFFIXSIZE		16	/* suffix size */
X/*
X * Predefined macro names
X */
X#define MCFLAGS		"CFLAGS"
X#define MDESTDIR	"DEST"
X#define MEXTERNALS	"EXTHDRS"
X#define MFFLAGS		"FFLAGS"
X#define MHEADERS	"HDRS"
X#define MLIBLIST	"LIBS"
X#define MLIBRARY	"LIBRARY"
X#define MMAKEFILE	"MAKEFILE"
X#define MMOREINCDIRS	"MOREINCDIRS"
X#define MOBJECTS	"OBJS"
X#define MPFLAGS		"PFLAGS"
X#define MPROGRAM	"PROGRAM"
X#define MSOURCE		"SRCS"
X#define MSUFFIX		"SUFFIX"
X/*
X * Predefined macro values
X */
X#define VERROR		       -1
X#define VUNKNOWN		0
X#define VREADONLY		1
X#define VREADWRITE		2
X#define VLIBRARY		3
X#define VPROGRAM		4
X#define VDESTDIR		5
X/*
X * Include statement styles
X */
X#define INCLUDE_C		'C'	/* #include "file" */
X#define INCLUDE_FORTRAN		'F'	/* include "file" or #include "file" */
X#define INCLUDE_PASCAL		'P'	/* #include "file" */
X#define INCLUDE_NONE		0	/* no include file */
X/*
X * Marker to indicate start of included file dependencies
X */
X#define DEPENDMARK		"###"
@\End\of\File\
else
  echo "shar: Will not over write src/Mkmf.h"
fi
if `test ! -s src/defaultrul.h`
then
echo "x - src/defaultrul.h"
sed 's/^X//' > src/defaultrul.h << '@\End\of\File\'
X".y.c", 	/* Yacc */
X".l.c", 	/* Lex */
@\End\of\File\
else
  echo "shar: Will not over write src/defaultrul.h"
fi
if `test ! -s src/defaultsfx.h`
then
echo "x - src/defaultsfx.h"
sed 's/^X//' > src/defaultsfx.h << '@\End\of\File\'
X".c", SFXSRC, INCLUDE_C,	/* C */
X".e", SFXSRC, INCLUDE_FORTRAN,	/* Efl */
X".F", SFXSRC, INCLUDE_FORTRAN,	/* Fortran */
X".f", SFXSRC, INCLUDE_FORTRAN,	/* Fortran */
X".h", SFXHEAD, INCLUDE_NONE,	/* header */
X".i", SFXHEAD, INCLUDE_NONE,	/* Pascal include */
X".l", SFXSRC, INCLUDE_C,	/* Lex */
X".o", SFXOBJ, INCLUDE_NONE,	/* object */
X".p", SFXSRC, INCLUDE_PASCAL,	/* Pascal */
X".r", SFXSRC, INCLUDE_FORTRAN,	/* Ratfor */
X".s", SFXSRC, INCLUDE_NONE,	/* Assembler */
X".y", SFXSRC, INCLUDE_C,	/* Yacc */
@\End\of\File\
else
  echo "shar: Will not over write src/defaultsfx.h"
fi
if `test ! -s src/dlist.h`
then
echo "x - src/dlist.h"
sed 's/^X//' > src/dlist.h << '@\End\of\File\'
X/* $Header: dlist.h,v 1.1 85/04/23 13:56:24 nicklin Exp $ */
X
X/*
X * Dependency list definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Dependency list block
X */
Xtypedef struct _dlblk
X	{
X	int d_type;			/* source file type */
X	struct slblk *d_src;		/* points to a source list block */
X	struct _iblk *d_incl;		/* pointer to include block chain */
X	struct _dlblk *d_next;		/* ptr to next list block */
X	} DLBLK;
X/*
X * Dependency list head block
X */
Xtypedef struct _dlisthb
X	{
X	DLBLK *d_head;			/* pointer to first list block */
X	DLBLK *d_tail;			/* pointer to last list block */
X	} DLIST;
X/*
X * Functions defined for dependency list operations
X */
Xextern DLBLK *dlappend();		/* append to list */
Xextern DLIST *dlinit();			/* initialize list */
Xextern void dlprint();			/* print list */
@\End\of\File\
else
  echo "shar: Will not over write src/dlist.h"
fi
if `test ! -s src/getarg.h`
then
echo "x - src/getarg.h"
sed 's/^X//' > src/getarg.h << '@\End\of\File\'
X/* $Header: getarg.h,v 1.1 85/03/14 15:32:56 nicklin Exp $ */
X
X/*
X * Get command line argument
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Argument syntax: `-xargument' or `-x argument'
X */
X#define GETARG(p) ((p[1] != '\0') ? ++p : (--argc, *++argv))
X
X/*
X * Argument syntax: `-xargument'
X *
X * #define GETARG(p) (++p)
X */
@\End\of\File\
else
  echo "shar: Will not over write src/getarg.h"
fi
if `test ! -s src/hash.h`
then
echo "x - src/hash.h"
sed 's/^X//' > src/hash.h << '@\End\of\File\'
X/* $Header: hash.h,v 1.2 85/03/26 15:49:56 nicklin Exp $ */
X
X/*
X * Hash table definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Singly-linked list block containing a pointer to a hash table
X * block for an include file
X */
Xtypedef struct _iblk
X	{
X	int i_loop;
X	struct _hblk *i_hblk;
X	struct _iblk *i_next;
X	} INCBLK;
X/*
X * Hash table block
X */
Xtypedef struct _hblk
X	{
X	char *h_key;			/* points to key */
X	char *h_def;			/* points to definition string */
X	int h_val;			/* integer value */
X	struct _iblk *h_sub;		/* ptr to include subchain */
X	struct _hblk *h_tag;		/* ptr to auxiliary tag chain */
X	struct _hblk *h_next;		/* ptr to next block */
X	} HASHBLK;
X/*
X * Hash pointer table struct
X */
Xtypedef struct _hash
X	{
X	HASHBLK **hashtab;		/* hash pointer table */
X	int hashsiz;			/* hash table size */
X	} HASH;
X/*
X * Functions defined for hash tables
X */
Xextern HASHBLK *htbrm();		/* remove hash table block */
Xextern int hthash();			/* compute hash value */
Xextern HASH *htinit();			/* initialize hash table */
Xextern HASHBLK *htinstall();		/* install hash table entry */
Xextern HASHBLK *htlookup();		/* find hash table entry */
Xextern void htrm();			/* remove hash table entry */
@\End\of\File\
else
  echo "shar: Will not over write src/hash.h"
fi
if `test ! -s src/macro.h`
then
echo "x - src/macro.h"
sed 's/^X//' > src/macro.h << '@\End\of\File\'
X/* $Header: macro.h,v 1.2 85/03/19 09:18:02 nicklin Exp $ */
X
X/*
X * General macro function definitions
X *
X * Author: Peter J. Nicklin
X */
X
Xint strcmp();				/* string comparison */
X
X#undef CHDIR
X#define CHDIR(d) \
X	(chdir(d) == 0)			/* change directory */
X
X#undef DOTDIR
X#define DOTDIR(dp) \
X	(dp->d_name[0] == '.' && dp->d_name[1] == '\0')
X					/* current directory? */
X#undef DOTDOTDIR
X#define DOTDOTDIR(dp) \
X	(dp->d_name[0] == '.' && dp->d_name[1] == '.' && dp->d_name[2] == '\0')
X					/* parent directory? */
X#undef EQUAL
X#define EQUAL(s1,s2) \
X	(strcmp(s1,s2) == 0)		/* string comparison */
X
X#undef MIN
X#define MIN(a,b) \
X	(((a) < (b)) ? (a) : (b))	/* minimum of two values */
X
X#undef MAX
X#define MAX(a,b) \
X	(((a) > (b)) ? (a) : (b))	/* maximum of two values */
X
X#undef WHITESPACE
X#define WHITESPACE(c) \
X	(c == ' ' || c == '\t')		/* unseen space in a file */
@\End\of\File\
else
  echo "shar: Will not over write src/macro.h"
fi
if `test ! -s src/null.h`
then
echo "x - src/null.h"
sed 's/^X//' > src/null.h << '@\End\of\File\'
X/* $Header: null.h,v 1.1 85/03/14 15:33:08 nicklin Exp $ */
X
X/*
X * NULL constant definition
X *
X * Author: Peter J. Nicklin
X */
X
X#define CNULL		(char *) 0
X#ifndef NULL
X#define NULL		0
X#endif
@\End\of\File\
else
  echo "shar: Will not over write src/null.h"
fi
if `test ! -s src/path.h`
then
echo "x - src/path.h"
sed 's/^X//' > src/path.h << '@\End\of\File\'
X/* $Header: path.h,v 1.1 85/03/14 15:33:11 nicklin Exp $ */
X
X/*
X * Pathname definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Buffer sizes
X */
X#define ALIASSIZE	30		/* project directory alias size */
X#define TYPESIZE	30		/* project directory type label size */
X#define DIRDESCSIZE	128		/* project directory description size */
X#define P_BUFSIZE	1024		/* pathname buffer size */
X#define	PATHSIZE	256		/* maximum pathname length */
X#define PPATHSIZE	128		/* maximum project pathname length */
X#define TYPBUFSIZE	256		/* directory type labels buffer */
X
X/* 
X * Nomenclature (WARNING: Check definition usage BEFORE changing)
X */
X#define _CDIRC		'.'		/* current directory character */
X#define _HDIRC		'~'		/* home directory character */
X#define _PDIRC		'^'		/* project root directory character */
X#define _PDTSC		'/'		/* project dir type labels sep char */
X#define _PPSC		'^'		/* project path separator character */
X#define _PSC		'/'		/* pathname separator character */
X#define _RDIRC		'/'		/* root directory character */
X#define CURDIR		"."		/* current directory */
X#define PARENTDIR	".."		/* parent directory */
X#define PATHSEP		"/"		/* pathname separator */
X#define PPATHSEP	"^"		/* project pathname separator */
X#define ROOTDIR		"/"		/* root directory */
X#define ROOTPROJECT	"^"		/* root project */
X#define USERPROJECT	"~"		/* user's root project */
X
X/*
X * Pathname types
X */
X#define P_IFMT		0xf0000		/* project pathname mask */
X#define	P_IFNEW		0x00000		/* new directory or file */
X#define P_IFREG		0x10000		/* regular directory or file */
X#define	P_IFHOME	0x20000		/* root project root directory */
X#define P_IFPDIR	0x30000		/* project directory */
X#define	P_IFPROOT	0x40000		/* project root directory */
X
X/*
X * Pathname struct
X */
Xtypedef struct _path
X	{
X	unsigned long p_mode;		/* type of pathname */
X	char *p_alias;			/* pathname alias */
X	char *p_path;			/* pathname */
X	char *p_type;			/* project directory type labels */
X	char *p_desc;			/* project directory description */
X	char p_buf[P_BUFSIZE];		/* pathname buffer */
X	char p_project[PATHSIZE];	/* pathname's project */
X	} PATH;
@\End\of\File\
else
  echo "shar: Will not over write src/path.h"
fi
if `test ! -s src/rule.h`
then
echo "x - src/rule.h"
sed 's/^X//' > src/rule.h << '@\End\of\File\'
X/* $Header: rule.h,v 1.1 85/05/02 08:01:11 nicklin Exp $ */
X
X/*
X * Rule definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Rule table block struct
X */
Xtypedef struct _ruleblk
X	{
X	char *r_rule;			/* pointer to rule string */
X	struct _ruleblk *r_next;	/* ptr to next rule list block */
X	} RULEBLK;
@\End\of\File\
else
  echo "shar: Will not over write src/rule.h"
fi
if `test ! -s src/sccsid.h`
then
echo "x - src/sccsid.h"
sed 's/^X//' > src/sccsid.h << '@\End\of\File\'
X/* $Header: sccsid.h,v 1.1 85/05/17 08:53:55 nicklin Exp $ */
X
X/*
X * Release identification
X *
X * Author: Peter J. Nicklin
X */
Xstatic char *sccsid = "@(#)V4BSDRel2";
@\End\of\File\
else
  echo "shar: Will not over write src/sccsid.h"
fi
if `test ! -s src/slist.h`
then
echo "x - src/slist.h"
sed 's/^X//' > src/slist.h << '@\End\of\File\'
X/* $Header: slist.h,v 1.1 85/03/14 15:33:33 nicklin Exp $ */
X
X/*
X * Singly-linked list definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Singly-linked list macros
X */
X#define SLNUM(slist)	(slist)->nk
X/*
X * Singly-linked list block
X */
Xtypedef struct slblk
X	{
X	char *key;			/* points to a key */
X	struct slblk *next;		/* ptr to next list block */
X	} SLBLK;
X/*
X * Singly-linked list head block
X */
Xtypedef struct slisthb
X	{
X	int nk;				/* number of keys in list */
X	int maxkey;			/* length of longest key */
X	SLBLK *head;			/* pointer to first list block */
X	SLBLK *curblk;			/* pointer to current block */
X	SLBLK *tail;			/* pointer to last list block */
X	} SLIST;
X/*
X * Functions defined for singly-linked list operations
X */
Xextern char *slappend();		/* append key */
Xextern char *slget();			/* get next key */
Xextern SLIST *slinit();			/* initialize list */
Xextern char *slinsert();		/* insert key */
Xextern int slpop();			/* pop key */
Xextern char *slprepend();		/* prepend key */
Xextern void slprint();			/* print list */
Xextern void slrewind();			/* rewind list */
Xextern void slrm();			/* remove list item */
Xextern int slsort();			/* sort list */
Xextern void slsplice();			/* splice two lists */
@\End\of\File\
else
  echo "shar: Will not over write src/slist.h"
fi
if `test ! -s src/spms.h`
then
echo "x - src/spms.h"
sed 's/^X//' > src/spms.h << '@\End\of\File\'
X/* $Header: spms.h,v 1.1 85/03/14 15:33:41 nicklin Exp $ */
X
X/*
X * SPMS definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Nomenclature
X */
X#define CURPROJECT	"..."		/* current project root directory */
X#define PARENTPROJECT	"...."		/* parent project root directory */
X#define PROJECTLOG	"projectlog"	/* log-file in project root dir */
X#define PROJECTRC	".projectrc"	/* project environment file */
X#define SPMSBIN		"/usr/new"	/* SPMS binaries */
X#define SPMSLIB		"/usr/new/lib"	/* SPMS data files */
X#define SPMSROOT	"/usr/new"	/* SPMS root directory */
@\End\of\File\
else
  echo "shar: Will not over write src/spms.h"
fi
if `test ! -s src/suffix.h`
then
echo "x - src/suffix.h"
sed 's/^X//' > src/suffix.h << '@\End\of\File\'
X/* $Header: suffix.h,v 1.1 85/03/14 15:38:45 nicklin Exp $ */
X
X/*
X * Suffix definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Suffix types 
X */
X#define SFXHEAD			'h'	/* header file name suffix */
X#define SFXOBJ			'o'	/* object file name suffix */
X#define SFXOUT			'x'	/* executable file name suffix */
X#define SFXSRC			's'	/* source file name suffix */
X
X/*
X * Suffix table structs
X */
Xtypedef struct _suffix
X	{
X	char *suffix;			/* points to a suffix */
X	int sfxtyp;			/* type of file name suffix */
X	int inctyp;			/* type of included file */
X	} SUFFIX;
X
Xtypedef struct _sfxblk
X	{
X	SUFFIX sfx;			/* suffix struct */
X	struct _sfxblk *next;		/* ptr to next suffix list block */
X	} SFXBLK;
@\End\of\File\
else
  echo "shar: Will not over write src/suffix.h"
fi
if `test ! -s src/system.h`
then
echo "x - src/system.h"
sed 's/^X//' > src/system.h << '@\End\of\File\'
X/* $Header: system.h,v 1.5 85/06/27 12:10:18 nicklin Exp $ */
X
X/*
X * System-dependent definitions
X *
X * Author: Peter J. Nicklin
X */
X#define FILEXIST(file)		(access(file,0) ? 0 : 1)
X#define FILEWRITE(file)		(access(file,6) ? 0 : 1)
X
X#ifdef V4BSD
X#include <sys/file.h>
X#define CREATE(name,flags,mode)	open(name,flags|FCREAT,mode)
X#define FORK()			vfork()
X#define OPEN(name,flags,mode)	open(name,flags,mode)
X#define RENAME(from,to)		rename(from,to)
X#else
X#define NBBY 8            
X#define O_RDONLY		000
X#define O_WRONLY		001
X#define O_RDWR			002
X#define CREATE(name,flags,mode)	creat(name,mode)
X#define FORK()			fork()
X#define OPEN(name,flags,mode)	open(name,flags)
X#define RENAME(from,to)		unlink(to); link(from,to); unlink(from)
X#endif
@\End\of\File\
else
  echo "shar: Will not over write src/system.h"
fi
if `test ! -s src/target.h`
then
echo "x - src/target.h"
sed 's/^X//' > src/target.h << '@\End\of\File\'
X/* $Header: target.h,v 1.1 85/03/14 15:38:49 nicklin Exp $ */
X
X/*
X * Target definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Target struct
X */
Xtypedef struct _target
X	{
X	int type;			/* prog, lib, or other target type */
X	int dest;			/* target destination flag */
X	} TARGET;
@\End\of\File\
else
  echo "shar: Will not over write src/target.h"
fi
if `test ! -s src/yesno.h`
then
echo "x - src/yesno.h"
sed 's/^X//' > src/yesno.h << '@\End\of\File\'
X/* $Header: yesno.h,v 1.1 85/03/14 15:34:01 nicklin Exp $ */
X
X/*
X * YES/NO constant definitions
X *
X * Author: Peter J. Nicklin
X */
X
X#define YES 1
X#define NO  0
@\End\of\File\
else
  echo "shar: Will not over write src/yesno.h"
fi
if `test ! -s src/oMakefile`
then
echo "x - src/oMakefile"
sed 's/^X//' > src/oMakefile << '@\End\of\File\'
X# $Header: Makefile,v 1.1 84/09/14 15:37:40 nicklin Exp $
X#
XCFLAGS	      = -D$(VERSION) -O
X
XHOMEDIR	      = /usr4/texers/jwm
X
XDEST	      = $(HOMEDIR)/bin
X
XEXTHDRS	      =
X
XHDRS	      = Mkmf.h \
X		defaultrul.h \
X		defaultsfx.h \
X		dlist.h \
X		getarg.h \
X		hash.h \
X		macro.h \
X		null.h \
X		path.h \
X		rule.h \
X		sccsid.h \
X		slist.h \
X		spms.h \
X		suffix.h \
X		system.h \
X		target.h \
X		yesno.h
X
XLDFLAGS	      =
X
XLIBS	      =
X
XLINKER	      = cc
X
XLINTFLAGS     = -D$(VERSION)
X
XLINTLIST      = -lc
X
XMAKEFILE      = Makefile
X
XOBJS	      = Mkmf.o \
X		badopt.o \
X		buildlist.o \
X		depend.o \
X		dlist.o \
X		editmf.o \
X		getcwp.o \
X		getproject.o \
X		hash.o \
X		iolin.o \
X		macro.o \
X		misc.o \
X		mustfopen.o \
X		optpath.o \
X		pathcat.o \
X		pathhead.o \
X		pperror.o \
X		rule.o \
X		slappend.o \
X		slinit.o \
X		slsort.o \
X		strpcpy.o \
X		strsav.o \
X		suffix.o \
X		usage.o \
X		warn.o \
X		warn2.o \
X		warns.o
X
XPRINT	      = pr
X
XPROGRAM	      = mkmf
X
XSRCS	      = Mkmf.c \
X		badopt.c \
X		buildlist.c \
X		depend.c \
X		dlist.c \
X		editmf.c \
X		getcwp.c \
X		getproject.c \
X		hash.c \
X		iolin.c \
X		macro.c \
X		misc.c \
X		mustfopen.c \
X		optpath.c \
X		pathcat.c \
X		pathhead.c \
X		pperror.c \
X		rule.c \
X		slappend.c \
X		slinit.c \
X		slsort.c \
X		strpcpy.c \
X		strsav.c \
X		suffix.c \
X		usage.c \
X		warn.c \
X		warn2.c \
X		warns.c
X
XVERSION	      = V4BSD
X
Xall:		$(PROGRAM)
X
X$(PROGRAM):     $(OBJS) $(LIBS)
X		@echo -n "Loading $(PROGRAM) ... "
X		@$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
X		@echo "done"
X
Xclean:;		@rm -f $(OBJS)
X
Xco:;		@co -r$(VERSION) $(HDRS) $(SRCS)
X
Xdepend:;	@mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) \
X		'DEST=$$(HOMEDIR)/bin' HOMEDIR=`echo $$HOME`
X
Xdiff:;		@rcsdiff -r$(VERSION) $(HDRS) $(SRCS)
X
Xindex:;		@ctags -wx $(HDRS) $(SRCS)
X
Xinstall:	$(PROGRAM)
X		@echo Installing $(PROGRAM) in $(DEST)
X		@install $(IFLAGS) $(PROGRAM) $(DEST)
X		
X
Xlint:;	        @lint $(LINTFLAGS) $(SRCS) $(LINTLIST)
X
Xprint:;		@$(PRINT) $(HDRS) $(SRCS)
X
Xprogram:        $(PROGRAM)
X
Xtags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
X
Xupdate:		$(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
X		@make -f $(MAKEFILE) DEST=$(DEST) install tags
X###
XMkmf.o: sccsid.h Mkmf.h getarg.h hash.h null.h path.h target.h slist.h \
X	suffix.h system.h yesno.h defaultrul.h defaultsfx.h
Xbadopt.o: null.h
Xbuildlist.o: Mkmf.h hash.h null.h path.h slist.h suffix.h system.h yesno.h
Xdepend.o: Mkmf.h dlist.h hash.h macro.h null.h path.h slist.h system.h \
X	yesno.h
Xdlist.o: Mkmf.h dlist.h hash.h null.h slist.h yesno.h
Xeditmf.o: Mkmf.h dlist.h hash.h macro.h null.h slist.h system.h yesno.h
Xgetcwp.o: null.h
Xgetproject.o: null.h
Xhash.o: null.h hash.h macro.h
Xiolin.o: yesno.h
Xmacro.o: Mkmf.h hash.h macro.h null.h slist.h yesno.h
Xmisc.o: Mkmf.h hash.h macro.h null.h path.h target.h spms.h suffix.h \
X	system.h yesno.h
Xoptpath.o: path.h
Xpathcat.o: path.h
Xpathhead.o: null.h path.h
Xrule.o: Mkmf.h null.h rule.h slist.h suffix.h system.h yesno.h
Xslappend.o: macro.h null.h slist.h
Xslinit.o: null.h slist.h
Xslsort.o: null.h slist.h yesno.h
Xstrsav.o: null.h
Xsuffix.o: Mkmf.h hash.h macro.h null.h suffix.h yesno.h
Xusage.o: null.h
Xwarn.o: null.h
Xwarn2.o: null.h
Xwarns.o: null.h
@\End\of\File\
else
  echo "shar: Will not over write src/oMakefile"
fi
if `test ! -d x.Makefile`
then
  mkdir x.Makefile
  echo "mkdir x.Makefile"
fi
if `test ! -s x.Makefile/t.Makefile`
then
echo "x - x.Makefile/t.Makefile"
sed 's/^X//' > x.Makefile/t.Makefile << '@\End\of\File\'
XLDFLAGS	      =
X
XLIBS	      =
X
XLINKER	      = cc
X
XOBJS	      =
X
XPROGRAM	      =
X
X$(PROGRAM):     $(OBJS) $(LIBS)
X		$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/t.Makefile"
fi
if `test ! -s x.Makefile/Makefile`
then
echo "x - x.Makefile/Makefile"
sed 's/^X//' > x.Makefile/Makefile << '@\End\of\File\'
X# $Header: Makefile,v 1.1 85/03/14 15:59:05 nicklin Exp $
X#
X#DEST	      = $(DESTDIR)/usr/new/lib
XDEST	      = $(DESTDIR)/lib
X
XMAKEFILE      = Makefile
X
XPRINT	      = pr
X
XPROGRAM	      = p.Makefile
X
XSRCS	      = l.Makefile \
X		p.Makefile \
X		t.Makefile
X
XSUFFIX	      = .Makefile:s
X
XVERSION	      = V4BSD
X
Xall:;
X
Xclean:;
X
Xco:;		@co -r$(VERSION) $(SRCS)
X
Xdepend:;
X
Xdiff:;		@rcsdiff -r$(VERSION) $(HDRS) $(SRCS)
X
Xindex:;
X
Xinstall:	$(SRCS)
X		@echo Installing $(SRCS) in $(DEST)
X		@cp $(SRCS) $(DEST)
X
Xlint:;
X
Xprint:;		@$(PRINT) $(SRCS)
X
Xtags:;
X
Xupdate:		$(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS)
X		@make -f $(MAKEFILE) DEST=$(DEST) install tags
X###
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/Makefile"
fi
if `test ! -s x.Makefile/l.Makefile`
then
echo "x - x.Makefile/l.Makefile"
sed 's/^X//' > x.Makefile/l.Makefile << '@\End\of\File\'
XCFLAGS        = -O
X
XDEST	      = .
X
XEXTHDRS	      =
X
XHDRS	      =
X
XLIBRARY	      = lib.a
X
XMAKEFILE      = Makefile
X
XOBJS	      =
X
XPRINT	      = pr
X
XSRCS	      =
X
Xall:		$(LIBRARY)
X
X$(LIBRARY):	$(OBJS)
X		ar cru $(LIBRARY) $(OBJS)
X		ranlib $(LIBRARY)
X
Xclean:;		rm -f $(OBJS)
X
Xdepend:;	mkmf -f $(MAKEFILE) LIBRARY=$(LIBRARY) DEST=$(DEST)
X
Xextract:;	ar xo $(DEST)/$(LIBRARY)
X		@rm -f __.SYMDEF
X
Xindex:;		ctags -wx $(HDRS) $(SRCS)
X
Xinstall:	$(LIBRARY)
X		install $(LIBRARY) $(DEST)
X		ranlib $(DEST)/$(LIBRARY)
X
Xlibrary:        $(LIBRARY)
X
Xprint:;		$(PRINT) $(HDRS) $(SRCS)
X
Xtags:           $(HDRS) $(SRCS); ctags $(HDRS) $(SRCS)
X
Xupdate:         $(DEST)/$(LIBRARY)
X
X$(DEST)/$(LIBRARY): $(SRCS) $(HDRS) $(EXTHDRS)
X		@-ar xo $(DEST)/$(LIBRARY)
X		@make -f $(MAKEFILE) DEST=$(DEST) install clean
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/l.Makefile"
fi
if `test ! -s x.Makefile/p.Makefile`
then
echo "x - x.Makefile/p.Makefile"
sed 's/^X//' > x.Makefile/p.Makefile << '@\End\of\File\'
XCFLAGS        = -O
X
XDEST	      = ${HOME}/bin
X
XEXTHDRS	      =
X
XHDRS	      =
X
XLDFLAGS	      =
X
XLIBS	      =
X
XLINKER	      = cc
X
XMAKEFILE      = Makefile
X
XOBJS	      =
X
XPRINT	      = pr
X
XPROGRAM	      = a.out
X
XSRCS	      =
X
Xall:		$(PROGRAM)
X
X$(PROGRAM):     $(OBJS) $(LIBS)
X		$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
X
Xclean:;		rm -f $(OBJS)
X
Xdepend:;	mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
X
Xindex:;		ctags -wx $(HDRS) $(SRCS)
X
Xinstall:	$(PROGRAM)
X		install -s $(PROGRAM) $(DEST)
X
Xprint:;		$(PRINT) $(HDRS) $(SRCS)
X
Xprogram:        $(PROGRAM)
X
Xtags:           $(HDRS) $(SRCS); ctags $(HDRS) $(SRCS)
X
Xupdate:		$(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
X		@make -f $(MAKEFILE) DEST=$(DEST) install
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/p.Makefile"
fi
echo "Finished archive 2 of 2"
# to concatenate archives, remove anything after this line
exit 0
