[net.micro.atari16] MAKE part 1 of 3

bammi@cwruecmp.UUCP (08/05/86)

#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	astat.h
#	check.c
#	compile.sh
#	decl.h
#	h.h
#	input.c
#	link.sh
#	lnk
#	macro.c
# This archive created: Tue Aug  5 02:46:35 1986
# By:	Jwahar R. Bammi ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'astat.h'" '(512 characters)'
if test -f 'astat.h'
then
	echo shar: over-writing existing file "'astat.h'"
fi
sed 's/^X//' << \SHAR_EOF > 'astat.h'
X	/************************************************\
X	*					         *
X	*	astat.h - Retrofit <sys/stat.h>		 *
X	*               for the Atari St machines        *
X	*					         *
X	*	J.R. Bammi				 *
X	*						 *
X	\************************************************/
X
X
Xstruct	stat
X{
X	char	st_sp1[21];    /* Junk 	   */
X	char	st_mode;       /* File attributes */
X	time_t	st_mod;        /* Mod time, we use the date & time as 1 long */
X	long	st_size;       /* File size	   */
X	char	st_sp2[14];    /* File name	   */
X};
SHAR_EOF
if test 512 -ne "`wc -c 'astat.h'`"
then
	echo shar: error transmitting "'astat.h'" '(should have been 512 characters)'
fi
echo shar: extracting "'check.c'" '(2525 characters)'
if test -f 'check.c'
then
	echo shar: over-writing existing file "'check.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'check.c'
X#define ATARIST
X
X	/*******************************************************\
X	*							*
X	*	A full featured MAKE Clone			*
X	*							*
X	*	Origional Author: (Thank You)			*
X	*	    Neil Russell				*
X	*	    ACSnet:  caret@tictoc.oz			*
X	*	    UUCP:  ...!seismo!munnari!tictoc.oz!caret	*
X	*	    ARPA:  caret%tictoc.oz@seismo.arpa		*
X	*							*
X	*	Atari St Port & C code cleanup:			*
X	*	    Jwahar R. Bammi				*
X	*	    UUCP:  .....!decvax!cwruecmp!bammi		*
X	*	   CSNET:  bammi@case				*
X	*	    ARPA:  bammi%case@csnet-relay		*
X	*     CompuServe:  71515,155				*
X	*							*
X	\*******************************************************/
X		    
X
X/*
X *	Check structures for make.
X */
X
X#include <stdio.h>
X#include "h.h"
X
X
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
X
X	for (mp = macrohead; mp; mp = mp->m_next)
X		fprintf(stderr, "%s = %s\n", mp->m_name, mp->m_val);
X
X	fputc('\n', stderr);
X
X	for (np = namehead.n_next; np; np = np->n_next)
X	{
X		fprintf(stderr, "%s:\n", np->n_name);
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
X			for (cp = lp->l_cmd; cp; cp = cp->c_next)
X				fprintf(stderr, "-\t%s\n", cp->c_cmd);
X			fputc('\n', stderr);
X		}
X		fputc('\n', stderr);
X	}
X}
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
X
X	if (np->n_flag & N_MARK)
X		fatal("Circular dependency from %s", np->n_name);
X
X	np->n_flag |= N_MARK;
X
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
X	np->n_flag &= ~N_MARK;
X}
X
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
X
X	for (np = namehead.n_next; np; np = np->n_next)
X		check(np);
X}
X
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
X
X	if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG))
X		return;
X
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}
SHAR_EOF
if test 2525 -ne "`wc -c 'check.c'`"
then
	echo shar: error transmitting "'check.c'" '(should have been 2525 characters)'
fi
echo shar: extracting "'compile.sh'" '(119 characters)'
if test -f 'compile.sh'
then
	echo shar: over-writing existing file "'compile.sh'"
fi
sed 's/^X//' << \SHAR_EOF > 'compile.sh'
Xcc -c check.c
Xcc -c input.c
Xcc -c macro.c
Xcc -c main.c
Xcc -c make.c
Xcc -c reader.c
Xcc -c rules.c
Xcc -c ststuff.c      
SHAR_EOF
if test 119 -ne "`wc -c 'compile.sh'`"
then
	echo shar: error transmitting "'compile.sh'" '(should have been 119 characters)'
fi
echo shar: extracting "'decl.h'" '(1126 characters)'
if test -f 'decl.h'
then
	echo shar: over-writing existing file "'decl.h'"
fi
sed 's/^X//' << \SHAR_EOF > 'decl.h'
X 	/***********************************************\
X 	*						*
X 	*  Decl.h - extern declarations for C libarary  *
X 	*						*
X	\***********************************************/
X
Xextern	FILE *fopen(), *freopen(), *fdopen();
Xextern	FILE *fopena(), *freopa();
Xextern	FILE *fopenb(), *freopb();
X
X
Xextern	char	*etoa();
Xextern	char	*ftoa();
Xextern	char	*getpass();
Xextern	char	*index();
Xextern	char	*mktemp();
Xextern	char	*rindex();
Xextern	char	*sprintf();
Xextern	char	*strcat();
Xextern	char	*strcpy();
Xextern	char	*strncat();
Xextern	char	*strncpy();
Xextern	char	*calloc(), *malloc(), *realloc(), *sbrk();
Xextern	char 	*gets(), *fgets();
Xextern	char 	*ttyname();
X
Xextern	double	atan();
Xextern	double	atof();
Xextern	double	ceil();
Xextern	double	cos();
Xextern	double	exp();
Xextern	double	fabs();
Xextern	double	floor();
Xextern	double	fmod();
Xextern	double	log();
Xextern	double	pow();
Xextern	double	sin();
Xextern	double	sinh();
Xextern	double	sqrt();
Xextern	double	tan();
Xextern	double	tanh();
X
Xextern	int	strlen();
Xextern	int	(*signal())();
X
Xextern	long 	atol();
Xextern	long 	ftell();
Xextern	long 	lseek(), tell();
Xextern	long	getl();
X
SHAR_EOF
if test 1126 -ne "`wc -c 'decl.h'`"
then
	echo shar: error transmitting "'decl.h'" '(should have been 1126 characters)'
fi
echo shar: extracting "'h.h'" '(4053 characters)'
if test -f 'h.h'
then
	echo shar: over-writing existing file "'h.h'"
fi
sed 's/^X//' << \SHAR_EOF > 'h.h'
X	/*******************************************************\
X	*							*
X	*	A full featured MAKE Clone			*
X	*							*
X	*	Origional Author: (Thank You)			*
X	*	    Neil Russell				*
X	*	    ACSnet:  caret@tictoc.oz			*
X	*	    UUCP:  ...!seismo!munnari!tictoc.oz!caret	*
X	*	    ARPA:  caret%tictoc.oz@seismo.arpa		*
X	*							*
X	*	Atari St Port & C code cleanup:			*
X	*	    Jwahar R. Bammi				*
X	*	    UUCP:  .....!decvax!cwruecmp!bammi		*
X	*	   CSNET:  bammi@case				*
X	*	    ARPA:  bammi%case@csnet-relay		*
X	*     CompuServe:  71515,155				*
X	*							*
X	\*******************************************************/
X		    
X
X/*
X *	Include header for make
X *
X *	-- 7/86 JRB Added Atari ST suport
X */
X#ifdef atarist
X#define ATARIST
X#endif
X
X#ifdef ATARIST
X
X#include <osbind.h>
X#include "decl.h"
X
X/* #define MEGRULES	*/	/* Define if default .c.o rule is to be
X   				 * genarated to use the Megamax C Compiler
X				 */
X/* #define MEGAMAX	*/	/* If using Megamax C to compile Make
X 				 * This symbol has NO relation to the
X				 * symbol MEGRULES 
X				 */
X
X#ifdef MEGAMAX
X#define void		/* Alcyon 4.14 understands void */
X#undef Fdatime		/* Megamax has it incorrectly defined */
X#define	Fdatime(a,b,c)	gemdos(0x57,a,b,c)
X
X#endif /* MEGAMAX */
X
X#ifdef TRUE
X#undef TRUE
X#endif
X
X#ifdef FALSE
X#undef FALSE
X#endif
X
X#ifdef uchar
X#undef uchar
X#endif
X
X#ifdef NULL
X#undef NULL
X#define NULL	0L
X#endif
X
X#ifdef max
X#undef max
X#endif
X
X#ifdef MEGAMAX
X#define uchar	char	/* For the sake of Megamax and gang who still think
X			 * that unsigned is a type
X			 */
X#else
X#define uchar	unsigned char
X
X#endif /* MEGAMAX */
X
X#else
X
X#ifndef uchar
X#define uchar	unsigned char
X#endif
X
X#endif	/* ATARIST */
X
X
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
X#define DEFN1		"makefile"		/*  Default names  */
X
X#ifndef ATARIST
X#define DEFN2		"Makefile"
X#endif /* ATARIST - TOS is not case sensative  */
X
X#ifdef ATARIST
X
X#define LZ		2048			/*  BIG Line size  */
X
X#else
X
X#define LZ		1024			/* Line Size */
X
X#endif /* ATARIST */
X
X
X/*
X *	A name.  This represents a file, either to be made, or existant
X */
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
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
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
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
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
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};
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;
X
Xextern char *		fgets();
Xextern char *		index();
Xextern char *		rindex();
Xextern char *		malloc();
Xextern int		errno;
X
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();
X
X#ifdef ATARIST
Xint		system();
Xvoid		FlipWords();
X#endif /* ATARIST */
SHAR_EOF
if test 4053 -ne "`wc -c 'h.h'`"
then
	echo shar: error transmitting "'h.h'" '(should have been 4053 characters)'
fi
echo shar: extracting "'input.c'" '(6224 characters)'
if test -f 'input.c'
then
	echo shar: over-writing existing file "'input.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'input.c'
X#define ATARIST
X
X	/*******************************************************\
X	*							*
X	*	A full featured MAKE Clone			*
X	*							*
X	*	Origional Author: (Thank You)			*
X	*	    Neil Russell				*
X	*	    ACSnet:  caret@tictoc.oz			*
X	*	    UUCP:  ...!seismo!munnari!tictoc.oz!caret	*
X	*	    ARPA:  caret%tictoc.oz@seismo.arpa		*
X	*							*
X	*	Atari St Port & C code cleanup:			*
X	*	    Jwahar R. Bammi				*
X	*	    UUCP:  .....!decvax!cwruecmp!bammi		*
X	*	   CSNET:  bammi@case				*
X	*	    ARPA:  bammi%case@csnet-relay		*
X	*     CompuServe:  71515,155				*
X	*							*
X	\*******************************************************/
X		    
X
X/*
X *	Parse a makefile
X */
X
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "h.h"
X
X
Xstruct name		namehead = {
X					(struct name *)NULL,
X					(char *)NULL,
X					(struct line *)NULL,
X					(time_t)0,
X					(uchar)0
X				    };
X				    
Xstruct name *		firstname = (struct name *)NULL;
X
Xchar 			str1[LZ];		/*  General store  */
Xchar			str2[LZ];
X
X
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
X
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
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
X	return rp;
X}
X
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
X
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
X	if (dp == (struct depend *)0)
X		return rp;
X
X	for (rrp = dp; rrp->d_next; rrp = rrp->d_next)
X		;
X
X	rrp->d_next = rp;
X
X	return dp;
X}
X
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
X
X	if (rcp = rindex(str, '\n'))
X		*rcp = '\0';		/*  Loose newline  */
X
X	while (isspace(*str))
X		str++;
X
X	if (*str == '\0')		/*  If nothing left, the exit  */
X		return;
X
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
X	if (cp == (struct cmd *)0)
X		return rp;
X
X	for (rrp = cp; rrp->c_next; rrp = rrp->c_next)
X		;
X
X	rrp->c_next = rp;
X
X	return cp;
X}
X
X
X/*
X *	Add a new 'line' of stuff to a target.  This check to see
X *	if commands already exist for the target.
X */
Xvoid
Xnewline(np, dp, cp)
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
X
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
X	if (hascmds && cp)
X		error("Commands defined twice for target %s", np->n_name);
X
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
X	if (rrp)
X		rrp->l_next = rp;
X	else
X		np->n_line = rp;
X
X	np->n_flag |= N_TARG;
X}
X
X#define Is_special(X) ( 				\
X		       (strcmp(X,".SUFFIXES") == 0) ||  \
X		       (strcmp(X,".IGNORE") == 0)   ||  \
X		       (strcmp(X,".SILENT") == 0)   ||  \
X		       (strcmp(X,".PRECIOUS") == 0)     \
X		       )
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
X
X	if (getline(str1, fd))	/*  Read the first line  */
X		return;
X
X	for(;;)
X	{
X		if (*str1 == '\t')	/*  Rules without targets  */
X			error("Rules not allowed here");
X
X		p = str1;
X
X		while (isspace(*p))	/*  Find first target  */
X			p++;
X
X		while (((q = index(p, '=')) != (char *)0) &&
X		    (p != q) && (q[-1] == '\\'))	/*  Find value */
X		{
X			register char *		a;
X
X			a = q - 1;	/*  Del \ chr; move rest back  */
X			p = q;
X			while(*a++ = *q++)
X				;
X		}
X
X		if (q != (char *)0)
X		{
X			register char *		a;
X
X			*q++ = '\0';		/*  Separate name and val  */
X			while (isspace(*q))
X				q++;
X			if (p = rindex(q, '\n'))
X				*p = '\0';
X
X			p = str1;
X			if ((a = gettok(&p)) == (char *)0)
X				error("No macro name");
X
X			setmacro(a, q);
X
X			if (getline(str1, fd))
X				return;
X			continue;
X		}
X
X		expand(str1);
X		p = str1;
X
X		while (((q = index(p, ':')) != (char *)0) &&
X		    (p != q) && (q[-1] == '\\'))	/*  Find dependents  */
X		{
X			register char *		a;
X
X			a = q - 1;	/*  Del \ chr; move rest back  */
X			p = q;
X			while(*a++ = *q++)
X				;
X		}
X
X		if (q == (char *)0)
X			error("No targets provided");
X
X		*q++ = '\0';	/*  Separate targets and dependents  */
X
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
X		*((char *)((q = str1) + (long)strlen(str1) + 1L)) = '\0';
X			/*  Need two nulls for gettok (Remember separation)  */
X
X		cp = (struct cmd *)0;
X		if (getline(str2, fd) == FALSE)		/*  Get commands  */
X		{
X			while (*str2 == '\t')
X			{
X				cp = newcmd(&str2[0], cp);
X				if (getline(str2, fd))
X					break;
X			}
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);
X			if (!firstname)
X			{
X				if(!Is_special(p))
X				    firstname = np;
X			}
X			
X		}
X
X		if (feof(fd))				/*  EOF?  */
X			return;
X
X		strcpy(str1, str2);
X	}
X}
SHAR_EOF
if test 6224 -ne "`wc -c 'input.c'`"
then
	echo shar: error transmitting "'input.c'" '(should have been 6224 characters)'
