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