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