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