1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1990-2011 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman 
22*b30d1939SAndy Fiddaman /*
23*b30d1939SAndy Fiddaman  * mamake -- MAM make
24*b30d1939SAndy Fiddaman  *
25*b30d1939SAndy Fiddaman  * coded for portability
26*b30d1939SAndy Fiddaman  */
27*b30d1939SAndy Fiddaman 
28*b30d1939SAndy Fiddaman static char id[] = "\n@(#)$Id: mamake (AT&T Research) 2011-08-31 $\0\n";
29*b30d1939SAndy Fiddaman 
30*b30d1939SAndy Fiddaman #if _PACKAGE_ast
31*b30d1939SAndy Fiddaman 
32*b30d1939SAndy Fiddaman #include <ast.h>
33*b30d1939SAndy Fiddaman #include <error.h>
34*b30d1939SAndy Fiddaman 
35*b30d1939SAndy Fiddaman static const char usage[] =
36*b30d1939SAndy Fiddaman "[-?\n@(#)$Id: mamake (AT&T Research) 2011-08-31 $\n]"
37*b30d1939SAndy Fiddaman USAGE_LICENSE
38*b30d1939SAndy Fiddaman "[+NAME?mamake - make abstract machine make]"
39*b30d1939SAndy Fiddaman "[+DESCRIPTION?\bmamake\b reads \amake abstract machine\a target and"
40*b30d1939SAndy Fiddaman "	prerequisite file descriptions from a mamfile (see \b-f\b) and executes"
41*b30d1939SAndy Fiddaman "	actions to update targets that are older than their prerequisites."
42*b30d1939SAndy Fiddaman "	Mamfiles are generated by the \b--mam\b option of \bnmake\b(1) and"
43*b30d1939SAndy Fiddaman "	\bgmake\b(1) and are portable to environments that only have"
44*b30d1939SAndy Fiddaman "	\bsh\b(1) and \bcc\b(1).]"
45*b30d1939SAndy Fiddaman "[+?In practice \bmamake\b is used to bootstrap build \bnmake\b(1) and"
46*b30d1939SAndy Fiddaman "	\bksh\b(1) in new environments. Mamfiles are used rather than"
47*b30d1939SAndy Fiddaman "	old-\bmake\b makefiles because some features are not reliably supported"
48*b30d1939SAndy Fiddaman "	across all \bmake\b variants:]{"
49*b30d1939SAndy Fiddaman "		[+action execution?Multi-line actions are executed as a"
50*b30d1939SAndy Fiddaman "			unit by \b$SHELL\b. There are some shell constructs"
51*b30d1939SAndy Fiddaman "			that cannot be expressed in an old-\bmake\b makefile.]"
52*b30d1939SAndy Fiddaman "		[+viewpathing?\bVPATH\b is properly interpreted. This allows"
53*b30d1939SAndy Fiddaman "			source to be separate from generated files.]"
54*b30d1939SAndy Fiddaman "		[+recursion?Ordered subdirectory recursion over unrelated"
55*b30d1939SAndy Fiddaman "			makefiles.]"
56*b30d1939SAndy Fiddaman "	}"
57*b30d1939SAndy Fiddaman "[+?\bmamprobe\b(1) is called to probe and generate system specific variable"
58*b30d1939SAndy Fiddaman "	definitions. The probe information is regenerated when it is older"
59*b30d1939SAndy Fiddaman "	than the \bmamprobe\b command.]"
60*b30d1939SAndy Fiddaman "[+?For compatibility with \bnmake\b(1) the \b-K\b option and the"
61*b30d1939SAndy Fiddaman "	\brecurse\b and \bcc-*\b command line targets are ignored.]"
62*b30d1939SAndy Fiddaman "[e:?Explain reason for triggering action. Ignored if -F is on.]"
63*b30d1939SAndy Fiddaman "[f:?Read \afile\a instead of the default.]:[file:=Mamfile]"
64*b30d1939SAndy Fiddaman "[i:?Ignore action errors.]"
65*b30d1939SAndy Fiddaman "[k:?Continue after error with sibling prerequisites.]"
66*b30d1939SAndy Fiddaman "[n:?Print actions but do not execute. Recursion actions (see \b-r\b) are still"
67*b30d1939SAndy Fiddaman "	executed. Use \b-N\b to disable recursion actions too.]"
68*b30d1939SAndy Fiddaman "[r:?Recursively make leaf directories matching \apattern\a. Only leaf"
69*b30d1939SAndy Fiddaman "	directories containing a makefile named \bNmakefile\b, \bnmakefile\b,"
70*b30d1939SAndy Fiddaman "	\bMakefile\b or \bmakefile\b are considered. The first makefile"
71*b30d1939SAndy Fiddaman "	found in each leaf directory is scanned for leaf directory"
72*b30d1939SAndy Fiddaman "	prerequisites; the recusion order is determined by a topological sort"
73*b30d1939SAndy Fiddaman "	of these prerequisites.]:[pattern]"
74*b30d1939SAndy Fiddaman "[C:?Do all work in \adirectory\a. All messages will mention"
75*b30d1939SAndy Fiddaman "	\adirectory\a.]:[directory]"
76*b30d1939SAndy Fiddaman "[D:?Set the debug trace level to \alevel\a. Higher levels produce more"
77*b30d1939SAndy Fiddaman "	output.]#[level]"
78*b30d1939SAndy Fiddaman "[F:?Force all targets to be out of date.]"
79*b30d1939SAndy Fiddaman "[K:?Ignored.]"
80*b30d1939SAndy Fiddaman "[N:?Like \b-n\b but recursion actions (see \b-r\b) are also disabled.]"
81*b30d1939SAndy Fiddaman "[V:?Print the program version and exit.]"
82*b30d1939SAndy Fiddaman "[G:debug-symbols?Compile and link with debugging symbol options enabled.]"
83*b30d1939SAndy Fiddaman "[S:strip-symbols?Strip link-time static symbols from executables.]"
84*b30d1939SAndy Fiddaman 
85*b30d1939SAndy Fiddaman "\n"
86*b30d1939SAndy Fiddaman "\n[ target ... ] [ name=value ... ]\n"
87*b30d1939SAndy Fiddaman "\n"
88*b30d1939SAndy Fiddaman 
89*b30d1939SAndy Fiddaman "[+SEE ALSO?\bgmake\b(1), \bmake\b(1), \bmamprobe\b(1),"
90*b30d1939SAndy Fiddaman "	\bnmake\b(1), \bsh\b(1)]"
91*b30d1939SAndy Fiddaman ;
92*b30d1939SAndy Fiddaman 
93*b30d1939SAndy Fiddaman #else
94*b30d1939SAndy Fiddaman 
95*b30d1939SAndy Fiddaman #define elementsof(x)	(sizeof(x)/sizeof(x[0]))
96*b30d1939SAndy Fiddaman #define newof(p,t,n,x)	((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
97*b30d1939SAndy Fiddaman 
98*b30d1939SAndy Fiddaman #define NiL		((char*)0)
99*b30d1939SAndy Fiddaman 
100*b30d1939SAndy Fiddaman #endif
101*b30d1939SAndy Fiddaman 
102*b30d1939SAndy Fiddaman #include <stdio.h>
103*b30d1939SAndy Fiddaman #include <unistd.h>
104*b30d1939SAndy Fiddaman #include <ctype.h>
105*b30d1939SAndy Fiddaman #include <sys/types.h>
106*b30d1939SAndy Fiddaman #include <sys/stat.h>
107*b30d1939SAndy Fiddaman #include <time.h>
108*b30d1939SAndy Fiddaman 
109*b30d1939SAndy Fiddaman #if !_PACKAGE_ast && defined(__STDC__)
110*b30d1939SAndy Fiddaman #include <stdlib.h>
111*b30d1939SAndy Fiddaman #include <string.h>
112*b30d1939SAndy Fiddaman #endif
113*b30d1939SAndy Fiddaman 
114*b30d1939SAndy Fiddaman #define delimiter(c)	((c)==' '||(c)=='\t'||(c)=='\n'||(c)==';'||(c)=='('||(c)==')'||(c)=='`'||(c)=='|'||(c)=='&'||(c)=='=')
115*b30d1939SAndy Fiddaman 
116*b30d1939SAndy Fiddaman #define add(b,c)	(((b)->nxt >= (b)->end) ? append(b, "") : NiL, *(b)->nxt++ = (c))
117*b30d1939SAndy Fiddaman #define get(b)		((b)->nxt-(b)->buf)
118*b30d1939SAndy Fiddaman #define set(b,o)	((b)->nxt=(b)->buf+(o))
119*b30d1939SAndy Fiddaman #define use(b)		(*(b)->nxt=0,(b)->nxt=(b)->buf)
120*b30d1939SAndy Fiddaman 
121*b30d1939SAndy Fiddaman #define CHUNK		1024
122*b30d1939SAndy Fiddaman #define KEY(a,b,c,d)	((((unsigned long)(a))<<15)|(((unsigned long)(b))<<10)|(((unsigned long)(c))<<5)|(((unsigned long)(d))))
123*b30d1939SAndy Fiddaman #define NOW		((unsigned long)time((time_t*)0))
124*b30d1939SAndy Fiddaman #define ROTATE(p,l,r,t)	((t)=(p)->l,(p)->l=(t)->r,(t)->r=(p),(p)=(t))
125*b30d1939SAndy Fiddaman 
126*b30d1939SAndy Fiddaman #define RULE_active	0x0001		/* active target		*/
127*b30d1939SAndy Fiddaman #define RULE_dontcare	0x0002		/* ok if not found		*/
128*b30d1939SAndy Fiddaman #define RULE_error	0x0004		/* not found or not generated	*/
129*b30d1939SAndy Fiddaman #define RULE_exists	0x0008		/* target file exists		*/
130*b30d1939SAndy Fiddaman #define RULE_generated	0x0010		/* generated target		*/
131*b30d1939SAndy Fiddaman #define RULE_ignore	0x0020		/* ignore time			*/
132*b30d1939SAndy Fiddaman #define RULE_implicit	0x0040		/* implicit prerequisite	*/
133*b30d1939SAndy Fiddaman #define RULE_made	0x0080		/* already made			*/
134*b30d1939SAndy Fiddaman #define RULE_virtual	0x0100		/* not a file			*/
135*b30d1939SAndy Fiddaman 
136*b30d1939SAndy Fiddaman #define STREAM_KEEP	0x0001		/* don't fclose() on pop()	*/
137*b30d1939SAndy Fiddaman #define STREAM_MUST	0x0002		/* push() file must exist	*/
138*b30d1939SAndy Fiddaman #define STREAM_PIPE	0x0004		/* pclose() on pop()		*/
139*b30d1939SAndy Fiddaman 
140*b30d1939SAndy Fiddaman #ifndef S_IXUSR
141*b30d1939SAndy Fiddaman #define S_IXUSR		0100		/* owner execute permission	*/
142*b30d1939SAndy Fiddaman #endif
143*b30d1939SAndy Fiddaman #ifndef S_IXGRP
144*b30d1939SAndy Fiddaman #define S_IXGRP		0010		/* group execute permission	*/
145*b30d1939SAndy Fiddaman #endif
146*b30d1939SAndy Fiddaman #ifndef S_IXOTH
147*b30d1939SAndy Fiddaman #define S_IXOTH		0001		/* other execute permission	*/
148*b30d1939SAndy Fiddaman #endif
149*b30d1939SAndy Fiddaman 
150*b30d1939SAndy Fiddaman struct Rule_s;
151*b30d1939SAndy Fiddaman 
152*b30d1939SAndy Fiddaman typedef struct stat Stat_t;
153*b30d1939SAndy Fiddaman typedef FILE Stdio_t;
154*b30d1939SAndy Fiddaman 
155*b30d1939SAndy Fiddaman typedef struct Buf_s			/* buffer stream		*/
156*b30d1939SAndy Fiddaman {
157*b30d1939SAndy Fiddaman 	struct Buf_s*	old;		/* next dropped buffer		*/
158*b30d1939SAndy Fiddaman 	char*		end;		/* 1 past end of buffer		*/
159*b30d1939SAndy Fiddaman 	char*		nxt;		/* next char to add		*/
160*b30d1939SAndy Fiddaman 	char*		buf;		/* buffer space			*/
161*b30d1939SAndy Fiddaman } Buf_t;
162*b30d1939SAndy Fiddaman 
163*b30d1939SAndy Fiddaman typedef struct Dict_item_s		/* dictionary item		*/
164*b30d1939SAndy Fiddaman {
165*b30d1939SAndy Fiddaman 	struct Dict_item_s*	left;	/* left child			*/
166*b30d1939SAndy Fiddaman 	struct Dict_item_s*	right;	/* right child			*/
167*b30d1939SAndy Fiddaman 	void*			value;	/* user defined value		*/
168*b30d1939SAndy Fiddaman 	char			name[1];/* 0 terminated name		*/
169*b30d1939SAndy Fiddaman } Dict_item_t;
170*b30d1939SAndy Fiddaman 
171*b30d1939SAndy Fiddaman typedef struct Dict_s			/* dictionary handle		*/
172*b30d1939SAndy Fiddaman {
173*b30d1939SAndy Fiddaman 	Dict_item_t*	root;		/* root item			*/
174*b30d1939SAndy Fiddaman } Dict_t;
175*b30d1939SAndy Fiddaman 
176*b30d1939SAndy Fiddaman typedef struct List_s			/* Rule_t list			*/
177*b30d1939SAndy Fiddaman {
178*b30d1939SAndy Fiddaman 	struct List_s*	next;		/* next in list			*/
179*b30d1939SAndy Fiddaman 	struct Rule_s*	rule;		/* list item			*/
180*b30d1939SAndy Fiddaman } List_t;
181*b30d1939SAndy Fiddaman 
182*b30d1939SAndy Fiddaman typedef struct Rule_s			/* rule item			*/
183*b30d1939SAndy Fiddaman {
184*b30d1939SAndy Fiddaman 	char*		name;		/* unbound name			*/
185*b30d1939SAndy Fiddaman 	char*		path;		/* bound path			*/
186*b30d1939SAndy Fiddaman 	List_t*		prereqs;	/* prerequisites		*/
187*b30d1939SAndy Fiddaman 	struct Rule_s*	leaf;		/* recursion leaf alias		*/
188*b30d1939SAndy Fiddaman 	int		flags;		/* RULE_* flags			*/
189*b30d1939SAndy Fiddaman 	int		making;		/* currently make()ing		*/
190*b30d1939SAndy Fiddaman 	unsigned long	time;		/* modification time		*/
191*b30d1939SAndy Fiddaman } Rule_t;
192*b30d1939SAndy Fiddaman 
193*b30d1939SAndy Fiddaman typedef struct Stream_s			/* input file stream stack	*/
194*b30d1939SAndy Fiddaman {
195*b30d1939SAndy Fiddaman 	Stdio_t*	fp;		/* read stream			*/
196*b30d1939SAndy Fiddaman 	char*		file;		/* stream path			*/
197*b30d1939SAndy Fiddaman 	unsigned long	line;		/* stream line			*/
198*b30d1939SAndy Fiddaman 	int		flags;		/* stream flags			*/
199*b30d1939SAndy Fiddaman } Stream_t;
200*b30d1939SAndy Fiddaman 
201*b30d1939SAndy Fiddaman typedef struct View_s			/* viewpath level		*/
202*b30d1939SAndy Fiddaman {
203*b30d1939SAndy Fiddaman 	struct View_s*	next;		/* next level in viewpath	*/
204*b30d1939SAndy Fiddaman 	int		node;		/* viewpath node path length	*/
205*b30d1939SAndy Fiddaman 	char		dir[1];		/* viewpath level dir prefix	*/
206*b30d1939SAndy Fiddaman } View_t;
207*b30d1939SAndy Fiddaman 
208*b30d1939SAndy Fiddaman static struct				/* program state		*/
209*b30d1939SAndy Fiddaman {
210*b30d1939SAndy Fiddaman 	Buf_t*		buf;		/* work buffer			*/
211*b30d1939SAndy Fiddaman 	Buf_t*		old;		/* dropped buffers		*/
212*b30d1939SAndy Fiddaman 	Buf_t*		opt;		/* option buffer		*/
213*b30d1939SAndy Fiddaman 
214*b30d1939SAndy Fiddaman 	Dict_t*		leaf;		/* recursion leaf dictionary	*/
215*b30d1939SAndy Fiddaman 	Dict_t*		libs;		/* library dictionary		*/
216*b30d1939SAndy Fiddaman 	Dict_t*		rules;		/* rule dictionary		*/
217*b30d1939SAndy Fiddaman 	Dict_t*		vars;		/* variable dictionary		*/
218*b30d1939SAndy Fiddaman 
219*b30d1939SAndy Fiddaman 	View_t*		view;		/* viewpath levels		*/
220*b30d1939SAndy Fiddaman 
221*b30d1939SAndy Fiddaman 	char*		directory;	/* work in this directory	*/
222*b30d1939SAndy Fiddaman 	char*		id;		/* command name			*/
223*b30d1939SAndy Fiddaman 	char*		file;		/* first input file		*/
224*b30d1939SAndy Fiddaman 	char*		pwd;		/* current directory		*/
225*b30d1939SAndy Fiddaman 	char*		recurse;	/* recursion pattern		*/
226*b30d1939SAndy Fiddaman 	char*		shell;		/* ${SHELL}			*/
227*b30d1939SAndy Fiddaman 
228*b30d1939SAndy Fiddaman 	int		active;		/* targets currently active	*/
229*b30d1939SAndy Fiddaman 	int		debug;		/* negative of debug level	*/
230*b30d1939SAndy Fiddaman 	int		errors;		/* some error(s) occurred	*/
231*b30d1939SAndy Fiddaman 	int		exec;		/* execute actions		*/
232*b30d1939SAndy Fiddaman 	int		explain;	/* explain actions		*/
233*b30d1939SAndy Fiddaman 	int		force;		/* all targets out of date	*/
234*b30d1939SAndy Fiddaman 	int		ignore;		/* ignore command errors	*/
235*b30d1939SAndy Fiddaman 	int		indent;		/* debug indent			*/
236*b30d1939SAndy Fiddaman 	int		keepgoing;	/* do siblings on error		*/
237*b30d1939SAndy Fiddaman 	int		never;		/* never execute		*/
238*b30d1939SAndy Fiddaman 	int		peek;		/* next line already in input	*/
239*b30d1939SAndy Fiddaman 	int		probed;		/* probe already done		*/
240*b30d1939SAndy Fiddaman 	int		verified;	/* don't bother with verify()	*/
241*b30d1939SAndy Fiddaman 
242*b30d1939SAndy Fiddaman 	Stream_t	streams[4];	/* input file stream stack	*/
243*b30d1939SAndy Fiddaman 	Stream_t*	sp;		/* input stream stack pointer	*/
244*b30d1939SAndy Fiddaman 
245*b30d1939SAndy Fiddaman 	char		input[8*CHUNK];	/* input buffer			*/
246*b30d1939SAndy Fiddaman } state;
247*b30d1939SAndy Fiddaman 
248*b30d1939SAndy Fiddaman static unsigned long	make(Rule_t*);
249*b30d1939SAndy Fiddaman 
250*b30d1939SAndy Fiddaman static char		mamfile[] = "Mamfile";
251*b30d1939SAndy Fiddaman static char		sh[] = "/bin/sh";
252*b30d1939SAndy Fiddaman 
253*b30d1939SAndy Fiddaman extern char**		environ;
254*b30d1939SAndy Fiddaman 
255*b30d1939SAndy Fiddaman #if !_PACKAGE_ast
256*b30d1939SAndy Fiddaman 
257*b30d1939SAndy Fiddaman #if defined(NeXT) || defined(__NeXT)
258*b30d1939SAndy Fiddaman #define getcwd(a,b)	getwd(a)
259*b30d1939SAndy Fiddaman #endif
260*b30d1939SAndy Fiddaman 
261*b30d1939SAndy Fiddaman /*
262*b30d1939SAndy Fiddaman  * emit usage message and exit
263*b30d1939SAndy Fiddaman  */
264*b30d1939SAndy Fiddaman 
265*b30d1939SAndy Fiddaman static void
usage()266*b30d1939SAndy Fiddaman usage()
267*b30d1939SAndy Fiddaman {
268*b30d1939SAndy Fiddaman 	fprintf(stderr, "Usage: %s [-iknFKNV] [-f mamfile] [-r pattern] [-C directory] [-D level] [target ...] [name=value ...]\n", state.id);
269*b30d1939SAndy Fiddaman 	exit(2);
270*b30d1939SAndy Fiddaman }
271*b30d1939SAndy Fiddaman 
272*b30d1939SAndy Fiddaman #endif
273*b30d1939SAndy Fiddaman 
274*b30d1939SAndy Fiddaman /*
275*b30d1939SAndy Fiddaman  * output error message identification
276*b30d1939SAndy Fiddaman  */
277*b30d1939SAndy Fiddaman 
278*b30d1939SAndy Fiddaman static void
identify(Stdio_t * sp)279*b30d1939SAndy Fiddaman identify(Stdio_t* sp)
280*b30d1939SAndy Fiddaman {
281*b30d1939SAndy Fiddaman 	if (state.directory)
282*b30d1939SAndy Fiddaman 		fprintf(sp, "%s [%s]: ", state.id, state.directory);
283*b30d1939SAndy Fiddaman 	else
284*b30d1939SAndy Fiddaman 		fprintf(sp, "%s: ", state.id);
285*b30d1939SAndy Fiddaman }
286*b30d1939SAndy Fiddaman 
287*b30d1939SAndy Fiddaman /*
288*b30d1939SAndy Fiddaman  * emit error message
289*b30d1939SAndy Fiddaman  * level:
290*b30d1939SAndy Fiddaman  *	<0	debug
291*b30d1939SAndy Fiddaman  *	 0	info
292*b30d1939SAndy Fiddaman  *	 1	warning
293*b30d1939SAndy Fiddaman  *	 2	error
294*b30d1939SAndy Fiddaman  *	>2	exit(level-2)
295*b30d1939SAndy Fiddaman  */
296*b30d1939SAndy Fiddaman 
297*b30d1939SAndy Fiddaman static void
report(int level,char * text,char * item,unsigned long stamp)298*b30d1939SAndy Fiddaman report(int level, char* text, char* item, unsigned long stamp)
299*b30d1939SAndy Fiddaman {
300*b30d1939SAndy Fiddaman 	int	i;
301*b30d1939SAndy Fiddaman 
302*b30d1939SAndy Fiddaman 	if (level >= state.debug)
303*b30d1939SAndy Fiddaman 	{
304*b30d1939SAndy Fiddaman 		if (level)
305*b30d1939SAndy Fiddaman 			identify(stderr);
306*b30d1939SAndy Fiddaman 		if (level < 0)
307*b30d1939SAndy Fiddaman 		{
308*b30d1939SAndy Fiddaman 			fprintf(stderr, "debug%d: ", level);
309*b30d1939SAndy Fiddaman 			for (i = 1; i < state.indent; i++)
310*b30d1939SAndy Fiddaman 				fprintf(stderr, "  ");
311*b30d1939SAndy Fiddaman 		}
312*b30d1939SAndy Fiddaman 		else
313*b30d1939SAndy Fiddaman 		{
314*b30d1939SAndy Fiddaman 			if (state.sp && state.sp->line)
315*b30d1939SAndy Fiddaman 			{
316*b30d1939SAndy Fiddaman 				if (state.sp->file)
317*b30d1939SAndy Fiddaman 					fprintf(stderr, "%s: ", state.sp->file);
318*b30d1939SAndy Fiddaman 				fprintf(stderr, "%ld: ", state.sp->line);
319*b30d1939SAndy Fiddaman 			}
320*b30d1939SAndy Fiddaman 			if (level == 1)
321*b30d1939SAndy Fiddaman 				fprintf(stderr, "warning: ");
322*b30d1939SAndy Fiddaman 			else if (level > 1)
323*b30d1939SAndy Fiddaman 				state.errors = 1;
324*b30d1939SAndy Fiddaman 		}
325*b30d1939SAndy Fiddaman 		if (item)
326*b30d1939SAndy Fiddaman 			fprintf(stderr, "%s: ", item);
327*b30d1939SAndy Fiddaman 		fprintf(stderr, "%s", text);
328*b30d1939SAndy Fiddaman 		if (stamp && state.debug <= -2)
329*b30d1939SAndy Fiddaman 			fprintf(stderr, " %10lu", stamp);
330*b30d1939SAndy Fiddaman 		fprintf(stderr, "\n");
331*b30d1939SAndy Fiddaman 		if (level > 2)
332*b30d1939SAndy Fiddaman 			exit(level - 2);
333*b30d1939SAndy Fiddaman 	}
334*b30d1939SAndy Fiddaman }
335*b30d1939SAndy Fiddaman 
336*b30d1939SAndy Fiddaman /*
337*b30d1939SAndy Fiddaman  * don't know how to make or exit code making
338*b30d1939SAndy Fiddaman  */
339*b30d1939SAndy Fiddaman 
340*b30d1939SAndy Fiddaman static void
dont(Rule_t * r,int code,int keepgoing)341*b30d1939SAndy Fiddaman dont(Rule_t* r, int code, int keepgoing)
342*b30d1939SAndy Fiddaman {
343*b30d1939SAndy Fiddaman 	identify(stderr);
344*b30d1939SAndy Fiddaman 	if (!code)
345*b30d1939SAndy Fiddaman 		fprintf(stderr, "don't know how to make %s\n", r->name);
346*b30d1939SAndy Fiddaman 	else
347*b30d1939SAndy Fiddaman 	{
348*b30d1939SAndy Fiddaman 		fprintf(stderr, "*** exit code %d making %s%s\n", code, r->name, state.ignore ? " ignored" : "");
349*b30d1939SAndy Fiddaman 		unlink(r->name);
350*b30d1939SAndy Fiddaman 		if (state.ignore)
351*b30d1939SAndy Fiddaman 			return;
352*b30d1939SAndy Fiddaman 	}
353*b30d1939SAndy Fiddaman 	if (!keepgoing)
354*b30d1939SAndy Fiddaman 		exit(1);
355*b30d1939SAndy Fiddaman 	state.errors++;
356*b30d1939SAndy Fiddaman 	r->flags |= RULE_error;
357*b30d1939SAndy Fiddaman }
358*b30d1939SAndy Fiddaman 
359*b30d1939SAndy Fiddaman /*
360*b30d1939SAndy Fiddaman  * local strrchr()
361*b30d1939SAndy Fiddaman  */
362*b30d1939SAndy Fiddaman 
363*b30d1939SAndy Fiddaman static char*
last(register char * s,register int c)364*b30d1939SAndy Fiddaman last(register char* s, register int c)
365*b30d1939SAndy Fiddaman {
366*b30d1939SAndy Fiddaman 	register char*	r = 0;
367*b30d1939SAndy Fiddaman 
368*b30d1939SAndy Fiddaman 	for (r = 0; *s; s++)
369*b30d1939SAndy Fiddaman 		if (*s == c)
370*b30d1939SAndy Fiddaman 			r = s;
371*b30d1939SAndy Fiddaman 	return r;
372*b30d1939SAndy Fiddaman }
373*b30d1939SAndy Fiddaman 
374*b30d1939SAndy Fiddaman /*
375*b30d1939SAndy Fiddaman  * open a buffer stream
376*b30d1939SAndy Fiddaman  */
377*b30d1939SAndy Fiddaman 
378*b30d1939SAndy Fiddaman static Buf_t*
buffer(void)379*b30d1939SAndy Fiddaman buffer(void)
380*b30d1939SAndy Fiddaman {
381*b30d1939SAndy Fiddaman 	register Buf_t*	buf;
382*b30d1939SAndy Fiddaman 
383*b30d1939SAndy Fiddaman 	if (buf = state.old)
384*b30d1939SAndy Fiddaman 		state.old = state.old->old;
385*b30d1939SAndy Fiddaman 	else if (!(buf = newof(0, Buf_t, 1, 0)) || !(buf->buf = newof(0, char, CHUNK, 0)))
386*b30d1939SAndy Fiddaman 		report(3, "out of space [buffer]", NiL, (unsigned long)0);
387*b30d1939SAndy Fiddaman 	buf->end = buf->buf + CHUNK;
388*b30d1939SAndy Fiddaman 	buf->nxt = buf->buf;
389*b30d1939SAndy Fiddaman 	return buf;