Initial revision
This commit is contained in:
		
							parent
							
								
									7515b51d64
								
							
						
					
					
						commit
						a0a265736c
					
				
					 11 changed files with 1971 additions and 0 deletions
				
			
		
							
								
								
									
										10
									
								
								util/make/.distr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								util/make/.distr
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | Makefile | ||||||
|  | README | ||||||
|  | check.c | ||||||
|  | h.h | ||||||
|  | input.c | ||||||
|  | macro.c | ||||||
|  | main.c | ||||||
|  | make.c | ||||||
|  | reader.c | ||||||
|  | rules.c | ||||||
							
								
								
									
										29
									
								
								util/make/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								util/make/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | # Makefile for make!
 | ||||||
|  | EMHOME=../.. | ||||||
|  | 
 | ||||||
|  | OBJS	=	check.o input.o macro.o main.o \
 | ||||||
|  | 		make.o reader.o rules.o | ||||||
|  | # unix not defined under Xenix ???
 | ||||||
|  | CFLAGS = -Dunix	 | ||||||
|  | 
 | ||||||
|  | all:	make | ||||||
|  | 
 | ||||||
|  | install: make | ||||||
|  | 	cp make $(EMHOME)/bin/make | ||||||
|  | 
 | ||||||
|  | cmp:	make | ||||||
|  | 	cmp make $(EMHOME)/bin/make | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -f *.o make | ||||||
|  | 
 | ||||||
|  | pr: | ||||||
|  | 	@pr README Makefile h.h main.c check.c input.c macro.c make.c reader.c rules.c | ||||||
|  | 
 | ||||||
|  | opr: | ||||||
|  | 	make pr ^ opr | ||||||
|  | 
 | ||||||
|  | make:	$(OBJS) | ||||||
|  | 	$(CC) -i -o make $(OBJS) | ||||||
|  | 
 | ||||||
|  | $(OBJS):	h.h | ||||||
							
								
								
									
										42
									
								
								util/make/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								util/make/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | Following is a repost of the public domain 'make' that I posted | ||||||
|  | to net.sources a couple of months ago.  I have fixed a few bugs, and | ||||||
|  | added some more features, and the resulting changes amounted to | ||||||
|  | about as much text as the whole program (hence the repost). | ||||||
|  | 
 | ||||||
|  | For those that missed the net.sources posting, this is a public domain | ||||||
|  | re-implementation of the UNIX make program.  There is no manual included; | ||||||
|  | for documentation, refer to a UNIX manual, or the source. | ||||||
|  | 
 | ||||||
|  | Here is a list of the changes made: | ||||||
|  | 
 | ||||||
|  | i)	If '-' (ignore) or '@' (silent) where used at the start | ||||||
|  | 	of a command, their effect was not turned off for the following | ||||||
|  | 	commands. | ||||||
|  | ii)	A special target (.SUFFIXES, .PRECIOUS) or a rule (.c.o, .a.o), | ||||||
|  | 	if first in the file would be taken as the default target. | ||||||
|  | 	This resulted in error messages like "Don't know how to | ||||||
|  | 	make .c", because things like .SUFFIXES were being made. | ||||||
|  | 	This was further complicated by --- | ||||||
|  | iii)	Special target lines with no dependents (ie. .SUFFIXES:\n) | ||||||
|  | 	were not clearing out the existing dependents like | ||||||
|  | 	they should. | ||||||
|  | iv)	Default rules could not be redefined because of the error | ||||||
|  | 	checking for commands being defined twice.  Now you are | ||||||
|  | 	allowed to define a target beinging with '.', having | ||||||
|  | 	no dependents with commands. | ||||||
|  | v)	The -q option didn't do the time comparison correctly, | ||||||
|  | 	or clear the variable used to keep track of this.  Thus | ||||||
|  | 	it didn't work very well. | ||||||
|  | vi)	The syntax ${..} for macro's supported by UNIX make was | ||||||
|  | 	not supported. | ||||||
|  | vii)	There wuz a couple of spelling errors. | ||||||
|  | viii)	When make checked for implicit rules on targets without | ||||||
|  | 	a suffix, there were problems.  (Note: The ~ feature of | ||||||
|  | 	UNIX make wasn't and still isn't supported) | ||||||
|  | ix)	The -n option did not print @ lines like it was supposed to. | ||||||
|  | x)	:: added.  (See UNIX manual) | ||||||
|  | xi)	$? added.  (see UNIX manual) | ||||||
|  | 
 | ||||||
|  | Hacked further by Ceriel Jacobs to make it work better. Use this "make" to | ||||||
|  | install ACK under Microsoft Xenix V3.2. Some of the makefiles are just too | ||||||
|  | big for the Xenix "make". Strange, they work on a PDP-11 ... | ||||||
							
								
								
									
										117
									
								
								util/make/check.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								util/make/check.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | ||||||
|  | /*
 | ||||||
|  |  *	Check structures for make. | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include "h.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Prints out the structures as defined in memory.  Good for check | ||||||
|  |  *	that you make file does what you want (and for debugging make). | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | prt() | ||||||
|  | { | ||||||
|  | 	register struct name *		np; | ||||||
|  | 	register struct depend *	dp; | ||||||
|  | 	register struct line *		lp; | ||||||
|  | 	register struct cmd *		cp; | ||||||
|  | 	register struct macro *		mp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	for (mp = macrohead; mp; mp = mp->m_next) | ||||||
|  | 		fprintf(stderr, "%s = %s\n", mp->m_name, mp->m_val); | ||||||
|  | 
 | ||||||
|  | 	fputc('\n', stderr); | ||||||
|  | 
 | ||||||
|  | 	for (np = namehead.n_next; np; np = np->n_next) | ||||||
|  | 	{ | ||||||
|  | 		if (np->n_flag & N_DOUBLE) | ||||||
|  | 			fprintf(stderr, "%s::\n", np->n_name); | ||||||
|  | 		else | ||||||
|  | 			fprintf(stderr, "%s:\n", np->n_name); | ||||||
|  | 		if (np == firstname) | ||||||
|  | 			fprintf(stderr, "(MAIN NAME)\n"); | ||||||
|  | 		for (lp = np->n_line; lp; lp = lp->l_next) | ||||||
|  | 		{ | ||||||
|  | 			fputc(':', stderr); | ||||||
|  | 			for (dp = lp->l_dep; dp; dp = dp->d_next) | ||||||
|  | 				fprintf(stderr, " %s", dp->d_name->n_name); | ||||||
|  | 			fputc('\n', stderr); | ||||||
|  | 
 | ||||||
|  | 			for (cp = lp->l_cmd; cp; cp = cp->c_next) | ||||||
|  | #ifdef os9 | ||||||
|  | 				fprintf(stderr, "-   %s\n", cp->c_cmd); | ||||||
|  | #else | ||||||
|  | 				fprintf(stderr, "-\t%s\n", cp->c_cmd); | ||||||
|  | #endif | ||||||
|  | 			fputc('\n', stderr); | ||||||
|  | 		} | ||||||
|  | 		fputc('\n', stderr); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Recursive routine that does the actual checking. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | check(np) | ||||||
|  | struct name *		np; | ||||||
|  | { | ||||||
|  | 	register struct depend *	dp; | ||||||
|  | 	register struct line *		lp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (np->n_flag & N_MARK) | ||||||
|  | 		fatal("Circular dependency from %s", np->n_name); | ||||||
|  | 
 | ||||||
|  | 	np->n_flag |= N_MARK; | ||||||
|  | 
 | ||||||
|  | 	for (lp = np->n_line; lp; lp = lp->l_next) | ||||||
|  | 		for (dp = lp->l_dep; dp; dp = dp->d_next) | ||||||
|  | 			check(dp->d_name); | ||||||
|  | 
 | ||||||
|  | 	np->n_flag &= ~N_MARK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Look for circular dependancies. | ||||||
|  |  *	ie. | ||||||
|  |  *		a: b | ||||||
|  |  *		b: a | ||||||
|  |  *	is a circular dep | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | circh() | ||||||
|  | { | ||||||
|  | 	register struct name *	np; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	for (np = namehead.n_next; np; np = np->n_next) | ||||||
|  | 		check(np); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Check the target .PRECIOUS, and mark its dependentd as precious | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | precious() | ||||||
|  | { | ||||||
|  | 	register struct depend *	dp; | ||||||
|  | 	register struct line *		lp; | ||||||
|  | 	register struct name *		np; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG)) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	for (lp = np->n_line; lp; lp = lp->l_next) | ||||||
|  | 		for (dp = lp->l_dep; dp; dp = dp->d_next) | ||||||
|  | 			dp->d_name->n_flag |= N_PREC; | ||||||
|  | } | ||||||
							
								
								
									
										145
									
								
								util/make/h.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								util/make/h.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,145 @@ | ||||||
|  | /*
 | ||||||
|  |  *	Include header for make | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifndef uchar | ||||||
|  | #ifdef os9 | ||||||
|  | #define uchar		char | ||||||
|  | #define void		int | ||||||
|  | #define fputc		putc | ||||||
|  | #else | ||||||
|  | #define uchar		unsigned char | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define bool		int | ||||||
|  | #define time_t		long | ||||||
|  | #define TRUE		(1) | ||||||
|  | #define FALSE		(0) | ||||||
|  | #define max(a,b)	((a)>(b)?(a):(b)) | ||||||
|  | 
 | ||||||
|  | #define DEFN1		"makefile"		/*  Default names  */ | ||||||
|  | #ifdef unix | ||||||
|  | #define DEFN2		"Makefile" | ||||||
|  | #endif | ||||||
|  | #ifdef eon | ||||||
|  | #define DEFN2		"Makefile" | ||||||
|  | #endif | ||||||
|  | /* os9 is case insensitive */ | ||||||
|  | 
 | ||||||
