xref: /csrg-svn/usr.bin/make/parse.c (revision 40393)
1*40393Sbostic /*-
2*40393Sbostic  * parse.c --
3*40393Sbostic  *	Functions to parse a makefile.
4*40393Sbostic  *
5*40393Sbostic  *	One function, Parse_Init, must be called before any functions
6*40393Sbostic  *	in this module are used. After that, the function Parse_File is the
7*40393Sbostic  *	main entry point and controls most of the other functions in this
8*40393Sbostic  *	module.
9*40393Sbostic  *
10*40393Sbostic  *	Most important structures are kept in Lsts. Directories for
11*40393Sbostic  *	the #include "..." function are kept in the 'parseIncPath' Lst, while
12*40393Sbostic  *	those for the #include <...> are kept in the 'sysIncPath' Lst. The
13*40393Sbostic  *	targets currently being defined are kept in the 'targets' Lst.
14*40393Sbostic  *
15*40393Sbostic  *	The variables 'fname' and 'lineno' are used to track the name
16*40393Sbostic  *	of the current file and the line number in that file so that error
17*40393Sbostic  *	messages can be more meaningful.
18*40393Sbostic  *
19*40393Sbostic  * Copyright (c) 1988, 1989 by the Regents of the University of California
20*40393Sbostic  * Copyright (c) 1988, 1989 by Adam de Boor
21*40393Sbostic  * Copyright (c) 1989 by Berkeley Softworks
22*40393Sbostic  *
23*40393Sbostic  * Permission to use, copy, modify, and distribute this
24*40393Sbostic  * software and its documentation for any non-commercial purpose
25*40393Sbostic  * and without fee is hereby granted, provided that the above copyright
26*40393Sbostic  * notice appears in all copies.  The University of California,
27*40393Sbostic  * Berkeley Softworks and Adam de Boor make no representations about
28*40393Sbostic  * the suitability of this software for any purpose.  It is provided
29*40393Sbostic  * "as is" without express or implied warranty.
30*40393Sbostic  *
31*40393Sbostic  * Interface:
32*40393Sbostic  *	Parse_Init	    	    Initialization function which must be
33*40393Sbostic  *	    	  	    	    called before anything else in this module
34*40393Sbostic  *	    	  	    	    is used.
35*40393Sbostic  *
36*40393Sbostic  *	Parse_File	    	    Function used to parse a makefile. It must
37*40393Sbostic  *	    	  	    	    be given the name of the file, which should
38*40393Sbostic  *	    	  	    	    already have been opened, and a function
39*40393Sbostic  *	    	  	    	    to call to read a character from the file.
40*40393Sbostic  *
41*40393Sbostic  *	Parse_IsVar	    	    Returns TRUE if the given line is a
42*40393Sbostic  *	    	  	    	    variable assignment. Used by MainParseArgs
43*40393Sbostic  *	    	  	    	    to determine if an argument is a target
44*40393Sbostic  *	    	  	    	    or a variable assignment. Used internally
45*40393Sbostic  *	    	  	    	    for pretty much the same thing...
46*40393Sbostic  *
47*40393Sbostic  *	Parse_Error	    	    Function called when an error occurs in
48*40393Sbostic  *	    	  	    	    parsing. Used by the variable and
49*40393Sbostic  *	    	  	    	    conditional modules.
50*40393Sbostic  *	Parse_MainName	    	    Returns a Lst of the main target to create.
51*40393Sbostic  */
52*40393Sbostic #ifndef lint
53*40393Sbostic static char     *rcsid = "$Id: parse.c,v 1.75 89/11/14 13:42:56 adam Exp $ SPRITE (Berkeley)";
54*40393Sbostic #endif lint
55*40393Sbostic 
56*40393Sbostic #include    <stdio.h>
57*40393Sbostic #include    <ctype.h>
58*40393Sbostic #include    "make.h"
59*40393Sbostic #include    "buf.h"
60*40393Sbostic 
61*40393Sbostic /*
62*40393Sbostic  * These values are returned by ParseEOF to tell Parse_File whether to
63*40393Sbostic  * CONTINUE parsing, i.e. it had only reached the end of an include file,
64*40393Sbostic  * or if it's DONE.
65*40393Sbostic  */
66*40393Sbostic #define	CONTINUE	1
67*40393Sbostic #define	DONE		0
68*40393Sbostic static int 	    ParseEOF();
69*40393Sbostic 
70*40393Sbostic static Lst     	    targets;	/* targets we're working on */
71*40393Sbostic static Boolean	    inLine;	/* true if currently in a dependency
72*40393Sbostic 				 * line or its commands */
73*40393Sbostic 
74*40393Sbostic static char    	    *fname;	/* name of current file (for errors) */
75*40393Sbostic static int          lineno;	/* line number in current file */
76*40393Sbostic static FILE   	    *curFILE; 	/* current makefile */
77*40393Sbostic 
78*40393Sbostic static int	    fatals = 0;
79*40393Sbostic 
80*40393Sbostic static GNode	    *mainNode;	/* The main target to create. This is the
81*40393Sbostic 				 * first target on the first dependency
82*40393Sbostic 				 * line in the first makefile */
83*40393Sbostic /*
84*40393Sbostic  * Definitions for handling #include specifications
85*40393Sbostic  */
86*40393Sbostic typedef struct IFile {
87*40393Sbostic     char           *fname;	    /* name of previous file */
88*40393Sbostic     int             lineno;	    /* saved line number */
89*40393Sbostic     FILE *       F;		    /* the open stream */
90*40393Sbostic }              	  IFile;
91*40393Sbostic 
92*40393Sbostic static Lst      includes;  	/* stack of IFiles generated by
93*40393Sbostic 				 * #includes */
94*40393Sbostic Lst         	parseIncPath;	/* list of directories for "..." includes */
95*40393Sbostic Lst         	sysIncPath;	/* list of directories for <...> includes */
96*40393Sbostic 
97*40393Sbostic /*-
98*40393Sbostic  * anyExport is used to trace if any target will need exportation. If none
99*40393Sbostic  * does, then any .EXPORT target can be ignored and the process needn't
100*40393Sbostic  * be slowed down by trying to connect to some load-balancing system.
101*40393Sbostic  */
102*40393Sbostic static Boolean anyExport = FALSE;
103*40393Sbostic 
104*40393Sbostic /*-
105*40393Sbostic  * specType contains the SPECial TYPE of the current target. It is
106*40393Sbostic  * Not if the target is unspecial. If it *is* special, however, the children
107*40393Sbostic  * are linked as children of the parent but not vice versa. This variable is
108*40393Sbostic  * set in ParseDoDependency
109*40393Sbostic  */
110*40393Sbostic typedef enum {
111*40393Sbostic     Begin,  	    /* .BEGIN */
112*40393Sbostic     Default,	    /* .DEFAULT */
113*40393Sbostic     End,    	    /* .END */
114*40393Sbostic     Export, 	    /* .EXPORT */
115*40393Sbostic     Ignore,	    /* .IGNORE */
116*40393Sbostic     Includes,	    /* .INCLUDES */
117*40393Sbostic     Interrupt,	    /* .INTERRUPT */
118*40393Sbostic     Libs,	    /* .LIBS */
119*40393Sbostic     MFlags,	    /* .MFLAGS or .MAKEFLAGS */
120*40393Sbostic     Main,	    /* .MAIN and we don't have anything user-specified to
121*40393Sbostic 		     * make */
122*40393Sbostic     NoExport,	    /* .NOEXPORT */
123*40393Sbostic     Not,	    /* Not special */
124*40393Sbostic     NotParallel,    /* .NOTPARALELL */
125*40393Sbostic     Null,   	    /* .NULL */
126*40393Sbostic     Order,  	    /* .ORDER */
127*40393Sbostic     Path,	    /* .PATH */
128*40393Sbostic     Precious,	    /* .PRECIOUS */
129*40393Sbostic     Shell,	    /* .SHELL */
130*40393Sbostic     Silent,	    /* .SILENT */
131*40393Sbostic     SingleShell,    /* .SINGLESHELL */
132*40393Sbostic     Suffixes,	    /* .SUFFIXES */
133*40393Sbostic     Attribute,	    /* Generic attribute */
134*40393Sbostic } ParseSpecial;
135*40393Sbostic 
136*40393Sbostic ParseSpecial specType;
137*40393Sbostic 
138*40393Sbostic /*
139*40393Sbostic  * Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER
140*40393Sbostic  * seen, then set to each successive source on the line.
141*40393Sbostic  */
142*40393Sbostic static GNode	*predecessor;
143*40393Sbostic 
144*40393Sbostic /*
145*40393Sbostic  * The parseKeywords table is searched using binary search when deciding
146*40393Sbostic  * if a target or source is special. The 'spec' field is the ParseSpecial
147*40393Sbostic  * type of the keyword ("Not" if the keyword isn't special as a target) while
148*40393Sbostic  * the 'op' field is the operator to apply to the list of targets if the
149*40393Sbostic  * keyword is used as a source ("0" if the keyword isn't special as a source)
150*40393Sbostic  */
151*40393Sbostic static struct {
152*40393Sbostic     char    	  *name;    	/* Name of keyword */
153*40393Sbostic     ParseSpecial  spec;	    	/* Type when used as a target */
154*40393Sbostic     int	    	  op;	    	/* Operator when used as a source */
155*40393Sbostic } parseKeywords[] = {
156*40393Sbostic { ".BEGIN", 	  Begin,    	0 },
157*40393Sbostic { ".DEFAULT",	  Default,  	0 },
158*40393Sbostic { ".DONTCARE",	  Attribute,   	OP_DONTCARE },
159*40393Sbostic { ".END",   	  End,	    	0 },
160*40393Sbostic { ".EXEC",	  Attribute,   	OP_EXEC },
161*40393Sbostic { ".EXPORT",	  Export,   	OP_EXPORT },
162*40393Sbostic { ".EXPORTSAME",  Attribute,	OP_EXPORTSAME },
163*40393Sbostic { ".IGNORE",	  Ignore,   	OP_IGNORE },
164*40393Sbostic { ".INCLUDES",	  Includes, 	0 },
165*40393Sbostic { ".INTERRUPT",	  Interrupt,	0 },
166*40393Sbostic { ".INVISIBLE",	  Attribute,   	OP_INVISIBLE },
167*40393Sbostic { ".JOIN",  	  Attribute,   	OP_JOIN },
168*40393Sbostic { ".LIBS",  	  Libs,	    	0 },
169*40393Sbostic { ".M68020",	  Attribute,	OP_M68020 },
170*40393Sbostic { ".MAIN",	  Main,		0 },
171*40393Sbostic { ".MAKE",  	  Attribute,   	OP_MAKE },
172*40393Sbostic { ".MAKEFLAGS",	  MFlags,   	0 },
173*40393Sbostic { ".MFLAGS",	  MFlags,   	0 },
174*40393Sbostic { ".NOEXPORT",	  NoExport,   	OP_NOEXPORT },
175*40393Sbostic { ".NOTMAIN",	  Attribute,   	OP_NOTMAIN },
176*40393Sbostic { ".NOTPARALLEL", NotParallel,	0 },
177*40393Sbostic { ".NULL",  	  Null,	    	0 },
178*40393Sbostic { ".ORDER", 	  Order,    	0 },
179*40393Sbostic { ".PATH",	  Path,		0 },
180*40393Sbostic { ".PRECIOUS",	  Precious, 	OP_PRECIOUS },
181*40393Sbostic { ".RECURSIVE",	  Attribute,	OP_MAKE },
182*40393Sbostic { ".SHELL", 	  Shell,    	0 },
183*40393Sbostic { ".SILENT",	  Silent,   	OP_SILENT },
184*40393Sbostic { ".SINGLESHELL", SingleShell,	0 },
185*40393Sbostic { ".SUFFIXES",	  Suffixes, 	0 },
186*40393Sbostic { ".USE",   	  Attribute,   	OP_USE },
187*40393Sbostic };
188*40393Sbostic 
189*40393Sbostic /*-
190*40393Sbostic  *----------------------------------------------------------------------
191*40393Sbostic  * ParseFindKeyword --
192*40393Sbostic  *	Look in the table of keywords for one matching the given string.
193*40393Sbostic  *
194*40393Sbostic  * Results:
195*40393Sbostic  *	The index of the keyword, or -1 if it isn't there.
196*40393Sbostic  *
197*40393Sbostic  * Side Effects:
198*40393Sbostic  *	None
199*40393Sbostic  *----------------------------------------------------------------------
200*40393Sbostic  */
201*40393Sbostic static int
202*40393Sbostic ParseFindKeyword (str)
203*40393Sbostic     char	    *str;		/* String to find */
204*40393Sbostic {
205*40393Sbostic     register int    start,
206*40393Sbostic 		    end,
207*40393Sbostic 		    cur;
208*40393Sbostic     register int    diff;
209*40393Sbostic 
210*40393Sbostic     start = 0;
211*40393Sbostic     end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
212*40393Sbostic 
213*40393Sbostic     do {
214*40393Sbostic 	cur = start + ((end - start) / 2);
215*40393Sbostic 	diff = strcmp (str, parseKeywords[cur].name);
216*40393Sbostic 
217*40393Sbostic 	if (diff == 0) {
218*40393Sbostic 	    return (cur);
219*40393Sbostic 	} else if (diff < 0) {
220*40393Sbostic 	    end = cur - 1;
221*40393Sbostic 	} else {
222*40393Sbostic 	    start = cur + 1;
223*40393Sbostic 	}
224*40393Sbostic     } while (start <= end);
225*40393Sbostic     return (-1);
226*40393Sbostic }
227*40393Sbostic 
228*40393Sbostic /*-
229*40393Sbostic  *---------------------------------------------------------------------
230*40393Sbostic  * Parse_Error  --
231*40393Sbostic  *	Error message abort function for parsing. Prints out the context
232*40393Sbostic  *	of the error (line number and file) as well as the message with
233*40393Sbostic  *	two optional arguments.
234*40393Sbostic  *
235*40393Sbostic  * Results:
236*40393Sbostic  *	None
237*40393Sbostic  *
238*40393Sbostic  * Side Effects:
239*40393Sbostic  *	"fatals" is incremented if the level is PARSE_FATAL.
240*40393Sbostic  *---------------------------------------------------------------------
241*40393Sbostic  */
242*40393Sbostic /* VARARGS1 */
243*40393Sbostic void
244*40393Sbostic Parse_Error (type, fmt, arg1, arg2)
245*40393Sbostic     int	    	  type;	/* Error type: PARSE_WARNING if just a warning,
246*40393Sbostic 			 * PARSE_FATAL if can't continue (after parsing) */
247*40393Sbostic     char          *fmt;	/* printf format string */
248*40393Sbostic     int     	  arg1;	/* First optional argument for the fmt string */
249*40393Sbostic     int	    	  arg2;	/* Second optional argument for the fmt string */
250*40393Sbostic {
251*40393Sbostic     if ((type != PARSE_WARNING) || !noWarnings) {
252*40393Sbostic 	fprintf (stderr, "\"%s\", line %d: ", fname, lineno);
253*40393Sbostic 	if (type == PARSE_WARNING) {
254*40393Sbostic 	    fprintf (stderr, "Warning: ");
255*40393Sbostic 	}
256*40393Sbostic 	fprintf (stderr, fmt, arg1, arg2);
257*40393Sbostic 	putc ('\n', stderr);
258*40393Sbostic 
259*40393Sbostic 	if (type == PARSE_FATAL) {
260*40393Sbostic 	    fatals += 1;
261*40393Sbostic 	}
262*40393Sbostic     }
263*40393Sbostic }
264*40393Sbostic 
265*40393Sbostic /*-
266*40393Sbostic  *-----------------------------------------------------------------------
267*40393Sbostic  * Parse_AnyExport --
268*40393Sbostic  *	Return TRUE if any target was labeled for exportation.
269*40393Sbostic  *
270*40393Sbostic  * Results:
271*40393Sbostic  *	TRUE or FALSE...
272*40393Sbostic  *
273*40393Sbostic  * Side Effects:
274*40393Sbostic  *	None.
275*40393Sbostic  *
276*40393Sbostic  *-----------------------------------------------------------------------
277*40393Sbostic  */
278*40393Sbostic Boolean
279*40393Sbostic Parse_AnyExport()
280*40393Sbostic {
281*40393Sbostic     return (anyExport);
282*40393Sbostic }
283*40393Sbostic 
284*40393Sbostic /*-
285*40393Sbostic  *---------------------------------------------------------------------
286*40393Sbostic  * ParseLinkSrc  --
287*40393Sbostic  *	Link the parent node to its new child. Used in a Lst_ForEach by
288*40393Sbostic  *	ParseDoDependency. If the specType isn't 'Not', the parent
289*40393Sbostic  *	isn't linked as a parent of the child.
290*40393Sbostic  *
291*40393Sbostic  * Results:
292*40393Sbostic  *	Always = 0
293*40393Sbostic  *
294*40393Sbostic  * Side Effects:
295*40393Sbostic  *	New elements are added to the parents list of cgn and the
296*40393Sbostic  *	children list of cgn. the unmade field of pgn is updated
297*40393Sbostic  *	to reflect the additional child.
298*40393Sbostic  *---------------------------------------------------------------------
299*40393Sbostic  */
300*40393Sbostic static int
301*40393Sbostic ParseLinkSrc (pgn, cgn)
302*40393Sbostic     GNode          *pgn;	/* The parent node */
303*40393Sbostic     GNode          *cgn;	/* The child node */
304*40393Sbostic {
305*40393Sbostic     if (Lst_Member (pgn->children, (ClientData)cgn) == NILLNODE) {
306*40393Sbostic 	(void)Lst_AtEnd (pgn->children, (ClientData)cgn);
307*40393Sbostic 	if (specType == Not) {
308*40393Sbostic 	    (void)Lst_AtEnd (cgn->parents, (ClientData)pgn);
309*40393Sbostic 	}
310*40393Sbostic 	pgn->unmade += 1;
311*40393Sbostic     }
312*40393Sbostic     return (0);
313*40393Sbostic }
314*40393Sbostic 
315*40393Sbostic /*-
316*40393Sbostic  *---------------------------------------------------------------------
317*40393Sbostic  * ParseDoOp  --
318*40393Sbostic  *	Apply the parsed operator to the given target node. Used in a
319*40393Sbostic  *	Lst_ForEach call by ParseDoDependency once all targets have
320*40393Sbostic  *	been found and their operator parsed. If the previous and new
321*40393Sbostic  *	operators are incompatible, a major error is taken.
322*40393Sbostic  *
323*40393Sbostic  * Results:
324*40393Sbostic  *	Always 0
325*40393Sbostic  *
326*40393Sbostic  * Side Effects:
327*40393Sbostic  *	The type field of the node is altered to reflect any new bits in
328*40393Sbostic  *	the op.
329*40393Sbostic  *---------------------------------------------------------------------
330*40393Sbostic  */
331*40393Sbostic static int
332*40393Sbostic ParseDoOp (gn, op)
333*40393Sbostic     GNode          *gn;		/* The node to which the operator is to be
334*40393Sbostic 				 * applied */
335*40393Sbostic     int             op;		/* The operator to apply */
336*40393Sbostic {
337*40393Sbostic     /*
338*40393Sbostic      * If the dependency mask of the operator and the node don't match and
339*40393Sbostic      * the node has actually had an operator applied to it before, and
340*40393Sbostic      * the operator actually has some dependency information in it, complain.
341*40393Sbostic      */
342*40393Sbostic     if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
343*40393Sbostic 	!OP_NOP(gn->type) && !OP_NOP(op))
344*40393Sbostic     {
345*40393Sbostic 	Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name);
346*40393Sbostic 	return (1);
347*40393Sbostic     }
348*40393Sbostic 
349*40393Sbostic     if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
350*40393Sbostic 	/*
351*40393Sbostic 	 * If the node was the object of a :: operator, we need to create a
352*40393Sbostic 	 * new instance of it for the children and commands on this dependency
353*40393Sbostic 	 * line. The new instance is placed on the 'cohorts' list of the
354*40393Sbostic 	 * initial one (note the initial one is not on its own cohorts list)
355*40393Sbostic 	 * and the new instance is linked to all parents of the initial
356*40393Sbostic 	 * instance.
357*40393Sbostic 	 */
358*40393Sbostic 	register GNode	*cohort;
359*40393Sbostic 	LstNode	    	ln;
360*40393Sbostic 
361*40393Sbostic 	cohort = Targ_NewGN(gn->name);
362*40393Sbostic 	/*
363*40393Sbostic 	 * Duplicate links to parents so graph traversal is simple. Perhaps
364*40393Sbostic 	 * some type bits should be duplicated?
365*40393Sbostic 	 *
366*40393Sbostic 	 * Make the cohort invisible as well to avoid duplicating it into
367*40393Sbostic 	 * other variables. True, parents of this target won't tend to do
368*40393Sbostic 	 * anything with their local variables, but better safe than
369*40393Sbostic 	 * sorry.
370*40393Sbostic 	 */
371*40393Sbostic 	Lst_ForEach(gn->parents, ParseLinkSrc, (ClientData)cohort);
372*40393Sbostic 	cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
373*40393Sbostic 	(void)Lst_AtEnd(gn->cohorts, (ClientData)cohort);
374*40393Sbostic 
375*40393Sbostic 	/*
376*40393Sbostic 	 * Replace the node in the targets list with the new copy
377*40393Sbostic 	 */
378*40393Sbostic 	ln = Lst_Member(targets, (ClientData)gn);
379*40393Sbostic 	Lst_Replace(ln, (ClientData)cohort);
380*40393Sbostic 	gn = cohort;
381*40393Sbostic     }
382*40393Sbostic     /*
383*40393Sbostic      * We don't want to nuke any previous flags (whatever they were) so we
384*40393Sbostic      * just OR the new operator into the old
385*40393Sbostic      */
386*40393Sbostic     gn->type |= op;
387*40393Sbostic 
388*40393Sbostic     return (0);
389*40393Sbostic }
390*40393Sbostic 
391*40393Sbostic /*-
392*40393Sbostic  *---------------------------------------------------------------------
393*40393Sbostic  * ParseDoSrc  --
394*40393Sbostic  *	Given the name of a source, figure out if it is an attribute
395*40393Sbostic  *	and apply it to the targets if it is. Else decide if there is
396*40393Sbostic  *	some attribute which should be applied *to* the source because
397*40393Sbostic  *	of some special target and apply it if so. Otherwise, make the
398*40393Sbostic  *	source be a child of the targets in the list 'targets'
399*40393Sbostic  *
400*40393Sbostic  * Results:
401*40393Sbostic  *	None
402*40393Sbostic  *
403*40393Sbostic  * Side Effects:
404*40393Sbostic  *	Operator bits may be added to the list of targets or to the source.
405*40393Sbostic  *	The targets may have a new source added to their lists of children.
406*40393Sbostic  *---------------------------------------------------------------------
407*40393Sbostic  */
408*40393Sbostic static void
409*40393Sbostic ParseDoSrc (tOp, src)
410*40393Sbostic     int		tOp;	/* operator (if any) from special targets */
411*40393Sbostic     char	*src;	/* name of the source to handle */
412*40393Sbostic {
413*40393Sbostic     int		op;	/* operator (if any) from special source */
414*40393Sbostic     GNode	*gn;
415*40393Sbostic 
416*40393Sbostic     op = 0;
417*40393Sbostic     if (*src == '.' && isupper (src[1])) {
418*40393Sbostic 	int keywd = ParseFindKeyword(src);
419*40393Sbostic 	if (keywd != -1) {
420*40393Sbostic 	    op = parseKeywords[keywd].op;
421*40393Sbostic 	}
422*40393Sbostic     }
423*40393Sbostic     if (op != 0) {
424*40393Sbostic 	Lst_ForEach (targets, ParseDoOp, (ClientData)op);
425*40393Sbostic 	if (op == OP_EXPORT) {
426*40393Sbostic 	    anyExport = TRUE;
427*40393Sbostic 	}
428*40393Sbostic     } else if (specType == Main) {
429*40393Sbostic 	/*
430*40393Sbostic 	 * If we have noted the existence of a .MAIN, it means we need
431*40393Sbostic 	 * to add the sources of said target to the list of things
432*40393Sbostic 	 * to create. The string 'src' is likely to be free, so we
433*40393Sbostic 	 * must make a new copy of it. Note that this will only be
434*40393Sbostic 	 * invoked if the user didn't specify a target on the command
435*40393Sbostic 	 * line. This is to allow #ifmake's to succeed, or something...
436*40393Sbostic 	 */
437*40393Sbostic 	(void) Lst_AtEnd (create, (ClientData)Str_New(src));
438*40393Sbostic 	/*
439*40393Sbostic 	 * Add the name to the .TARGETS variable as well, so the user cna
440*40393Sbostic 	 * employ that, if desired.
441*40393Sbostic 	 */
442*40393Sbostic 	Var_Append(".TARGETS", src, VAR_GLOBAL);
443*40393Sbostic     } else if (specType == Order) {
444*40393Sbostic 	/*
445*40393Sbostic 	 * Create proper predecessor/successor links between the previous
446*40393Sbostic 	 * source and the current one.
447*40393Sbostic 	 */
448*40393Sbostic 	gn = Targ_FindNode(src, TARG_CREATE);
449*40393Sbostic 	if (predecessor != NILGNODE) {
450*40393Sbostic 	    (void)Lst_AtEnd(predecessor->successors, (ClientData)gn);
451*40393Sbostic 	    (void)Lst_AtEnd(gn->preds, (ClientData)predecessor);
452*40393Sbostic 	}
453*40393Sbostic 	/*
454*40393Sbostic 	 * The current source now becomes the predecessor for the next one.
455*40393Sbostic 	 */
456*40393Sbostic 	predecessor = gn;
457*40393Sbostic     } else {
458*40393Sbostic 	/*
459*40393Sbostic 	 * If the source is not an attribute, we need to find/create
460*40393Sbostic 	 * a node for it. After that we can apply any operator to it
461*40393Sbostic 	 * from a special target or link it to its parents, as
462*40393Sbostic 	 * appropriate.
463*40393Sbostic 	 *
464*40393Sbostic 	 * In the case of a source that was the object of a :: operator,
465*40393Sbostic 	 * the attribute is applied to all of its instances (as kept in
466*40393Sbostic 	 * the 'cohorts' list of the node) or all the cohorts are linked
467*40393Sbostic 	 * to all the targets.
468*40393Sbostic 	 */
469*40393Sbostic 	gn = Targ_FindNode (src, TARG_CREATE);
470*40393Sbostic 	if (tOp) {
471*40393Sbostic 	    gn->type |= tOp;
472*40393Sbostic 	} else {
473*40393Sbostic 	    Lst_ForEach (targets, ParseLinkSrc, (ClientData)gn);
474*40393Sbostic 	}
475*40393Sbostic 	if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
476*40393Sbostic 	    register GNode  	*cohort;
477*40393Sbostic 	    register LstNode	ln;
478*40393Sbostic 
479*40393Sbostic 	    for (ln=Lst_First(gn->cohorts); ln != NILLNODE; ln = Lst_Succ(ln)){
480*40393Sbostic 		cohort = (GNode *)Lst_Datum(ln);
481*40393Sbostic 		if (tOp) {
482*40393Sbostic 		    cohort->type |= tOp;
483*40393Sbostic 		} else {
484*40393Sbostic 		    Lst_ForEach(targets, ParseLinkSrc, (ClientData)cohort);
485*40393Sbostic 		}
486*40393Sbostic 	    }
487*40393Sbostic 	}
488*40393Sbostic     }
489*40393Sbostic }
490*40393Sbostic 
491*40393Sbostic /*-
492*40393Sbostic  *-----------------------------------------------------------------------
493*40393Sbostic  * ParseFindMain --
494*40393Sbostic  *	Find a real target in the list and set it to be the main one.
495*40393Sbostic  *	Called by ParseDoDependency when a main target hasn't been found
496*40393Sbostic  *	yet.
497*40393Sbostic  *
498*40393Sbostic  * Results:
499*40393Sbostic  *	0 if main not found yet, 1 if it is.
500*40393Sbostic  *
501*40393Sbostic  * Side Effects:
502*40393Sbostic  *	mainNode is changed and Targ_SetMain is called.
503*40393Sbostic  *
504*40393Sbostic  *-----------------------------------------------------------------------
505*40393Sbostic  */
506*40393Sbostic static int
507*40393Sbostic ParseFindMain(gn)
508*40393Sbostic     GNode   	  *gn;	    /* Node to examine */
509*40393Sbostic {
510*40393Sbostic     if ((gn->type & (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)) == 0) {
511*40393Sbostic 	mainNode = gn;
512*40393Sbostic 	Targ_SetMain(gn);
513*40393Sbostic 	return (1);
514*40393Sbostic     } else {
515*40393Sbostic 	return (0);
516*40393Sbostic     }
517*40393Sbostic }
518*40393Sbostic 
519*40393Sbostic /*-
520*40393Sbostic  *-----------------------------------------------------------------------
521*40393Sbostic  * ParseAddDir --
522*40393Sbostic  *	Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
523*40393Sbostic  *
524*40393Sbostic  * Results:
525*40393Sbostic  *	=== 0
526*40393Sbostic  *
527*40393Sbostic  * Side Effects:
528*40393Sbostic  *	See Dir_AddDir.
529*40393Sbostic  *
530*40393Sbostic  *-----------------------------------------------------------------------
531*40393Sbostic  */
532*40393Sbostic static int
533*40393Sbostic ParseAddDir(path, name)
534*40393Sbostic     Lst	    path;
535*40393Sbostic     char    *name;
536*40393Sbostic {
537*40393Sbostic     Dir_AddDir(path, name);
538*40393Sbostic     return(0);
539*40393Sbostic }
540*40393Sbostic 
541*40393Sbostic /*-
542*40393Sbostic  *-----------------------------------------------------------------------
543*40393Sbostic  * ParseClearPath --
544*40393Sbostic  *	Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
545*40393Sbostic  *
546*40393Sbostic  * Results:
547*40393Sbostic  *	=== 0
548*40393Sbostic  *
549*40393Sbostic  * Side Effects:
550*40393Sbostic  *	See Dir_ClearPath
551*40393Sbostic  *
552*40393Sbostic  *-----------------------------------------------------------------------
553*40393Sbostic  */
554*40393Sbostic static int
555*40393Sbostic ParseClearPath(path)
556*40393Sbostic     Lst	    path;
557*40393Sbostic {
558*40393Sbostic     Dir_ClearPath(path);
559*40393Sbostic     return(0);
560*40393Sbostic }
561*40393Sbostic 
562*40393Sbostic /*-
563*40393Sbostic  *---------------------------------------------------------------------
564*40393Sbostic  * ParseDoDependency  --
565*40393Sbostic  *	Parse the dependency line in line.
566*40393Sbostic  *
567*40393Sbostic  * Results:
568*40393Sbostic  *	None
569*40393Sbostic  *
570*40393Sbostic  * Side Effects:
571*40393Sbostic  *	The nodes of the sources are linked as children to the nodes of the
572*40393Sbostic  *	targets. Some nodes may be created.
573*40393Sbostic  *
574*40393Sbostic  *	We parse a dependency line by first extracting words from the line and
575*40393Sbostic  * finding nodes in the list of all targets with that name. This is done
576*40393Sbostic  * until a character is encountered which is an operator character. Currently
577*40393Sbostic  * these are only ! and :. At this point the operator is parsed and the
578*40393Sbostic  * pointer into the line advanced until the first source is encountered.
579*40393Sbostic  * 	The parsed operator is applied to each node in the 'targets' list,
580*40393Sbostic  * which is where the nodes found for the targets are kept, by means of
581*40393Sbostic  * the ParseDoOp function.
582*40393Sbostic  *	The sources are read in much the same way as the targets were except
583*40393Sbostic  * that now they are expanded using the wildcarding scheme of the C-Shell
584*40393Sbostic  * and all instances of the resulting words in the list of all targets
585*40393Sbostic  * are found. Each of the resulting nodes is then linked to each of the
586*40393Sbostic  * targets as one of its children.
587*40393Sbostic  *	Certain targets are handled specially. These are the ones detailed
588*40393Sbostic  * by the specType variable.
589*40393Sbostic  *	The storing of transformation rules is also taken care of here.
590*40393Sbostic  * A target is recognized as a transformation rule by calling
591*40393Sbostic  * Suff_IsTransform. If it is a transformation rule, its node is gotten
592*40393Sbostic  * from the suffix module via Suff_AddTransform rather than the standard
593*40393Sbostic  * Targ_FindNode in the target module.
594*40393Sbostic  *---------------------------------------------------------------------
595*40393Sbostic  */
596*40393Sbostic static void
597*40393Sbostic ParseDoDependency (line)
598*40393Sbostic     char           *line;	/* the line to parse */
599*40393Sbostic {
600*40393Sbostic     register char  *cp;		/* our current position */
601*40393Sbostic     register GNode *gn;		/* a general purpose temporary node */
602*40393Sbostic     register int    op;		/* the operator on the line */
603*40393Sbostic     char            savec;	/* a place to save a character */
604*40393Sbostic     Lst    	    paths;   	/* List of search paths to alter when parsing
605*40393Sbostic 				 * a list of .PATH targets */
606*40393Sbostic     int	    	    tOp;    	/* operator from special target */
607*40393Sbostic     Lst	    	    sources;	/* list of source names after expansion */
608*40393Sbostic     Lst 	    curTargs;	/* list of target names to be found and added
609*40393Sbostic 				 * to the targets list */
610*40393Sbostic 
611*40393Sbostic     tOp = 0;
612*40393Sbostic 
613*40393Sbostic     specType = Not;
614*40393Sbostic     paths = (Lst)NULL;
615*40393Sbostic 
616*40393Sbostic     curTargs = Lst_Init(FALSE);
617*40393Sbostic 
618*40393Sbostic     do {
619*40393Sbostic 	for (cp = line;
620*40393Sbostic 	     *cp && !isspace (*cp) &&
621*40393Sbostic 	     (*cp != '!') && (*cp != ':') && (*cp != '(');
622*40393Sbostic 	     cp++)
623*40393Sbostic 	{
624*40393Sbostic 	    if (*cp == '$') {
625*40393Sbostic 		/*
626*40393Sbostic 		 * Must be a dynamic source (would have been expanded
627*40393Sbostic 		 * otherwise), so call the Var module to parse the puppy
628*40393Sbostic 		 * so we can safely advance beyond it...There should be
629*40393Sbostic 		 * no errors in this, as they would have been discovered
630*40393Sbostic 		 * in the initial Var_Subst and we wouldn't be here.
631*40393Sbostic 		 */
632*40393Sbostic 		int 	length;
633*40393Sbostic 		Boolean	freeIt;
634*40393Sbostic 		char	*result;
635*40393Sbostic 
636*40393Sbostic 		result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
637*40393Sbostic 
638*40393Sbostic 		if (freeIt) {
639*40393Sbostic 		    free(result);
640*40393Sbostic 		}
641*40393Sbostic 		cp += length-1;
642*40393Sbostic 	    }
643*40393Sbostic 	    continue;
644*40393Sbostic 	}
645*40393Sbostic 	if (*cp == '(') {
646*40393Sbostic 	    /*
647*40393Sbostic 	     * Archives must be handled specially to make sure the OP_ARCHV
648*40393Sbostic 	     * flag is set in their 'type' field, for one thing, and because
649*40393Sbostic 	     * things like "archive(file1.o file2.o file3.o)" are permissible.
650*40393Sbostic 	     * Arch_ParseArchive will set 'line' to be the first non-blank
651*40393Sbostic 	     * after the archive-spec. It creates/finds nodes for the members
652*40393Sbostic 	     * and places them on the given list, returning SUCCESS if all
653*40393Sbostic 	     * went well and FAILURE if there was an error in the
654*40393Sbostic 	     * specification. On error, line should remain untouched.
655*40393Sbostic 	     */
656*40393Sbostic 	    if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
657*40393Sbostic 		Parse_Error (PARSE_FATAL,
658*40393Sbostic 			     "Error in archive specification: \"%s\"", line);
659*40393Sbostic 		return;
660*40393Sbostic 	    } else {
661*40393Sbostic 		continue;
662*40393Sbostic 	    }
663*40393Sbostic 	}
664*40393Sbostic 	savec = *cp;
665*40393Sbostic 
666*40393Sbostic 	if (!*cp) {
667*40393Sbostic 	    /*
668*40393Sbostic 	     * Ending a dependency line without an operator is a Bozo
669*40393Sbostic 	     * no-no
670*40393Sbostic 	     */
671*40393Sbostic 	    Parse_Error (PARSE_FATAL, "Need an operator");
672*40393Sbostic 	    return;
673*40393Sbostic 	}
674*40393Sbostic 	*cp = '\0';
675*40393Sbostic 	/*
676*40393Sbostic 	 * Have a word in line. See if it's a special target and set
677*40393Sbostic 	 * specType to match it.
678*40393Sbostic 	 */
679*40393Sbostic 	if (*line == '.' && isupper (line[1])) {
680*40393Sbostic 	    /*
681*40393Sbostic 	     * See if the target is a special target that must have it
682*40393Sbostic 	     * or its sources handled specially.
683*40393Sbostic 	     */
684*40393Sbostic 	    int keywd = ParseFindKeyword(line);
685*40393Sbostic 	    if (keywd != -1) {
686*40393Sbostic 		if (specType == Path && parseKeywords[keywd].spec != Path) {
687*40393Sbostic 		    Parse_Error(PARSE_FATAL, "Mismatched special targets");
688*40393Sbostic 		    return;
689*40393Sbostic 		}
690*40393Sbostic 
691*40393Sbostic 		specType = parseKeywords[keywd].spec;
692*40393Sbostic 		tOp = parseKeywords[keywd].op;
693*40393Sbostic 
694*40393Sbostic 		/*
695*40393Sbostic 		 * Certain special targets have special semantics:
696*40393Sbostic 		 *	.PATH		Have to set the dirSearchPath
697*40393Sbostic 		 *			variable too
698*40393Sbostic 		 *	.EXPORT		Doesn't really apply the
699*40393Sbostic 		 *			.EXPORT operator to its
700*40393Sbostic 		 *			sources, so we reset tOp.
701*40393Sbostic 		 *	.MAIN		Its sources are only used if
702*40393Sbostic 		 *			nothing has been specified to
703*40393Sbostic 		 *			create.
704*40393Sbostic 		 *	.DEFAULT    	Need to create a node to hang
705*40393Sbostic 		 *			commands on, but we don't want
706*40393Sbostic 		 *			it in the graph, nor do we want
707*40393Sbostic 		 *			it to be the Main Target, so we
708*40393Sbostic 		 *			create it, set OP_NOTMAIN and
709*40393Sbostic 		 *			add it to the list, setting
710*40393Sbostic 		 *			DEFAULT to the new node for
711*40393Sbostic 		 *			later use. We claim the node is
712*40393Sbostic 		 *	    	    	A transformation rule to make
713*40393Sbostic 		 *	    	    	life easier later, when we'll
714*40393Sbostic 		 *	    	    	use Make_HandleUse to actually
715*40393Sbostic 		 *	    	    	apply the .DEFAULT commands.
716*40393Sbostic 		 *	.BEGIN
717*40393Sbostic 		 *	.END
718*40393Sbostic 		 *	.INTERRUPT  	Are not to be considered the
719*40393Sbostic 		 *			main target.
720*40393Sbostic 		 *  	.NOTPARALLEL	Make only one target at a time.
721*40393Sbostic 		 *  	.SINGLESHELL	Create a shell for each command.
722*40393Sbostic 		 *  	.ORDER	    	Must set initial predecessor to NIL
723*40393Sbostic 		 */
724*40393Sbostic 		switch (specType) {
725*40393Sbostic 		    case Path:
726*40393Sbostic 			if (paths == NULL) {
727*40393Sbostic 			    paths = Lst_Init(FALSE);
728*40393Sbostic 			}
729*40393Sbostic 			(void)Lst_AtEnd(paths, (ClientData)dirSearchPath);
730*40393Sbostic 			break;
731*40393Sbostic 		    case Export:
732*40393Sbostic 			tOp = 0;
733*40393Sbostic 			break;
734*40393Sbostic 		    case Main:
735*40393Sbostic 			if (!Lst_IsEmpty(create)) {
736*40393Sbostic 			    specType = Not;
737*40393Sbostic 			}
738*40393Sbostic 			break;
739*40393Sbostic 		    case Begin:
740*40393Sbostic 		    case End:
741*40393Sbostic 		    case Interrupt:
742*40393Sbostic 			gn = Targ_FindNode(line, TARG_CREATE);
743*40393Sbostic 			gn->type |= OP_NOTMAIN;
744*40393Sbostic 			(void)Lst_AtEnd(targets, (ClientData)gn);
745*40393Sbostic 			break;
746*40393Sbostic 		    case Default:
747*40393Sbostic 			gn = Targ_NewGN(".DEFAULT");
748*40393Sbostic 			gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
749*40393Sbostic 			(void)Lst_AtEnd(targets, (ClientData)gn);
750*40393Sbostic 			DEFAULT = gn;
751*40393Sbostic 			break;
752*40393Sbostic 		    case NotParallel:
753*40393Sbostic 		    {
754*40393Sbostic 			extern int  maxJobs;
755*40393Sbostic 
756*40393Sbostic 			maxJobs = 1;
757*40393Sbostic 			break;
758*40393Sbostic 		    }
759*40393Sbostic 		    case SingleShell:
760*40393Sbostic 			backwards = 1;
761*40393Sbostic 			break;
762*40393Sbostic 		    case Order:
763*40393Sbostic 			predecessor = NILGNODE;
764*40393Sbostic 			break;
765*40393Sbostic 		}
766*40393Sbostic 	    } else if (strncmp (line, ".PATH", 5) == 0) {
767*40393Sbostic 		/*
768*40393Sbostic 		 * .PATH<suffix> has to be handled specially.
769*40393Sbostic 		 * Call on the suffix module to give us a path to
770*40393Sbostic 		 * modify.
771*40393Sbostic 		 */
772*40393Sbostic 		Lst 	path;
773*40393Sbostic 
774*40393Sbostic 		specType = Path;
775*40393Sbostic 		path = Suff_GetPath (&line[5]);
776*40393Sbostic 		if (path == NILLST) {
777*40393Sbostic 		    Parse_Error (PARSE_FATAL,
778*40393Sbostic 				 "Suffix '%s' not defined (yet)",
779*40393Sbostic 				 &line[5]);
780*40393Sbostic 		    return;
781*40393Sbostic 		} else {
782*40393Sbostic 		    if (paths == (Lst)NULL) {
783*40393Sbostic 			paths = Lst_Init(FALSE);
784*40393Sbostic 		    }
785*40393Sbostic 		    (void)Lst_AtEnd(paths, (ClientData)path);
786*40393Sbostic 		}
787*40393Sbostic 	    }
788*40393Sbostic 	}
789*40393Sbostic 
790*40393Sbostic 	/*
791*40393Sbostic 	 * Have word in line. Get or create its node and stick it at
792*40393Sbostic 	 * the end of the targets list
793*40393Sbostic 	 */
794*40393Sbostic 	if ((specType == Not) && (*line != '\0')) {
795*40393Sbostic 	    if (Dir_HasWildcards(line)) {
796*40393Sbostic 		/*
797*40393Sbostic 		 * Targets are to be sought only in the current directory,
798*40393Sbostic 		 * so create an empty path for the thing. Note we need to
799*40393Sbostic 		 * use Dir_Destroy in the destruction of the path as the
800*40393Sbostic 		 * Dir module could have added a directory to the path...
801*40393Sbostic 		 */
802*40393Sbostic 		Lst	    emptyPath = Lst_Init(FALSE);
803*40393Sbostic 
804*40393Sbostic 		Dir_Expand(line, emptyPath, curTargs);
805*40393Sbostic 
806*40393Sbostic 		Lst_Destroy(emptyPath, Dir_Destroy);
807*40393Sbostic 	    } else {
808*40393Sbostic 		/*
809*40393Sbostic 		 * No wildcards, but we want to avoid code duplication,
810*40393Sbostic 		 * so create a list with the word on it.
811*40393Sbostic 		 */
812*40393Sbostic 		(void)Lst_AtEnd(curTargs, (ClientData)line);
813*40393Sbostic 	    }
814*40393Sbostic 
815*40393Sbostic 	    while(!Lst_IsEmpty(curTargs)) {
816*40393Sbostic 		char	*targName = (char *)Lst_DeQueue(curTargs);
817*40393Sbostic 
818*40393Sbostic 		if (!Suff_IsTransform (targName)) {
819*40393Sbostic 		    gn = Targ_FindNode (targName, TARG_CREATE);
820*40393Sbostic 		} else {
821*40393Sbostic 		    gn = Suff_AddTransform (targName);
822*40393Sbostic 		}
823*40393Sbostic 
824*40393Sbostic 		(void)Lst_AtEnd (targets, (ClientData)gn);
825*40393Sbostic 	    }
826*40393Sbostic 	} else if (specType == Path && *line != '.' && *line != '\0') {
827*40393Sbostic 	    Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
828*40393Sbostic 	}
829*40393Sbostic 
830*40393Sbostic 	*cp = savec;
831*40393Sbostic 	/*
832*40393Sbostic 	 * If it is a special type and not .PATH, it's the only target we
833*40393Sbostic 	 * allow on this line...
834*40393Sbostic 	 */
835*40393Sbostic 	if (specType != Not && specType != Path) {
836*40393Sbostic 	    Boolean warn = FALSE;
837*40393Sbostic 
838*40393Sbostic 	    while ((*cp != '!') && (*cp != ':') && *cp) {
839*40393Sbostic 		if (*cp != ' ' && *cp != '\t') {
840*40393Sbostic 		    warn = TRUE;
841*40393Sbostic 		}
842*40393Sbostic 		cp++;
843*40393Sbostic 	    }
844*40393Sbostic 	    if (warn) {
845*40393Sbostic 		Parse_Error(PARSE_WARNING, "Extra target ignored");
846*40393Sbostic 	    }
847*40393Sbostic 	} else {
848*40393Sbostic 	    while (*cp && isspace (*cp)) {
849*40393Sbostic 		cp++;
850*40393Sbostic 	    }
851*40393Sbostic 	}
852*40393Sbostic 	line = cp;
853*40393Sbostic     } while ((*line != '!') && (*line != ':') && *line);
854*40393Sbostic 
855*40393Sbostic     /*
856*40393Sbostic      * Don't need the list of target names anymore...
857*40393Sbostic      */
858*40393Sbostic     Lst_Destroy(curTargs, NOFREE);
859*40393Sbostic 
860*40393Sbostic     if (!Lst_IsEmpty(targets)) {
861*40393Sbostic 	switch(specType) {
862*40393Sbostic 	    default:
863*40393Sbostic 		Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
864*40393Sbostic 		break;
865*40393Sbostic 	    case Default:
866*40393Sbostic 	    case Begin:
867*40393Sbostic 	    case End:
868*40393Sbostic 	    case Interrupt:
869*40393Sbostic 		/*
870*40393Sbostic 		 * These four create nodes on which to hang commands, so
871*40393Sbostic 		 * targets shouldn't be empty...
872*40393Sbostic 		 */
873*40393Sbostic 	    case Not:
874*40393Sbostic 		/*
875*40393Sbostic 		 * Nothing special here -- targets can be empty if it wants.
876*40393Sbostic 		 */
877*40393Sbostic 		break;
878*40393Sbostic 	}
879*40393Sbostic     }
880*40393Sbostic 
881*40393Sbostic     /*
882*40393Sbostic      * Have now parsed all the target names. Must parse the operator next. The
883*40393Sbostic      * result is left in  op .
884*40393Sbostic      */
885*40393Sbostic     if (*cp == '!') {
886*40393Sbostic 	op = OP_FORCE;
887*40393Sbostic     } else if (*cp == ':') {
888*40393Sbostic 	if (cp[1] == ':') {
889*40393Sbostic 	    op = OP_DOUBLEDEP;
890*40393Sbostic 	    cp++;
891*40393Sbostic 	} else {
892*40393Sbostic 	    op = OP_DEPENDS;
893*40393Sbostic 	}
894*40393Sbostic     } else {
895*40393Sbostic 	Parse_Error (PARSE_FATAL, "Missing dependency operator");
896*40393Sbostic 	return;
897*40393Sbostic     }
898*40393Sbostic 
899*40393Sbostic     cp++;			/* Advance beyond operator */
900*40393Sbostic 
901*40393Sbostic     Lst_ForEach (targets, ParseDoOp, (ClientData)op);
902*40393Sbostic 
903*40393Sbostic     /*
904*40393Sbostic      * Get to the first source
905*40393Sbostic      */
906*40393Sbostic     while (*cp && isspace (*cp)) {
907*40393Sbostic 	cp++;
908*40393Sbostic     }
909*40393Sbostic     line = cp;
910*40393Sbostic 
911*40393Sbostic     /*
912*40393Sbostic      * Several special targets take different actions if present with no
913*40393Sbostic      * sources:
914*40393Sbostic      *	a .SUFFIXES line with no sources clears out all old suffixes
915*40393Sbostic      *	a .PRECIOUS line makes all targets precious
916*40393Sbostic      *	a .IGNORE line ignores errors for all targets
917*40393Sbostic      *	a .SILENT line creates silence when making all targets
918*40393Sbostic      *	a .PATH removes all directories from the search path(s).
919*40393Sbostic      *	a .NOEXPORT turns off exportation for all jobs.
920*40393Sbostic      */
921*40393Sbostic     if (!*line) {
922*40393Sbostic 	switch (specType) {
923*40393Sbostic 	    case Suffixes:
924*40393Sbostic 		Suff_ClearSuffixes ();
925*40393Sbostic 		break;
926*40393Sbostic 	    case Precious:
927*40393Sbostic 		allPrecious = TRUE;
928*40393Sbostic 		break;
929*40393Sbostic 	    case Ignore:
930*40393Sbostic 		ignoreErrors = TRUE;
931*40393Sbostic 		break;
932*40393Sbostic 	    case Silent:
933*40393Sbostic 		beSilent = TRUE;
934*40393Sbostic 		break;
935*40393Sbostic 	    case Path:
936*40393Sbostic 		Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
937*40393Sbostic 		break;
938*40393Sbostic 	    case NoExport:
939*40393Sbostic 		noExport = TRUE;
940*40393Sbostic 		break;
941*40393Sbostic 	}
942*40393Sbostic     } else if (specType == MFlags) {
943*40393Sbostic 	/*
944*40393Sbostic 	 * Call on functions in main.c to deal with these arguments and
945*40393Sbostic 	 * set the initial character to a null-character so the loop to
946*40393Sbostic 	 * get sources won't get anything
947*40393Sbostic 	 */
948*40393Sbostic 	Main_ParseArgLine (line);
949*40393Sbostic 	*line = '\0';
950*40393Sbostic     } else if (specType == Shell) {
951*40393Sbostic 	if (Job_ParseShell (line) != SUCCESS) {
952*40393Sbostic 	    Parse_Error (PARSE_FATAL, "improper shell specification");
953*40393Sbostic 	    return;
954*40393Sbostic 	}
955*40393Sbostic 	*line = '\0';
956*40393Sbostic     } else if ((specType == NotParallel) || (specType == SingleShell)) {
957*40393Sbostic 	*line = '\0';
958*40393Sbostic     }
959*40393Sbostic 
960*40393Sbostic     /*
961*40393Sbostic      * NOW GO FOR THE SOURCES
962*40393Sbostic      */
963*40393Sbostic     if ((specType == Suffixes) || (specType == Path) ||
964*40393Sbostic 	(specType == Includes) || (specType == Libs) ||
965*40393Sbostic 	(specType == Export)   || (specType == Null))
966*40393Sbostic     {
967*40393Sbostic 	while (*line) {
968*40393Sbostic 	    /*
969*40393Sbostic 	     * If the target was one that doesn't take files as its sources
970*40393Sbostic 	     * but takes something like suffixes, we take each
971*40393Sbostic 	     * space-separated word on the line as a something and deal
972*40393Sbostic 	     * with it accordingly.
973*40393Sbostic 	     *
974*40393Sbostic 	     * If the target was .SUFFIXES, we take each source as a
975*40393Sbostic 	     * suffix and add it to the list of suffixes maintained by the
976*40393Sbostic 	     * Suff module.
977*40393Sbostic 	     *
978*40393Sbostic 	     * If the target was a .PATH, we add the source as a directory
979*40393Sbostic 	     * to search on the search path.
980*40393Sbostic 	     *
981*40393Sbostic 	     * If it was .INCLUDES, the source is taken to be the suffix of
982*40393Sbostic 	     * files which will be #included and whose search path should
983*40393Sbostic 	     * be present in the .INCLUDES variable.
984*40393Sbostic 	     *
985*40393Sbostic 	     * If it was .LIBS, the source is taken to be the suffix of
986*40393Sbostic 	     * files which are considered libraries and whose search path
987*40393Sbostic 	     * should be present in the .LIBS variable.
988*40393Sbostic 	     *
989*40393Sbostic 	     * If it was .EXPORT, the source is the location of the export
990*40393Sbostic 	     * server and is passed to the Rmt module as such.
991*40393Sbostic 	     *
992*40393Sbostic 	     * If it was .NULL, the source is the suffix to use when a file
993*40393Sbostic 	     * has no valid suffix.
994*40393Sbostic 	     */
995*40393Sbostic 	    char  savec;
996*40393Sbostic 	    while (*cp && !isspace (*cp)) {
997*40393Sbostic 		cp++;
998*40393Sbostic 	    }
999*40393Sbostic 	    savec = *cp;
1000*40393Sbostic 	    *cp = '\0';
1001*40393Sbostic 	    switch (specType) {
1002*40393Sbostic 		case Suffixes:
1003*40393Sbostic 		    Suff_AddSuffix (line);
1004*40393Sbostic 		    break;
1005*40393Sbostic 		case Path:
1006*40393Sbostic 		    Lst_ForEach(paths, ParseAddDir, (ClientData)line);
1007*40393Sbostic 		    break;
1008*40393Sbostic 		case Includes:
1009*40393Sbostic 		    Suff_AddInclude (line);
1010*40393Sbostic 		    break;
1011*40393Sbostic 		case Libs:
1012*40393Sbostic 		    Suff_AddLib (line);
1013*40393Sbostic 		    break;
1014*40393Sbostic 		case Export:
1015*40393Sbostic 		    Rmt_AddServer (line);
1016*40393Sbostic 		    break;
1017*40393Sbostic 		case Null:
1018*40393Sbostic 		    Suff_SetNull (line);
1019*40393Sbostic 		    break;
1020*40393Sbostic 	    }
1021*40393Sbostic 	    *cp = savec;
1022*40393Sbostic 	    if (savec != '\0') {
1023*40393Sbostic 		cp++;
1024*40393Sbostic 	    }
1025*40393Sbostic 	    while (*cp && isspace (*cp)) {
1026*40393Sbostic 		cp++;
1027*40393Sbostic 	    }
1028*40393Sbostic 	    line = cp;
1029*40393Sbostic 	}
1030*40393Sbostic 	if (paths) {
1031*40393Sbostic 	    Lst_Destroy(paths, NOFREE);
1032*40393Sbostic 	}
1033*40393Sbostic     } else {
1034*40393Sbostic 	while (*line) {
1035*40393Sbostic 	    /*
1036*40393Sbostic 	     * The targets take real sources, so we must beware of archive
1037*40393Sbostic 	     * specifications (i.e. things with left parentheses in them)
1038*40393Sbostic 	     * and handle them accordingly.
1039*40393Sbostic 	     */
1040*40393Sbostic 	    while (*cp && !isspace (*cp)) {
1041*40393Sbostic 		if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
1042*40393Sbostic 		    /*
1043*40393Sbostic 		     * Only stop for a left parenthesis if it isn't at the
1044*40393Sbostic 		     * start of a word (that'll be for variable changes
1045*40393Sbostic 		     * later) and isn't preceded by a dollar sign (a dynamic
1046*40393Sbostic 		     * source).
1047*40393Sbostic 		     */
1048*40393Sbostic 		    break;
1049*40393Sbostic 		} else {
1050*40393Sbostic 		    cp++;
1051*40393Sbostic 		}
1052*40393Sbostic 	    }
1053*40393Sbostic 
1054*40393Sbostic 	    if (*cp == '(') {
1055*40393Sbostic 		GNode	  *gn;
1056*40393Sbostic 
1057*40393Sbostic 		sources = Lst_Init (FALSE);
1058*40393Sbostic 		if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) {
1059*40393Sbostic 		    Parse_Error (PARSE_FATAL,
1060*40393Sbostic 				 "Error in source archive spec \"%s\"", line);
1061*40393Sbostic 		    return;
1062*40393Sbostic 		}
1063*40393Sbostic 
1064*40393Sbostic 		while (!Lst_IsEmpty (sources)) {
1065*40393Sbostic 		    gn = (GNode *) Lst_DeQueue (sources);
1066*40393Sbostic 		    ParseDoSrc (tOp, gn->name);
1067*40393Sbostic 		}
1068*40393Sbostic 		Lst_Destroy (sources, NOFREE);
1069*40393Sbostic 		cp = line;
1070*40393Sbostic 	    } else {
1071*40393Sbostic 		if (*cp) {
1072*40393Sbostic 		    *cp = '\0';
1073*40393Sbostic 		    cp += 1;
1074*40393Sbostic 		}
1075*40393Sbostic 
1076*40393Sbostic 		ParseDoSrc (tOp, line);
1077*40393Sbostic 	    }
1078*40393Sbostic 	    while (*cp && isspace (*cp)) {
1079*40393Sbostic 		cp++;
1080*40393Sbostic 	    }
1081*40393Sbostic 	    line = cp;
1082*40393Sbostic 	}
1083*40393Sbostic     }
1084*40393Sbostic 
1085*40393Sbostic     if (mainNode == NILGNODE) {
1086*40393Sbostic 	/*
1087*40393Sbostic 	 * If we have yet to decide on a main target to make, in the
1088*40393Sbostic 	 * absence of any user input, we want the first target on
1089*40393Sbostic 	 * the first dependency line that is actually a real target
1090*40393Sbostic 	 * (i.e. isn't a .USE or .EXEC rule) to be made.
1091*40393Sbostic 	 */
1092*40393Sbostic 	Lst_ForEach (targets, ParseFindMain, (ClientData)0);
1093*40393Sbostic     }
1094*40393Sbostic 
1095*40393Sbostic }
1096*40393Sbostic 
1097*40393Sbostic /*-
1098*40393Sbostic  *---------------------------------------------------------------------
1099*40393Sbostic  * Parse_IsVar  --
1100*40393Sbostic  *	Return TRUE if the passed line is a variable assignment. A variable
1101*40393Sbostic  *	assignment consists of a single word followed by optional whitespace
1102*40393Sbostic  *	followed by either a += or an = operator.
1103*40393Sbostic  *	This function is used both by the Parse_File function and main when
1104*40393Sbostic  *	parsing the command-line arguments.
1105*40393Sbostic  *
1106*40393Sbostic  * Results:
1107*40393Sbostic  *	TRUE if it is. FALSE if it ain't
1108*40393Sbostic  *
1109*40393Sbostic  * Side Effects:
1110*40393Sbostic  *	none
1111*40393Sbostic  *---------------------------------------------------------------------
1112*40393Sbostic  */
1113*40393Sbostic Boolean
1114*40393Sbostic Parse_IsVar (line)
1115*40393Sbostic     register char  *line;	/* the line to check */
1116*40393Sbostic {
1117*40393Sbostic     register Boolean wasSpace = FALSE;	/* set TRUE if found a space */
1118*40393Sbostic     register Boolean haveName = FALSE;	/* Set TRUE if have a variable name */
1119*40393Sbostic 
1120*40393Sbostic     /*
1121*40393Sbostic      * Skip to variable name
1122*40393Sbostic      */
1123*40393Sbostic     while ((*line == ' ') || (*line == '\t')) {
1124*40393Sbostic 	line++;
1125*40393Sbostic     }
1126*40393Sbostic 
1127*40393Sbostic     while (*line != '=') {
1128*40393Sbostic 	if (*line == '\0') {
1129*40393Sbostic 	    /*
1130*40393Sbostic 	     * end-of-line -- can't be a variable assignment.
1131*40393Sbostic 	     */
1132*40393Sbostic 	    return (FALSE);
1133*40393Sbostic 	} else if ((*line == ' ') || (*line == '\t')) {
1134*40393Sbostic 	    /*
1135*40393Sbostic 	     * there can be as much white space as desired so long as there is
1136*40393Sbostic 	     * only one word before the operator
1137*40393Sbostic 	     */
1138*40393Sbostic 	    wasSpace = TRUE;
1139*40393Sbostic 	} else if (wasSpace && haveName) {
1140*40393Sbostic 	    /*
1141*40393Sbostic 	     * Stop when an = operator is found.
1142*40393Sbostic 	     */
1143*40393Sbostic 	    if ((*line == '+') || (*line == ':') || (*line == '?') ||
1144*40393Sbostic 		(*line == '!')) {
1145*40393Sbostic 		break;
1146*40393Sbostic 	    }
1147*40393Sbostic 
1148*40393Sbostic 	    /*
1149*40393Sbostic 	     * This is the start of another word, so not assignment.
1150*40393Sbostic 	     */
1151*40393Sbostic 	    return (FALSE);
1152*40393Sbostic 	} else {
1153*40393Sbostic 	    haveName = TRUE;
1154*40393Sbostic 	    wasSpace = FALSE;
1155*40393Sbostic 	}
1156*40393Sbostic 	line++;
1157*40393Sbostic     }
1158*40393Sbostic 
1159*40393Sbostic     /*
1160*40393Sbostic      * A final check: if we stopped on a +, ?, ! or :, the next character must
1161*40393Sbostic      * be an = or it ain't a valid assignment
1162*40393Sbostic      */
1163*40393Sbostic     if (((*line == '+') ||
1164*40393Sbostic 	 (*line == '?') ||
1165*40393Sbostic 	 (*line == ':') ||
1166*40393Sbostic 	 (*line == '!')) &&
1167*40393Sbostic 	(line[1] != '='))
1168*40393Sbostic     {
1169*40393Sbostic 	return (FALSE);
1170*40393Sbostic     } else {
1171*40393Sbostic 	return (haveName);
1172*40393Sbostic     }
1173*40393Sbostic }
1174*40393Sbostic 
1175*40393Sbostic /*-
1176*40393Sbostic  *---------------------------------------------------------------------
1177*40393Sbostic  * Parse_DoVar  --
1178*40393Sbostic  *	Take the variable assignment in the passed line and do it in the
1179*40393Sbostic  *	global context.
1180*40393Sbostic  *
1181*40393Sbostic  *	Note: There is a lexical ambiguity with assignment modifier characters
1182*40393Sbostic  *	in variable names. This routine interprets the character before the =
1183*40393Sbostic  *	as a modifier. Therefore, an assignment like
1184*40393Sbostic  *	    C++=/usr/bin/CC
1185*40393Sbostic  *	is interpreted as "C+ +=" instead of "C++ =".
1186*40393Sbostic  *
1187*40393Sbostic  * Results:
1188*40393Sbostic  *	none
1189*40393Sbostic  *
1190*40393Sbostic  * Side Effects:
1191*40393Sbostic  *	the variable structure of the given variable name is altered in the
1192*40393Sbostic  *	global context.
1193*40393Sbostic  *---------------------------------------------------------------------
1194*40393Sbostic  */
1195*40393Sbostic void
1196*40393Sbostic Parse_DoVar (line, ctxt)
1197*40393Sbostic     char            *line;	/* a line guaranteed to be a variable
1198*40393Sbostic 				 * assignment. This reduces error checks */
1199*40393Sbostic     GNode   	    *ctxt;    	/* Context in which to do the assignment */
1200*40393Sbostic {
1201*40393Sbostic     register char   *cp;	/* pointer into line */
1202*40393Sbostic     enum {
1203*40393Sbostic 	VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1204*40393Sbostic     }	    	    type;   	/* Type of assignment */
1205*40393Sbostic     char            *opc;	/* ptr to operator character to
1206*40393Sbostic 				 * null-terminate the variable name */
1207*40393Sbostic 
1208*40393Sbostic     /*
1209*40393Sbostic      * Skip to variable name
1210*40393Sbostic      */
1211*40393Sbostic     while ((*line == ' ') || (*line == '\t')) {
1212*40393Sbostic 	line++;
1213*40393Sbostic     }
1214*40393Sbostic 
1215*40393Sbostic     /*
1216*40393Sbostic      * Skip to operator character, nulling out whitespace as we go
1217*40393Sbostic      */
1218*40393Sbostic     for (cp = line + 1; *cp != '='; cp++) {
1219*40393Sbostic 	if (isspace (*cp)) {
1220*40393Sbostic 	    *cp = '\0';
1221*40393Sbostic 	}
1222*40393Sbostic     }
1223*40393Sbostic     opc = cp-1;		/* operator is the previous character */
1224*40393Sbostic     *cp++ = '\0';	/* nuke the = */
1225*40393Sbostic 
1226*40393Sbostic     /*
1227*40393Sbostic      * Check operator type
1228*40393Sbostic      */
1229*40393Sbostic     switch (*opc) {
1230*40393Sbostic 	case '+':
1231*40393Sbostic 	    type = VAR_APPEND;
1232*40393Sbostic 	    *opc = '\0';
1233*40393Sbostic 	    break;
1234*40393Sbostic 
1235*40393Sbostic 	case '?':
1236*40393Sbostic 	    /*
1237*40393Sbostic 	     * If the variable already has a value, we don't do anything.
1238*40393Sbostic 	     */
1239*40393Sbostic 	    *opc = '\0';
1240*40393Sbostic 	    if (Var_Exists(line, ctxt)) {
1241*40393Sbostic 		return;
1242*40393Sbostic 	    } else {
1243*40393Sbostic 		type = VAR_NORMAL;
1244*40393Sbostic 	    }
1245*40393Sbostic 	    break;
1246*40393Sbostic 
1247*40393Sbostic 	case ':':
1248*40393Sbostic 	    type = VAR_SUBST;
1249*40393Sbostic 	    *opc = '\0';
1250*40393Sbostic 	    break;
1251*40393Sbostic 
1252*40393Sbostic 	case '!':
1253*40393Sbostic 	    type = VAR_SHELL;
1254*40393Sbostic 	    *opc = '\0';
1255*40393Sbostic 	    break;
1256*40393Sbostic 
1257*40393Sbostic 	default:
1258*40393Sbostic 	    type = VAR_NORMAL;
1259*40393Sbostic 	    break;
1260*40393Sbostic     }
1261*40393Sbostic 
1262*40393Sbostic     while (isspace (*cp)) {
1263*40393Sbostic 	cp++;
1264*40393Sbostic     }
1265*40393Sbostic 
1266*40393Sbostic     if (type == VAR_APPEND) {
1267*40393Sbostic 	Var_Append (line, cp, ctxt);
1268*40393Sbostic     } else if (type == VAR_SUBST) {
1269*40393Sbostic 	/*
1270*40393Sbostic 	 * Allow variables in the old value to be undefined, but leave their
1271*40393Sbostic 	 * invocation alone -- this is done by forcing oldVars to be false.
1272*40393Sbostic 	 * XXX: This can cause recursive variables, but that's not hard to do,
1273*40393Sbostic 	 * and this allows someone to do something like
1274*40393Sbostic 	 *
1275*40393Sbostic 	 *  CFLAGS = $(.INCLUDES)
1276*40393Sbostic 	 *  CFLAGS := -I.. $(CFLAGS)
1277*40393Sbostic 	 *
1278*40393Sbostic 	 * And not get an error.
1279*40393Sbostic 	 */
1280*40393Sbostic 	Boolean	  oldOldVars = oldVars;
1281*40393Sbostic 
1282*40393Sbostic 	oldVars = FALSE;
1283*40393Sbostic 	cp = Var_Subst(cp, ctxt, FALSE);
1284*40393Sbostic 	oldVars = oldOldVars;
1285*40393Sbostic 
1286*40393Sbostic 	Var_Set(line, cp, ctxt);
1287*40393Sbostic 	free(cp);
1288*40393Sbostic     } else if (type == VAR_SHELL) {
1289*40393Sbostic 	char	result[BUFSIZ];	/* Result of command */
1290*40393Sbostic 	char	*args[4];   	/* Args for invoking the shell */
1291*40393Sbostic 	int 	fds[2];	    	/* Pipe streams */
1292*40393Sbostic 	int 	cpid;	    	/* Child PID */
1293*40393Sbostic 	int 	pid;	    	/* PID from wait() */
1294*40393Sbostic 	Boolean	freeCmd;    	/* TRUE if the command needs to be freed, i.e.
1295*40393Sbostic 				 * if any variable expansion was performed */
1296*40393Sbostic 
1297*40393Sbostic 	/*
1298*40393Sbostic 	 * Set up arguments for shell
1299*40393Sbostic 	 */
1300*40393Sbostic 	args[0] = "sh";
1301*40393Sbostic 	args[1] = "-c";
1302*40393Sbostic 	if (index(cp, '$') != (char *)NULL) {
1303*40393Sbostic 	    /*
1304*40393Sbostic 	     * There's a dollar sign in the command, so perform variable
1305*40393Sbostic 	     * expansion on the whole thing. The resulting string will need
1306*40393Sbostic 	     * freeing when we're done, so set freeCmd to TRUE.
1307*40393Sbostic 	     */
1308*40393Sbostic 	    args[2] = Var_Subst(cp, VAR_CMD, TRUE);
1309*40393Sbostic 	    freeCmd = TRUE;
1310*40393Sbostic 	} else {
1311*40393Sbostic 	    args[2] = cp;
1312*40393Sbostic 	    freeCmd = FALSE;
1313*40393Sbostic 	}
1314*40393Sbostic 	args[3] = (char *)NULL;
1315*40393Sbostic 
1316*40393Sbostic 	/*
1317*40393Sbostic 	 * Open a pipe for fetching its output
1318*40393Sbostic 	 */
1319*40393Sbostic 	pipe(fds);
1320*40393Sbostic 
1321*40393Sbostic 	/*
1322*40393Sbostic 	 * Fork
1323*40393Sbostic 	 */
1324*40393Sbostic 	cpid = vfork();
1325*40393Sbostic 	if (cpid == 0) {
1326*40393Sbostic 	    /*
1327*40393Sbostic 	     * Close input side of pipe
1328*40393Sbostic 	     */
1329*40393Sbostic 	    close(fds[0]);
1330*40393Sbostic 
1331*40393Sbostic 	    /*
1332*40393Sbostic 	     * Duplicate the output stream to the shell's output, then
1333*40393Sbostic 	     * shut the extra thing down. Note we don't fetch the error
1334*40393Sbostic 	     * stream...why not? Why?
1335*40393Sbostic 	     */
1336*40393Sbostic 	    dup2(fds[1], 1);
1337*40393Sbostic 	    close(fds[1]);
1338*40393Sbostic 
1339*40393Sbostic 	    execv("/bin/sh", args);
1340*40393Sbostic 	    _exit(1);
1341*40393Sbostic 	} else if (cpid < 0) {
1342*40393Sbostic 	    /*
1343*40393Sbostic 	     * Couldn't fork -- tell the user and make the variable null
1344*40393Sbostic 	     */
1345*40393Sbostic 	    Parse_Error(PARSE_WARNING, "Couldn't exec \"%s\"", cp);
1346*40393Sbostic 	    Var_Set(line, "", ctxt);
1347*40393Sbostic 	} else {
1348*40393Sbostic 	    int	status;
1349*40393Sbostic 	    int cc;
1350*40393Sbostic 
1351*40393Sbostic 	    /*
1352*40393Sbostic 	     * No need for the writing half
1353*40393Sbostic 	     */
1354*40393Sbostic 	    close(fds[1]);
1355*40393Sbostic 
1356*40393Sbostic 	    /*
1357*40393Sbostic 	     * Wait for the process to exit.
1358*40393Sbostic 	     *
1359*40393Sbostic 	     * XXX: If the child writes more than a pipe's worth, we will
1360*40393Sbostic 	     * deadlock.
1361*40393Sbostic 	     */
1362*40393Sbostic 	    while(((pid = wait(&status)) != cpid) && (pid >= 0)) {
1363*40393Sbostic 		;
1364*40393Sbostic 	    }
1365*40393Sbostic 
1366*40393Sbostic 	    /*
1367*40393Sbostic 	     * Read all the characters the child wrote.
1368*40393Sbostic 	     */
1369*40393Sbostic 	    cc = read(fds[0], result, sizeof(result));
1370*40393Sbostic 
1371*40393Sbostic 	    if (cc < 0) {
1372*40393Sbostic 		/*
1373*40393Sbostic 		 * Couldn't read the child's output -- tell the user and
1374*40393Sbostic 		 * set the variable to null
1375*40393Sbostic 		 */
1376*40393Sbostic 		Parse_Error(PARSE_WARNING, "Couldn't read shell's output");
1377*40393Sbostic 		cc = 0;
1378*40393Sbostic 	    }
1379*40393Sbostic 
1380*40393Sbostic 	    if (status) {
1381*40393Sbostic 		/*
1382*40393Sbostic 		 * Child returned an error -- tell the user but still use
1383*40393Sbostic 		 * the result.
1384*40393Sbostic 		 */
1385*40393Sbostic 		Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp);
1386*40393Sbostic 	    }
1387*40393Sbostic 	    /*
1388*40393Sbostic 	     * Null-terminate the result, convert newlines to spaces and
1389*40393Sbostic 	     * install it in the variable.
1390*40393Sbostic 	     */
1391*40393Sbostic 	    result[cc] = '\0';
1392*40393Sbostic 	    cp = &result[cc] - 1;
1393*40393Sbostic 
1394*40393Sbostic 	    if (*cp == '\n') {
1395*40393Sbostic 		/*
1396*40393Sbostic 		 * A final newline is just stripped
1397*40393Sbostic 		 */
1398*40393Sbostic 		*cp-- = '\0';
1399*40393Sbostic 	    }
1400*40393Sbostic 	    while (cp >= result) {
1401*40393Sbostic 		if (*cp == '\n') {
1402*40393Sbostic 		    *cp = ' ';
1403*40393Sbostic 		}
1404*40393Sbostic 		cp--;
1405*40393Sbostic 	    }
1406*40393Sbostic 	    Var_Set(line, result, ctxt);
1407*40393Sbostic 
1408*40393Sbostic 	    /*
1409*40393Sbostic 	     * Close the input side of the pipe.
1410*40393Sbostic 	     */
1411*40393Sbostic 	    close(fds[0]);
1412*40393Sbostic 	}
1413*40393Sbostic 	if (freeCmd) {
1414*40393Sbostic 	    free(args[2]);
1415*40393Sbostic 	}
1416*40393Sbostic     } else {
1417*40393Sbostic 	/*
1418*40393Sbostic 	 * Normal assignment -- just do it.
1419*40393Sbostic 	 */
1420*40393Sbostic 	Var_Set (line, cp, ctxt);
1421*40393Sbostic     }
1422*40393Sbostic }
1423*40393Sbostic 
1424*40393Sbostic /*-
1425*40393Sbostic  *---------------------------------------------------------------------
1426*40393Sbostic  * ParseAddCmd  --
1427*40393Sbostic  *	Lst_ForEach function to add a command line to all targets
1428*40393Sbostic  *
1429*40393Sbostic  * Results:
1430*40393Sbostic  *	Always 0
1431*40393Sbostic  *
1432*40393Sbostic  * Side Effects:
1433*40393Sbostic  *	A new element is added to the commands list of the node.
1434*40393Sbostic  *---------------------------------------------------------------------
1435*40393Sbostic  */
1436*40393Sbostic static int
1437*40393Sbostic ParseAddCmd (gn, cmd)
1438*40393Sbostic     GNode          *gn;		/* the node to which the command is to be
1439*40393Sbostic 				 * added */
1440*40393Sbostic     char           *cmd;	/* the command to add */
1441*40393Sbostic {
1442*40393Sbostic     if (gn->type & OP_HAS_COMMANDS) {
1443*40393Sbostic 	Parse_Error(PARSE_WARNING, "Extra command line for \"%s\" ignored",
1444*40393Sbostic 		    gn->name);
1445*40393Sbostic     } else {
1446*40393Sbostic 	(void)Lst_AtEnd (gn->commands, (ClientData)cmd);
1447*40393Sbostic     }
1448*40393Sbostic 
1449*40393Sbostic     return (0);
1450*40393Sbostic }
1451*40393Sbostic 
1452*40393Sbostic /*-
1453*40393Sbostic  *-----------------------------------------------------------------------
1454*40393Sbostic  * ParseHasCommands --
1455*40393Sbostic  *	Callback procedure for Parse_File when destroying the list of
1456*40393Sbostic  *	targets on the last dependency line. Marks a target as already
1457*40393Sbostic  *	having commands if it does, to keep from having shell commands
1458*40393Sbostic  *	on multiple dependency lines.
1459*40393Sbostic  *
1460*40393Sbostic  * Results:
1461*40393Sbostic  *	Always 0.
1462*40393Sbostic  *
1463*40393Sbostic  * Side Effects:
1464*40393Sbostic  *	OP_HAS_COMMANDS may be set for the target.
1465*40393Sbostic  *
1466*40393Sbostic  *-----------------------------------------------------------------------
1467*40393Sbostic  */
1468*40393Sbostic static int
1469*40393Sbostic ParseHasCommands(gn)
1470*40393Sbostic     GNode   	  *gn;	    /* Node to examine */
1471*40393Sbostic {
1472*40393Sbostic     if (!Lst_IsEmpty(gn->commands)) {
1473*40393Sbostic 	gn->type |= OP_HAS_COMMANDS;
1474*40393Sbostic     }
1475*40393Sbostic     return(0);
1476*40393Sbostic }
1477*40393Sbostic 
1478*40393Sbostic /*-
1479*40393Sbostic  *-----------------------------------------------------------------------
1480*40393Sbostic  * Parse_AddIncludeDir --
1481*40393Sbostic  *	Add a directory to the path searched for included makefiles
1482*40393Sbostic  *	bracketed by double-quotes. Used by functions in main.c
1483*40393Sbostic  *
1484*40393Sbostic  * Results:
1485*40393Sbostic  *	None.
1486*40393Sbostic  *
1487*40393Sbostic  * Side Effects:
1488*40393Sbostic  *	The directory is appended to the list.
1489*40393Sbostic  *
1490*40393Sbostic  *-----------------------------------------------------------------------
1491*40393Sbostic  */
1492*40393Sbostic void
1493*40393Sbostic Parse_AddIncludeDir (dir)
1494*40393Sbostic     char    	  *dir;	    /* The name of the directory to add */
1495*40393Sbostic {
1496*40393Sbostic     Dir_AddDir (parseIncPath, dir);
1497*40393Sbostic }
1498*40393Sbostic 
1499*40393Sbostic /*-
1500*40393Sbostic  *---------------------------------------------------------------------
1501*40393Sbostic  * ParseDoInclude  --
1502*40393Sbostic  *	Push to another file.
1503*40393Sbostic  *
1504*40393Sbostic  *	The input is the line minus the #include. A file spec is a string
1505*40393Sbostic  *	enclosed in <> or "". The former is looked for only in sysIncPath.
1506*40393Sbostic  *	The latter in . and the directories specified by -I command line
1507*40393Sbostic  *	options
1508*40393Sbostic  *
1509*40393Sbostic  * Results:
1510*40393Sbostic  *	None
1511*40393Sbostic  *
1512*40393Sbostic  * Side Effects:
1513*40393Sbostic  *	A structure is added to the includes Lst and readProc, lineno,
1514*40393Sbostic  *	fname and curFILE are altered for the new file
1515*40393Sbostic  *---------------------------------------------------------------------
1516*40393Sbostic  */
1517*40393Sbostic static void
1518*40393Sbostic ParseDoInclude (file)
1519*40393Sbostic     char          *file;	/* file specification */
1520*40393Sbostic {
1521*40393Sbostic     char          *fullname;	/* full pathname of file */
1522*40393Sbostic     IFile         *oldFile;	/* state associated with current file */
1523*40393Sbostic     Lst           path;	    	/* the path to use to find the file */
1524*40393Sbostic     char          endc;	    	/* the character which ends the file spec */
1525*40393Sbostic     char          *cp;		/* current position in file spec */
1526*40393Sbostic     Boolean 	  isSystem; 	/* TRUE if makefile is a system makefile */
1527*40393Sbostic 
1528*40393Sbostic     /*
1529*40393Sbostic      * Skip to delimiter character so we know where to look
1530*40393Sbostic      */
1531*40393Sbostic     while ((*file == ' ') || (*file == '\t')) {
1532*40393Sbostic 	file++;
1533*40393Sbostic     }
1534*40393Sbostic 
1535*40393Sbostic     if ((*file != '"') && (*file != '<')) {
1536*40393Sbostic 	/*
1537*40393Sbostic 	 * XXX: Should give some sort of error message, I suppose, but because
1538*40393Sbostic 	 * # is used for both comments and directives, we can't be sure if
1539*40393Sbostic 	 * the thing might not just be a comment, so we just return...
1540*40393Sbostic 	 */
1541*40393Sbostic 	return;
1542*40393Sbostic     }
1543*40393Sbostic 
1544*40393Sbostic     /*
1545*40393Sbostic      * Set the search path on which to find the include file based on the
1546*40393Sbostic      * characters which bracket its name. Angle-brackets imply it's
1547*40393Sbostic      * a system Makefile while double-quotes imply it's a user makefile
1548*40393Sbostic      */
1549*40393Sbostic     if (*file == '<') {
1550*40393Sbostic 	isSystem = TRUE;
1551*40393Sbostic 	endc = '>';
1552*40393Sbostic     } else {
1553*40393Sbostic 	isSystem = FALSE;
1554*40393Sbostic 	endc = '"';
1555*40393Sbostic     }
1556*40393Sbostic 
1557*40393Sbostic     /*
1558*40393Sbostic      * Skip to matching delimiter
1559*40393Sbostic      */
1560*40393Sbostic     for (cp = ++file; *cp && *cp != endc; cp++) {
1561*40393Sbostic 	continue;
1562*40393Sbostic     }
1563*40393Sbostic 
1564*40393Sbostic     if (*cp != endc) {
1565*40393Sbostic 	Parse_Error (PARSE_FATAL,
1566*40393Sbostic 		     "Unclosed %cinclude filename. '%c' expected",
1567*40393Sbostic 		     SPECIAL_CHAR, endc);
1568*40393Sbostic 	return;
1569*40393Sbostic     }
1570*40393Sbostic     *cp = '\0';
1571*40393Sbostic 
1572*40393Sbostic     /*
1573*40393Sbostic      * Substitute for any variables in the file name before trying to
1574*40393Sbostic      * find the thing.
1575*40393Sbostic      */
1576*40393Sbostic     file = Var_Subst (file, VAR_CMD, FALSE);
1577*40393Sbostic 
1578*40393Sbostic     /*
1579*40393Sbostic      * Now we know the file's name and its search path, we attempt to
1580*40393Sbostic      * find the durn thing. A return of NULL indicates the file don't
1581*40393Sbostic      * exist.
1582*40393Sbostic      */
1583*40393Sbostic     if (!isSystem) {
1584*40393Sbostic 	/*
1585*40393Sbostic 	 * Include files contained in double-quotes are first searched for
1586*40393Sbostic 	 * relative to the including file's location. We don't want to
1587*40393Sbostic 	 * cd there, of course, so we just tack on the old file's
1588*40393Sbostic 	 * leading path components and call Dir_FindFile to see if
1589*40393Sbostic 	 * we can locate the beast.
1590*40393Sbostic 	 */
1591*40393Sbostic 	char	  *prefEnd;
1592*40393Sbostic 
1593*40393Sbostic 	prefEnd = rindex (fname, '/');
1594*40393Sbostic 	if (prefEnd != (char *)NULL) {
1595*40393Sbostic 	    char  	*newName;
1596*40393Sbostic 
1597*40393Sbostic 	    *prefEnd = '\0';
1598*40393Sbostic 	    newName = Str_Concat (fname, file, STR_ADDSLASH);
1599*40393Sbostic 	    fullname = Dir_FindFile (newName, parseIncPath);
1600*40393Sbostic 	    if (fullname == (char *)NULL) {
1601*40393Sbostic 		fullname = Dir_FindFile(newName, dirSearchPath);
1602*40393Sbostic 	    }
1603*40393Sbostic 	    free (newName);
1604*40393Sbostic 	    *prefEnd = '/';
1605*40393Sbostic 	} else {
1606*40393Sbostic 	    fullname = (char *)NULL;
1607*40393Sbostic 	}
1608*40393Sbostic     } else {
1609*40393Sbostic 	fullname = (char *)NULL;
1610*40393Sbostic     }
1611*40393Sbostic 
1612*40393Sbostic     if (fullname == (char *)NULL) {
1613*40393Sbostic 	/*
1614*40393Sbostic 	 * System makefile or makefile wasn't found in same directory as
1615*40393Sbostic 	 * included makefile. Search for it first on the -I search path,
1616*40393Sbostic 	 * then on the .PATH search path, if not found in a -I directory.
1617*40393Sbostic 	 * XXX: Suffix specific?
1618*40393Sbostic 	 */
1619*40393Sbostic 	fullname = Dir_FindFile (file, parseIncPath);
1620*40393Sbostic 	if (fullname == (char *)NULL) {
1621*40393Sbostic 	    fullname = Dir_FindFile(file, dirSearchPath);
1622*40393Sbostic 	}
1623*40393Sbostic     }
1624*40393Sbostic 
1625*40393Sbostic     if (fullname == (char *)NULL) {
1626*40393Sbostic 	/*
1627*40393Sbostic 	 * Still haven't found the makefile. Look for it on the system
1628*40393Sbostic 	 * path as a last resort.
1629*40393Sbostic 	 */
1630*40393Sbostic 	fullname = Dir_FindFile(file, sysIncPath);
1631*40393Sbostic     }
1632*40393Sbostic 
1633*40393Sbostic     if (fullname == (char *) NULL) {
1634*40393Sbostic 	*cp = endc;
1635*40393Sbostic 	Parse_Error (PARSE_FATAL, "Could not find %s", file);
1636*40393Sbostic 	return;
1637*40393Sbostic     }
1638*40393Sbostic 
1639*40393Sbostic     /*
1640*40393Sbostic      * Once we find the absolute path to the file, we get to save all the
1641*40393Sbostic      * state from the current file before we can start reading this
1642*40393Sbostic      * include file. The state is stored in an IFile structure which
1643*40393Sbostic      * is placed on a list with other IFile structures. The list makes
1644*40393Sbostic      * a very nice stack to track how we got here...
1645*40393Sbostic      */
1646*40393Sbostic     oldFile = (IFile *) malloc (sizeof (IFile));
1647*40393Sbostic     oldFile->fname = fname;
1648*40393Sbostic 
1649*40393Sbostic     oldFile->F = curFILE;
1650*40393Sbostic     oldFile->lineno = lineno;
1651*40393Sbostic 
1652*40393Sbostic     (void) Lst_AtFront (includes, (ClientData)oldFile);
1653*40393Sbostic 
1654*40393Sbostic     /*
1655*40393Sbostic      * Once the previous state has been saved, we can get down to reading
1656*40393Sbostic      * the new file. We set up the name of the file to be the absolute
1657*40393Sbostic      * name of the include file so error messages refer to the right
1658*40393Sbostic      * place. Naturally enough, we start reading at line number 0.
1659*40393Sbostic      */
1660*40393Sbostic     fname = fullname;
1661*40393Sbostic     lineno = 0;
1662*40393Sbostic 
1663*40393Sbostic     curFILE = fopen (fullname, "r");
1664*40393Sbostic     if (curFILE == (FILE * ) NULL) {
1665*40393Sbostic 	Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1666*40393Sbostic 	/*
1667*40393Sbostic 	 * Pop to previous file
1668*40393Sbostic 	 */
1669*40393Sbostic 	(void) ParseEOF();
1670*40393Sbostic     }
1671*40393Sbostic }
1672*40393Sbostic 
1673*40393Sbostic /*-
1674*40393Sbostic  *---------------------------------------------------------------------
1675*40393Sbostic  * ParseEOF  --
1676*40393Sbostic  *	Called when EOF is reached in the current file. If we were reading
1677*40393Sbostic  *	an include file, the includes stack is popped and things set up
1678*40393Sbostic  *	to go back to reading the previous file at the previous location.
1679*40393Sbostic  *
1680*40393Sbostic  * Results:
1681*40393Sbostic  *	CONTINUE if there's more to do. DONE if not.
1682*40393Sbostic  *
1683*40393Sbostic  * Side Effects:
1684*40393Sbostic  *	The old curFILE, is closed. The includes list is shortened.
1685*40393Sbostic  *	lineno, curFILE, and fname are changed if CONTINUE is returned.
1686*40393Sbostic  *---------------------------------------------------------------------
1687*40393Sbostic  */
1688*40393Sbostic static int
1689*40393Sbostic ParseEOF ()
1690*40393Sbostic {
1691*40393Sbostic     IFile     *ifile;	/* the state on the top of the includes stack */
1692*40393Sbostic 
1693*40393Sbostic     if (Lst_IsEmpty (includes)) {
1694*40393Sbostic 	return (DONE);
1695*40393Sbostic     }
1696*40393Sbostic 
1697*40393Sbostic     ifile = (IFile *) Lst_DeQueue (includes);
1698*40393Sbostic     free (fname);
1699*40393Sbostic     fname = ifile->fname;
1700*40393Sbostic     lineno = ifile->lineno;
1701*40393Sbostic     fclose (curFILE);
1702*40393Sbostic     curFILE = ifile->F;
1703*40393Sbostic     free ((Address)ifile);
1704*40393Sbostic     return (CONTINUE);
1705*40393Sbostic }
1706*40393Sbostic 
1707*40393Sbostic /*-
1708*40393Sbostic  *---------------------------------------------------------------------
1709*40393Sbostic  * ParseReadc  --
1710*40393Sbostic  *	Read a character from the current file and update the line number
1711*40393Sbostic  *	counter as necessary
1712*40393Sbostic  *
1713*40393Sbostic  * Results:
1714*40393Sbostic  *	The character that was read
1715*40393Sbostic  *
1716*40393Sbostic  * Side Effects:
1717*40393Sbostic  *	The lineno counter is incremented if the character is a newline
1718*40393Sbostic  *---------------------------------------------------------------------
1719*40393Sbostic  */
1720*40393Sbostic #ifdef notdef
1721*40393Sbostic static int parseReadChar;
1722*40393Sbostic 
1723*40393Sbostic #define ParseReadc() (((parseReadChar = getc(curFILE)) == '\n') ? \
1724*40393Sbostic 		      (lineno++, '\n') : parseReadChar)
1725*40393Sbostic #else
1726*40393Sbostic #define ParseReadc() (getc(curFILE))
1727*40393Sbostic #endif /* notdef */
1728*40393Sbostic 
1729*40393Sbostic 
1730*40393Sbostic /*-
1731*40393Sbostic  *---------------------------------------------------------------------
1732*40393Sbostic  * ParseReadLine --
1733*40393Sbostic  *	Read an entire line from the input file. Called only by Parse_File.
1734*40393Sbostic  *	To facilitate escaped newlines and what have you, a character is
1735*40393Sbostic  *	buffered in 'lastc', which is '\0' when no characters have been
1736*40393Sbostic  *	read. When we break out of the loop, c holds the terminating
1737*40393Sbostic  *	character and lastc holds a character that should be added to
1738*40393Sbostic  *	the line (unless we don't read anything but a terminator).
1739*40393Sbostic  *
1740*40393Sbostic  * Results:
1741*40393Sbostic  *	A line w/o its newline
1742*40393Sbostic  *
1743*40393Sbostic  * Side Effects:
1744*40393Sbostic  *	Only those associated with reading a character
1745*40393Sbostic  *---------------------------------------------------------------------
1746*40393Sbostic  */
1747*40393Sbostic static char *
1748*40393Sbostic ParseReadLine ()
1749*40393Sbostic {
1750*40393Sbostic     Buffer  	  buf;	    	/* Buffer for current line */
1751*40393Sbostic     register int  c;	      	/* the current character */
1752*40393Sbostic     register int  lastc;    	/* The most-recent character */
1753*40393Sbostic     Boolean	  semiNL;     	/* treat semi-colons as newlines */
1754*40393Sbostic     Boolean	  ignDepOp;   	/* TRUE if should ignore dependency operators
1755*40393Sbostic 				 * for the purposes of setting semiNL */
1756*40393Sbostic     Boolean 	  ignComment;	/* TRUE if should ignore comments (in a
1757*40393Sbostic 				 * shell command */
1758*40393Sbostic     char    	  *line;    	/* Result */
1759*40393Sbostic     int	    	  lineLength;	/* Length of result */
1760*40393Sbostic 
1761*40393Sbostic     semiNL = FALSE;
1762*40393Sbostic     ignDepOp = FALSE;
1763*40393Sbostic     ignComment = FALSE;
1764*40393Sbostic 
1765*40393Sbostic     /*
1766*40393Sbostic      * Handle special-characters at the beginning of the line. Either a
1767*40393Sbostic      * leading tab (shell command) or pound-sign (possible conditional)
1768*40393Sbostic      * forces us to ignore comments and dependency operators and treat
1769*40393Sbostic      * semi-colons as semi-colons (by leaving semiNL FALSE). This also
1770*40393Sbostic      * discards completely blank lines.
1771*40393Sbostic      */
1772*40393Sbostic     while(1) {
1773*40393Sbostic 	c = ParseReadc();
1774*40393Sbostic 
1775*40393Sbostic 	if ((c == '\t') || (c == SPECIAL_CHAR)) {
1776*40393Sbostic 	    ignComment = ignDepOp = TRUE;
1777*40393Sbostic 	    break;
1778*40393Sbostic 	} else if (c == '\n') {
1779*40393Sbostic 	    lineno++;
1780*40393Sbostic 	} else {
1781*40393Sbostic 	    /*
1782*40393Sbostic 	     * Anything else breaks out without doing anything
1783*40393Sbostic 	     */
1784*40393Sbostic 	    break;
1785*40393Sbostic 	}
1786*40393Sbostic     }
1787*40393Sbostic 
1788*40393Sbostic     if (c != EOF) {
1789*40393Sbostic 	lastc = c;
1790*40393Sbostic 	buf = Buf_Init(BSIZE);
1791*40393Sbostic 
1792*40393Sbostic 	while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
1793*40393Sbostic 	       (c != EOF))
1794*40393Sbostic 	{
1795*40393Sbostic test_char:
1796*40393Sbostic 	    switch(c) {
1797*40393Sbostic 	    case '\n':
1798*40393Sbostic 		/*
1799*40393Sbostic 		 * Escaped newline: read characters until a non-space or an
1800*40393Sbostic 		 * unescaped newline and replace them all by a single space.
1801*40393Sbostic 		 * This is done by storing the space over the backslash and
1802*40393Sbostic 		 * dropping through with the next nonspace. If it is a
1803*40393Sbostic 		 * semi-colon and semiNL is TRUE, it will be recognized as a
1804*40393Sbostic 		 * newline in the code below this...
1805*40393Sbostic 		 */
1806*40393Sbostic 		lineno++;
1807*40393Sbostic 		lastc = ' ';
1808*40393Sbostic 		while ((c = ParseReadc ()) == ' ' || c == '\t') {
1809*40393Sbostic 		    continue;
1810*40393Sbostic 		}
1811*40393Sbostic 		if (c == EOF || c == '\n') {
1812*40393Sbostic 		    goto line_read;
1813*40393Sbostic 		} else {
1814*40393Sbostic 		    /*
1815*40393Sbostic 		     * Check for comments, semiNL's, etc. -- easier than
1816*40393Sbostic 		     * ungetc(c, curFILE); continue;
1817*40393Sbostic 		     */
1818*40393Sbostic 		    goto test_char;
1819*40393Sbostic 		}
1820*40393Sbostic 		break;
1821*40393Sbostic 	    case ';':
1822*40393Sbostic 		/*
1823*40393Sbostic 		 * Semi-colon: Need to see if it should be interpreted as a
1824*40393Sbostic 		 * newline
1825*40393Sbostic 		 */
1826*40393Sbostic 		if (semiNL) {
1827*40393Sbostic 		    /*
1828*40393Sbostic 		     * To make sure the command that may be following this
1829*40393Sbostic 		     * semi-colon begins with a tab, we push one back into the
1830*40393Sbostic 		     * input stream. This will overwrite the semi-colon in the
1831*40393Sbostic 		     * buffer. If there is no command following, this does no
1832*40393Sbostic 		     * harm, since the newline remains in the buffer and the
1833*40393Sbostic 		     * whole line is ignored.
1834*40393Sbostic 		     */
1835*40393Sbostic 		    ungetc('\t', curFILE);
1836*40393Sbostic 		    goto line_read;
1837*40393Sbostic 		}
1838*40393Sbostic 		break;
1839*40393Sbostic 	    case '=':
1840*40393Sbostic 		if (!semiNL) {
1841*40393Sbostic 		    /*
1842*40393Sbostic 		     * Haven't seen a dependency operator before this, so this
1843*40393Sbostic 		     * must be a variable assignment -- don't pay attention to
1844*40393Sbostic 		     * dependency operators after this.
1845*40393Sbostic 		     */
1846*40393Sbostic 		    ignDepOp = TRUE;
1847*40393Sbostic 		} else if (lastc == ':' || lastc == '!') {
1848*40393Sbostic 		    /*
1849*40393Sbostic 		     * Well, we've seen a dependency operator already, but it
1850*40393Sbostic 		     * was the previous character, so this is really just an
1851*40393Sbostic 		     * expanded variable assignment. Revert semi-colons to
1852*40393Sbostic 		     * being just semi-colons again and ignore any more
1853*40393Sbostic 		     * dependency operators.
1854*40393Sbostic 		     *
1855*40393Sbostic 		     * XXX: Note that a line like "foo : a:=b" will blow up,
1856*40393Sbostic 		     * but who'd write a line like that anyway?
1857*40393Sbostic 		     */
1858*40393Sbostic 		    ignDepOp = TRUE; semiNL = FALSE;
1859*40393Sbostic 		}
1860*40393Sbostic 		break;
1861*40393Sbostic 	    case '#':
1862*40393Sbostic 		if (!ignComment) {
1863*40393Sbostic 		    if (backwards || (lastc != '\\')) {
1864*40393Sbostic 			/*
1865*40393Sbostic 			 * If the character is a hash mark and it isn't escaped
1866*40393Sbostic 			 * (or we're being compatible), the thing is a comment.
1867*40393Sbostic 			 * Skip to the end of the line.
1868*40393Sbostic 			 */
1869*40393Sbostic 			do {
1870*40393Sbostic 			    c = ParseReadc();
1871*40393Sbostic 			} while ((c != '\n') && (c != EOF));
1872*40393Sbostic 			goto line_read;
1873*40393Sbostic 		    } else {
1874*40393Sbostic 			/*
1875*40393Sbostic 			 * Don't add the backslash. Just let the # get copied
1876*40393Sbostic 			 * over.
1877*40393Sbostic 			 */
1878*40393Sbostic 			lastc = c;
1879*40393Sbostic 			continue;
1880*40393Sbostic 		    }
1881*40393Sbostic 		}
1882*40393Sbostic 		break;
1883*40393Sbostic 	    case ':':
1884*40393Sbostic 	    case '!':
1885*40393Sbostic 		if (!ignDepOp && (c == ':' || c == '!')) {
1886*40393Sbostic 		    /*
1887*40393Sbostic 		     * A semi-colon is recognized as a newline only on
1888*40393Sbostic 		     * dependency lines. Dependency lines are lines with a
1889*40393Sbostic 		     * colon or an exclamation point. Ergo...
1890*40393Sbostic 		     */
1891*40393Sbostic 		    semiNL = TRUE;
1892*40393Sbostic 		}
1893*40393Sbostic 		break;
1894*40393Sbostic 	    }
1895*40393Sbostic 	    /*
1896*40393Sbostic 	     * Copy in the previous character and save this one in lastc.
1897*40393Sbostic 	     */
1898*40393Sbostic 	    Buf_AddByte (buf, (Byte)lastc);
1899*40393Sbostic 	    lastc = c;
1900*40393Sbostic 
1901*40393Sbostic 	}
1902*40393Sbostic     line_read:
1903*40393Sbostic 	lineno++;
1904*40393Sbostic 
1905*40393Sbostic 	if (lastc != '\0') {
1906*40393Sbostic 	    Buf_AddByte (buf, (Byte)lastc);
1907*40393Sbostic 	}
1908*40393Sbostic 	Buf_AddByte (buf, (Byte)'\0');
1909*40393Sbostic 	line = (char *)Buf_GetAll (buf, &lineLength);
1910*40393Sbostic 	Buf_Destroy (buf, FALSE);
1911*40393Sbostic 
1912*40393Sbostic 	if (line[0] == SPECIAL_CHAR) {
1913*40393Sbostic 	    /*
1914*40393Sbostic 	     * The line might be a conditional. Ask the conditional module
1915*40393Sbostic 	     * about it and act accordingly
1916*40393Sbostic 	     */
1917*40393Sbostic 	    switch (Cond_Eval (line)) {
1918*40393Sbostic 	    case COND_SKIP:
1919*40393Sbostic 		do {
1920*40393Sbostic 		    /*
1921*40393Sbostic 		     * Skip to next conditional that evaluates to COND_PARSE.
1922*40393Sbostic 		     */
1923*40393Sbostic 		    free (line);
1924*40393Sbostic 		    c = ParseReadc();
1925*40393Sbostic 		    /*
1926*40393Sbostic 		     * Skip lines until get to one that begins with a
1927*40393Sbostic 		     * special char.
1928*40393Sbostic 		     */
1929*40393Sbostic 		    while ((c != SPECIAL_CHAR) && (c != EOF)) {
1930*40393Sbostic 			while (((c != '\n') || (lastc == '\\')) &&
1931*40393Sbostic 			       (c != EOF))
1932*40393Sbostic 			{
1933*40393Sbostic 			    /*
1934*40393Sbostic 			     * Advance to next unescaped newline
1935*40393Sbostic 			     */
1936*40393Sbostic 			    if ((lastc = c) == '\n') {
1937*40393Sbostic 				lineno++;
1938*40393Sbostic 			    }
1939*40393Sbostic 			    c = ParseReadc();
1940*40393Sbostic 			}
1941*40393Sbostic 			lineno++;
1942*40393Sbostic 
1943*40393Sbostic 			lastc = c;
1944*40393Sbostic 			c = ParseReadc ();
1945*40393Sbostic 		    }
1946*40393Sbostic 
1947*40393Sbostic 		    if (c == EOF) {
1948*40393Sbostic 			Parse_Error (PARSE_FATAL, "Unclosed conditional");
1949*40393Sbostic 			return ((char *)NULL);
1950*40393Sbostic 		    }
1951*40393Sbostic 
1952*40393Sbostic 		    /*
1953*40393Sbostic 		     * Read the entire line into buf
1954*40393Sbostic 		     */
1955*40393Sbostic 		    buf = Buf_Init (BSIZE);
1956*40393Sbostic 		    do {
1957*40393Sbostic 			Buf_AddByte (buf, (Byte)c);
1958*40393Sbostic 			c = ParseReadc();
1959*40393Sbostic 		    } while ((c != '\n') && (c != EOF));
1960*40393Sbostic 		    lineno++;
1961*40393Sbostic 
1962*40393Sbostic 		    Buf_AddByte (buf, (Byte)'\0');
1963*40393Sbostic 		    line = (char *)Buf_GetAll (buf, &lineLength);
1964*40393Sbostic 		    Buf_Destroy (buf, FALSE);
1965*40393Sbostic 		} while (Cond_Eval(line) != COND_PARSE);
1966*40393Sbostic 		/*FALLTHRU*/
1967*40393Sbostic 	    case COND_PARSE:
1968*40393Sbostic 		free (line);
1969*40393Sbostic 		line = ParseReadLine();
1970*40393Sbostic 		break;
1971*40393Sbostic 	    }
1972*40393Sbostic 	}
1973*40393Sbostic 
1974*40393Sbostic 	return (line);
1975*40393Sbostic     } else {
1976*40393Sbostic 	/*
1977*40393Sbostic 	 * Hit end-of-file, so return a NULL line to indicate this.
1978*40393Sbostic 	 */
1979*40393Sbostic 	return((char *)NULL);
1980*40393Sbostic     }
1981*40393Sbostic }
1982*40393Sbostic 
1983*40393Sbostic /*-
1984*40393Sbostic  *-----------------------------------------------------------------------
1985*40393Sbostic  * ParseFinishLine --
1986*40393Sbostic  *	Handle the end of a dependency group.
1987*40393Sbostic  *
1988*40393Sbostic  * Results:
1989*40393Sbostic  *	Nothing.
1990*40393Sbostic  *
1991*40393Sbostic  * Side Effects:
1992*40393Sbostic  *	inLine set FALSE. 'targets' list destroyed.
1993*40393Sbostic  *
1994*40393Sbostic  *-----------------------------------------------------------------------
1995*40393Sbostic  */
1996*40393Sbostic static void
1997*40393Sbostic ParseFinishLine()
1998*40393Sbostic {
1999*40393Sbostic     extern int Suff_EndTransform();
2000*40393Sbostic 
2001*40393Sbostic     if (inLine) {
2002*40393Sbostic 	Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL);
2003*40393Sbostic 	Lst_Destroy (targets, ParseHasCommands);
2004*40393Sbostic 	inLine = FALSE;
2005*40393Sbostic     }
2006*40393Sbostic }
2007*40393Sbostic 
2008*40393Sbostic 
2009*40393Sbostic /*-
2010*40393Sbostic  *---------------------------------------------------------------------
2011*40393Sbostic  * Parse_File --
2012*40393Sbostic  *	Parse a file into its component parts, incorporating it into the
2013*40393Sbostic  *	current dependency graph. This is the main function and controls
2014*40393Sbostic  *	almost every other function in this module
2015*40393Sbostic  *
2016*40393Sbostic  * Results:
2017*40393Sbostic  *	None
2018*40393Sbostic  *
2019*40393Sbostic  * Side Effects:
2020*40393Sbostic  *	Loads. Nodes are added to the list of all targets, nodes and links
2021*40393Sbostic  *	are added to the dependency graph. etc. etc. etc.
2022*40393Sbostic  *---------------------------------------------------------------------
2023*40393Sbostic  */
2024*40393Sbostic void
2025*40393Sbostic Parse_File(name, stream)
2026*40393Sbostic     char          *name;	/* the name of the file being read */
2027*40393Sbostic     FILE *	  stream;   	/* Stream open to makefile to parse */
2028*40393Sbostic {
2029*40393Sbostic     register char *cp,		/* pointer into the line */
2030*40393Sbostic                   *line;	/* the line we're working on */
2031*40393Sbostic 
2032*40393Sbostic     inLine = FALSE;
2033*40393Sbostic     fname = name;
2034*40393Sbostic     curFILE = stream;
2035*40393Sbostic     lineno = 0;
2036*40393Sbostic     fatals = 0;
2037*40393Sbostic 
2038*40393Sbostic     do {
2039*40393Sbostic 	while (line = ParseReadLine ()) {
2040*40393Sbostic 	    if (*line == SPECIAL_CHAR) {
2041*40393Sbostic 		/*
2042*40393Sbostic 		 * Lines that begin with the special character are either
2043*40393Sbostic 		 * include or undef directives.
2044*40393Sbostic 		 */
2045*40393Sbostic 		for (cp = line + 1; isspace (*cp); cp++) {
2046*40393Sbostic 		    continue;
2047*40393Sbostic 		}
2048*40393Sbostic 		if (strncmp (cp, "include", 7) == 0) {
2049*40393Sbostic 		    ParseDoInclude (cp + 7);
2050*40393Sbostic 		    goto nextLine;
2051*40393Sbostic 		} else if (strncmp(cp, "undef", 5) == 0) {
2052*40393Sbostic 		    char *cp2;
2053*40393Sbostic 		    for (cp += 5; isspace(*cp); cp++) {
2054*40393Sbostic 			continue;
2055*40393Sbostic 		    }
2056*40393Sbostic 
2057*40393Sbostic 		    for (cp2 = cp; !isspace(*cp2) && (*cp2 != '\0'); cp2++) {
2058*40393Sbostic 			continue;
2059*40393Sbostic 		    }
2060*40393Sbostic 
2061*40393Sbostic 		    *cp2 = '\0';
2062*40393Sbostic 
2063*40393Sbostic 		    Var_Delete(cp, VAR_GLOBAL);
2064*40393Sbostic 		    goto nextLine;
2065*40393Sbostic 		}
2066*40393Sbostic 	    }
2067*40393Sbostic 	    if (*line == '#') {
2068*40393Sbostic 		/*
2069*40393Sbostic 		 * If we're this far, the line must be a comment, even if
2070*40393Sbostic 		 * SPECIAL_CHAR is '#'
2071*40393Sbostic 		 */
2072*40393Sbostic 		goto nextLine;
2073*40393Sbostic 	    }
2074*40393Sbostic 
2075*40393Sbostic 	    if (*line == '\t'
2076*40393Sbostic #ifdef POSIX
2077*40393Sbostic 		       || *line == ' '
2078*40393Sbostic #endif
2079*40393Sbostic 		       )
2080*40393Sbostic 	    {
2081*40393Sbostic 		/*
2082*40393Sbostic 		 * If a line starts with a tab (or space in POSIX-land), it
2083*40393Sbostic 		 * can only hope to be a creation command.
2084*40393Sbostic 		 */
2085*40393Sbostic 	    shellCommand:
2086*40393Sbostic 		for (cp = line + 1; isspace (*cp); cp++) {
2087*40393Sbostic 		    continue;
2088*40393Sbostic 		}
2089*40393Sbostic 		if (*cp) {
2090*40393Sbostic 		    if (inLine) {
2091*40393Sbostic 			/*
2092*40393Sbostic 			 * So long as it's not a blank line and we're actually
2093*40393Sbostic 			 * in a dependency spec, add the command to the list of
2094*40393Sbostic 			 * commands of all targets in the dependency spec
2095*40393Sbostic 			 */
2096*40393Sbostic 			Lst_ForEach (targets, ParseAddCmd, (ClientData)cp);
2097*40393Sbostic 			continue;
2098*40393Sbostic 		    } else {
2099*40393Sbostic 			Parse_Error (PARSE_FATAL,
2100*40393Sbostic 				     "Unassociated shell command \"%.20s\"",
2101*40393Sbostic 				     cp);
2102*40393Sbostic 		    }
2103*40393Sbostic 		}
2104*40393Sbostic 	    } else if (Parse_IsVar (line)) {
2105*40393Sbostic 		ParseFinishLine();
2106*40393Sbostic 		Parse_DoVar (line, VAR_GLOBAL);
2107*40393Sbostic 	    } else {
2108*40393Sbostic 		/*
2109*40393Sbostic 		 * We now know it's a dependency line so it needs to have all
2110*40393Sbostic 		 * variables expanded before being parsed. Tell the variable
2111*40393Sbostic 		 * module to complain if some variable is undefined...
2112*40393Sbostic 		 * To make life easier on novices, if the line is indented we
2113*40393Sbostic 		 * first make sure the line has a dependency operator in it.
2114*40393Sbostic 		 * If it doesn't have an operator and we're in a dependency
2115*40393Sbostic 		 * line's script, we assume it's actually a shell command
2116*40393Sbostic 		 * and add it to the current list of targets.
2117*40393Sbostic 		 *
2118*40393Sbostic 		 * Note that POSIX declares all lines that start with
2119*40393Sbostic 		 * whitespace are shell commands, so there's no need to check
2120*40393Sbostic 		 * here...
2121*40393Sbostic 		 */
2122*40393Sbostic 		Boolean	nonSpace = FALSE;
2123*40393Sbostic 
2124*40393Sbostic 		cp = line;
2125*40393Sbostic #ifndef POSIX
2126*40393Sbostic 		if (line[0] == ' ') {
2127*40393Sbostic 		    while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
2128*40393Sbostic 			if (!isspace(*cp)) {
2129*40393Sbostic 			    nonSpace = TRUE;
2130*40393Sbostic 			}
2131*40393Sbostic 			cp++;
2132*40393Sbostic 		    }
2133*40393Sbostic 		}
2134*40393Sbostic 
2135*40393Sbostic 		if (*cp == '\0') {
2136*40393Sbostic 		    if (inLine) {
2137*40393Sbostic 			Parse_Error (PARSE_WARNING,
2138*40393Sbostic 				     "Shell command needs a leading tab");
2139*40393Sbostic 			goto shellCommand;
2140*40393Sbostic 		    } else if (nonSpace) {
2141*40393Sbostic 			Parse_Error (PARSE_FATAL, "Missing operator");
2142*40393Sbostic 		    }
2143*40393Sbostic 		} else {
2144*40393Sbostic #endif
2145*40393Sbostic 		    ParseFinishLine();
2146*40393Sbostic 
2147*40393Sbostic 		    cp = Var_Subst (line, VAR_CMD, TRUE);
2148*40393Sbostic 		    free (line);
2149*40393Sbostic 		    line = cp;
2150*40393Sbostic 
2151*40393Sbostic 		    /*
2152*40393Sbostic 		     * Need a non-circular list for the target nodes
2153*40393Sbostic 		     */
2154*40393Sbostic 		    targets = Lst_Init (FALSE);
2155*40393Sbostic 		    inLine = TRUE;
2156*40393Sbostic 
2157*40393Sbostic 		    ParseDoDependency (line);
2158*40393Sbostic #ifndef POSIX
2159*40393Sbostic 		}
2160*40393Sbostic #endif
2161*40393Sbostic 	    }
2162*40393Sbostic 
2163*40393Sbostic 	    nextLine:
2164*40393Sbostic 
2165*40393Sbostic 	    free (line);
2166*40393Sbostic 	}
2167*40393Sbostic 	/*
2168*40393Sbostic 	 * Reached EOF, but it may be just EOF of an include file...
2169*40393Sbostic 	 */
2170*40393Sbostic     } while (ParseEOF() == CONTINUE);
2171*40393Sbostic 
2172*40393Sbostic     /*
2173*40393Sbostic      * Make sure conditionals are clean
2174*40393Sbostic      */
2175*40393Sbostic     Cond_End();
2176*40393Sbostic 
2177*40393Sbostic     if (fatals) {
2178*40393Sbostic 	fprintf (stderr, "Fatal errors encountered -- cannot continue\n");
2179*40393Sbostic 	exit (1);
2180*40393Sbostic     }
2181*40393Sbostic }
2182*40393Sbostic 
2183*40393Sbostic /*-
2184*40393Sbostic  *---------------------------------------------------------------------
2185*40393Sbostic  * Parse_Init --
2186*40393Sbostic  *	initialize the parsing module
2187*40393Sbostic  *
2188*40393Sbostic  * Results:
2189*40393Sbostic  *	none
2190*40393Sbostic  *
2191*40393Sbostic  * Side Effects:
2192*40393Sbostic  *	the parseIncPath list is initialized...
2193*40393Sbostic  *---------------------------------------------------------------------
2194*40393Sbostic  */
2195*40393Sbostic Parse_Init ()
2196*40393Sbostic {
2197*40393Sbostic     char    	*cp;
2198*40393Sbostic     char    	*start;
2199*40393Sbostic     static char syspath[] = DEFSYSPATH;	/* Avoid faults on read-only string
2200*40393Sbostic 					 * constant... */
2201*40393Sbostic 
2202*40393Sbostic     mainNode = NILGNODE;
2203*40393Sbostic     parseIncPath = Lst_Init (FALSE);
2204*40393Sbostic     sysIncPath = Lst_Init (FALSE);
2205*40393Sbostic     includes = Lst_Init (FALSE);
2206*40393Sbostic 
2207*40393Sbostic     /*
2208*40393Sbostic      * Add the directories from the DEFSYSPATH (more than one may be given
2209*40393Sbostic      * as dir1:...:dirn) to the system include path.
2210*40393Sbostic      */
2211*40393Sbostic     for (start = syspath; *start != '\0'; start = cp) {
2212*40393Sbostic 	for (cp = start; *cp != '\0' && *cp != ':'; cp++) {
2213*40393Sbostic 	    ;
2214*40393Sbostic 	}
2215*40393Sbostic 	if (*cp == '\0') {
2216*40393Sbostic 	    Dir_AddDir(sysIncPath, start);
2217*40393Sbostic 	} else {
2218*40393Sbostic 	    *cp++ = '\0';
2219*40393Sbostic 	    Dir_AddDir(sysIncPath, start);
2220*40393Sbostic 	}
2221*40393Sbostic     }
2222*40393Sbostic }
2223*40393Sbostic 
2224*40393Sbostic /*-
2225*40393Sbostic  *-----------------------------------------------------------------------
2226*40393Sbostic  * Parse_MainName --
2227*40393Sbostic  *	Return a Lst of the main target to create for main()'s sake. If
2228*40393Sbostic  *	no such target exists, we Punt with an obnoxious error message.
2229*40393Sbostic  *
2230*40393Sbostic  * Results:
2231*40393Sbostic  *	A Lst of the single node to create.
2232*40393Sbostic  *
2233*40393Sbostic  * Side Effects:
2234*40393Sbostic  *	None.
2235*40393Sbostic  *
2236*40393Sbostic  *-----------------------------------------------------------------------
2237*40393Sbostic  */
2238*40393Sbostic Lst
2239*40393Sbostic Parse_MainName()
2240*40393Sbostic {
2241*40393Sbostic     Lst           main;	/* result list */
2242*40393Sbostic 
2243*40393Sbostic     main = Lst_Init (FALSE);
2244*40393Sbostic 
2245*40393Sbostic     if (mainNode == NILGNODE) {
2246*40393Sbostic 	Punt ("I don't know what to DO!\n");
2247*40393Sbostic     	/*NOTREACHED*/
2248*40393Sbostic     } else if (mainNode->type & OP_DOUBLEDEP) {
2249*40393Sbostic 	Lst_Concat(main, mainNode->cohorts, LST_CONCNEW);
2250*40393Sbostic     }
2251*40393Sbostic     (void) Lst_AtEnd (main, (ClientData)mainNode);
2252*40393Sbostic     return (main);
2253*40393Sbostic }
2254