parse.c revision 92921
167754Smsmith/*
267754Smsmith * Copyright (c) 1988, 1989, 1990, 1993
367754Smsmith *	The Regents of the University of California.  All rights reserved.
4102550Siwasaki * Copyright (c) 1989 by Berkeley Softworks
567754Smsmith * All rights reserved.
667754Smsmith *
767754Smsmith * This code is derived from software contributed to Berkeley by
867754Smsmith * Adam de Boor.
967754Smsmith *
1067754Smsmith * Redistribution and use in source and binary forms, with or without
1167754Smsmith * modification, are permitted provided that the following conditions
1291116Smsmith * are met:
1370243Smsmith * 1. Redistributions of source code must retain the above copyright
1467754Smsmith *    notice, this list of conditions and the following disclaimer.
1567754Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1667754Smsmith *    notice, this list of conditions and the following disclaimer in the
1767754Smsmith *    documentation and/or other materials provided with the distribution.
1867754Smsmith * 3. All advertising materials mentioning features or use of this software
1967754Smsmith *    must display the following acknowledgement:
2067754Smsmith *	This product includes software developed by the University of
2167754Smsmith *	California, Berkeley and its contributors.
2267754Smsmith * 4. Neither the name of the University nor the names of its contributors
2367754Smsmith *    may be used to endorse or promote products derived from this software
2467754Smsmith *    without specific prior written permission.
2567754Smsmith *
2667754Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2767754Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2867754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2967754Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3067754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3167754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3267754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3367754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3467754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3567754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3667754Smsmith * SUCH DAMAGE.
3767754Smsmith *
3867754Smsmith * @(#)parse.c	8.3 (Berkeley) 3/19/94
3967754Smsmith */
4067754Smsmith
4167754Smsmith#ifndef lint
4267754Smsmith#include <sys/cdefs.h>
4367754Smsmith__RCSID("$FreeBSD: head/usr.bin/make/parse.c 92921 2002-03-22 01:33:25Z imp $");
4467754Smsmith#endif /* not lint */
4567754Smsmith
4667754Smsmith/*-
4767754Smsmith * parse.c --
4867754Smsmith *	Functions to parse a makefile.
4967754Smsmith *
5067754Smsmith *	One function, Parse_Init, must be called before any functions
5167754Smsmith *	in this module are used. After that, the function Parse_File is the
5267754Smsmith *	main entry point and controls most of the other functions in this
5367754Smsmith *	module.
5467754Smsmith *
5567754Smsmith *	Most important structures are kept in Lsts. Directories for
5667754Smsmith *	the #include "..." function are kept in the 'parseIncPath' Lst, while
5767754Smsmith *	those for the #include <...> are kept in the 'sysIncPath' Lst. The
5867754Smsmith *	targets currently being defined are kept in the 'targets' Lst.
5967754Smsmith *
6067754Smsmith *	The variables 'fname' and 'lineno' are used to track the name
6167754Smsmith *	of the current file and the line number in that file so that error
6267754Smsmith *	messages can be more meaningful.
6367754Smsmith *
6467754Smsmith * Interface:
6567754Smsmith *	Parse_Init	    	    Initialization function which must be
6667754Smsmith *	    	  	    	    called before anything else in this module
6767754Smsmith *	    	  	    	    is used.
6867754Smsmith *
6967754Smsmith *	Parse_End		    Cleanup the module
7067754Smsmith *
7167754Smsmith *	Parse_File	    	    Function used to parse a makefile. It must
7267754Smsmith *	    	  	    	    be given the name of the file, which should
7367754Smsmith *	    	  	    	    already have been opened, and a function
7467754Smsmith *	    	  	    	    to call to read a character from the file.
7567754Smsmith *
7667754Smsmith *	Parse_IsVar	    	    Returns TRUE if the given line is a
7767754Smsmith *	    	  	    	    variable assignment. Used by MainParseArgs
7867754Smsmith *	    	  	    	    to determine if an argument is a target
7967754Smsmith *	    	  	    	    or a variable assignment. Used internally
8067754Smsmith *	    	  	    	    for pretty much the same thing...
8167754Smsmith *
8267754Smsmith *	Parse_Error	    	    Function called when an error occurs in
8367754Smsmith *	    	  	    	    parsing. Used by the variable and
8467754Smsmith *	    	  	    	    conditional modules.
8567754Smsmith *	Parse_MainName	    	    Returns a Lst of the main target to create.
8667754Smsmith */
8767754Smsmith
8867754Smsmith#ifdef __STDC__
8967754Smsmith#include <stdarg.h>
9067754Smsmith#else
9167754Smsmith#include <varargs.h>
9267754Smsmith#endif
9367754Smsmith#include <ctype.h>
9467754Smsmith#include <err.h>
9567754Smsmith#include <stdio.h>
9667754Smsmith#include "make.h"
9767754Smsmith#include "hash.h"
9867754Smsmith#include "dir.h"
9967754Smsmith#include "job.h"
10067754Smsmith#include "buf.h"
10167754Smsmith#include "pathnames.h"
10267754Smsmith
10367754Smsmith/*
10467754Smsmith * These values are returned by ParseEOF to tell Parse_File whether to
10567754Smsmith * CONTINUE parsing, i.e. it had only reached the end of an include file,
10667754Smsmith * or if it's DONE.
10767754Smsmith */
10867754Smsmith#define	CONTINUE	1
10967754Smsmith#define	DONE		0
11067754Smsmithstatic Lst     	    targets;	/* targets we're working on */
11167754Smsmithstatic Lst     	    targCmds;	/* command lines for targets */
11267754Smsmithstatic Boolean	    inLine;	/* true if currently in a dependency
11367754Smsmith				 * line or its commands */
11467754Smsmithtypedef struct {
11567754Smsmith    char *str;
11667754Smsmith    char *ptr;
11767754Smsmith} PTR;
11867754Smsmith
11967754Smsmithstatic char    	    *fname;	/* name of current file (for errors) */
12067754Smsmithstatic int          lineno;	/* line number in current file */
12167754Smsmithstatic FILE   	    *curFILE = NULL; 	/* current makefile */
122102550Siwasaki
12367754Smsmithstatic PTR 	    *curPTR = NULL; 	/* current makefile */
124102550Siwasaki
12591116Smsmithstatic int	    fatals = 0;
12667754Smsmith
12767754Smsmithstatic GNode	    *mainNode;	/* The main target to create. This is the
12867754Smsmith				 * first target on the first dependency
12967754Smsmith				 * line in the first makefile */
13099679Siwasaki/*
13167754Smsmith * Definitions for handling #include specifications
13267754Smsmith */
13367754Smsmithtypedef struct IFile {
13467754Smsmith    char           *fname;	    /* name of previous file */
13567754Smsmith    int             lineno;	    /* saved line number */
13667754Smsmith    FILE *          F;		    /* the open stream */
13767754Smsmith    PTR *	    p;	    	    /* the char pointer */
13883174Smsmith} IFile;
13967754Smsmith
14067754Smsmithstatic Lst      includes;  	/* stack of IFiles generated by
14167754Smsmith				 * #includes */
14299679SiwasakiLst         	parseIncPath;	/* list of directories for "..." includes */
14399679SiwasakiLst         	sysIncPath;	/* list of directories for <...> includes */
14499679Siwasaki
14599679Siwasaki/*-
14699679Siwasaki * specType contains the SPECial TYPE of the current target. It is
14799679Siwasaki * Not if the target is unspecial. If it *is* special, however, the children
14899679Siwasaki * are linked as children of the parent but not vice versa. This variable is
14967754Smsmith * set in ParseDoDependency
15067754Smsmith */
15167754Smsmithtypedef enum {
15267754Smsmith    Begin,  	    /* .BEGIN */
15367754Smsmith    Default,	    /* .DEFAULT */
15467754Smsmith    End,    	    /* .END */
15567754Smsmith    Ignore,	    /* .IGNORE */
15667754Smsmith    Includes,	    /* .INCLUDES */
15767754Smsmith    Interrupt,	    /* .INTERRUPT */
15867754Smsmith    Libs,	    /* .LIBS */
15967754Smsmith    MFlags,	    /* .MFLAGS or .MAKEFLAGS */
16091116Smsmith    Main,	    /* .MAIN and we don't have anything user-specified to
16191116Smsmith		     * make */
16267754Smsmith    NoExport,	    /* .NOEXPORT */
16367754Smsmith    Not,	    /* Not special */
16467754Smsmith    NotParallel,    /* .NOTPARALELL */
16567754Smsmith    Null,   	    /* .NULL */
16667754Smsmith    Order,  	    /* .ORDER */
16767754Smsmith    Parallel,	    /* .PARALLEL */
16867754Smsmith    ExPath,	    /* .PATH */
16967754Smsmith    Phony,	    /* .PHONY */
17067754Smsmith#ifdef POSIX
17167754Smsmith    Posix,	    /* .POSIX */
17267754Smsmith#endif
17367754Smsmith    Precious,	    /* .PRECIOUS */
17467754Smsmith    ExShell,	    /* .SHELL */
17567754Smsmith    Silent,	    /* .SILENT */
17667754Smsmith    SingleShell,    /* .SINGLESHELL */
17767754Smsmith    Suffixes,	    /* .SUFFIXES */
17867754Smsmith    Wait,	    /* .WAIT */
17967754Smsmith    Attribute	    /* Generic attribute */
18083174Smsmith} ParseSpecial;
18167754Smsmith
18299679Siwasakistatic ParseSpecial specType;
18367754Smsmithstatic int waiting;
18467754Smsmith
18567754Smsmith/*
18667754Smsmith * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
18767754Smsmith * seen, then set to each successive source on the line.
18899679Siwasaki */
18967754Smsmithstatic GNode	*predecessor;
19067754Smsmith
19167754Smsmith/*
19267754Smsmith * The parseKeywords table is searched using binary search when deciding
19399679Siwasaki * if a target or source is special. The 'spec' field is the ParseSpecial
19467754Smsmith * type of the keyword ("Not" if the keyword isn't special as a target) while
19567754Smsmith * the 'op' field is the operator to apply to the list of targets if the
19691116Smsmith * keyword is used as a source ("0" if the keyword isn't special as a source)
19767754Smsmith */
19867754Smsmithstatic struct {
19967754Smsmith    char    	  *name;    	/* Name of keyword */
20067754Smsmith    ParseSpecial  spec;	    	/* Type when used as a target */
20167754Smsmith    int	    	  op;	    	/* Operator when used as a source */
20267754Smsmith} parseKeywords[] = {
20367754Smsmith{ ".BEGIN", 	  Begin,    	0 },
20467754Smsmith{ ".DEFAULT",	  Default,  	0 },
20567754Smsmith{ ".END",   	  End,	    	0 },
20667754Smsmith{ ".EXEC",	  Attribute,   	OP_EXEC },
20767754Smsmith{ ".IGNORE",	  Ignore,   	OP_IGNORE },
20887031Smsmith{ ".INCLUDES",	  Includes, 	0 },
20991116Smsmith{ ".INTERRUPT",	  Interrupt,	0 },
21087031Smsmith{ ".INVISIBLE",	  Attribute,   	OP_INVISIBLE },
21191116Smsmith{ ".JOIN",  	  Attribute,   	OP_JOIN },
21287031Smsmith{ ".LIBS",  	  Libs,	    	0 },
21387031Smsmith{ ".MAIN",	  Main,		0 },
21487031Smsmith{ ".MAKE",  	  Attribute,   	OP_MAKE },
21567754Smsmith{ ".MAKEFLAGS",	  MFlags,   	0 },
21691116Smsmith{ ".MFLAGS",	  MFlags,   	0 },
21767754Smsmith{ ".NOTMAIN",	  Attribute,   	OP_NOTMAIN },
21867754Smsmith{ ".NOTPARALLEL", NotParallel,	0 },
21967754Smsmith{ ".NO_PARALLEL", NotParallel,	0 },
22067754Smsmith{ ".NULL",  	  Null,	    	0 },
22167754Smsmith{ ".OPTIONAL",	  Attribute,   	OP_OPTIONAL },
22267754Smsmith{ ".ORDER", 	  Order,    	0 },
22367754Smsmith{ ".PARALLEL",	  Parallel,	0 },
22467754Smsmith{ ".PATH",	  ExPath,	0 },
22567754Smsmith{ ".PHONY",	  Phony,	OP_PHONY },
22667754Smsmith#ifdef POSIX
22767754Smsmith{ ".POSIX",	  Posix,	0 },
22867754Smsmith#endif
22967754Smsmith{ ".PRECIOUS",	  Precious, 	OP_PRECIOUS },
23067754Smsmith{ ".RECURSIVE",	  Attribute,	OP_MAKE },
23167754Smsmith{ ".SHELL", 	  ExShell,    	0 },
23267754Smsmith{ ".SILENT",	  Silent,   	OP_SILENT },
23367754Smsmith{ ".SINGLESHELL", SingleShell,	0 },
23467754Smsmith{ ".SUFFIXES",	  Suffixes, 	0 },
23567754Smsmith{ ".USE",   	  Attribute,   	OP_USE },
23699679Siwasaki{ ".WAIT",	  Wait, 	0 },
23799679Siwasaki};
23899679Siwasaki
23967754Smsmithstatic int ParseFindKeyword(char *);
24067754Smsmithstatic int ParseLinkSrc(void *, void *);
24167754Smsmithstatic int ParseDoOp(void *, void *);
24267754Smsmithstatic int ParseAddDep(void *, void *);
24367754Smsmithstatic void ParseDoSrc(int, char *, Lst);
24467754Smsmithstatic int ParseFindMain(void *, void *);
24567754Smsmithstatic int ParseAddDir(void *, void *);
24667754Smsmithstatic int ParseClearPath(void *, void *);
24767754Smsmithstatic void ParseDoDependency(char *);
24867754Smsmithstatic int ParseAddCmd(void *, void *);
24967754Smsmithstatic int ParseReadc(void);
25067754Smsmithstatic void ParseUnreadc(int);
25167754Smsmithstatic void ParseHasCommands(void *);
25267754Smsmithstatic void ParseDoInclude(char *);
25367754Smsmithstatic void ParseDoError(char *);
25467754Smsmith#ifdef SYSVINCLUDE
25567754Smsmithstatic void ParseTraditionalInclude(char *);
25667754Smsmith#endif
25767754Smsmithstatic int ParseEOF(int);
25867754Smsmithstatic char *ParseReadLine(void);
25967754Smsmithstatic char *ParseSkipLine(int);
26067754Smsmithstatic void ParseFinishLine(void);
26167754Smsmith
26267754Smsmith/*-
26367754Smsmith *----------------------------------------------------------------------
26467754Smsmith * ParseFindKeyword --
26567754Smsmith *	Look in the table of keywords for one matching the given string.
26667754Smsmith *
26767754Smsmith * Results:
26883174Smsmith *	The index of the keyword, or -1 if it isn't there.
26967754Smsmith *
27067754Smsmith * Side Effects:
27187031Smsmith *	None
27267754Smsmith *----------------------------------------------------------------------
27367754Smsmith */
27467754Smsmithstatic int
27567754SmsmithParseFindKeyword (str)
27683174Smsmith    char	    *str;		/* String to find */
27767754Smsmith{
27867754Smsmith    register int    start,
27967754Smsmith		    end,
28067754Smsmith		    cur;
28167754Smsmith    register int    diff;
28267754Smsmith
28367754Smsmith    start = 0;
28467754Smsmith    end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
28567754Smsmith
28667754Smsmith    do {
28767754Smsmith	cur = start + ((end - start) / 2);
28867754Smsmith	diff = strcmp (str, parseKeywords[cur].name);
28967754Smsmith
29067754Smsmith	if (diff == 0) {
29167754Smsmith	    return (cur);
29267754Smsmith	} else if (diff < 0) {
29367754Smsmith	    end = cur - 1;
29467754Smsmith	} else {
29567754Smsmith	    start = cur + 1;
29667754Smsmith	}
29767754Smsmith    } while (start <= end);
29867754Smsmith    return (-1);
29967754Smsmith}
30067754Smsmith
30167754Smsmith/*-
30267754Smsmith * Parse_Error  --
30367754Smsmith *	Error message abort function for parsing. Prints out the context
30467754Smsmith *	of the error (line number and file) as well as the message with
30567754Smsmith *	two optional arguments.
30667754Smsmith *
30767754Smsmith * Results:
30867754Smsmith *	None
30967754Smsmith *
31067754Smsmith * Side Effects:
31167754Smsmith *	"fatals" is incremented if the level is PARSE_FATAL.
31267754Smsmith */
31367754Smsmith/* VARARGS */
31467754Smsmithvoid
31567754Smsmith#ifdef __STDC__
31667754SmsmithParse_Error(int type, char *fmt, ...)
31767754Smsmith#else
31867754SmsmithParse_Error(va_alist)
31967754Smsmith	va_dcl
32067754Smsmith#endif
32167754Smsmith{
32267754Smsmith	va_list ap;
32367754Smsmith#ifdef __STDC__
32467754Smsmith	va_start(ap, fmt);
32567754Smsmith#else
32699679Siwasaki	int type;		/* Error type (PARSE_WARNING, PARSE_FATAL) */
32767754Smsmith	char *fmt;
32867754Smsmith
32967754Smsmith	va_start(ap);
33067754Smsmith	type = va_arg(ap, int);
33167754Smsmith	fmt = va_arg(ap, char *);
33267754Smsmith#endif
33383174Smsmith
33483174Smsmith	(void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno);
33567754Smsmith	if (type == PARSE_WARNING)
33667754Smsmith		(void)fprintf(stderr, "warning: ");
33783174Smsmith	(void)vfprintf(stderr, fmt, ap);
33867754Smsmith	va_end(ap);
33967754Smsmith	(void)fprintf(stderr, "\n");
34067754Smsmith	(void)fflush(stderr);
34167754Smsmith	if (type == PARSE_FATAL)
34267754Smsmith		fatals += 1;
34399679Siwasaki}
34467754Smsmith
34567754Smsmith/*-
34667754Smsmith *---------------------------------------------------------------------
34767754Smsmith * ParseLinkSrc  --
34867754Smsmith *	Link the parent node to its new child. Used in a Lst_ForEach by
34967754Smsmith *	ParseDoDependency. If the specType isn't 'Not', the parent
35067754Smsmith *	isn't linked as a parent of the child.
35167754Smsmith *
35267754Smsmith * Results:
35367754Smsmith *	Always = 0
35467754Smsmith *
35567754Smsmith * Side Effects:
35667754Smsmith *	New elements are added to the parents list of cgn and the
35767754Smsmith *	children list of cgn. the unmade field of pgn is updated
35867754Smsmith *	to reflect the additional child.
35967754Smsmith *---------------------------------------------------------------------
36067754Smsmith */
36167754Smsmithstatic int
36267754SmsmithParseLinkSrc (pgnp, cgnp)
36367754Smsmith    void *     pgnp;	/* The parent node */
36467754Smsmith    void *     cgnp;	/* The child node */
36567754Smsmith{
36691116Smsmith    GNode          *pgn = (GNode *) pgnp;
36791116Smsmith    GNode          *cgn = (GNode *) cgnp;
36882367Smsmith    if (Lst_Member (pgn->children, (void *)cgn) == NULL) {
36991116Smsmith	(void)Lst_AtEnd (pgn->children, (void *)cgn);
37067754Smsmith	if (specType == Not) {
37167754Smsmith	    (void)Lst_AtEnd (cgn->parents, (void *)pgn);
37267754Smsmith	}
37367754Smsmith	pgn->unmade += 1;
37467754Smsmith    }
37567754Smsmith    return (0);
37667754Smsmith}
37767754Smsmith
37867754Smsmith/*-
37967754Smsmith *---------------------------------------------------------------------
38067754Smsmith * ParseDoOp  --
38167754Smsmith *	Apply the parsed operator to the given target node. Used in a
38267754Smsmith *	Lst_ForEach call by ParseDoDependency once all targets have
38391116Smsmith *	been found and their operator parsed. If the previous and new
38467754Smsmith *	operators are incompatible, a major error is taken.
38567754Smsmith *
38667754Smsmith * Results:
38767754Smsmith *	Always 0
38867754Smsmith *
38967754Smsmith * Side Effects:
39067754Smsmith *	The type field of the node is altered to reflect any new bits in
39167754Smsmith *	the op.
39267754Smsmith *---------------------------------------------------------------------
39367754Smsmith */
39499679Siwasakistatic int
39580062SmsmithParseDoOp (gnp, opp)
39677424Smsmith    void *     gnp;		/* The node to which the operator is to be
39780062Smsmith				 * applied */
39867754Smsmith    void *     opp;		/* The operator to apply */
39967754Smsmith{
40099679Siwasaki    GNode          *gn = (GNode *) gnp;
40167754Smsmith    int             op = *(int *) opp;
40267754Smsmith    /*
40367754Smsmith     * If the dependency mask of the operator and the node don't match and
40467754Smsmith     * the node has actually had an operator applied to it before, and
40569746Smsmith     * the operator actually has some dependency information in it, complain.
40667754Smsmith     */
40767754Smsmith    if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
40867754Smsmith	!OP_NOP(gn->type) && !OP_NOP(op))
40999679Siwasaki    {
41067754Smsmith	Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name);
41183174Smsmith	return (1);
41283174Smsmith    }
41367754Smsmith
41467754Smsmith    if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
41567754Smsmith	/*
41667754Smsmith	 * If the node was the object of a :: operator, we need to create a
41767754Smsmith	 * new instance of it for the children and commands on this dependency
41867754Smsmith	 * line. The new instance is placed on the 'cohorts' list of the
41977424Smsmith	 * initial one (note the initial one is not on its own cohorts list)
42067754Smsmith	 * and the new instance is linked to all parents of the initial
42167754Smsmith	 * instance.
42267754Smsmith	 */
42367754Smsmith	register GNode	*cohort;
42467754Smsmith	LstNode	    	ln;
42567754Smsmith
42683174Smsmith	cohort = Targ_NewGN(gn->name);
42767754Smsmith	/*
42867754Smsmith	 * Duplicate links to parents so graph traversal is simple. Perhaps
42999679Siwasaki	 * some type bits should be duplicated?
43067754Smsmith	 *
43182367Smsmith	 * Make the cohort invisible as well to avoid duplicating it into
43282367Smsmith	 * other variables. True, parents of this target won't tend to do
43367754Smsmith	 * anything with their local variables, but better safe than
43482367Smsmith	 * sorry.
43582367Smsmith	 */
43682367Smsmith	Lst_ForEach(gn->parents, ParseLinkSrc, (void *)cohort);
43767754Smsmith	cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
43882367Smsmith	(void)Lst_AtEnd(gn->cohorts, (void *)cohort);
43982367Smsmith
44083174Smsmith	/*
44182367Smsmith	 * Replace the node in the targets list with the new copy
44283174Smsmith	 */
44382367Smsmith	ln = Lst_Member(targets, (void *)gn);
44482367Smsmith	Lst_Replace(ln, (void *)cohort);
44582367Smsmith	gn = cohort;
44683174Smsmith    }
44782367Smsmith    /*
44883174Smsmith     * We don't want to nuke any previous flags (whatever they were) so we
44982367Smsmith     * just OR the new operator into the old
45083174Smsmith     */
45182367Smsmith    gn->type |= op;
45282367Smsmith
45383174Smsmith    return (0);
45483174Smsmith}
45582367Smsmith
45682367Smsmith/*-
45782367Smsmith *---------------------------------------------------------------------
45882367Smsmith * ParseAddDep  --
45991116Smsmith *	Check if the pair of GNodes given needs to be synchronized.
46082367Smsmith *	This has to be when two nodes are on different sides of a
46182367Smsmith *	.WAIT directive.
46282367Smsmith *
46391116Smsmith * Results:
46482367Smsmith *	Returns 1 if the two targets need to be ordered, 0 otherwise.
46582367Smsmith *	If it returns 1, the search can stop
46683174Smsmith *
46782367Smsmith * Side Effects:
46882367Smsmith *	A dependency can be added between the two nodes.
46982367Smsmith *
47082367Smsmith *---------------------------------------------------------------------
47182367Smsmith */
47282367Smsmithstatic int
47367754SmsmithParseAddDep(pp, sp)
47467754Smsmith    void * pp;
47599679Siwasaki    void * sp;
47667754Smsmith{
47767754Smsmith    GNode *p = (GNode *) pp;
47867754Smsmith    GNode *s = (GNode *) sp;
47967754Smsmith
48067754Smsmith    if (p->order < s->order) {
48167754Smsmith	/*
48267754Smsmith	 * XXX: This can cause loops, and loops can cause unmade targets,
48367754Smsmith	 * but checking is tedious, and the debugging output can show the
48467754Smsmith	 * problem
48567754Smsmith	 */
48677424Smsmith	(void)Lst_AtEnd(p->successors, (void *)s);
48767754Smsmith	(void)Lst_AtEnd(s->preds, (void *)p);
48867754Smsmith	return 0;
48967754Smsmith    }
49067754Smsmith    else
49199679Siwasaki	return 1;
49267754Smsmith}
49367754Smsmith
49467754Smsmith
49567754Smsmith/*-
49671867Smsmith *---------------------------------------------------------------------
49767754Smsmith * ParseDoSrc  --
49867754Smsmith *	Given the name of a source, figure out if it is an attribute
49967754Smsmith *	and apply it to the targets if it is. Else decide if there is
50077424Smsmith *	some attribute which should be applied *to* the source because
50167754Smsmith *	of some special target and apply it if so. Otherwise, make the
50267754Smsmith *	source be a child of the targets in the list 'targets'
50367754Smsmith *
50467754Smsmith * Results:
50567754Smsmith *	None
50667754Smsmith *
50767754Smsmith * Side Effects:
50867754Smsmith *	Operator bits may be added to the list of targets or to the source.
50977424Smsmith *	The targets may have a new source added to their lists of children.
51067754Smsmith *---------------------------------------------------------------------
51167754Smsmith */
51267754Smsmithstatic void
51367754SmsmithParseDoSrc (tOp, src, allsrc)
51467754Smsmith    int		tOp;	/* operator (if any) from special targets */
51567754Smsmith    char	*src;	/* name of the source to handle */
51687031Smsmith    Lst		allsrc;	/* List of all sources to wait for */
51767754Smsmith{
51867754Smsmith    GNode	*gn = NULL;
51967754Smsmith
52099679Siwasaki    if (*src == '.' && isupper (src[1])) {
52199679Siwasaki	int keywd = ParseFindKeyword(src);
52299679Siwasaki	if (keywd != -1) {
52367754Smsmith	    int op = parseKeywords[keywd].op;
52467754Smsmith	    if (op != 0) {
52567754Smsmith		Lst_ForEach (targets, ParseDoOp, (void *)&op);
52667754Smsmith		return;
52767754Smsmith	    }
52883174Smsmith	    if (parseKeywords[keywd].spec == Wait) {
52999679Siwasaki		waiting++;
530102550Siwasaki		return;
53183174Smsmith	    }
53299679Siwasaki	}
53383174Smsmith    }
53483174Smsmith
53583174Smsmith    switch (specType) {
53683174Smsmith    case Main:
53783174Smsmith	/*
53883174Smsmith	 * If we have noted the existence of a .MAIN, it means we need
53999679Siwasaki	 * to add the sources of said target to the list of things
54083174Smsmith	 * to create. The string 'src' is likely to be free, so we
54199679Siwasaki	 * must make a new copy of it. Note that this will only be
54299679Siwasaki	 * invoked if the user didn't specify a target on the command
54399679Siwasaki	 * line. This is to allow #ifmake's to succeed, or something...
54467754Smsmith	 */
54567754Smsmith	(void) Lst_AtEnd (create, (void *)estrdup(src));
54667754Smsmith	/*
54767754Smsmith	 * Add the name to the .TARGETS variable as well, so the user cna
54867754Smsmith	 * employ that, if desired.
54967754Smsmith	 */
55067754Smsmith	Var_Append(".TARGETS", src, VAR_GLOBAL);
551102550Siwasaki	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 != NULL) {
560	    (void)Lst_AtEnd(predecessor->successors, (void *)gn);
561	    (void)Lst_AtEnd(gn->preds, (void *)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, (void *)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 != NULL; ln = Lst_Succ(ln)){
592		cohort = (GNode *)Lst_Datum(ln);
593		if (tOp) {
594		    cohort->type |= tOp;
595		} else {
596		    Lst_ForEach(targets, ParseLinkSrc, (void *)cohort);
597		}
598	    }
599	}
600	break;
601    }
602
603    gn->order = waiting;
604    (void)Lst_AtEnd(allsrc, (void *)gn);
605    if (waiting) {
606	Lst_ForEach(allsrc, ParseAddDep, (void *)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    void *	  gnp;	    /* Node to examine */
628    void *    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    void *	  path;
656    void *    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    void * path;
678    void * 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 NULL
847		 */
848		switch (specType) {
849		    case ExPath:
850			if (paths == NULL) {
851			    paths = Lst_Init(FALSE);
852			}
853			(void)Lst_AtEnd(paths, (void *)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, (void *)gn);
866			break;
867		    case Default:
868			gn = Targ_NewGN(".DEFAULT");
869			gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
870			(void)Lst_AtEnd(targets, (void *)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 = NULL;
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 == NULL) {
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, (void *)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, (void *)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, (void *)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, (void *)&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, (void *)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, (void *)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 == NULL) {
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, (void *)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		else
1417		    --opc;
1418
1419	    if (strncmp(opc, ":sh", 3) == 0) {
1420		type = VAR_SHELL;
1421		*opc = '\0';
1422		break;
1423	    }
1424#endif
1425	    type = VAR_NORMAL;
1426	    break;
1427    }
1428
1429    while (isspace (*cp)) {
1430	cp++;
1431    }
1432
1433    if (type == VAR_APPEND) {
1434	Var_Append (line, cp, ctxt);
1435    } else if (type == VAR_SUBST) {
1436	/*
1437	 * Allow variables in the old value to be undefined, but leave their
1438	 * invocation alone -- this is done by forcing oldVars to be false.
1439	 * XXX: This can cause recursive variables, but that's not hard to do,
1440	 * and this allows someone to do something like
1441	 *
1442	 *  CFLAGS = $(.INCLUDES)
1443	 *  CFLAGS := -I.. $(CFLAGS)
1444	 *
1445	 * And not get an error.
1446	 */
1447	Boolean	  oldOldVars = oldVars;
1448
1449	oldVars = FALSE;
1450	cp = Var_Subst(NULL, cp, ctxt, FALSE);
1451	oldVars = oldOldVars;
1452
1453	Var_Set(line, cp, ctxt);
1454	free(cp);
1455    } else if (type == VAR_SHELL) {
1456	Boolean	freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
1457				  * if any variable expansion was performed */
1458	char *res, *err;
1459
1460	if (strchr(cp, '$') != NULL) {
1461	    /*
1462	     * There's a dollar sign in the command, so perform variable
1463	     * expansion on the whole thing. The resulting string will need
1464	     * freeing when we're done, so set freeCmd to TRUE.
1465	     */
1466	    cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
1467	    freeCmd = TRUE;
1468	}
1469
1470	res = Cmd_Exec(cp, &err);
1471	Var_Set(line, res, ctxt);
1472	free(res);
1473
1474	if (err)
1475	    Parse_Error(PARSE_WARNING, err, cp);
1476
1477	if (freeCmd)
1478	    free(cp);
1479    } else {
1480	/*
1481	 * Normal assignment -- just do it.
1482	 */
1483	Var_Set(line, cp, ctxt);
1484    }
1485}
1486
1487
1488/*-
1489 * ParseAddCmd  --
1490 *	Lst_ForEach function to add a command line to all targets
1491 *
1492 * Results:
1493 *	Always 0
1494 *
1495 * Side Effects:
1496 *	A new element is added to the commands list of the node.
1497 */
1498static int
1499ParseAddCmd(gnp, cmd)
1500    void * gnp;	/* the node to which the command is to be added */
1501    void * cmd;	/* the command to add */
1502{
1503    GNode *gn = (GNode *) gnp;
1504    /* if target already supplied, ignore commands */
1505    if (!(gn->type & OP_HAS_COMMANDS))
1506	(void)Lst_AtEnd(gn->commands, cmd);
1507    return(0);
1508}
1509
1510/*-
1511 *-----------------------------------------------------------------------
1512 * ParseHasCommands --
1513 *	Callback procedure for Parse_File when destroying the list of
1514 *	targets on the last dependency line. Marks a target as already
1515 *	having commands if it does, to keep from having shell commands
1516 *	on multiple dependency lines.
1517 *
1518 * Results:
1519 *	None
1520 *
1521 * Side Effects:
1522 *	OP_HAS_COMMANDS may be set for the target.
1523 *
1524 *-----------------------------------------------------------------------
1525 */
1526static void
1527ParseHasCommands(gnp)
1528    void * 	  gnp;	    /* Node to examine */
1529{
1530    GNode *gn = (GNode *) gnp;
1531    if (!Lst_IsEmpty(gn->commands)) {
1532	gn->type |= OP_HAS_COMMANDS;
1533    }
1534}
1535
1536/*-
1537 *-----------------------------------------------------------------------
1538 * Parse_AddIncludeDir --
1539 *	Add a directory to the path searched for included makefiles
1540 *	bracketed by double-quotes. Used by functions in main.c
1541 *
1542 * Results:
1543 *	None.
1544 *
1545 * Side Effects:
1546 *	The directory is appended to the list.
1547 *
1548 *-----------------------------------------------------------------------
1549 */
1550void
1551Parse_AddIncludeDir (dir)
1552    char    	  *dir;	    /* The name of the directory to add */
1553{
1554    Dir_AddDir (parseIncPath, dir);
1555}
1556
1557/*---------------------------------------------------------------------
1558 * ParseDoError  --
1559 *	Handle error directive
1560 *
1561 *	The input is the line minus the ".error".  We substitute variables,
1562 *	print the message and exit(1) or just print a warning if the ".error"
1563 *	directive is malformed.
1564 *
1565 *---------------------------------------------------------------------
1566 */
1567static void
1568ParseDoError(errmsg)
1569    char          *errmsg;	/* error message */
1570{
1571	if (!isspace(*errmsg)) {
1572		Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg);
1573		return;
1574	}
1575
1576	while (isspace(*errmsg))
1577		errmsg++;
1578
1579	errmsg = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
1580
1581	/* use fprintf/exit instead of Parse_Error to terminate immediately */
1582	fprintf(stderr, "\"%s\", line %d: %s\n", fname, lineno, errmsg);
1583	exit(1);
1584}
1585
1586/*-
1587 *---------------------------------------------------------------------
1588 * ParseDoInclude  --
1589 *	Push to another file.
1590 *
1591 *	The input is the line minus the #include. A file spec is a string
1592 *	enclosed in <> or "". The former is looked for only in sysIncPath.
1593 *	The latter in . and the directories specified by -I command line
1594 *	options
1595 *
1596 * Results:
1597 *	None
1598 *
1599 * Side Effects:
1600 *	A structure is added to the includes Lst and readProc, lineno,
1601 *	fname and curFILE are altered for the new file
1602 *---------------------------------------------------------------------
1603 */
1604static void
1605ParseDoInclude (file)
1606    char          *file;	/* file specification */
1607{
1608    char          *fullname;	/* full pathname of file */
1609    IFile         *oldFile;	/* state associated with current file */
1610    char          endc;	    	/* the character which ends the file spec */
1611    char          *cp;		/* current position in file spec */
1612    Boolean 	  isSystem; 	/* TRUE if makefile is a system makefile */
1613
1614    /*
1615     * Skip to delimiter character so we know where to look
1616     */
1617    while ((*file == ' ') || (*file == '\t')) {
1618	file++;
1619    }
1620
1621    if ((*file != '"') && (*file != '<')) {
1622	Parse_Error (PARSE_FATAL,
1623	    ".include filename must be delimited by '\"' or '<'");
1624	return;
1625    }
1626
1627    /*
1628     * Set the search path on which to find the include file based on the
1629     * characters which bracket its name. Angle-brackets imply it's
1630     * a system Makefile while double-quotes imply it's a user makefile
1631     */
1632    if (*file == '<') {
1633	isSystem = TRUE;
1634	endc = '>';
1635    } else {
1636	isSystem = FALSE;
1637	endc = '"';
1638    }
1639
1640    /*
1641     * Skip to matching delimiter
1642     */
1643    for (cp = ++file; *cp && *cp != endc; cp++) {
1644	continue;
1645    }
1646
1647    if (*cp != endc) {
1648	Parse_Error (PARSE_FATAL,
1649		     "Unclosed %cinclude filename. '%c' expected",
1650		     '.', endc);
1651	return;
1652    }
1653    *cp = '\0';
1654
1655    /*
1656     * Substitute for any variables in the file name before trying to
1657     * find the thing.
1658     */
1659    file = Var_Subst (NULL, file, VAR_CMD, FALSE);
1660
1661    /*
1662     * Now we know the file's name and its search path, we attempt to
1663     * find the durn thing. A return of NULL indicates the file don't
1664     * exist.
1665     */
1666    if (!isSystem) {
1667	/*
1668	 * Include files contained in double-quotes are first searched for
1669	 * relative to the including file's location. We don't want to
1670	 * cd there, of course, so we just tack on the old file's
1671	 * leading path components and call Dir_FindFile to see if
1672	 * we can locate the beast.
1673	 */
1674	char	  *prefEnd, *Fname;
1675
1676	/* Make a temporary copy of this, to be safe. */
1677	Fname = estrdup(fname);
1678
1679	prefEnd = strrchr (Fname, '/');
1680	if (prefEnd != (char *)NULL) {
1681	    char  	*newName;
1682
1683	    *prefEnd = '\0';
1684	    if (file[0] == '/')
1685		newName = estrdup(file);
1686	    else
1687		newName = str_concat (Fname, file, STR_ADDSLASH);
1688	    fullname = Dir_FindFile (newName, parseIncPath);
1689	    if (fullname == (char *)NULL) {
1690		fullname = Dir_FindFile(newName, dirSearchPath);
1691	    }
1692	    free (newName);
1693	    *prefEnd = '/';
1694	} else {
1695	    fullname = (char *)NULL;
1696	}
1697	free (Fname);
1698    } else {
1699	fullname = (char *)NULL;
1700    }
1701
1702    if (fullname == (char *)NULL) {
1703	/*
1704	 * System makefile or makefile wasn't found in same directory as
1705	 * included makefile. Search for it first on the -I search path,
1706	 * then on the .PATH search path, if not found in a -I directory.
1707	 * XXX: Suffix specific?
1708	 */
1709	fullname = Dir_FindFile (file, parseIncPath);
1710	if (fullname == (char *)NULL) {
1711	    fullname = Dir_FindFile(file, dirSearchPath);
1712	}
1713    }
1714
1715    if (fullname == (char *)NULL) {
1716	/*
1717	 * Still haven't found the makefile. Look for it on the system
1718	 * path as a last resort.
1719	 */
1720	fullname = Dir_FindFile(file, sysIncPath);
1721    }
1722
1723    if (fullname == (char *) NULL) {
1724	*cp = endc;
1725	Parse_Error (PARSE_FATAL, "Could not find %s", file);
1726	return;
1727    }
1728
1729    free(file);
1730
1731    /*
1732     * Once we find the absolute path to the file, we get to save all the
1733     * state from the current file before we can start reading this
1734     * include file. The state is stored in an IFile structure which
1735     * is placed on a list with other IFile structures. The list makes
1736     * a very nice stack to track how we got here...
1737     */
1738    oldFile = (IFile *) emalloc (sizeof (IFile));
1739    oldFile->fname = fname;
1740
1741    oldFile->F = curFILE;
1742    oldFile->p = curPTR;
1743    oldFile->lineno = lineno;
1744
1745    (void) Lst_AtFront (includes, (void *)oldFile);
1746
1747    /*
1748     * Once the previous state has been saved, we can get down to reading
1749     * the new file. We set up the name of the file to be the absolute
1750     * name of the include file so error messages refer to the right
1751     * place. Naturally enough, we start reading at line number 0.
1752     */
1753    fname = fullname;
1754    lineno = 0;
1755
1756    curFILE = fopen (fullname, "r");
1757    curPTR = NULL;
1758    if (curFILE == (FILE * ) NULL) {
1759	Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1760	/*
1761	 * Pop to previous file
1762	 */
1763	(void) ParseEOF(0);
1764    }
1765}
1766
1767
1768
1769/*-
1770 *---------------------------------------------------------------------
1771 * Parse_FromString  --
1772 *	Start Parsing from the given string
1773 *
1774 * Results:
1775 *	None
1776 *
1777 * Side Effects:
1778 *	A structure is added to the includes Lst and readProc, lineno,
1779 *	fname and curFILE are altered for the new file
1780 *---------------------------------------------------------------------
1781 */
1782void
1783Parse_FromString(str)
1784    char *str;
1785{
1786    IFile         *oldFile;	/* state associated with this file */
1787
1788    if (DEBUG(FOR))
1789	(void) fprintf(stderr, "%s\n----\n", str);
1790
1791    oldFile = (IFile *) emalloc (sizeof (IFile));
1792    oldFile->lineno = lineno;
1793    oldFile->fname = fname;
1794    oldFile->F = curFILE;
1795    oldFile->p = curPTR;
1796
1797    (void) Lst_AtFront (includes, (void *)oldFile);
1798
1799    curFILE = NULL;
1800    curPTR = (PTR *) emalloc (sizeof (PTR));
1801    curPTR->str = curPTR->ptr = str;
1802    lineno = 0;
1803    fname = estrdup(fname);
1804}
1805
1806
1807#ifdef SYSVINCLUDE
1808/*-
1809 *---------------------------------------------------------------------
1810 * ParseTraditionalInclude  --
1811 *	Push to another file.
1812 *
1813 *	The input is the line minus the "include".  The file name is
1814 *	the string following the "include".
1815 *
1816 * Results:
1817 *	None
1818 *
1819 * Side Effects:
1820 *	A structure is added to the includes Lst and readProc, lineno,
1821 *	fname and curFILE are altered for the new file
1822 *---------------------------------------------------------------------
1823 */
1824static void
1825ParseTraditionalInclude (file)
1826    char          *file;	/* file specification */
1827{
1828    char          *fullname;	/* full pathname of file */
1829    IFile         *oldFile;	/* state associated with current file */
1830    char          *cp;		/* current position in file spec */
1831    char	  *prefEnd;
1832
1833    /*
1834     * Skip over whitespace
1835     */
1836    while ((*file == ' ') || (*file == '\t')) {
1837	file++;
1838    }
1839
1840    if (*file == '\0') {
1841	Parse_Error (PARSE_FATAL,
1842		     "Filename missing from \"include\"");
1843	return;
1844    }
1845
1846    /*
1847     * Skip to end of line or next whitespace
1848     */
1849    for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1850	continue;
1851    }
1852
1853    *cp = '\0';
1854
1855    /*
1856     * Substitute for any variables in the file name before trying to
1857     * find the thing.
1858     */
1859    file = Var_Subst (NULL, file, VAR_CMD, FALSE);
1860
1861    /*
1862     * Now we know the file's name, we attempt to find the durn thing.
1863     * A return of NULL indicates the file don't exist.
1864     *
1865     * Include files are first searched for relative to the including
1866     * file's location. We don't want to cd there, of course, so we
1867     * just tack on the old file's leading path components and call
1868     * Dir_FindFile to see if we can locate the beast.
1869     * XXX - this *does* search in the current directory, right?
1870     */
1871
1872    prefEnd = strrchr (fname, '/');
1873    if (prefEnd != (char *)NULL) {
1874	char  	*newName;
1875
1876	*prefEnd = '\0';
1877	newName = str_concat (fname, file, STR_ADDSLASH);
1878	fullname = Dir_FindFile (newName, parseIncPath);
1879	if (fullname == (char *)NULL) {
1880	    fullname = Dir_FindFile(newName, dirSearchPath);
1881	}
1882	free (newName);
1883	*prefEnd = '/';
1884    } else {
1885	fullname = (char *)NULL;
1886    }
1887
1888    if (fullname == (char *)NULL) {
1889	/*
1890	 * System makefile or makefile wasn't found in same directory as
1891	 * included makefile. Search for it first on the -I search path,
1892	 * then on the .PATH search path, if not found in a -I directory.
1893	 * XXX: Suffix specific?
1894	 */
1895	fullname = Dir_FindFile (file, parseIncPath);
1896	if (fullname == (char *)NULL) {
1897	    fullname = Dir_FindFile(file, dirSearchPath);
1898	}
1899    }
1900
1901    if (fullname == (char *)NULL) {
1902	/*
1903	 * Still haven't found the makefile. Look for it on the system
1904	 * path as a last resort.
1905	 */
1906	fullname = Dir_FindFile(file, sysIncPath);
1907    }
1908
1909    if (fullname == (char *) NULL) {
1910	Parse_Error (PARSE_FATAL, "Could not find %s", file);
1911	return;
1912    }
1913
1914    /*
1915     * Once we find the absolute path to the file, we get to save all the
1916     * state from the current file before we can start reading this
1917     * include file. The state is stored in an IFile structure which
1918     * is placed on a list with other IFile structures. The list makes
1919     * a very nice stack to track how we got here...
1920     */
1921    oldFile = (IFile *) emalloc (sizeof (IFile));
1922    oldFile->fname = fname;
1923
1924    oldFile->F = curFILE;
1925    oldFile->p = curPTR;
1926    oldFile->lineno = lineno;
1927
1928    (void) Lst_AtFront (includes, (void *)oldFile);
1929
1930    /*
1931     * Once the previous state has been saved, we can get down to reading
1932     * the new file. We set up the name of the file to be the absolute
1933     * name of the include file so error messages refer to the right
1934     * place. Naturally enough, we start reading at line number 0.
1935     */
1936    fname = fullname;
1937    lineno = 0;
1938
1939    curFILE = fopen (fullname, "r");
1940    curPTR = NULL;
1941    if (curFILE == (FILE * ) NULL) {
1942	Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
1943	/*
1944	 * Pop to previous file
1945	 */
1946	(void) ParseEOF(1);
1947    }
1948}
1949#endif
1950
1951/*-
1952 *---------------------------------------------------------------------
1953 * ParseEOF  --
1954 *	Called when EOF is reached in the current file. If we were reading
1955 *	an include file, the includes stack is popped and things set up
1956 *	to go back to reading the previous file at the previous location.
1957 *
1958 * Results:
1959 *	CONTINUE if there's more to do. DONE if not.
1960 *
1961 * Side Effects:
1962 *	The old curFILE, is closed. The includes list is shortened.
1963 *	lineno, curFILE, and fname are changed if CONTINUE is returned.
1964 *---------------------------------------------------------------------
1965 */
1966static int
1967ParseEOF (opened)
1968    int opened;
1969{
1970    IFile     *ifile;	/* the state on the top of the includes stack */
1971
1972    if (Lst_IsEmpty (includes)) {
1973	return (DONE);
1974    }
1975
1976    ifile = (IFile *) Lst_DeQueue (includes);
1977    free (fname);
1978    fname = ifile->fname;
1979    lineno = ifile->lineno;
1980    if (opened && curFILE)
1981	(void) fclose (curFILE);
1982    if (curPTR) {
1983	free(curPTR->str);
1984	free(curPTR);
1985    }
1986    curFILE = ifile->F;
1987    curPTR = ifile->p;
1988    free (ifile);
1989    return (CONTINUE);
1990}
1991
1992/*-
1993 *---------------------------------------------------------------------
1994 * ParseReadc  --
1995 *	Read a character from the current file
1996 *
1997 * Results:
1998 *	The character that was read
1999 *
2000 * Side Effects:
2001 *---------------------------------------------------------------------
2002 */
2003static int
2004ParseReadc()
2005{
2006    if (curFILE)
2007	return fgetc(curFILE);
2008
2009    if (curPTR && *curPTR->ptr)
2010	return *curPTR->ptr++;
2011    return EOF;
2012}
2013
2014
2015/*-
2016 *---------------------------------------------------------------------
2017 * ParseUnreadc  --
2018 *	Put back a character to the current file
2019 *
2020 * Results:
2021 *	None.
2022 *
2023 * Side Effects:
2024 *---------------------------------------------------------------------
2025 */
2026static void
2027ParseUnreadc(c)
2028    int c;
2029{
2030    if (curFILE) {
2031	ungetc(c, curFILE);
2032	return;
2033    }
2034    if (curPTR) {
2035	*--(curPTR->ptr) = c;
2036	return;
2037    }
2038}
2039
2040
2041/* ParseSkipLine():
2042 *	Grab the next line
2043 */
2044static char *
2045ParseSkipLine(skip)
2046    int skip; 		/* Skip lines that don't start with . */
2047{
2048    char *line;
2049    int c, lastc, lineLength = 0;
2050    Buffer buf;
2051
2052    buf = Buf_Init(MAKE_BSIZE);
2053
2054    do {
2055        Buf_Discard(buf, lineLength);
2056        lastc = '\0';
2057
2058        while (((c = ParseReadc()) != '\n' || lastc == '\\')
2059               && c != EOF) {
2060            if (c == '\n') {
2061                Buf_ReplaceLastByte(buf, (Byte)' ');
2062                lineno++;
2063
2064                while ((c = ParseReadc()) == ' ' || c == '\t');
2065
2066                if (c == EOF)
2067                    break;
2068            }
2069
2070            Buf_AddByte(buf, (Byte)c);
2071            lastc = c;
2072        }
2073
2074        if (c == EOF) {
2075            Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
2076            Buf_Destroy(buf, TRUE);
2077            return((char *)NULL);
2078        }
2079
2080        lineno++;
2081        Buf_AddByte(buf, (Byte)'\0');
2082        line = (char *)Buf_GetAll(buf, &lineLength);
2083    } while (skip == 1 && line[0] != '.');
2084
2085    Buf_Destroy(buf, FALSE);
2086    return line;
2087}
2088
2089
2090/*-
2091 *---------------------------------------------------------------------
2092 * ParseReadLine --
2093 *	Read an entire line from the input file. Called only by Parse_File.
2094 *	To facilitate escaped newlines and what have you, a character is
2095 *	buffered in 'lastc', which is '\0' when no characters have been
2096 *	read. When we break out of the loop, c holds the terminating
2097 *	character and lastc holds a character that should be added to
2098 *	the line (unless we don't read anything but a terminator).
2099 *
2100 * Results:
2101 *	A line w/o its newline
2102 *
2103 * Side Effects:
2104 *	Only those associated with reading a character
2105 *---------------------------------------------------------------------
2106 */
2107static char *
2108ParseReadLine ()
2109{
2110    Buffer  	  buf;	    	/* Buffer for current line */
2111    register int  c;	      	/* the current character */
2112    register int  lastc;    	/* The most-recent character */
2113    Boolean	  semiNL;     	/* treat semi-colons as newlines */
2114    Boolean	  ignDepOp;   	/* TRUE if should ignore dependency operators
2115				 * for the purposes of setting semiNL */
2116    Boolean 	  ignComment;	/* TRUE if should ignore comments (in a
2117				 * shell command */
2118    char 	  *line;    	/* Result */
2119    char          *ep;		/* to strip trailing blanks */
2120    int	    	  lineLength;	/* Length of result */
2121
2122    semiNL = FALSE;
2123    ignDepOp = FALSE;
2124    ignComment = FALSE;
2125
2126    /*
2127     * Handle special-characters at the beginning of the line. Either a
2128     * leading tab (shell command) or pound-sign (possible conditional)
2129     * forces us to ignore comments and dependency operators and treat
2130     * semi-colons as semi-colons (by leaving semiNL FALSE). This also
2131     * discards completely blank lines.
2132     */
2133    for (;;) {
2134	c = ParseReadc();
2135
2136	if (c == '\t') {
2137	    ignComment = ignDepOp = TRUE;
2138	    break;
2139	} else if (c == '\n') {
2140	    lineno++;
2141	} else if (c == '#') {
2142	    ParseUnreadc(c);
2143	    break;
2144	} else {
2145	    /*
2146	     * Anything else breaks out without doing anything
2147	     */
2148	    break;
2149	}
2150    }
2151
2152    if (c != EOF) {
2153	lastc = c;
2154	buf = Buf_Init(MAKE_BSIZE);
2155
2156	while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
2157	       (c != EOF))
2158	{
2159test_char:
2160	    switch(c) {
2161	    case '\n':
2162		/*
2163		 * Escaped newline: read characters until a non-space or an
2164		 * unescaped newline and replace them all by a single space.
2165		 * This is done by storing the space over the backslash and
2166		 * dropping through with the next nonspace. If it is a
2167		 * semi-colon and semiNL is TRUE, it will be recognized as a
2168		 * newline in the code below this...
2169		 */
2170		lineno++;
2171		lastc = ' ';
2172		while ((c = ParseReadc ()) == ' ' || c == '\t') {
2173		    continue;
2174		}
2175		if (c == EOF || c == '\n') {
2176		    goto line_read;
2177		} else {
2178		    /*
2179		     * Check for comments, semiNL's, etc. -- easier than
2180		     * ParseUnreadc(c); continue;
2181		     */
2182		    goto test_char;
2183		}
2184		/*NOTREACHED*/
2185		break;
2186
2187	    case ';':
2188		/*
2189		 * Semi-colon: Need to see if it should be interpreted as a
2190		 * newline
2191		 */
2192		if (semiNL) {
2193		    /*
2194		     * To make sure the command that may be following this
2195		     * semi-colon begins with a tab, we push one back into the
2196		     * input stream. This will overwrite the semi-colon in the
2197		     * buffer. If there is no command following, this does no
2198		     * harm, since the newline remains in the buffer and the
2199		     * whole line is ignored.
2200		     */
2201		    ParseUnreadc('\t');
2202		    goto line_read;
2203		}
2204		break;
2205	    case '=':
2206		if (!semiNL) {
2207		    /*
2208		     * Haven't seen a dependency operator before this, so this
2209		     * must be a variable assignment -- don't pay attention to
2210		     * dependency operators after this.
2211		     */
2212		    ignDepOp = TRUE;
2213		} else if (lastc == ':' || lastc == '!') {
2214		    /*
2215		     * Well, we've seen a dependency operator already, but it
2216		     * was the previous character, so this is really just an
2217		     * expanded variable assignment. Revert semi-colons to
2218		     * being just semi-colons again and ignore any more
2219		     * dependency operators.
2220		     *
2221		     * XXX: Note that a line like "foo : a:=b" will blow up,
2222		     * but who'd write a line like that anyway?
2223		     */
2224		    ignDepOp = TRUE; semiNL = FALSE;
2225		}
2226		break;
2227	    case '#':
2228		if (!ignComment) {
2229		    if (
2230#if 0
2231		    compatMake &&
2232#endif
2233		    (lastc != '\\')) {
2234			/*
2235			 * If the character is a hash mark and it isn't escaped
2236			 * (or we're being compatible), the thing is a comment.
2237			 * Skip to the end of the line.
2238			 */
2239			do {
2240			    c = ParseReadc();
2241			} while ((c != '\n') && (c != EOF));
2242			goto line_read;
2243		    } else {
2244			/*
2245			 * Don't add the backslash. Just let the # get copied
2246			 * over.
2247			 */
2248			lastc = c;
2249			continue;
2250		    }
2251		}
2252		break;
2253	    case ':':
2254	    case '!':
2255		if (!ignDepOp && (c == ':' || c == '!')) {
2256		    /*
2257		     * A semi-colon is recognized as a newline only on
2258		     * dependency lines. Dependency lines are lines with a
2259		     * colon or an exclamation point. Ergo...
2260		     */
2261		    semiNL = TRUE;
2262		}
2263		break;
2264	    }
2265	    /*
2266	     * Copy in the previous character and save this one in lastc.
2267	     */
2268	    Buf_AddByte (buf, (Byte)lastc);
2269	    lastc = c;
2270
2271	}
2272    line_read:
2273	lineno++;
2274
2275	if (lastc != '\0') {
2276	    Buf_AddByte (buf, (Byte)lastc);
2277	}
2278	Buf_AddByte (buf, (Byte)'\0');
2279	line = (char *)Buf_GetAll (buf, &lineLength);
2280	Buf_Destroy (buf, FALSE);
2281
2282	/*
2283	 * Strip trailing blanks and tabs from the line.
2284	 * Do not strip a blank or tab that is preceded by
2285	 * a '\'
2286	 */
2287	ep = line;
2288	while (*ep)
2289	    ++ep;
2290	while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
2291	    if (ep > line + 1 && ep[-2] == '\\')
2292		break;
2293	    --ep;
2294	}
2295	*ep = 0;
2296
2297	if (line[0] == '.') {
2298	    /*
2299	     * The line might be a conditional. Ask the conditional module
2300	     * about it and act accordingly
2301	     */
2302	    switch (Cond_Eval (line)) {
2303	    case COND_SKIP:
2304		/*
2305		 * Skip to next conditional that evaluates to COND_PARSE.
2306		 */
2307		do {
2308		    free (line);
2309		    line = ParseSkipLine(1);
2310		} while (line && Cond_Eval(line) != COND_PARSE);
2311		if (line == NULL)
2312		    break;
2313		/*FALLTHRU*/
2314	    case COND_PARSE:
2315		free (line);
2316		line = ParseReadLine();
2317		break;
2318	    case COND_INVALID:
2319		if (For_Eval(line)) {
2320		    int ok;
2321		    free(line);
2322		    do {
2323			/*
2324			 * Skip after the matching end
2325			 */
2326			line = ParseSkipLine(0);
2327			if (line == NULL) {
2328			    Parse_Error (PARSE_FATAL,
2329				     "Unexpected end of file in for loop.\n");
2330			    break;
2331			}
2332			ok = For_Eval(line);
2333			free(line);
2334		    }
2335		    while (ok);
2336		    if (line != NULL)
2337			For_Run();
2338		    line = ParseReadLine();
2339		}
2340		break;
2341	    }
2342	}
2343	return (line);
2344
2345    } else {
2346	/*
2347	 * Hit end-of-file, so return a NULL line to indicate this.
2348	 */
2349	return((char *)NULL);
2350    }
2351}
2352
2353/*-
2354 *-----------------------------------------------------------------------
2355 * ParseFinishLine --
2356 *	Handle the end of a dependency group.
2357 *
2358 * Results:
2359 *	Nothing.
2360 *
2361 * Side Effects:
2362 *	inLine set FALSE. 'targets' list destroyed.
2363 *
2364 *-----------------------------------------------------------------------
2365 */
2366static void
2367ParseFinishLine()
2368{
2369    if (inLine) {
2370	Lst_ForEach(targets, Suff_EndTransform, (void *)NULL);
2371	Lst_Destroy (targets, ParseHasCommands);
2372	targets = NULL;
2373	inLine = FALSE;
2374    }
2375}
2376
2377
2378/*-
2379 *---------------------------------------------------------------------
2380 * Parse_File --
2381 *	Parse a file into its component parts, incorporating it into the
2382 *	current dependency graph. This is the main function and controls
2383 *	almost every other function in this module
2384 *
2385 * Results:
2386 *	None
2387 *
2388 * Side Effects:
2389 *	Loads. Nodes are added to the list of all targets, nodes and links
2390 *	are added to the dependency graph. etc. etc. etc.
2391 *---------------------------------------------------------------------
2392 */
2393void
2394Parse_File(name, stream)
2395    char          *name;	/* the name of the file being read */
2396    FILE *	  stream;   	/* Stream open to makefile to parse */
2397{
2398    register char *cp,		/* pointer into the line */
2399                  *line;	/* the line we're working on */
2400
2401    inLine = FALSE;
2402    fname = name;
2403    curFILE = stream;
2404    lineno = 0;
2405    fatals = 0;
2406
2407    do {
2408	while ((line = ParseReadLine ()) != NULL) {
2409	    if (*line == '.') {
2410		/*
2411		 * Lines that begin with the special character are either
2412		 * include or undef directives.
2413		 */
2414		for (cp = line + 1; isspace (*cp); cp++) {
2415		    continue;
2416		}
2417		if (strncmp (cp, "include", 7) == 0) {
2418		    ParseDoInclude (cp + 7);
2419		    goto nextLine;
2420		} else if (strncmp (cp, "error", 5) == 0) {
2421		    ParseDoError(cp + 5);
2422	            goto nextLine;
2423		} else if (strncmp(cp, "undef", 5) == 0) {
2424		    char *cp2;
2425		    for (cp += 5; isspace((unsigned char) *cp); cp++) {
2426			continue;
2427		    }
2428
2429		    for (cp2 = cp; !isspace((unsigned char) *cp2) &&
2430				   (*cp2 != '\0'); cp2++) {
2431			continue;
2432		    }
2433
2434		    *cp2 = '\0';
2435
2436		    Var_Delete(cp, VAR_GLOBAL);
2437		    goto nextLine;
2438		}
2439	    }
2440	    if (*line == '#') {
2441		/* If we're this far, the line must be a comment. */
2442		goto nextLine;
2443	    }
2444
2445	    if (*line == '\t') {
2446		/*
2447		 * If a line starts with a tab, it can only hope to be
2448		 * a creation command.
2449		 */
2450#ifndef POSIX
2451	    shellCommand:
2452#endif
2453		for (cp = line + 1; isspace (*cp); cp++) {
2454		    continue;
2455		}
2456		if (*cp) {
2457		    if (inLine) {
2458			/*
2459			 * So long as it's not a blank line and we're actually
2460			 * in a dependency spec, add the command to the list of
2461			 * commands of all targets in the dependency spec
2462			 */
2463			Lst_ForEach (targets, ParseAddCmd, cp);
2464			Lst_AtEnd(targCmds, (void *) line);
2465			continue;
2466		    } else {
2467			Parse_Error (PARSE_FATAL,
2468				     "Unassociated shell command \"%s\"",
2469				     cp);
2470		    }
2471		}
2472#ifdef SYSVINCLUDE
2473	    } else if (strncmp (line, "include", 7) == 0 &&
2474		       isspace((unsigned char) line[7]) &&
2475		       strchr(line, ':') == NULL) {
2476		/*
2477		 * It's an S3/S5-style "include".
2478		 */
2479		ParseTraditionalInclude (line + 7);
2480		goto nextLine;
2481#endif
2482	    } else if (Parse_IsVar (line)) {
2483		ParseFinishLine();
2484		Parse_DoVar (line, VAR_GLOBAL);
2485	    } else {
2486		/*
2487		 * We now know it's a dependency line so it needs to have all
2488		 * variables expanded before being parsed. Tell the variable
2489		 * module to complain if some variable is undefined...
2490		 * To make life easier on novices, if the line is indented we
2491		 * first make sure the line has a dependency operator in it.
2492		 * If it doesn't have an operator and we're in a dependency
2493		 * line's script, we assume it's actually a shell command
2494		 * and add it to the current list of targets.
2495		 */
2496#ifndef POSIX
2497		Boolean	nonSpace = FALSE;
2498#endif
2499
2500		cp = line;
2501		if (isspace((unsigned char) line[0])) {
2502		    while ((*cp != '\0') && isspace((unsigned char) *cp)) {
2503			cp++;
2504		    }
2505		    if (*cp == '\0') {
2506			goto nextLine;
2507		    }
2508#ifndef POSIX
2509		    while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
2510			nonSpace = TRUE;
2511			cp++;
2512		    }
2513#endif
2514		}
2515
2516#ifndef POSIX
2517		if (*cp == '\0') {
2518		    if (inLine) {
2519			Parse_Error (PARSE_WARNING,
2520				     "Shell command needs a leading tab");
2521			goto shellCommand;
2522		    } else if (nonSpace) {
2523			Parse_Error (PARSE_FATAL, "Missing operator");
2524		    }
2525		} else {
2526#endif
2527		    ParseFinishLine();
2528
2529		    cp = Var_Subst (NULL, line, VAR_CMD, TRUE);
2530		    free (line);
2531		    line = cp;
2532
2533		    /*
2534		     * Need a non-circular list for the target nodes
2535		     */
2536		    if (targets)
2537			Lst_Destroy(targets, NOFREE);
2538
2539		    targets = Lst_Init (FALSE);
2540		    inLine = TRUE;
2541
2542		    ParseDoDependency (line);
2543#ifndef POSIX
2544		}
2545#endif
2546	    }
2547
2548	    nextLine:
2549
2550	    free (line);
2551	}
2552	/*
2553	 * Reached EOF, but it may be just EOF of an include file...
2554	 */
2555    } while (ParseEOF(1) == CONTINUE);
2556
2557    /*
2558     * Make sure conditionals are clean
2559     */
2560    Cond_End();
2561
2562    if (fatals)
2563	errx(1, "fatal errors encountered -- cannot continue");
2564}
2565
2566/*-
2567 *---------------------------------------------------------------------
2568 * Parse_Init --
2569 *	initialize the parsing module
2570 *
2571 * Results:
2572 *	none
2573 *
2574 * Side Effects:
2575 *	the parseIncPath list is initialized...
2576 *---------------------------------------------------------------------
2577 */
2578void
2579Parse_Init ()
2580{
2581    mainNode = NULL;
2582    parseIncPath = Lst_Init (FALSE);
2583    sysIncPath = Lst_Init (FALSE);
2584    includes = Lst_Init (FALSE);
2585    targCmds = Lst_Init (FALSE);
2586}
2587
2588void
2589Parse_End()
2590{
2591    Lst_Destroy(targCmds, (void (*)(void *)) free);
2592    if (targets)
2593	Lst_Destroy(targets, NOFREE);
2594    Lst_Destroy(sysIncPath, Dir_Destroy);
2595    Lst_Destroy(parseIncPath, Dir_Destroy);
2596    Lst_Destroy(includes, NOFREE);	/* Should be empty now */
2597}
2598
2599
2600/*-
2601 *-----------------------------------------------------------------------
2602 * Parse_MainName --
2603 *	Return a Lst of the main target to create for main()'s sake. If
2604 *	no such target exists, we Punt with an obnoxious error message.
2605 *
2606 * Results:
2607 *	A Lst of the single node to create.
2608 *
2609 * Side Effects:
2610 *	None.
2611 *
2612 *-----------------------------------------------------------------------
2613 */
2614Lst
2615Parse_MainName()
2616{
2617    Lst           listmain;	/* result list */
2618
2619    listmain = Lst_Init (FALSE);
2620
2621    if (mainNode == NULL) {
2622	Punt ("no target to make.");
2623    	/*NOTREACHED*/
2624    } else if (mainNode->type & OP_DOUBLEDEP) {
2625	(void) Lst_AtEnd (listmain, (void *)mainNode);
2626	Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW);
2627    }
2628    else
2629	(void) Lst_AtEnd (listmain, (void *)mainNode);
2630    return (listmain);
2631}
2632