fi
echo shar: extracting "'link.sh'" '(43 characters)'
if test -f 'link.sh'
then
	echo shar: over-writing existing file "'link.sh'"
fi
sed 's/^X//' << \SHAR_EOF > 'link.sh'
Xlink68 [com[lnk]]
Xrelmod make
Xrm make.68k
X
SHAR_EOF
if test 43 -ne "`wc -c 'link.sh'`"
then
	echo shar: error transmitting "'link.sh'" '(should have been 43 characters)'
fi
echo shar: extracting "'lnk'" '(89 characters)'
if test -f 'lnk'
then
	echo shar: over-writing existing file "'lnk'"
fi
sed 's/^X//' << \SHAR_EOF > 'lnk'
Xmake.68k=gemstart,check,input,macro,main,make,reader,rules,ststuff, \
Xosbind,gemlib,libf
SHAR_EOF
if test 89 -ne "`wc -c 'lnk'`"
then
	echo shar: error transmitting "'lnk'" '(should have been 89 characters)'
fi
echo shar: extracting "'macro.c'" '(3039 characters)'
if test -f 'macro.c'
then
	echo shar: over-writing existing file "'macro.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'macro.c'
X#define ATARIST
X
X	/*******************************************************\
X	*							*
X	*	A full featured MAKE Clone			*
X	*							*
X	*	Origional Author: (Thank You)			*
X	*	    Neil Russell				*
X	*	    ACSnet:  caret@tictoc.oz			*
X	*	    UUCP:  ...!seismo!munnari!tictoc.oz!caret	*
X	*	    ARPA:  caret%tictoc.oz@seismo.arpa		*
X	*							*
X	*	Atari St Port & C code cleanup:			*
X	*	    Jwahar R. Bammi				*
X	*	    UUCP:  .....!decvax!cwruecmp!bammi		*
X	*	   CSNET:  bammi@case				*
X	*	    ARPA:  bammi%case@csnet-relay		*
X	*     CompuServe:  71515,155				*
X	*							*
X	\*******************************************************/
X		    
X
X/*
X *	Macro control for make
X */
X
X#include <stdio.h>
X#include "h.h"
X
X
Xstruct macro *		macrohead = (struct macro *)NULL;
X
X
Xstruct macro *
Xgetmp(name)
Xchar *			name;
X{
X	register struct macro *	rp;
X
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}
X
X
Xchar *
Xgetmacro(name)
Xchar *			name;
X{
X	struct macro *		mp;
X
X	if (mp = getmp(name))
X		return mp->m_val;
X	else
X		return "";
X}
X
X
Xstruct macro *
Xsetmacro(name, val)
Xchar *			name;
Xchar *			val;
X{
X	register struct macro *	rp;
X	register char *		cp;
X
X
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
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
X		rp->m_next = macrohead;
X		macrohead = rp;
X		rp->m_flag = FALSE;
X
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
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
X	return rp;
X}
X
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
X
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
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
X	strcpy(a, str);
X	doexp(&p, a, &len, b);
X}
SHAR_EOF
if test 3039 -ne "`wc -c 'macro.c'`"
then
	echo shar: error transmitting "'macro.c'" '(should have been 3039 characters)'
fi
#	End of shell archive
exit 0
-- 
					Jwahar R. Bammi
 		        Usenet:  .....!decvax!cwruecmp!bammi
		        CSnet:  bammi@case         Arpa:  bammi%case@csnet-relay
			CompuServe:  71515,155