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