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