|  | #define LZ		(2048)			/*  Line size  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	A name.  This represents a file, either to be made, or existant | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | struct name | ||||||
|  | { | ||||||
|  | 	struct name *		n_next;		/* Next in the list of names */ | ||||||
|  | 	char *			n_name;		/* Called */ | ||||||
|  | 	struct line *		n_line;		/* Dependencies */ | ||||||
|  | 	time_t			n_time;		/* Modify time of this name */ | ||||||
|  | 	uchar			n_flag;		/* Info about the name */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define N_MARK		0x01			/* For cycle check */ | ||||||
|  | #define N_DONE		0x02			/* Name looked at */ | ||||||
|  | #define N_TARG		0x04			/* Name is a target */ | ||||||
|  | #define N_PREC		0x08			/* Target is precious */ | ||||||
|  | #define N_DOUBLE	0x10			/* Double colon target */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Definition of a target line. | ||||||
|  |  */ | ||||||
|  | struct	line | ||||||
|  | { | ||||||
|  | 	struct line *		l_next;		/* Next line (for ::) */ | ||||||
|  | 	struct depend *		l_dep;		/* Dependents for this line */ | ||||||
|  | 	struct cmd *		l_cmd;		/* Commands for this line */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	List of dependents for a line | ||||||
|  |  */ | ||||||
|  | struct	depend | ||||||
|  | { | ||||||
|  | 	struct depend *		d_next;		/* Next dependent */ | ||||||
|  | 	struct name *		d_name;		/* Name of dependent */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Commands for a line | ||||||
|  |  */ | ||||||
|  | struct	cmd | ||||||
|  | { | ||||||
|  | 	struct cmd *		c_next;		/* Next command line */ | ||||||
|  | 	char *			c_cmd;		/* Command line */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Macro storage | ||||||
|  |  */ | ||||||
|  | struct	macro | ||||||
|  | { | ||||||
|  | 	struct macro *	m_next;		/* Next variable */ | ||||||
|  | 	char *		m_name;		/* Called ... */ | ||||||
|  | 	char *		m_val;		/* Its value */ | ||||||
|  | 	uchar		m_flag;		/* Infinite loop check */ | ||||||
|  | 	uchar		m_prio;		/* 5 levels:
 | ||||||
|  | 					   - 0 for internal ($(CC), etc) | ||||||
|  | 					   - 1 (reserved for environment) | ||||||
|  | 					   - 2 for makefile | ||||||
|  | 					   - 3 for command line | ||||||
|  | 					   - 4 for special ($*,$<, etc) | ||||||
|  | 					*/ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern char *		myname; | ||||||
|  | extern struct name	namehead; | ||||||
|  | extern struct macro *	macrohead; | ||||||
|  | extern struct name *	firstname; | ||||||
|  | extern bool		silent; | ||||||
|  | extern bool		ignore; | ||||||
|  | extern bool		rules; | ||||||
|  | extern bool		dotouch; | ||||||
|  | extern bool		quest; | ||||||
|  | extern bool		domake; | ||||||
|  | extern char		str1[]; | ||||||
|  | extern char		str2[]; | ||||||
|  | extern int		lineno; | ||||||
|  | 
 | ||||||
|  | char *			fgets(); | ||||||
|  | char *			index(); | ||||||
|  | char *			rindex(); | ||||||
|  | char *			malloc(); | ||||||
|  | char *			strcpy(); | ||||||
|  | char *			strcat(); | ||||||
|  | extern int		errno; | ||||||
|  | 
 | ||||||
|  | void			circh(); | ||||||
|  | char *			getmacro(); | ||||||
|  | struct macro *		setmacro(); | ||||||
|  | void			input(); | ||||||
|  | void			error(); | ||||||
|  | void			expand(); | ||||||
|  | void			fatal(); | ||||||
|  | int			make(); | ||||||
|  | void			modtime(); | ||||||
|  | struct name *		newname(); | ||||||
|  | struct depend *		newdep(); | ||||||
|  | struct cmd *		newcmd(); | ||||||
|  | void			newline(); | ||||||
|  | void			prt(); | ||||||
|  | char *			suffix(); | ||||||
|  | void			touch(); | ||||||
|  | void			makerules(); | ||||||
|  | char *			gettok(); | ||||||
|  | void			precious(); | ||||||
							
								
								
									
										342
									
								
								util/make/input.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								util/make/input.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,342 @@ | ||||||
|  | /*
 | ||||||
|  |  *	Parse a makefile | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include	<ctype.h> | ||||||
|  | #include "h.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | struct name		namehead; | ||||||
|  | struct name *		firstname; | ||||||
|  | 
 | ||||||
|  | char 			str1[LZ];		/*  General store  */ | ||||||
|  | char			str2[LZ]; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Intern a name.  Return a pointer to the name struct | ||||||
|  |  */ | ||||||
|  | struct name * | ||||||
|  | newname(name) | ||||||
|  | char *			name; | ||||||
|  | { | ||||||
|  | 	register struct name *	rp; | ||||||
|  | 	register struct name *	rrp; | ||||||
|  | 	register char *		cp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	for | ||||||
|  | 	( | ||||||
|  | 		rp = namehead.n_next, rrp = &namehead; | ||||||
|  | 		rp; | ||||||
|  | 		rp = rp->n_next, rrp = rrp->n_next | ||||||
|  | 	) | ||||||
|  | 		if (strcmp(name, rp->n_name) == 0) | ||||||
|  | 			return rp; | ||||||
|  | 
 | ||||||
|  | 	if ((rp = (struct name *)malloc(sizeof (struct name))) | ||||||
|  | 				== (struct name *)0) | ||||||
|  | 		fatal("No memory for name"); | ||||||
|  | 	rrp->n_next = rp; | ||||||
|  | 	rp->n_next = (struct name *)0; | ||||||
|  | 	if ((cp = malloc((unsigned)(strlen(name)+1))) == (char *)0) | ||||||
|  | 		fatal("No memory for name"); | ||||||
|  | 	strcpy(cp, name); | ||||||
|  | 	rp->n_name = cp; | ||||||
|  | 	rp->n_line = (struct line *)0; | ||||||
|  | 	rp->n_time = (time_t)0; | ||||||
|  | 	rp->n_flag = 0; | ||||||
|  | 
 | ||||||
|  | 	return rp; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Add a dependant to the end of the supplied list of dependants. | ||||||
|  |  *	Return the new head pointer for that list. | ||||||
|  |  */ | ||||||
|  | struct depend * | ||||||
|  | newdep(np, dp) | ||||||
|  | struct name *		np; | ||||||
|  | struct depend *		dp; | ||||||
|  | { | ||||||
|  | 	register struct depend *	rp; | ||||||
|  | 	register struct depend *	rrp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if ((rp = (struct depend *)malloc(sizeof (struct depend))) | ||||||
|  | 				== (struct depend *)0) | ||||||
|  | 		fatal("No memory for dependant"); | ||||||
|  | 	rp->d_next = (struct depend *)0; | ||||||
|  | 	rp->d_name = np; | ||||||
|  | 
 | ||||||
|  | 	if (dp == (struct depend *)0) | ||||||
|  | 		return rp; | ||||||
|  | 
 | ||||||
|  | 	for (rrp = dp; rrp->d_next; rrp = rrp->d_next) | ||||||
|  | 		; | ||||||
|  | 
 | ||||||
|  | 	rrp->d_next = rp; | ||||||
|  | 
 | ||||||
|  | 	return dp; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Add a command to the end of the supplied list of commands. | ||||||
|  |  *	Return the new head pointer for that list. | ||||||
|  |  */ | ||||||
|  | struct cmd * | ||||||
|  | newcmd(str, cp) | ||||||
|  | char *			str; | ||||||
|  | struct cmd *		cp; | ||||||
|  | { | ||||||
|  | 	register struct cmd *	rp; | ||||||
|  | 	register struct cmd *	rrp; | ||||||
|  | 	register char *		rcp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (rcp = rindex(str, '\n')) | ||||||
|  | 		*rcp = '\0';		/*  Loose newline  */ | ||||||
|  | 
 | ||||||
|  | 	while (isspace(*str)) | ||||||
|  | 		str++; | ||||||
|  | 
 | ||||||
|  | 	if (*str == '\0')		/*  If nothing left, the exit  */ | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	if ((rp = (struct cmd *)malloc(sizeof (struct cmd))) | ||||||
|  | 				== (struct cmd *)0) | ||||||
|  | 		fatal("No memory for command"); | ||||||
|  | 	rp->c_next = (struct cmd *)0; | ||||||
|  | 	if ((rcp = malloc((unsigned)(strlen(str)+1))) == (char *)0) | ||||||
|  | 		fatal("No memory for command"); | ||||||
|  | 	strcpy(rcp, str); | ||||||
|  | 	rp->c_cmd = rcp; | ||||||
|  | 
 | ||||||
|  | 	if (cp == (struct cmd *)0) | ||||||
|  | 		return rp; | ||||||
|  | 
 | ||||||
|  | 	for (rrp = cp; rrp->c_next; rrp = rrp->c_next) | ||||||
|  | 		; | ||||||
|  | 
 | ||||||
|  | 	rrp->c_next = rp; | ||||||
|  | 
 | ||||||
|  | 	return cp; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Add a new 'line' of stuff to a target.  This check to see | ||||||
|  |  *	if commands already exist for the target.  If flag is set, | ||||||
|  |  *	the line is a double colon target. | ||||||
|  |  * | ||||||
|  |  *	Kludges: | ||||||
|  |  *	i)  If the new name begins with a '.', and there are no dependents, | ||||||
|  |  *	    then the target must cease to be a target.  This is for .SUFFIXES. | ||||||
|  |  *	ii) If the new name begins with a '.', with no dependents and has | ||||||
|  |  *	    commands, then replace the current commands.  This is for | ||||||
|  |  *	    redefining commands for a default rule. | ||||||
|  |  *	Neither of these free the space used by dependents or commands, | ||||||
|  |  *	since they could be used by another target. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | newline(np, dp, cp, flag) | ||||||
|  | struct name *		np; | ||||||
|  | struct depend *		dp; | ||||||
|  | struct cmd *		cp; | ||||||
|  | { | ||||||
|  | 	bool			hascmds = FALSE;  /*  Target has commands  */ | ||||||
|  | 	register struct line *	rp; | ||||||
|  | 	register struct line *	rrp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	/* Handle the .SUFFIXES case */ | ||||||
|  | 	if (! strcmp(np->n_name, ".SUFFIXES") && !dp && !cp) | ||||||
|  | 	{ | ||||||
|  | 		for (rp = np->n_line; rp; rp = rrp) | ||||||
|  | 		{ | ||||||
|  | 			rrp = rp->l_next; | ||||||
|  | 			free((char *)rp); | ||||||
|  | 		} | ||||||
|  | 		np->n_line = (struct line *)0; | ||||||
|  | 		np->n_flag &= ~N_TARG; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* This loop must happen since rrp is used later. */ | ||||||
|  | 	for | ||||||
|  | 	( | ||||||
|  | 		rp = np->n_line, rrp = (struct line *)0; | ||||||
|  | 		rp; | ||||||
|  | 		rrp = rp, rp = rp->l_next | ||||||
|  | 	) | ||||||
|  | 		if (rp->l_cmd) | ||||||
|  | 			hascmds = TRUE; | ||||||
|  | 
 | ||||||
|  | 	if (hascmds && cp && !(np->n_flag & N_DOUBLE)) | ||||||
|  | 		/* Handle the implicit rules redefinition case */ | ||||||
|  | 		if (np->n_name[0] == '.' && dp == (struct depend *)0) | ||||||
|  | 		{ | ||||||
|  | 			np->n_line->l_cmd = cp; | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			error("Commands defined twice for target %s", np->n_name); | ||||||
|  | 	if (np->n_flag & N_TARG) | ||||||
|  | 		if (!(np->n_flag & N_DOUBLE) != !flag)		/* like xor */ | ||||||
|  | 			error("Inconsistent rules for target %s", np->n_name); | ||||||
|  | 
 | ||||||
|  | 	if ((rp = (struct line *)malloc(sizeof (struct line))) | ||||||
|  | 				== (struct line *)0) | ||||||
|  | 		fatal("No memory for line"); | ||||||
|  | 	rp->l_next = (struct line *)0; | ||||||
|  | 	rp->l_dep = dp; | ||||||
|  | 	rp->l_cmd = cp; | ||||||
|  | 
 | ||||||
|  | 	if (rrp) | ||||||
|  | 		rrp->l_next = rp; | ||||||
|  | 	else | ||||||
|  | 		np->n_line = rp; | ||||||
|  | 
 | ||||||
|  | 	np->n_flag |= N_TARG; | ||||||
|  | 	if (flag) | ||||||
|  | 		np->n_flag |= N_DOUBLE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Parse input from the makefile, and construct a tree structure | ||||||
|  |  *	of it. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | input(fd) | ||||||
|  | FILE *			fd; | ||||||
|  | { | ||||||
|  | 	char *			p;		/*  General  */ | ||||||
|  | 	char *			q; | ||||||
|  | 	struct name *		np; | ||||||
|  | 	struct depend *		dp; | ||||||
|  | 	struct cmd *		cp; | ||||||
|  | 	bool			dbl; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (getline(str1, fd))	/*  Read the first line  */ | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	for(;;) | ||||||
|  | 	{ | ||||||
|  | #ifdef os9 | ||||||
|  | 		if (*str1 == ' ')	/*  Rules without targets  */ | ||||||
|  | #else | ||||||
|  | 		if (*str1 == '\t')	/*  Rules without targets  */ | ||||||
|  | #endif | ||||||
|  | 			error("Rules not allowed here"); | ||||||
|  | 
 | ||||||
|  | 		p = str1; | ||||||
|  | 
 | ||||||
|  | 		while (isspace(*p))	/*  Find first target  */ | ||||||
|  | 			p++; | ||||||
|  | 
 | ||||||
|  | 		while (((q = index(p, '=')) != (char *)0) && | ||||||
|  | 		    (p != q) && (q[-1] == '\\'))	/*  Find value */ | ||||||
|  | 		{ | ||||||
|  | 			register char *		a; | ||||||
|  | 
 | ||||||
|  | 			a = q - 1;	/*  Del \ chr; move rest back  */ | ||||||
|  | 			p = q; | ||||||
|  | 			while(*a++ = *q++) | ||||||
|  | 				; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (q != (char *)0) | ||||||
|  | 		{ | ||||||
|  | 			register char *		a; | ||||||
|  | 
 | ||||||
|  | 			*q++ = '\0';		/*  Separate name and val  */ | ||||||
|  | 			while (isspace(*q)) | ||||||
|  | 				q++; | ||||||
|  | 			if (p = rindex(q, '\n')) | ||||||
|  | 				*p = '\0'; | ||||||
|  | 
 | ||||||
|  | 			p = str1; | ||||||
|  | 			if ((a = gettok(&p)) == (char *)0) | ||||||
|  | 				error("No macro name"); | ||||||
|  | 
 | ||||||
|  | 			setmacro(a, q, 2); | ||||||
|  | 
 | ||||||
|  | 			if (getline(str1, fd)) | ||||||
|  | 				return; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		expand(str1); | ||||||
|  | 		p = str1; | ||||||
|  | 
 | ||||||
|  | 		while (((q = index(p, ':')) != (char *)0) && | ||||||
|  | 		    (p != q) && (q[-1] == '\\'))	/*  Find dependents  */ | ||||||
|  | 		{ | ||||||
|  | 			register char *		a; | ||||||
|  | 
 | ||||||
|  | 			a = q - 1;	/*  Del \ chr; move rest back  */ | ||||||
|  | 			p = q; | ||||||
|  | 			while(*a++ = *q++) | ||||||
|  | 				; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (q == (char *)0) | ||||||
|  | 			error("No targets provided"); | ||||||
|  | 
 | ||||||
|  | 		*q++ = '\0';	/*  Separate targets and dependents  */ | ||||||
|  | 
 | ||||||
|  | 		if (*q == ':')		/* Double colon */ | ||||||
|  | 		{ | ||||||
|  | 			dbl = 1; | ||||||
|  | 			q++; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			dbl = 0; | ||||||
|  | 
 | ||||||
|  | 		for (dp = (struct depend *)0; ((p = gettok(&q)) != (char *)0);) | ||||||
|  | 					/*  get list of dep's */ | ||||||
|  | 		{ | ||||||
|  | 			np = newname(p);		/*  Intern name  */ | ||||||
|  | 			dp = newdep(np, dp);		/*  Add to dep list */ | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		*((q = str1) + strlen(str1) + 1) = '\0'; | ||||||
|  | 			/*  Need two nulls for gettok (Remember separation)  */ | ||||||
|  | 
 | ||||||
|  | 		cp = (struct cmd *)0; | ||||||
|  | 		if (getline(str2, fd) == FALSE)		/*  Get commands  */ | ||||||
|  | 		{ | ||||||
|  | #ifdef os9 | ||||||
|  | 			while (*str2 == ' ') | ||||||
|  | #else | ||||||
|  | 			while (*str2 == '\t') | ||||||
|  | #endif | ||||||
|  | 			{ | ||||||
|  | 				cp = newcmd(&str2[0], cp); | ||||||
|  | 				if (getline(str2, fd)) | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		while ((p = gettok(&q)) != (char *)0)	/* Get list of targ's */ | ||||||
|  | 		{ | ||||||
|  | 			np = newname(p);		/*  Intern name  */ | ||||||
|  | 			newline(np, dp, cp, dbl); | ||||||
|  | 			if (!firstname && p[0] != '.') | ||||||
|  | 				firstname = np; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (feof(fd))				/*  EOF?  */ | ||||||
|  | 			return; | ||||||
|  | 
 | ||||||
|  | 		strcpy(str1, str2); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										167
									
								
								util/make/macro.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								util/make/macro.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,167 @@ | ||||||
|  | /*
 | ||||||
|  |  *	Macro control for make | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #include "h.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | struct macro *		macrohead; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | struct macro * | ||||||
|  | getmp(name) | ||||||
|  | char *			name; | ||||||
|  | { | ||||||
|  | 	register struct macro *	rp; | ||||||
|  | 
 | ||||||
|  | 	for (rp = macrohead; rp; rp = rp->m_next) | ||||||
|  | 		if (strcmp(name, rp->m_name) == 0) | ||||||
|  | 			return rp; | ||||||
|  | 	return (struct macro *)0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | getmacro(name) | ||||||
|  | char *			name; | ||||||
|  | { | ||||||
|  | 	struct macro *		mp; | ||||||
|  | 
 | ||||||
|  | 	if (mp = getmp(name)) | ||||||
|  | 		return mp->m_val; | ||||||
|  | 	else | ||||||
|  | 		return ""; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | struct macro * | ||||||
|  | setmacro(name, val, prio) | ||||||
|  | char *			name; | ||||||
|  | char *			val; | ||||||
|  | { | ||||||
|  | 	register struct macro *	rp; | ||||||
|  | 	register char *		cp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 			/*  Replace macro definition if it exists  */ | ||||||
|  | 	for (rp = macrohead; rp; rp = rp->m_next) | ||||||
|  | 		if (strcmp(name, rp->m_name) == 0) | ||||||
|  | 		{ | ||||||
|  | 			if (prio < rp->m_prio) | ||||||
|  | 				return rp; | ||||||
|  | 			free(rp->m_val);	/*  Free space from old  */ | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	if (!rp)		/*  If not defined, allocate space for new  */ | ||||||
|  | 	{ | ||||||
|  | 		if ((rp = (struct macro *)malloc(sizeof (struct macro))) | ||||||
|  | 					 == (struct macro *)0) | ||||||
|  | 			fatal("No memory for macro"); | ||||||
|  | 
 | ||||||
|  | 		rp->m_next = macrohead; | ||||||
|  | 		macrohead = rp; | ||||||
|  | 		rp->m_flag = FALSE; | ||||||
|  | 
 | ||||||
|  | 		if ((cp = malloc((unsigned)(strlen(name)+1))) == (char *)0) | ||||||
|  | 			fatal("No memory for macro"); | ||||||
|  | 		strcpy(cp, name); | ||||||
|  | 		rp->m_name = cp; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((cp = malloc((unsigned)(strlen(val)+1))) == (char *)0) | ||||||
|  | 		fatal("No memory for macro"); | ||||||
|  | 	strcpy(cp, val);		/*  Copy in new value  */ | ||||||
|  | 	rp->m_val = cp; | ||||||
|  | 	rp->m_prio = prio; | ||||||
|  | 
 | ||||||
|  | 	return rp; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define MBUFSIZ	128 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Do the dirty work for expand | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | doexp(to, from, len, buf) | ||||||
|  | char **			to; | ||||||
|  | char *			from; | ||||||
|  | int *			len; | ||||||
|  | char *			buf; | ||||||
|  | { | ||||||
|  | 	register char *		rp; | ||||||
|  | 	register char *		p; | ||||||
|  | 	register char *		q; | ||||||
|  | 	register struct macro *	mp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	rp = from; | ||||||
|  | 	p = *to; | ||||||
|  | 	while (*rp) | ||||||
|  | 	{ | ||||||
|  | 		if (*rp != '$') | ||||||
|  | 		{ | ||||||
|  | 			*p++ = *rp++; | ||||||
|  | 			(*len)--; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			q = buf; | ||||||
|  | 			if (*++rp == '{') | ||||||
|  | 				while (*++rp && *rp != '}') { | ||||||
|  | 					if (q < &buf[MBUFSIZ-1]) *q++ = *rp; | ||||||
|  | 				} | ||||||
|  | 			else if (*rp == '(') | ||||||
|  | 				while (*++rp && *rp != ')') { | ||||||
|  | 					if (q < &buf[MBUFSIZ-1]) *q++ = *rp; | ||||||
|  | 				} | ||||||
|  | 			else if (!*rp) | ||||||
|  | 			{ | ||||||
|  | 				*p++ = '$'; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 				*q++ = *rp; | ||||||
|  | 			*q = '\0'; | ||||||
|  | 			if (*rp) | ||||||
|  | 				rp++; | ||||||
|  | 			if (!(mp = getmp(buf))) | ||||||
|  | 				mp = setmacro(buf, "", 2); | ||||||
|  | 			if (mp->m_flag) | ||||||
|  | 				fatal("Infinitely recursive macro %s", mp->m_name); | ||||||
|  | 			mp->m_flag = TRUE; | ||||||
|  | 			*to = p; | ||||||
|  | 			doexp(to, mp->m_val, len, buf); | ||||||
|  | 			p = *to; | ||||||
|  | 			mp->m_flag = FALSE; | ||||||
|  | 		} | ||||||
|  | 		if (*len <= 0) | ||||||
|  | 			error("Expanded line too line"); | ||||||
|  | 	} | ||||||
|  | 	*p = '\0'; | ||||||
|  | 	*to = p; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Expand any macros in str. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | expand(str) | ||||||
|  | char *		str; | ||||||
|  | { | ||||||
|  | 	char			*a; | ||||||
|  | 	static char		b[MBUFSIZ];	/* temp storage for macroname */ | ||||||
|  | 	char *			p = str; | ||||||
|  | 	int			len = LZ-1; | ||||||
|  | 
 | ||||||
|  | 	a = malloc((unsigned)(strlen(str)+1)); | ||||||
|  | 	if (!a) fatal("No memory for expand"); | ||||||
|  | 	strcpy(a, str); | ||||||
|  | 	doexp(&p, a, &len, b); | ||||||
|  | 	free(a); | ||||||
|  | } | ||||||
							
								
								
									
										261
									
								
								util/make/main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								util/make/main.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,261 @@ | ||||||
|  | /*
 | ||||||
|  |  *	make [-f makefile] [-ins] [target(s) ...] | ||||||
|  |  * | ||||||
|  |  *	(Better than EON mk but not quite as good as UNIX make) | ||||||
|  |  * | ||||||
|  |  *	-f makefile name | ||||||
|  |  *	-i ignore exit status | ||||||
|  |  *	-n Pretend to make | ||||||
|  |  *	-p Print all macros & targets | ||||||
|  |  *	-q Question up-to-dateness of target.  Return exit status 1 if not | ||||||
|  |  *	-r Don't not use inbuilt rules | ||||||
|  |  *	-s Make silently | ||||||
|  |  *	-t Touch files instead of making them | ||||||
|  |  *	-m Change memory requirements (EON only) | ||||||
|  |  *	-k For the time being: accept but ignore | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include "h.h" | ||||||
|  | 
 | ||||||
|  | #ifdef unix | ||||||
|  | #include <errno.h> | ||||||
|  | #endif | ||||||
|  | #ifdef eon | ||||||
|  | #include <sys/err.h> | ||||||
|  | #endif | ||||||
|  | #ifdef os9 | ||||||
|  | #include <errno.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifdef eon | ||||||
|  | #define MEMSPACE	(16384) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | char *			myname; | ||||||
|  | char *			makefile;	/*  The make file  */ | ||||||
|  | #ifdef eon | ||||||
|  | unsigned		memspace = MEMSPACE; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | FILE *			ifd;		/*  Input file desciptor  */ | ||||||
|  | bool			domake = TRUE;	/*  Go through the motions option  */ | ||||||
|  | bool			ignore = FALSE;	/*  Ignore exit status option  */ | ||||||
|  | bool			silent = FALSE;	/*  Silent option  */ | ||||||
|  | bool			print = FALSE;	/*  Print debuging information  */ | ||||||
|  | bool			rules = TRUE;	/*  Use inbuilt rules  */ | ||||||
|  | bool			dotouch = FALSE;/*  Touch files instead of making  */ | ||||||
|  | bool			quest = FALSE;	/*  Question up-to-dateness of file  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | main(argc, argv) | ||||||
|  | int			argc; | ||||||
|  | char **			argv; | ||||||
|  | { | ||||||
|  | 	register char *		p;		/*  For argument processing  */ | ||||||
|  | 	int			estat = 0;	/*  For question  */ | ||||||
|  | 	register struct name *	np; | ||||||
|  | 	int			nargc = 0; | ||||||
|  | 	char			**nargv; | ||||||
|  | 	int			fflag = 0; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	myname = (argc-- < 1) ? "make" : *argv++; | ||||||
|  | 	nargv = argv; | ||||||
|  | 
 | ||||||
|  | 	while (argc > 0) | ||||||
|  | 	{ | ||||||
|  | 		argc--;		/*  One less to process  */ | ||||||
|  | 		p = *argv++;	/*  Now processing this one  */ | ||||||
|  | 
 | ||||||
|  | 		if (*p == '-') while (*++p != '\0') | ||||||
|  | 		{ | ||||||
|  | 			switch(*p) | ||||||
|  | 			{ | ||||||
|  | 			case 'f':	/*  Alternate file name  */ | ||||||
|  | 				fflag = 1; | ||||||
|  | 				break; | ||||||
|  | #ifdef eon | ||||||
|  | 			case 'm':	/*  Change space requirements  */ | ||||||
|  | 				if (*++p == '\0') | ||||||
|  | 				{ | ||||||
|  | 					if (argc-- <= 0) | ||||||
|  | 						usage(); | ||||||
|  | 					p = *argv++; | ||||||
|  | 				} | ||||||
|  | 				memspace = atoi(p); | ||||||
|  | 				goto end_of_args; | ||||||
|  | #endif | ||||||
|  | 			case 'n':	/*  Pretend mode  */ | ||||||
|  | 				domake = FALSE; | ||||||
|  | 				break; | ||||||
|  | 			case 'i':	/*  Ignore fault mode  */ | ||||||
|  | 				ignore = TRUE; | ||||||
|  | 				break; | ||||||
|  | 			case 's':	/*  Silent about commands  */ | ||||||
|  | 				silent = TRUE; | ||||||
|  | 				break; | ||||||
|  | 			case 'p': | ||||||
|  | 				print = TRUE; | ||||||
|  | 				break; | ||||||
|  | 			case 'r': | ||||||
|  | 				rules = FALSE; | ||||||
|  | 				break; | ||||||
|  | 			case 't': | ||||||
|  | 				dotouch = TRUE; | ||||||
|  | 				break; | ||||||
|  | 			case 'q': | ||||||
|  | 				quest = TRUE; | ||||||
|  | 				break; | ||||||
|  | 			case 'k': | ||||||
|  | 				break; | ||||||
|  | 			default:	/*  Wrong option  */ | ||||||
|  | 				usage(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			if (fflag) { | ||||||
|  | 				if (argc <= 0) usage(); | ||||||
|  | 				makefile = p; | ||||||
|  | 				fflag = 0; | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				nargc++; | ||||||
|  | 				*nargv++ = p; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	end_of_args:; | ||||||
|  | 	} | ||||||
|  | 	argv = nargv - nargc; | ||||||
|  | 	argc = nargc; | ||||||
|  | 
 | ||||||
|  | #ifdef eon | ||||||
|  | 	if (initalloc(memspace) == 0xffff)  /*  Must get memory for alloc  */ | ||||||
|  | 		fatal("Cannot initalloc memory"); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	if (makefile && strcmp(makefile, "-") == 0)	/*  Can use stdin as makefile  */ | ||||||
|  | 		ifd = stdin; | ||||||
|  | 	else | ||||||
|  | 		if (!makefile)		/*  If no file, then use default */ | ||||||
|  | 		{ | ||||||
|  | 			if ((ifd = fopen(DEFN1, "r")) == (FILE *)0) | ||||||
|  | #ifdef eon | ||||||
|  | 				if (errno != ER_NOTF) | ||||||
|  | 					fatal("Can't open %s; error %02x", DEFN1, errno); | ||||||
|  | #endif | ||||||
|  | #ifdef unix | ||||||
|  | 				if (errno != ENOENT) | ||||||
|  | 					fatal("Can't open %s; error %02x", DEFN1, errno); | ||||||
|  | #endif | ||||||
|  | #ifndef os9 | ||||||
|  | 			if ((ifd == (FILE *)0) | ||||||
|  | 				  && ((ifd = fopen(DEFN2, "r")) == (FILE *)0)) | ||||||
|  | 				fatal("Can't open %s", DEFN2); | ||||||
|  | #else | ||||||
|  | 				fatal("Can't open %s", DEFN1); | ||||||
|  | #endif | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			if ((ifd = fopen(makefile, "r")) == (FILE *)0) | ||||||
|  | 				fatal("Can't open %s", makefile); | ||||||
|  | 
 | ||||||
|  | 	makerules(); | ||||||
|  | 
 | ||||||
|  | 	setmacro("$", "$", 4); | ||||||
|  | 
 | ||||||
|  | 	while (argc && (p = index(*argv, '='))) | ||||||
|  | 	{ | ||||||
|  | 		char		c; | ||||||
|  | 
 | ||||||
|  | 		c = *p; | ||||||
|  | 		*p = '\0'; | ||||||
|  | 		setmacro(*argv, p+1, 3); | ||||||
|  | 		*p = c; | ||||||
|  | 
 | ||||||
|  | 		argv++; | ||||||
|  | 		argc--; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	input(ifd);	/*  Input all the gunga  */ | ||||||
|  | 	fclose(ifd);	/*  Finished with makefile  */ | ||||||
|  | 	lineno = 0;	/*  Any calls to error now print no line number */ | ||||||
|  | 
 | ||||||
|  | 	if (print) | ||||||
|  | 		prt();	/*  Print out structures  */ | ||||||
|  | 
 | ||||||
|  | 	np = newname(".SILENT"); | ||||||
|  | 	if (np->n_flag & N_TARG) | ||||||
|  | 		silent = TRUE; | ||||||
|  | 
 | ||||||
|  | 	np = newname(".IGNORE"); | ||||||
|  | 	if (np->n_flag & N_TARG) | ||||||
|  | 		ignore = TRUE; | ||||||
|  | 
 | ||||||
|  | 	precious(); | ||||||
|  | 
 | ||||||
|  | 	if (!firstname) | ||||||
|  | 		fatal("No targets defined"); | ||||||
|  | 
 | ||||||
|  | 	circh();	/*  Check circles in target definitions  */ | ||||||
|  | 
 | ||||||
|  | 	if (!argc) | ||||||
|  | 		estat = make(firstname, 0); | ||||||
|  | 	else while (argc--) | ||||||
|  | 	{ | ||||||
|  | 		if (!print && !silent && strcmp(*argv, "love") == 0) | ||||||
|  | 			printf("Not war!\n"); | ||||||
|  | 		estat |= make(newname(*argv++), 0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (quest) | ||||||
|  | 		exit(estat); | ||||||
|  | 	else | ||||||
|  | 		exit(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | usage() | ||||||
|  | { | ||||||
|  | 	fprintf(stderr, "Usage: %s [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n", myname); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*VARARGS1*/ | ||||||
|  | void | ||||||
|  | fatal(msg, a1, a2, a3, a4, a5, a6) | ||||||
|  | char	*msg; | ||||||
|  | { | ||||||
|  | 	fprintf(stderr, "%s: ", myname); | ||||||
|  | 	fprintf(stderr, msg, a1, a2, a3, a4, a5, a6); | ||||||
|  | 	fputc('\n', stderr); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | index(s, c) | ||||||
|  | 	register char *s, c; | ||||||
|  | { | ||||||
|  | 	while (*s) | ||||||
|  | 		if (*s++ == c) | ||||||
|  | 			return --s; | ||||||
|  | 	return (char *)0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | rindex(str, chr) | ||||||
|  | 	register char *str, chr; | ||||||
|  | { | ||||||
|  | 	register char *retptr = 0; | ||||||
|  | 
 | ||||||
|  | 	while (*str) | ||||||
|  | 		if (*str++ == chr) | ||||||
|  | 			retptr = &str[-1]; | ||||||
|  | 	return retptr; | ||||||
|  | } | ||||||
							
								
								
									
										482
									
								
								util/make/make.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										482
									
								
								util/make/make.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,482 @@ | ||||||
|  | /*
 | ||||||
|  |  *	Do the actual making for make | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #ifdef unix | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #endif | ||||||
|  | #ifdef eon | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <sys/err.h> | ||||||
|  | #endif | ||||||
|  | #ifdef os9 | ||||||
|  | #include <time.h> | ||||||
|  | #include <os9.h> | ||||||
|  | #include <modes.h> | ||||||
|  | #include <direct.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #endif | ||||||
|  | #include "h.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Exec a shell that returns exit status correctly (/bin/esh). | ||||||
|  |  *	The standard EON shell returns the process number of the last | ||||||
|  |  *	async command, used by the debugger (ugg). | ||||||
|  |  *	[exec on eon is like a fork+exec on unix] | ||||||
|  |  */ | ||||||
|  | int | ||||||
|  | dosh(string, shell) | ||||||
|  | char *			string; | ||||||
|  | char *			shell; | ||||||
|  | { | ||||||
|  | 	int	number; | ||||||
|  | 
 | ||||||
|  | #ifdef unix | ||||||
|  | 	return system(string); | ||||||
|  | #endif | ||||||
|  | #ifdef eon | ||||||
|  | 	return ((number = execl(shell, shell,"-c", string, 0)) == -1) ? | ||||||
|  | 		-1:	/* couldn't start the shell */ | ||||||
|  | 		wait(number);	/* return its exit status */ | ||||||
|  | #endif | ||||||
|  | #ifdef os9 | ||||||
|  | 	int	status, pid; | ||||||
|  | 
 | ||||||
|  | 	strcat(string, "\n"); | ||||||
|  | 	if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1) | ||||||
|  | 		return -1;		/* Couldn't start a shell */ | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		if ((pid = wait(&status)) == -1) | ||||||
|  | 			return -1;	/* child already died!?!? */ | ||||||
|  | 	} while (pid != number); | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Do commands to make a target | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | docmds1(np, lp) | ||||||
|  | struct name *		np; | ||||||
|  | struct line *		lp; | ||||||
|  | { | ||||||
|  | 	bool			ssilent; | ||||||
|  | 	bool			signore; | ||||||
|  | 	int			estat; | ||||||
|  | 	register char *		q; | ||||||
|  | 	register char *		p; | ||||||
|  | 	char *			shell; | ||||||
|  | 	register struct cmd *	cp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (*(shell = getmacro("SHELL")) == '\0') | ||||||
|  | #ifdef eon | ||||||
|  | 		shell = ":bin/esh"; | ||||||
|  | #endif | ||||||
|  | #ifdef unix | ||||||
|  | 		shell = "/bin/sh"; | ||||||
|  | #endif | ||||||
|  | #ifdef os9 | ||||||
|  | 		shell = "shell"; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	for (cp = lp->l_cmd; cp; cp = cp->c_next) | ||||||
|  | 	{ | ||||||
|  | 		strcpy(str1, cp->c_cmd); | ||||||
|  | 		expand(str1); | ||||||
|  | 		q = str1; | ||||||
|  | 		ssilent = silent; | ||||||
|  | 		signore = ignore; | ||||||
|  | 		while ((*q == '@') || (*q == '-')) | ||||||
|  | 		{ | ||||||
|  | 			if (*q == '@')	   /*  Specific silent  */ | ||||||
|  | 				ssilent = TRUE; | ||||||
|  | 			else		   /*  Specific ignore  */ | ||||||
|  | 				signore = TRUE; | ||||||
|  | 			q++;		   /*  Not part of the command  */ | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (!domake) | ||||||
|  | 			ssilent = 0; | ||||||
|  | 
 | ||||||
|  | 		if (!ssilent) | ||||||
|  | 			fputs("    ", stdout); | ||||||
|  | 
 | ||||||
|  | 		for (p=q; *p; p++) | ||||||
|  | 		{ | ||||||
|  | 			if (*p == '\n' && p[1] != '\0') | ||||||
|  | 			{ | ||||||
|  | 				*p = ' '; | ||||||
|  | 				if (!ssilent) | ||||||
|  | 					fputs("\\\n", stdout); | ||||||
|  | 			} | ||||||
|  | 			else if (!ssilent) | ||||||
|  | 				putchar(*p); | ||||||
|  | 		} | ||||||
|  | 		if (!ssilent) { | ||||||
|  | 			putchar('\n'); | ||||||
|  | 			fflush(stdout); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (domake) | ||||||
|  | 		{			/*  Get the shell to execute it  */ | ||||||
|  | 			if ((estat = dosh(q, shell)) != 0) | ||||||
|  | 			{ | ||||||
|  | 				if (estat == -1) | ||||||
|  | 					fatal("Couldn't execute %s", shell); | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					printf("%s: Error code %d", myname, estat); | ||||||
|  | 					if (signore) | ||||||
|  | 						fputs(" (Ignored)\n", stdout); | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						putchar('\n'); | ||||||
|  | 						if (!(np->n_flag & N_PREC)) | ||||||
|  | 							if (unlink(np->n_name) == 0) | ||||||
|  | 								printf("%s: '%s' removed.\n", myname, np->n_name); | ||||||
|  | 						exit(1); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				fflush(stdout); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | docmds(np) | ||||||
|  | struct name *		np; | ||||||
|  | { | ||||||
|  | 	register struct line *	lp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	for (lp = np->n_line; lp; lp = lp->l_next) | ||||||
|  | 		docmds1(np, lp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifdef os9 | ||||||
|  | /*
 | ||||||
|  |  *	Some stuffing around to get the modified time of a file | ||||||
|  |  *	in an os9 file system | ||||||
|  |  */ | ||||||
|  | getmdate(fd, tbp) | ||||||
|  | struct sgtbuf *		tbp; | ||||||
|  | { | ||||||
|  | 	struct registers	regs; | ||||||
|  | 	static struct fildes	fdbuf; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	regs.rg_a = fd; | ||||||
|  | 	regs.rg_b = SS_FD; | ||||||
|  | 	regs.rg_x = &fdbuf; | ||||||
|  | 	regs.rg_y = sizeof (fdbuf); | ||||||
|  | 
 | ||||||
|  | 	if (_os9(I_GETSTT, ®s) == -1) | ||||||
|  | 	{ | ||||||
|  | 		errno = regs.rg_b & 0xff; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	if (tbp) | ||||||
|  | 	{ | ||||||
|  | 		_strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date)); | ||||||
|  | 		tbp->t_second = 0;	/* Files are only acurate to mins */ | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Kludge routine to return an aproximation of how many | ||||||
|  |  *	seconds since 1980.  Dates will be in order, but will not | ||||||
|  |  *	be lineer | ||||||
|  |  */ | ||||||
|  | time_t | ||||||
|  | cnvtime(tbp) | ||||||
|  | struct sgtbuf		*tbp; | ||||||
|  | { | ||||||
|  | 	long			acc; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	acc = tbp->t_year - 80;		/* Baseyear is 1980 */ | ||||||
|  | 	acc = acc * 12 + tbp->t_month; | ||||||
|  | 	acc = acc * 31 + tbp->t_day; | ||||||
|  | 	acc = acc * 24 + tbp->t_hour; | ||||||
|  | 	acc = acc * 60 + tbp->t_minute; | ||||||
|  | 	acc = acc * 60 + tbp->t_second; | ||||||
|  | 
 | ||||||
|  | 	return acc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Get the current time in the internal format | ||||||
|  |  */ | ||||||
|  | time(tp) | ||||||
|  | time_t *		tp; | ||||||
|  | { | ||||||
|  | 	struct sgtbuf		tbuf; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (getime(&tbuf) < 0) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	if (tp) | ||||||
|  | 		*tp = cnvtime(&tbuf); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Get the modification time of a file.  If the first | ||||||
|  |  *	doesn't exist, it's modtime is set to 0. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | modtime(np) | ||||||
|  | struct name *		np; | ||||||
|  | { | ||||||
|  | #ifdef unix | ||||||
|  | 	struct stat		info; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (stat(np->n_name, &info) < 0) | ||||||
|  | 	{ | ||||||
|  | 		if (errno != ENOENT) | ||||||
|  | 			fatal("Can't open %s; error %d", np->n_name, errno); | ||||||
|  | 
 | ||||||
|  | 		np->n_time = 0L; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		np->n_time = info.st_mtime; | ||||||
|  | #endif | ||||||
|  | #ifdef eon | ||||||
|  | 	struct stat		info; | ||||||
|  | 	int			fd; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if ((fd = open(np->n_name, 0)) < 0) | ||||||
|  | 	{ | ||||||
|  | 		if (errno != ER_NOTF) | ||||||
|  | 			fatal("Can't open %s; error %02x", np->n_name, errno); | ||||||
|  | 
 | ||||||
|  | 		np->n_time = 0L; | ||||||
|  | 	} | ||||||
|  | 	else if (getstat(fd, &info) < 0) | ||||||
|  | 		fatal("Can't getstat %s; error %02x", np->n_name, errno); | ||||||
|  | 	else | ||||||
|  | 		np->n_time = info.st_mod; | ||||||
|  | 
 | ||||||
|  | 	close(fd); | ||||||
|  | #endif | ||||||
|  | #ifdef os9 | ||||||
|  | 	struct sgtbuf		info; | ||||||
|  | 	int			fd; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if ((fd = open(np->n_name, 0)) < 0) | ||||||
|  | 	{ | ||||||
|  | 		if (errno != E_PNNF) | ||||||
|  | 			fatal("Can't open %s; error %02x", np->n_name, errno); | ||||||
|  | 
 | ||||||
|  | 		np->n_time = 0L; | ||||||
|  | 	} | ||||||
|  | 	else if (getmdate(fd, &info) < 0) | ||||||
|  | 		fatal("Can't getstat %s; error %02x", np->n_name, errno); | ||||||
|  | 	else | ||||||
|  | 		np->n_time = cnvtime(&info); | ||||||
|  | 
 | ||||||
|  | 	close(fd); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Update the mod time of a file to now. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | touch(np) | ||||||
|  | struct name *		np; | ||||||
|  | { | ||||||
|  | 	char			c; | ||||||
|  | 	int			fd; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (!domake || !silent) | ||||||
|  | 		printf("    touch(%s)\n", np->n_name); | ||||||
|  | 
 | ||||||
|  | 	if (domake) | ||||||
|  | 	{ | ||||||
|  | #ifdef unix | ||||||
|  | 		long		a[2]; | ||||||
|  | 		long		time(); | ||||||
|  | 
 | ||||||
|  | 		a[0] = a[1] = time((long *)0); | ||||||
|  | 		if (utime(np->n_name, &a[0]) < 0) | ||||||
|  | 			printf("%s: '%s' not touched - non-existant\n", | ||||||
|  | 					myname, np->n_name); | ||||||
|  | #endif | ||||||
|  | #ifdef eon | ||||||
|  | 		if ((fd = open(np->n_name, 0)) < 0) | ||||||
|  | 			printf("%s: '%s' not touched - non-existant\n", | ||||||
|  | 					myname, np->n_name); | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			uread(fd, &c, 1, 0); | ||||||
|  | 			uwrite(fd, &c, 1); | ||||||
|  | 		} | ||||||
|  | 		close(fd); | ||||||
|  | #endif | ||||||
|  | #ifdef os9 | ||||||
|  | 		/*
 | ||||||
|  | 		 *	Strange that something almost as totally useless | ||||||
|  | 		 *	as this is easy to do in os9! | ||||||
|  | 		 */ | ||||||
|  | 		if ((fd = open(np->n_name, S_IWRITE)) < 0) | ||||||
|  | 			printf("%s: '%s' not touched - non-existant\n", | ||||||
|  | 					myname, np->n_name); | ||||||
|  | 		close(fd); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Recursive routine to make a target. | ||||||
|  |  */ | ||||||
|  | int | ||||||
|  | make(np, level) | ||||||
|  | struct name *		np; | ||||||
|  | int			level; | ||||||
|  | { | ||||||
|  | 	register struct depend *	dp; | ||||||
|  | 	register struct line *		lp; | ||||||
|  | 	register struct depend *	qdp; | ||||||
|  | 	time_t				dtime = 1; | ||||||
|  | 	bool				didsomething = 0; | ||||||
|  | 	int				dynamic = 0; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (np->n_flag & N_DONE) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	if (!np->n_time) | ||||||
|  | 		modtime(np);		/*  Gets modtime of this file  */ | ||||||
|  | 
 | ||||||
|  | 	if (rules) | ||||||
|  | 	{ | ||||||
|  | 		for (lp = np->n_line; lp; lp = lp->l_next) | ||||||
|  | 			if (lp->l_cmd) | ||||||
|  | 				break; | ||||||
|  | 		if (!lp) { | ||||||
|  | 			dyndep(np); | ||||||
|  | 			dynamic = 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!(np->n_flag & N_TARG) && np->n_time == 0L) | ||||||
|  | 		fatal("Don't know how to make %s", np->n_name); | ||||||
|  | 
 | ||||||
|  | 	for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next) | ||||||
|  | 	{ | ||||||
|  | 		for (dp = lp->l_dep; dp; dp = dp->d_next) | ||||||
|  | 		{ | ||||||
|  | 			char *sv = 0; | ||||||
|  | 			if (dynamic) { | ||||||
|  | 				char *s = getmacro("<"); | ||||||
|  | 
 | ||||||
|  | 				if (s) { | ||||||
|  | 					sv = malloc((unsigned)(strlen(s)+1)); | ||||||
|  | 					if (!sv) { | ||||||
|  | 						fatal("no space for saved $<"); | ||||||
|  | 					} | ||||||
|  | 					strcpy(sv, s); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			make(dp->d_name, level+1); | ||||||
|  | 			if (dynamic && sv) { | ||||||
|  | 				setmacro("<", sv, 4); | ||||||
|  | 				free(sv); | ||||||
|  | 			} | ||||||
|  | 			if (np->n_time < dp->d_name->n_time) | ||||||
|  | 				qdp = newdep(dp->d_name, qdp); | ||||||
|  | 			dtime = max(dtime, dp->d_name->n_time); | ||||||
|  | 		} | ||||||
|  | 		if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime)) | ||||||
|  | 		{ | ||||||
|  | 			make1(np, lp, qdp);	/* free()'s qdp */ | ||||||
|  | 			dtime = 1; | ||||||
|  | 			qdp = (struct depend *)0; | ||||||
|  | 			didsomething++; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	np->n_flag |= N_DONE; | ||||||
|  | 
 | ||||||
|  | 	if (quest) | ||||||
|  | 	{ | ||||||
|  | 		long		t; | ||||||
|  | 
 | ||||||
|  | 		t = np->n_time; | ||||||
|  | 		time(&np->n_time); | ||||||
|  | 		return t < dtime; | ||||||
|  | 	} | ||||||
|  | 	else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE)) | ||||||
|  | 	{ | ||||||
|  | 		make1(np, (struct line *)0, qdp);	/* free()'s qdp */ | ||||||
|  | 		time(&np->n_time); | ||||||
|  | 	} | ||||||
|  | 	else if (level == 0 && !didsomething) | ||||||
|  | 		printf("%s: '%s' is up to date\n", myname, np->n_name); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | make1(np, lp, qdp) | ||||||
|  | register struct depend *	qdp; | ||||||
|  | struct line *			lp; | ||||||
|  | struct name *			np; | ||||||
|  | { | ||||||
|  | 	register struct depend *	dp; | ||||||
|  | 	register char *p; | ||||||
|  | 	char *rindex(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	if (dotouch) | ||||||
|  | 		touch(np); | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		strcpy(str1, ""); | ||||||
|  | 		for (dp = qdp; dp; dp = qdp) | ||||||
|  | 		{ | ||||||
|  | 			if (strlen(str1)) | ||||||
|  | 				strcat(str1, " "); | ||||||
|  | 			strcat(str1, dp->d_name->n_name); | ||||||
|  | 			qdp = dp->d_next; | ||||||
|  | 			free((char *)dp); | ||||||
|  | 		} | ||||||
|  | 		setmacro("?", str1, 4); | ||||||
|  | 		setmacro("@", np->n_name, 4); | ||||||
|  | 		p = rindex(np->n_name, '.'); | ||||||
|  | 		if (p) *p = 0; | ||||||
|  | 		setmacro("*", np->n_name, 4); | ||||||
|  | 		if (p) *p = '.'; | ||||||
|  | 		if (lp)		/* lp set if doing a :: rule */ | ||||||
|  | 			docmds1(np, lp); | ||||||
|  | 		else | ||||||
|  | 			docmds(np); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										119
									
								
								util/make/reader.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								util/make/reader.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,119 @@ | ||||||
|  | /*
 | ||||||
|  |  *	Read in makefile | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include	<ctype.h> | ||||||
|  | #include "h.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int			lineno; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Syntax error handler.  Print message, with line number, and exits. | ||||||
|  |  */ | ||||||
|  | /*VARARGS1*/ | ||||||
|  | void | ||||||
|  | error(msg, a1, a2, a3) | ||||||
|  | char *			msg; | ||||||
|  | { | ||||||
|  | 	fprintf(stderr, "%s: ", myname); | ||||||
|  | 	fprintf(stderr, msg, a1, a2, a3); | ||||||
|  | 	if (lineno) | ||||||
|  | 		fprintf(stderr, " near line %d", lineno); | ||||||
|  | 	fputc('\n', stderr); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Read a line into the supplied string of length LZ.  Remove | ||||||
|  |  *	comments, ignore blank lines. Deal with	quoted (\) #, and | ||||||
|  |  *	quoted newlines.  If EOF return TRUE. | ||||||
|  |  */ | ||||||
|  | bool | ||||||
|  | getline(str, fd) | ||||||
|  | char *		str; | ||||||
|  | FILE *		fd; | ||||||
|  | { | ||||||
|  | 	register char *		p; | ||||||
|  | 	char *			q; | ||||||
|  | 	int			pos = 0; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	for (;;) | ||||||
|  | 	{ | ||||||
|  | 		if (fgets(str+pos, LZ-pos, fd) == (char *)0) | ||||||
|  | 			return TRUE;		/*  EOF  */ | ||||||
|  | 
 | ||||||
|  | 		lineno++; | ||||||
|  | 
 | ||||||
|  | 		if ((p = index(str+pos, '\n')) == (char *)0) | ||||||
|  | 			error("Line too long"); | ||||||
|  | 
 | ||||||
|  | 		if (p[-1] == '\\') | ||||||
|  | 		{ | ||||||
|  | 			p[-1] = '\n'; | ||||||
|  | 			pos = p - str; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		p = str; | ||||||
|  | 		while (((q = index(p, '#')) != (char *)0) && | ||||||
|  | 		    (p != q) && (q[-1] == '\\')) | ||||||
|  | 		{ | ||||||
|  | 			char	*a; | ||||||
|  | 
 | ||||||
|  | 			a = q - 1;	/*  Del \ chr; move rest back  */ | ||||||
|  | 			p = q; | ||||||
|  | 			while (*a++ = *q++) | ||||||
|  | 				; | ||||||
|  | 		} | ||||||
|  | 		if (q != (char *)0) | ||||||
|  | 		{ | ||||||
|  | 			q[0] = '\n'; | ||||||
|  | 			q[1] = '\0'; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		p = str; | ||||||
|  | 		while (isspace(*p))	/*  Checking for blank  */ | ||||||
|  | 			p++; | ||||||
|  | 
 | ||||||
|  | 		if (*p != '\0') | ||||||
|  | 			return FALSE; | ||||||
|  | 		pos = 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Get a word from the current line, surounded by white space. | ||||||
|  |  *	return a pointer to it. String returned has no white spaces | ||||||
|  |  *	in it. | ||||||
|  |  */ | ||||||
|  | char * | ||||||
|  | gettok(ptr) | ||||||
|  | char	**ptr; | ||||||
|  | { | ||||||
|  | 	register char *		p; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	while (isspace(**ptr))	/*  Skip spaces  */ | ||||||
|  | 		(*ptr)++; | ||||||
|  | 
 | ||||||
|  | 	if (**ptr == '\0')	/*  Nothing after spaces  */ | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	p = *ptr;		/*  word starts here  */ | ||||||
|  | 
 | ||||||
|  | 	while ((**ptr != '\0') && (!isspace(**ptr))) | ||||||
|  | 		(*ptr)++;	/*  Find end of word  */ | ||||||
|  | 
 | ||||||
|  | 	*(*ptr)++ = '\0';	/*  Terminate it  */ | ||||||
|  | 
 | ||||||
|  | 	return(p); | ||||||
|  | } | ||||||
							
								
								
									
										257
									
								
								util/make/rules.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								util/make/rules.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,257 @@ | ||||||
|  | /*
 | ||||||
|  |  *	Control of the implicit suffix rules | ||||||
|  |  * | ||||||
|  |  *	$Header$ | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #include "h.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Return a pointer to the suffix of a name | ||||||
|  |  */ | ||||||
|  | char * | ||||||
|  | suffix(name) | ||||||
|  | char *			name; | ||||||
|  | { | ||||||
|  | 	return rindex(name, '.'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Dynamic dependency.  This routine applies the suffis rules | ||||||
|  |  *	to try and find a source and a set of rules for a missing | ||||||
|  |  *	target.  If found, np is made into a target with the implicit | ||||||
|  |  *	source name, and rules.  Returns TRUE if np was made into | ||||||
|  |  *	a target. | ||||||
|  |  */ | ||||||
|  | bool | ||||||
|  | dyndep(np) | ||||||
|  | struct name *		np; | ||||||
|  | { | ||||||
|  | 	register char *		p; | ||||||
|  | 	register char *		q; | ||||||
|  | 	register char *		suff;		/*  Old suffix  */ | ||||||
|  | 	register char *		basename;	/*  Name without suffix  */ | ||||||
|  | 	struct name *		op;		/*  New dependent  */ | ||||||
|  | 	struct name *		sp;		/*  Suffix  */ | ||||||
|  | 	struct line *		lp; | ||||||
|  | 	struct depend *		dp; | ||||||
|  | 	char *			newsuff; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	p = str1; | ||||||
|  | 	q = np->n_name; | ||||||
|  | 	if (!(suff = suffix(q))) | ||||||
|  | 		return FALSE;		/* No suffix */ | ||||||
|  | 	while (q < suff) | ||||||
|  | 		*p++ = *q++; | ||||||
|  | 	*p = '\0'; | ||||||
|  | 	basename = setmacro("*", str1, 4)->m_val; | ||||||
|  | 
 | ||||||
|  | 	if (!((sp = newname(".SUFFIXES"))->n_flag & N_TARG)) | ||||||
|  | 		return FALSE; | ||||||
|  | 
 | ||||||
|  | 	for (lp = sp->n_line; lp; lp = lp->l_next) | ||||||
|  | 		for (dp = lp->l_dep; dp; dp = dp->d_next) | ||||||
|  | 		{ | ||||||
|  | 			newsuff = dp->d_name->n_name; | ||||||
|  | 			if (strlen(suff)+strlen(newsuff)+1 >= LZ) | ||||||
|  | 				fatal("Suffix rule too long"); | ||||||
|  | 			p = str1; | ||||||
|  | 			q = newsuff; | ||||||
|  | 			while (*p++ = *q++) | ||||||
|  | 				; | ||||||
|  | 			p--; | ||||||
|  | 			q = suff; | ||||||
|  | 			while (*p++ = *q++) | ||||||
|  | 				; | ||||||
|  | 			sp = newname(str1); | ||||||
|  | 			if (sp->n_flag & N_TARG) | ||||||
|  | 			{ | ||||||
|  | 				p = str1; | ||||||
|  | 				q = basename; | ||||||
|  | 				if (strlen(basename) + strlen(newsuff)+1 >= LZ) | ||||||
|  | 					fatal("Implicit name too long"); | ||||||
|  | 				while (*p++ = *q++) | ||||||
|  | 					; | ||||||
|  | 				p--; | ||||||
|  | 				q = newsuff; | ||||||
|  | 				while (*p++ = *q++) | ||||||
|  | 					; | ||||||
|  | 				op = newname(str1); | ||||||
|  | 				if (!op->n_time) | ||||||
|  | 					modtime(op); | ||||||
|  | 				if (op->n_time || (op->n_flag & N_TARG)) | ||||||
|  | 				{ | ||||||
|  | 					dp = newdep(op, (struct depend *)0); | ||||||
|  | 					newline(np, dp, sp->n_line->l_cmd, 0); | ||||||
|  | 					setmacro("<", op->n_name, 4); | ||||||
|  | 					return TRUE; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	return FALSE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Make the default rules | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | makerules() | ||||||
|  | { | ||||||
|  | 	struct cmd *		cp; | ||||||
|  | 	struct name *		np; | ||||||
|  | 	struct depend *		dp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifdef eon | ||||||
|  | 	setmacro("BDSCC", "asm", 0); | ||||||
|  | 	/*	setmacro("BDSCFLAGS", "", 0);	*/ | ||||||
|  | 	cp = newcmd("$(BDSCC) $(BDSCFLAGS) -n $<", (struct cmd *)0); | ||||||
|  | 	np = newname(".c.o"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	setmacro("CC", "c", 0); | ||||||
|  | 	setmacro("CFLAGS", "-O", 0); | ||||||
|  | 	cp = newcmd("$(CC) $(CFLAGS) -c $<", (struct cmd *)0); | ||||||
|  | 	np = newname(".c.obj"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	setmacro("M80", "asm -n", 0); | ||||||
|  | 	/*	setmacro("M80FLAGS", "", 0);	*/ | ||||||
|  | 	cp = newcmd("$(M80) $(M80FLAGS) $<", (struct cmd *)0); | ||||||
|  | 	np = newname(".mac.o"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	setmacro("AS", "zas", 0); | ||||||
|  | 	/*	setmacro("ASFLAGS", "", 0);	*/ | ||||||
|  | 	cp = newcmd("$(ZAS) $(ASFLAGS) -o $@ $<", (struct cmd *)0); | ||||||
|  | 	np = newname(".as.obj"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	np = newname(".as"); | ||||||
|  | 	dp = newdep(np, (struct depend *)0); | ||||||
|  | 	np = newname(".obj"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".c"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".o"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".mac"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".SUFFIXES"); | ||||||
|  | 	newline(np, dp, (struct cmd *)0, 0); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *	Some of the UNIX implicit rules | ||||||
|  |  */ | ||||||
|  | #ifdef unix | ||||||
|  | 	setmacro("CC", "cc", 0); | ||||||
|  | 	setmacro("CFLAGS", "-O", 0); | ||||||
|  | #ifdef MINIX | ||||||
|  | 	cp = newcmd("$(CC) $(CFLAGS) -S $<", (struct cmd *)0); | ||||||
|  | 	np = newname(".c.s"); | ||||||
|  | #else | ||||||
|  | 	cp = newcmd("$(CC) $(CFLAGS) -c $<", (struct cmd *)0); | ||||||
|  | 	np = newname(".c.o"); | ||||||
|  | #endif MINIX | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	setmacro("AS", "as", 0); | ||||||
|  | 	cp = newcmd("$(AS) -o $@ $<", (struct cmd *)0); | ||||||
|  | 	np = newname(".s.o"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	setmacro("YACC", "yacc", 0); | ||||||
|  | 	/*	setmacro("YFLAGS", "", 0);	*/ | ||||||
|  | 	cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0); | ||||||
|  | 	cp = newcmd("mv y.tab.c $@", cp); | ||||||
|  | 	np = newname(".y.c"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0); | ||||||
|  | 	cp = newcmd("$(CC) $(CFLAGS) -c y.tab.c", cp); | ||||||
|  | 	cp = newcmd("rm y.tab.c", cp); | ||||||
|  | 	cp = newcmd("mv y.tab.o $@", cp); | ||||||
|  | 	np = newname(".y.o"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	setmacro("LEX", "lex", 0); | ||||||
|  | 	/*	setmacro("LFLAGS", "", 0);	*/ | ||||||
|  | 	cp = newcmd("$(LEX) $(LFLAGS) $<", (struct cmd *)0); | ||||||
|  | 	cp = newcmd("mv lex.yy.c $@", cp); | ||||||
|  | 	np = newname(".l.c"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	cp = newcmd("$(LEX) $(LFLAGS) $<", (struct cmd *)0); | ||||||
|  | 	cp = newcmd("$(CC) $(CFLAGS) -c lex.yy.c", cp); | ||||||
|  | 	cp = newcmd("rm lex.yy.c", cp); | ||||||
|  | 	cp = newcmd("mv lex.yy.o $@", cp); | ||||||
|  | 	np = newname(".l.o"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	np = newname(".s"); | ||||||
|  | 	dp = newdep(np, (struct depend *)0); | ||||||
|  | 	np = newname(".o"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".c"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".y"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".l"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".SUFFIXES"); | ||||||
|  | 	newline(np, dp, (struct cmd *)0, 0); | ||||||
|  | #endif | ||||||
|  | #ifdef os9 | ||||||
|  | /*
 | ||||||
|  |  *	Fairlight use an enhanced version of the C sub-system. | ||||||
|  |  *	They have a specialised macro pre-processor. | ||||||
|  |  */ | ||||||
|  | 	setmacro("CC", "cc", 0); | ||||||
|  | 	setmacro("CFLAGS", "-z", 0); | ||||||
|  | 	cp = newcmd("$(CC) $(CFLAGS) -r $<", (struct cmd *)0); | ||||||
|  | 
 | ||||||
|  | 	np = newname(".c.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 	np = newname(".ca.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 	np = newname(".a.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 	np = newname(".o.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 	np = newname(".mc.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 	np = newname(".mca.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 	np = newname(".ma.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 	np = newname(".mo.r"); | ||||||
|  | 	newline(np, (struct depend *)0, cp, 0); | ||||||
|  | 
 | ||||||
|  | 	np = newname(".r"); | ||||||
|  | 	dp = newdep(np, (struct depend *)0); | ||||||
|  | 	np = newname(".mc"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".mca"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".c"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".ca"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".ma"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".mo"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".o"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".a"); | ||||||
|  | 	dp = newdep(np, dp); | ||||||
|  | 	np = newname(".SUFFIXES"); | ||||||
|  | 	newline(np, dp, (struct cmd *)0, 0); | ||||||
|  | #endif | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue