parse.c revision 143100
1141104Sharti/*-
21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * This code is derived from software contributed to Berkeley by
81590Srgrimes * Adam de Boor.
91590Srgrimes *
101590Srgrimes * Redistribution and use in source and binary forms, with or without
111590Srgrimes * modification, are permitted provided that the following conditions
121590Srgrimes * are met:
131590Srgrimes * 1. Redistributions of source code must retain the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer.
151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161590Srgrimes *    notice, this list of conditions and the following disclaimer in the
171590Srgrimes *    documentation and/or other materials provided with the distribution.
181590Srgrimes * 3. All advertising materials mentioning features or use of this software
191590Srgrimes *    must display the following acknowledgement:
201590Srgrimes *	This product includes software developed by the University of
211590Srgrimes *	California, Berkeley and its contributors.
221590Srgrimes * 4. Neither the name of the University nor the names of its contributors
231590Srgrimes *    may be used to endorse or promote products derived from this software
241590Srgrimes *    without specific prior written permission.
251590Srgrimes *
261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361590Srgrimes * SUCH DAMAGE.
3762833Swsanchez *
3862833Swsanchez * @(#)parse.c	8.3 (Berkeley) 3/19/94
391590Srgrimes */
401590Srgrimes
4162833Swsanchez#include <sys/cdefs.h>
4294587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/parse.c 143100 2005-03-03 10:07:28Z harti $");
431590Srgrimes
441590Srgrimes/*-
451590Srgrimes * parse.c --
461590Srgrimes *	Functions to parse a makefile.
471590Srgrimes *
481590Srgrimes *	One function, Parse_Init, must be called before any functions
491590Srgrimes *	in this module are used. After that, the function Parse_File is the
501590Srgrimes *	main entry point and controls most of the other functions in this
511590Srgrimes *	module.
521590Srgrimes *
531590Srgrimes *	Most important structures are kept in Lsts. Directories for
541590Srgrimes *	the #include "..." function are kept in the 'parseIncPath' Lst, while
551590Srgrimes *	those for the #include <...> are kept in the 'sysIncPath' Lst. The
561590Srgrimes *	targets currently being defined are kept in the 'targets' Lst.
571590Srgrimes *
58126824Sru *	The variables 'curFile.fname' and 'curFile.lineno' are used to track
59126824Sru *	the name of the current file and the line number in that file so that
60126824Sru *	error messages can be more meaningful.
611590Srgrimes *
621590Srgrimes * Interface:
631590Srgrimes *	Parse_Init	    	    Initialization function which must be
641590Srgrimes *	    	  	    	    called before anything else in this module
651590Srgrimes *	    	  	    	    is used.
661590Srgrimes *
671590Srgrimes *	Parse_File	    	    Function used to parse a makefile. It must
681590Srgrimes *	    	  	    	    be given the name of the file, which should
691590Srgrimes *	    	  	    	    already have been opened, and a function
701590Srgrimes *	    	  	    	    to call to read a character from the file.
711590Srgrimes *
721590Srgrimes *	Parse_IsVar	    	    Returns TRUE if the given line is a
731590Srgrimes *	    	  	    	    variable assignment. Used by MainParseArgs
741590Srgrimes *	    	  	    	    to determine if an argument is a target
751590Srgrimes *	    	  	    	    or a variable assignment. Used internally
761590Srgrimes *	    	  	    	    for pretty much the same thing...
771590Srgrimes *
781590Srgrimes *	Parse_Error	    	    Function called when an error occurs in
791590Srgrimes *	    	  	    	    parsing. Used by the variable and
801590Srgrimes *	    	  	    	    conditional modules.
811590Srgrimes *	Parse_MainName	    	    Returns a Lst of the main target to create.
821590Srgrimes */
831590Srgrimes
84141104Sharti#include <ctype.h>
851590Srgrimes#include <stdarg.h>
86141104Sharti#include <string.h>
87141104Sharti#include <stdlib.h>
8827644Scharnier#include <err.h>
89141104Sharti
90141104Sharti#include "arch.h"
91141104Sharti#include "buf.h"
92141104Sharti#include "cond.h"
93141104Sharti#include "config.h"
941590Srgrimes#include "dir.h"
95141104Sharti#include "for.h"
96141104Sharti#include "globals.h"
97141104Sharti#include "GNode.h"
981590Srgrimes#include "job.h"
99141104Sharti#include "make.h"
100141104Sharti#include "nonints.h"
101141104Sharti#include "parse.h"
1021590Srgrimes#include "pathnames.h"
103141104Sharti#include "str.h"
104141104Sharti#include "suff.h"
105141104Sharti#include "targ.h"
106141104Sharti#include "util.h"
107141104Sharti#include "var.h"
1081590Srgrimes
1091590Srgrimes/*
1101590Srgrimes * These values are returned by ParseEOF to tell Parse_File whether to
1111590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file,
1121590Srgrimes * or if it's DONE.
1131590Srgrimes */
1141590Srgrimes#define	CONTINUE	1
1151590Srgrimes#define	DONE		0
116138916Sharti
117138916Sharti/* targets we're working on */
118138916Shartistatic Lst targets = Lst_Initializer(targets);
119138916Sharti
1201590Srgrimesstatic Boolean	    inLine;	/* true if currently in a dependency
1211590Srgrimes				 * line or its commands */
1221590Srgrimesstatic int	    fatals = 0;
1231590Srgrimes
1241590Srgrimesstatic GNode	    *mainNode;	/* The main target to create. This is the
1251590Srgrimes				 * first target on the first dependency
1261590Srgrimes				 * line in the first makefile */
1271590Srgrimes
128132439ShartiIFile	    	curFile;	/* current makefile */
129126824Sru
130138916Sharti/* stack of IFiles generated by * #includes */
131138916Shartistatic Lst includes = Lst_Initializer(includes);
1321590Srgrimes
133138916Sharti/* list of directories for "..." includes */
134138916ShartiLst parseIncPath = Lst_Initializer(parseIncPath);
135138916Sharti
136138916Sharti/* list of directories for <...> includes */
137138916ShartiLst sysIncPath = Lst_Initializer(sysIncPath);
138138916Sharti
1391590Srgrimes/*-
1401590Srgrimes * specType contains the SPECial TYPE of the current target. It is
1411590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children
1421590Srgrimes * are linked as children of the parent but not vice versa. This variable is
1431590Srgrimes * set in ParseDoDependency
1441590Srgrimes */
1451590Srgrimestypedef enum {
1461590Srgrimes    Begin,  	    /* .BEGIN */
1471590Srgrimes    Default,	    /* .DEFAULT */
1481590Srgrimes    End,    	    /* .END */
1491590Srgrimes    Ignore,	    /* .IGNORE */
1501590Srgrimes    Includes,	    /* .INCLUDES */
1511590Srgrimes    Interrupt,	    /* .INTERRUPT */
1521590Srgrimes    Libs,	    /* .LIBS */
1531590Srgrimes    MFlags,	    /* .MFLAGS or .MAKEFLAGS */
1541590Srgrimes    Main,	    /* .MAIN and we don't have anything user-specified to
1551590Srgrimes		     * make */
1561590Srgrimes    NoExport,	    /* .NOEXPORT */
1571590Srgrimes    Not,	    /* Not special */
1581590Srgrimes    NotParallel,    /* .NOTPARALELL */
1591590Srgrimes    Null,   	    /* .NULL */
1601590Srgrimes    Order,  	    /* .ORDER */
16118730Ssteve    Parallel,	    /* .PARALLEL */
1621590Srgrimes    ExPath,	    /* .PATH */
16318730Ssteve    Phony,	    /* .PHONY */
16419344Ssteve    Posix,	    /* .POSIX */
1651590Srgrimes    Precious,	    /* .PRECIOUS */
1661590Srgrimes    ExShell,	    /* .SHELL */
1671590Srgrimes    Silent,	    /* .SILENT */
1681590Srgrimes    SingleShell,    /* .SINGLESHELL */
1691590Srgrimes    Suffixes,	    /* .SUFFIXES */
17018730Ssteve    Wait,	    /* .WAIT */
1711590Srgrimes    Attribute	    /* Generic attribute */
1721590Srgrimes} ParseSpecial;
1731590Srgrimes
1741590Srgrimesstatic ParseSpecial specType;
17518730Sstevestatic int waiting;
1761590Srgrimes
1771590Srgrimes/*
17869527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1791590Srgrimes * seen, then set to each successive source on the line.
1801590Srgrimes */
1811590Srgrimesstatic GNode	*predecessor;
1821590Srgrimes
1831590Srgrimes/*
1841590Srgrimes * The parseKeywords table is searched using binary search when deciding
1851590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial
1861590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while
1871590Srgrimes * the 'op' field is the operator to apply to the list of targets if the
1881590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source)
1891590Srgrimes */
1901590Srgrimesstatic struct {
191141252Sharti    const char	  *name;    	/* Name of keyword */
1921590Srgrimes    ParseSpecial  spec;	    	/* Type when used as a target */
1931590Srgrimes    int	    	  op;	    	/* Operator when used as a source */
1941590Srgrimes} parseKeywords[] = {
1951590Srgrimes{ ".BEGIN", 	  Begin,    	0 },
1961590Srgrimes{ ".DEFAULT",	  Default,  	0 },
1971590Srgrimes{ ".END",   	  End,	    	0 },
1981590Srgrimes{ ".EXEC",	  Attribute,   	OP_EXEC },
1991590Srgrimes{ ".IGNORE",	  Ignore,   	OP_IGNORE },
2001590Srgrimes{ ".INCLUDES",	  Includes, 	0 },
2011590Srgrimes{ ".INTERRUPT",	  Interrupt,	0 },
2021590Srgrimes{ ".INVISIBLE",	  Attribute,   	OP_INVISIBLE },
2031590Srgrimes{ ".JOIN",  	  Attribute,   	OP_JOIN },
2041590Srgrimes{ ".LIBS",  	  Libs,	    	0 },
2051590Srgrimes{ ".MAIN",	  Main,		0 },
2061590Srgrimes{ ".MAKE",  	  Attribute,   	OP_MAKE },
2071590Srgrimes{ ".MAKEFLAGS",	  MFlags,   	0 },
2081590Srgrimes{ ".MFLAGS",	  MFlags,   	0 },
2091590Srgrimes{ ".NOTMAIN",	  Attribute,   	OP_NOTMAIN },
2101590Srgrimes{ ".NOTPARALLEL", NotParallel,	0 },
21118730Ssteve{ ".NO_PARALLEL", NotParallel,	0 },
2121590Srgrimes{ ".NULL",  	  Null,	    	0 },
2139254Sache{ ".OPTIONAL",	  Attribute,   	OP_OPTIONAL },
2141590Srgrimes{ ".ORDER", 	  Order,    	0 },
21518730Ssteve{ ".PARALLEL",	  Parallel,	0 },
2161590Srgrimes{ ".PATH",	  ExPath,	0 },
21718730Ssteve{ ".PHONY",	  Phony,	OP_PHONY },
21819344Ssteve{ ".POSIX",	  Posix,	0 },
2191590Srgrimes{ ".PRECIOUS",	  Precious, 	OP_PRECIOUS },
2201590Srgrimes{ ".RECURSIVE",	  Attribute,	OP_MAKE },
2211590Srgrimes{ ".SHELL", 	  ExShell,    	0 },
2221590Srgrimes{ ".SILENT",	  Silent,   	OP_SILENT },
2231590Srgrimes{ ".SINGLESHELL", SingleShell,	0 },
2241590Srgrimes{ ".SUFFIXES",	  Suffixes, 	0 },
2251590Srgrimes{ ".USE",   	  Attribute,   	OP_USE },
22618730Ssteve{ ".WAIT",	  Wait, 	0 },
2271590Srgrimes};
2281590Srgrimes
22992921Simpstatic int ParseFindKeyword(char *);
23092921Simpstatic int ParseDoOp(void *, void *);
23192921Simpstatic int ParseAddDep(void *, void *);
232138512Shartistatic void ParseDoSrc(int, char *, Lst *);
23392921Simpstatic int ParseFindMain(void *, void *);
23492921Simpstatic int ParseAddDir(void *, void *);
23592921Simpstatic int ParseClearPath(void *, void *);
23692921Simpstatic void ParseDoDependency(char *);
23792921Simpstatic int ParseAddCmd(void *, void *);
23892921Simpstatic int ParseReadc(void);
23992921Simpstatic void ParseUnreadc(int);
24092921Simpstatic void ParseHasCommands(void *);
24192921Simpstatic void ParseDoInclude(char *);
24292921Simpstatic void ParseDoError(char *);
243128160Srustatic void ParseDoWarning(char *);
2441590Srgrimes#ifdef SYSVINCLUDE
24592921Simpstatic void ParseTraditionalInclude(char *);
2461590Srgrimes#endif
24792921Simpstatic int ParseEOF(int);
24892921Simpstatic char *ParseReadLine(void);
249126824Srustatic char *ParseSkipLine(int, int);
25092921Simpstatic void ParseFinishLine(void);
2511590Srgrimes
2521590Srgrimes/*-
2531590Srgrimes *----------------------------------------------------------------------
2541590Srgrimes * ParseFindKeyword --
2551590Srgrimes *	Look in the table of keywords for one matching the given string.
2561590Srgrimes *
2571590Srgrimes * Results:
2581590Srgrimes *	The index of the keyword, or -1 if it isn't there.
2591590Srgrimes *
2601590Srgrimes * Side Effects:
2611590Srgrimes *	None
2621590Srgrimes *----------------------------------------------------------------------
2631590Srgrimes */
2641590Srgrimesstatic int
265138232ShartiParseFindKeyword(char *str)
2661590Srgrimes{
26794584Sobrien    int		    start,
2681590Srgrimes		    end,
2691590Srgrimes		    cur;
27094584Sobrien    int		    diff;
2718874Srgrimes
2721590Srgrimes    start = 0;
273138232Sharti    end = (sizeof(parseKeywords) / sizeof(parseKeywords[0])) - 1;
2741590Srgrimes
2751590Srgrimes    do {
2761590Srgrimes	cur = start + ((end - start) / 2);
277138232Sharti	diff = strcmp(str, parseKeywords[cur].name);
2781590Srgrimes
2791590Srgrimes	if (diff == 0) {
2801590Srgrimes	    return (cur);
2811590Srgrimes	} else if (diff < 0) {
2821590Srgrimes	    end = cur - 1;
2831590Srgrimes	} else {
2841590Srgrimes	    start = cur + 1;
2851590Srgrimes	}
2861590Srgrimes    } while (start <= end);
2871590Srgrimes    return (-1);
2881590Srgrimes}
2891590Srgrimes
2901590Srgrimes/*-
2911590Srgrimes * Parse_Error  --
2921590Srgrimes *	Error message abort function for parsing. Prints out the context
2931590Srgrimes *	of the error (line number and file) as well as the message with
2941590Srgrimes *	two optional arguments.
2951590Srgrimes *
2961590Srgrimes * Results:
2971590Srgrimes *	None
2981590Srgrimes *
2991590Srgrimes * Side Effects:
3001590Srgrimes *	"fatals" is incremented if the level is PARSE_FATAL.
3011590Srgrimes */
3021590Srgrimes/* VARARGS */
3031590Srgrimesvoid
30498136SjmallettParse_Error(int type, const char *fmt, ...)
3051590Srgrimes{
3061590Srgrimes	va_list ap;
30793056Simp
3081590Srgrimes	va_start(ap, fmt);
309138232Sharti	fprintf(stderr, "\"%s\", line %d: ",
310126824Sru	    curFile.fname, curFile.lineno);
3111590Srgrimes	if (type == PARSE_WARNING)
312138232Sharti		fprintf(stderr, "warning: ");
313138232Sharti	vfprintf(stderr, fmt, ap);
3141590Srgrimes	va_end(ap);
315138232Sharti	fprintf(stderr, "\n");
316138232Sharti	fflush(stderr);
3171590Srgrimes	if (type == PARSE_FATAL)
3181590Srgrimes		fatals += 1;
3191590Srgrimes}
3201590Srgrimes
3211590Srgrimes/*-
3221590Srgrimes *---------------------------------------------------------------------
3231590Srgrimes * ParseLinkSrc  --
324143100Sharti *	Link the parent nodes to their new child. Used by
3251590Srgrimes *	ParseDoDependency. If the specType isn't 'Not', the parent
3261590Srgrimes *	isn't linked as a parent of the child.
3271590Srgrimes *
3281590Srgrimes * Side Effects:
329143100Sharti *	New elements are added to the parents lists of cgn and the
3301590Srgrimes *	children list of cgn. the unmade field of pgn is updated
3311590Srgrimes *	to reflect the additional child.
3321590Srgrimes *---------------------------------------------------------------------
3331590Srgrimes */
334143027Shartistatic void
335143027ShartiParseLinkSrc(Lst *parents, GNode *cgn)
3361590Srgrimes{
337143027Sharti	LstNode	*ln;
338143027Sharti	GNode *pgn;
339138232Sharti
340143027Sharti	LST_FOREACH(ln, parents) {
341143027Sharti		pgn = Lst_Datum(ln);
342143027Sharti		if (Lst_Member(&pgn->children, cgn) == NULL) {
343143027Sharti			Lst_AtEnd(&pgn->children, cgn);
344143027Sharti			if (specType == Not) {
345143027Sharti				Lst_AtEnd(&cgn->parents, pgn);
346143027Sharti			}
347143027Sharti			pgn->unmade += 1;
348143027Sharti		}
3491590Srgrimes	}
3501590Srgrimes}
3511590Srgrimes
3521590Srgrimes/*-
3531590Srgrimes *---------------------------------------------------------------------
3541590Srgrimes * ParseDoOp  --
3551590Srgrimes *	Apply the parsed operator to the given target node. Used in a
3561590Srgrimes *	Lst_ForEach call by ParseDoDependency once all targets have
3571590Srgrimes *	been found and their operator parsed. If the previous and new
3581590Srgrimes *	operators are incompatible, a major error is taken.
3591590Srgrimes *
3601590Srgrimes * Results:
3611590Srgrimes *	Always 0
3621590Srgrimes *
3631590Srgrimes * Side Effects:
3641590Srgrimes *	The type field of the node is altered to reflect any new bits in
3651590Srgrimes *	the op.
3661590Srgrimes *---------------------------------------------------------------------
3671590Srgrimes */
3681590Srgrimesstatic int
369138232ShartiParseDoOp(void *gnp, void *opp)
3701590Srgrimes{
371138264Sharti    GNode *gn = gnp;
372138264Sharti    int op = *(int *)opp;
373138232Sharti
3741590Srgrimes    /*
3751590Srgrimes     * If the dependency mask of the operator and the node don't match and
3761590Srgrimes     * the node has actually had an operator applied to it before, and
3778874Srgrimes     * the operator actually has some dependency information in it, complain.
3781590Srgrimes     */
3791590Srgrimes    if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
3801590Srgrimes	!OP_NOP(gn->type) && !OP_NOP(op))
3811590Srgrimes    {
382138232Sharti	Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
3831590Srgrimes	return (1);
3841590Srgrimes    }
3851590Srgrimes
3861590Srgrimes    if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
3871590Srgrimes	/*
3881590Srgrimes	 * If the node was the object of a :: operator, we need to create a
3891590Srgrimes	 * new instance of it for the children and commands on this dependency
3901590Srgrimes	 * line. The new instance is placed on the 'cohorts' list of the
3911590Srgrimes	 * initial one (note the initial one is not on its own cohorts list)
3921590Srgrimes	 * and the new instance is linked to all parents of the initial
3931590Srgrimes	 * instance.
3941590Srgrimes	 */
395138512Sharti	GNode *cohort;
396138512Sharti	LstNode *ln;
3978874Srgrimes
3981590Srgrimes	cohort = Targ_NewGN(gn->name);
3991590Srgrimes	/*
4001590Srgrimes	 * Duplicate links to parents so graph traversal is simple. Perhaps
4011590Srgrimes	 * some type bits should be duplicated?
4021590Srgrimes	 *
4031590Srgrimes	 * Make the cohort invisible as well to avoid duplicating it into
4041590Srgrimes	 * other variables. True, parents of this target won't tend to do
4051590Srgrimes	 * anything with their local variables, but better safe than
4061590Srgrimes	 * sorry.
4071590Srgrimes	 */
408143027Sharti	ParseLinkSrc(&gn->parents, cohort);
4091590Srgrimes	cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
410138916Sharti	Lst_AtEnd(&gn->cohorts, cohort);
4111590Srgrimes
4121590Srgrimes	/*
4131590Srgrimes	 * Replace the node in the targets list with the new copy
4141590Srgrimes	 */
415138916Sharti	ln = Lst_Member(&targets, gn);
416138264Sharti	Lst_Replace(ln, cohort);
4171590Srgrimes	gn = cohort;
4181590Srgrimes    }
4191590Srgrimes    /*
4201590Srgrimes     * We don't want to nuke any previous flags (whatever they were) so we
4218874Srgrimes     * just OR the new operator into the old
4221590Srgrimes     */
4231590Srgrimes    gn->type |= op;
4241590Srgrimes
4251590Srgrimes    return (0);
4261590Srgrimes}
4271590Srgrimes
4281590Srgrimes/*-
4291590Srgrimes *---------------------------------------------------------------------
43018730Ssteve * ParseAddDep  --
43118730Ssteve *	Check if the pair of GNodes given needs to be synchronized.
43218730Ssteve *	This has to be when two nodes are on different sides of a
43318730Ssteve *	.WAIT directive.
43418730Ssteve *
43518730Ssteve * Results:
43618730Ssteve *	Returns 1 if the two targets need to be ordered, 0 otherwise.
43718730Ssteve *	If it returns 1, the search can stop
43818730Ssteve *
43918730Ssteve * Side Effects:
44018730Ssteve *	A dependency can be added between the two nodes.
44118730Ssteve *
44218730Ssteve *---------------------------------------------------------------------
44318730Ssteve */
44449938Shoekstatic int
445104696SjmallettParseAddDep(void *pp, void *sp)
44618730Ssteve{
447138264Sharti    GNode *p = pp;
448138264Sharti    GNode *s = sp;
44918730Ssteve
45018730Ssteve    if (p->order < s->order) {
45118730Ssteve	/*
45218730Ssteve	 * XXX: This can cause loops, and loops can cause unmade targets,
45318730Ssteve	 * but checking is tedious, and the debugging output can show the
45418730Ssteve	 * problem
45518730Ssteve	 */
456138916Sharti	Lst_AtEnd(&p->successors, s);
457138916Sharti	Lst_AtEnd(&s->preds, p);
458138232Sharti	return (0);
45918730Ssteve    }
46018730Ssteve    else
461138232Sharti	return (1);
46218730Ssteve}
46318730Ssteve
46418730Ssteve
46518730Ssteve/*-
46618730Ssteve *---------------------------------------------------------------------
4671590Srgrimes * ParseDoSrc  --
4681590Srgrimes *	Given the name of a source, figure out if it is an attribute
4691590Srgrimes *	and apply it to the targets if it is. Else decide if there is
4701590Srgrimes *	some attribute which should be applied *to* the source because
4711590Srgrimes *	of some special target and apply it if so. Otherwise, make the
4721590Srgrimes *	source be a child of the targets in the list 'targets'
4731590Srgrimes *
4741590Srgrimes * Results:
4751590Srgrimes *	None
4761590Srgrimes *
4771590Srgrimes * Side Effects:
4781590Srgrimes *	Operator bits may be added to the list of targets or to the source.
4791590Srgrimes *	The targets may have a new source added to their lists of children.
4801590Srgrimes *---------------------------------------------------------------------
4811590Srgrimes */
4821590Srgrimesstatic void
483138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc)
4841590Srgrimes{
48518730Ssteve    GNode	*gn = NULL;
4861590Srgrimes
48798508Sjmallett    if (*src == '.' && isupper ((unsigned char) src[1])) {
4881590Srgrimes	int keywd = ParseFindKeyword(src);
4891590Srgrimes	if (keywd != -1) {
49018730Ssteve	    int op = parseKeywords[keywd].op;
49118730Ssteve	    if (op != 0) {
492138916Sharti		Lst_ForEach(&targets, ParseDoOp, &op);
49318730Ssteve		return;
49418730Ssteve	    }
49518730Ssteve	    if (parseKeywords[keywd].spec == Wait) {
49618730Ssteve		waiting++;
49718730Ssteve		return;
49818730Ssteve	    }
4991590Srgrimes	}
5001590Srgrimes    }
50118730Ssteve
50218730Ssteve    switch (specType) {
50318730Ssteve    case Main:
5041590Srgrimes	/*
5051590Srgrimes	 * If we have noted the existence of a .MAIN, it means we need
5061590Srgrimes	 * to add the sources of said target to the list of things
5071590Srgrimes	 * to create. The string 'src' is likely to be free, so we
5081590Srgrimes	 * must make a new copy of it. Note that this will only be
5091590Srgrimes	 * invoked if the user didn't specify a target on the command
5101590Srgrimes	 * line. This is to allow #ifmake's to succeed, or something...
5111590Srgrimes	 */
512138916Sharti	Lst_AtEnd(&create, estrdup(src));
5131590Srgrimes	/*
5141590Srgrimes	 * Add the name to the .TARGETS variable as well, so the user cna
5151590Srgrimes	 * employ that, if desired.
5161590Srgrimes	 */
5171590Srgrimes	Var_Append(".TARGETS", src, VAR_GLOBAL);
51818730Ssteve	return;
51918730Ssteve
52018730Ssteve    case Order:
5211590Srgrimes	/*
5221590Srgrimes	 * Create proper predecessor/successor links between the previous
5231590Srgrimes	 * source and the current one.
5241590Srgrimes	 */
5251590Srgrimes	gn = Targ_FindNode(src, TARG_CREATE);
52669527Swill	if (predecessor != NULL) {
527138916Sharti	    Lst_AtEnd(&predecessor->successors, gn);
528138916Sharti	    Lst_AtEnd(&gn->preds, predecessor);
5291590Srgrimes	}
5301590Srgrimes	/*
5311590Srgrimes	 * The current source now becomes the predecessor for the next one.
5321590Srgrimes	 */
5331590Srgrimes	predecessor = gn;
53418730Ssteve	break;
53518730Ssteve
53618730Ssteve    default:
5371590Srgrimes	/*
5381590Srgrimes	 * If the source is not an attribute, we need to find/create
5391590Srgrimes	 * a node for it. After that we can apply any operator to it
5401590Srgrimes	 * from a special target or link it to its parents, as
5411590Srgrimes	 * appropriate.
5421590Srgrimes	 *
5431590Srgrimes	 * In the case of a source that was the object of a :: operator,
5441590Srgrimes	 * the attribute is applied to all of its instances (as kept in
5451590Srgrimes	 * the 'cohorts' list of the node) or all the cohorts are linked
5461590Srgrimes	 * to all the targets.
5471590Srgrimes	 */
548138232Sharti	gn = Targ_FindNode(src, TARG_CREATE);
5491590Srgrimes	if (tOp) {
5501590Srgrimes	    gn->type |= tOp;
5511590Srgrimes	} else {
552143027Sharti	    ParseLinkSrc(&targets, gn);
5531590Srgrimes	}
5541590Srgrimes	if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
55594584Sobrien	    GNode  	*cohort;
556138512Sharti	    LstNode	*ln;
5571590Srgrimes
558138916Sharti	    for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Succ(ln)) {
559138264Sharti		cohort = Lst_Datum(ln);
5601590Srgrimes		if (tOp) {
5611590Srgrimes		    cohort->type |= tOp;
5621590Srgrimes		} else {
563143027Sharti		    ParseLinkSrc(&targets, cohort);
5641590Srgrimes		}
5651590Srgrimes	    }
5661590Srgrimes	}
56718730Ssteve	break;
5681590Srgrimes    }
56918730Ssteve
57018730Ssteve    gn->order = waiting;
571138264Sharti    Lst_AtEnd(allsrc, gn);
57218730Ssteve    if (waiting) {
573138264Sharti	Lst_ForEach(allsrc, ParseAddDep, gn);
57418730Ssteve    }
5751590Srgrimes}
5761590Srgrimes
5771590Srgrimes/*-
5781590Srgrimes *-----------------------------------------------------------------------
5791590Srgrimes * ParseFindMain --
5801590Srgrimes *	Find a real target in the list and set it to be the main one.
5811590Srgrimes *	Called by ParseDoDependency when a main target hasn't been found
5821590Srgrimes *	yet.
5831590Srgrimes *
5841590Srgrimes * Results:
5851590Srgrimes *	0 if main not found yet, 1 if it is.
5861590Srgrimes *
5871590Srgrimes * Side Effects:
5881590Srgrimes *	mainNode is changed and Targ_SetMain is called.
5891590Srgrimes *
5901590Srgrimes *-----------------------------------------------------------------------
5911590Srgrimes */
5921590Srgrimesstatic int
593104696SjmallettParseFindMain(void *gnp, void *dummy __unused)
5941590Srgrimes{
595138264Sharti    GNode *gn = gnp;
596138264Sharti
597138232Sharti    if ((gn->type & (OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM)) == 0) {
5981590Srgrimes	mainNode = gn;
5991590Srgrimes	Targ_SetMain(gn);
600104696Sjmallett	return (1);
6011590Srgrimes    } else {
602104696Sjmallett	return (0);
6031590Srgrimes    }
6041590Srgrimes}
6051590Srgrimes
6061590Srgrimes/*-
6071590Srgrimes *-----------------------------------------------------------------------
6081590Srgrimes * ParseAddDir --
6091590Srgrimes *	Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
6101590Srgrimes *
6111590Srgrimes * Results:
6121590Srgrimes *	=== 0
6131590Srgrimes *
6141590Srgrimes * Side Effects:
6151590Srgrimes *	See Dir_AddDir.
6161590Srgrimes *
6171590Srgrimes *-----------------------------------------------------------------------
6181590Srgrimes */
6191590Srgrimesstatic int
620104696SjmallettParseAddDir(void *path, void *name)
6211590Srgrimes{
622138232Sharti
623138264Sharti    Dir_AddDir(path, name);
6241590Srgrimes    return(0);
6251590Srgrimes}
6261590Srgrimes
6271590Srgrimes/*-
6281590Srgrimes *-----------------------------------------------------------------------
6291590Srgrimes * ParseClearPath --
6301590Srgrimes *	Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
6311590Srgrimes *
6321590Srgrimes * Results:
6331590Srgrimes *	=== 0
6341590Srgrimes *
6351590Srgrimes * Side Effects:
6361590Srgrimes *	See Dir_ClearPath
6371590Srgrimes *
6381590Srgrimes *-----------------------------------------------------------------------
6391590Srgrimes */
6401590Srgrimesstatic int
641104696SjmallettParseClearPath(void *path, void *dummy __unused)
6421590Srgrimes{
643138232Sharti
644138264Sharti    Dir_ClearPath(path);
645104696Sjmallett    return (0);
6461590Srgrimes}
6471590Srgrimes
6481590Srgrimes/*-
6491590Srgrimes *---------------------------------------------------------------------
6501590Srgrimes * ParseDoDependency  --
6511590Srgrimes *	Parse the dependency line in line.
6521590Srgrimes *
6531590Srgrimes * Results:
6541590Srgrimes *	None
6551590Srgrimes *
6561590Srgrimes * Side Effects:
6571590Srgrimes *	The nodes of the sources are linked as children to the nodes of the
6581590Srgrimes *	targets. Some nodes may be created.
6591590Srgrimes *
6601590Srgrimes *	We parse a dependency line by first extracting words from the line and
6611590Srgrimes * finding nodes in the list of all targets with that name. This is done
6621590Srgrimes * until a character is encountered which is an operator character. Currently
6631590Srgrimes * these are only ! and :. At this point the operator is parsed and the
6641590Srgrimes * pointer into the line advanced until the first source is encountered.
6651590Srgrimes * 	The parsed operator is applied to each node in the 'targets' list,
6661590Srgrimes * which is where the nodes found for the targets are kept, by means of
6671590Srgrimes * the ParseDoOp function.
6681590Srgrimes *	The sources are read in much the same way as the targets were except
6691590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell
6701590Srgrimes * and all instances of the resulting words in the list of all targets
6711590Srgrimes * are found. Each of the resulting nodes is then linked to each of the
6721590Srgrimes * targets as one of its children.
6731590Srgrimes *	Certain targets are handled specially. These are the ones detailed
6741590Srgrimes * by the specType variable.
6751590Srgrimes *	The storing of transformation rules is also taken care of here.
6761590Srgrimes * A target is recognized as a transformation rule by calling
6771590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten
6781590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard
6791590Srgrimes * Targ_FindNode in the target module.
6801590Srgrimes *---------------------------------------------------------------------
6811590Srgrimes */
6821590Srgrimesstatic void
683141270ShartiParseDoDependency(char *line)
6841590Srgrimes{
6855814Sjkh    char  	   *cp;		/* our current position */
6865814Sjkh    GNode 	   *gn;		/* a general purpose temporary node */
6875814Sjkh    int             op;		/* the operator on the line */
6881590Srgrimes    char            savec;	/* a place to save a character */
689138916Sharti    Lst paths;	/* Search paths to alter when parsing a list of .PATH targets */
6901590Srgrimes    int	    	    tOp;    	/* operator from special target */
6911590Srgrimes
6921590Srgrimes    tOp = 0;
6931590Srgrimes
6941590Srgrimes    specType = Not;
69518730Ssteve    waiting = 0;
696138916Sharti    Lst_Init(&paths);
6971590Srgrimes
6981590Srgrimes    do {
6991590Srgrimes	for (cp = line;
700138264Sharti	    *cp && !isspace((unsigned char)*cp) && *cp != '(';
701138264Sharti	    cp++)
7021590Srgrimes	{
7031590Srgrimes	    if (*cp == '$') {
7041590Srgrimes		/*
7051590Srgrimes		 * Must be a dynamic source (would have been expanded
7061590Srgrimes		 * otherwise), so call the Var module to parse the puppy
7071590Srgrimes		 * so we can safely advance beyond it...There should be
7081590Srgrimes		 * no errors in this, as they would have been discovered
7091590Srgrimes		 * in the initial Var_Subst and we wouldn't be here.
7101590Srgrimes		 */
711142937Sharti		size_t	length = 0;
7121590Srgrimes		Boolean	freeIt;
7131590Srgrimes		char	*result;
7141590Srgrimes
715138232Sharti		result = Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
7161590Srgrimes
7171590Srgrimes		if (freeIt) {
7181590Srgrimes		    free(result);
7191590Srgrimes		}
720138232Sharti		cp += length - 1;
721102178Sru	    } else if (*cp == '!' || *cp == ':') {
722102178Sru		/*
723102178Sru		 * We don't want to end a word on ':' or '!' if there is a
724107373Sru		 * better match later on in the string (greedy matching).
725107373Sru		 * This allows the user to have targets like:
726102178Sru		 *    fie::fi:fo: fum
727107373Sru		 *    foo::bar:
728107373Sru		 * where "fie::fi:fo" and "foo::bar" are the targets.  In
729107373Sru		 * real life this is used for perl5 library man pages where
730107373Sru		 * "::" separates an object from its class.
731107373Sru		 * Ie: "File::Spec::Unix".  This behaviour is also consistent
732107373Sru		 * with other versions of make.
733102178Sru		 */
734102178Sru		char *p = cp + 1;
735102178Sru
736103991Sjmallett		if (*cp == ':' && *p == ':')
737102178Sru		    p++;
738102178Sru
739102178Sru		/* Found the best match already. */
740102178Sru		if (*p == '\0' || isspace(*p))
741102178Sru		    break;
742102178Sru
743107373Sru		p += strcspn(p, "!:");
744102178Sru
745102178Sru		/* No better match later on... */
746102178Sru		if (*p == '\0')
747102178Sru		    break;
7481590Srgrimes	    }
7491590Srgrimes	    continue;
7501590Srgrimes	}
7511590Srgrimes	if (*cp == '(') {
7521590Srgrimes	    /*
7531590Srgrimes	     * Archives must be handled specially to make sure the OP_ARCHV
7541590Srgrimes	     * flag is set in their 'type' field, for one thing, and because
7551590Srgrimes	     * things like "archive(file1.o file2.o file3.o)" are permissible.
7561590Srgrimes	     * Arch_ParseArchive will set 'line' to be the first non-blank
7571590Srgrimes	     * after the archive-spec. It creates/finds nodes for the members
7581590Srgrimes	     * and places them on the given list, returning SUCCESS if all
7591590Srgrimes	     * went well and FAILURE if there was an error in the
7601590Srgrimes	     * specification. On error, line should remain untouched.
7611590Srgrimes	     */
762138916Sharti	    if (Arch_ParseArchive(&line, &targets, VAR_CMD) != SUCCESS) {
763138232Sharti		Parse_Error(PARSE_FATAL,
7641590Srgrimes			     "Error in archive specification: \"%s\"", line);
7651590Srgrimes		return;
7661590Srgrimes	    } else {
7671590Srgrimes		continue;
7681590Srgrimes	    }
7691590Srgrimes	}
7701590Srgrimes	savec = *cp;
7718874Srgrimes
7721590Srgrimes	if (!*cp) {
7731590Srgrimes	    /*
7741590Srgrimes	     * Ending a dependency line without an operator is a Bozo
77598506Sjmallett	     * no-no.  As a heuristic, this is also often triggered by
77698506Sjmallett	     * undetected conflicts from cvs/rcs merges.
7771590Srgrimes	     */
77898506Sjmallett	    if ((strncmp(line, "<<<<<<", 6) == 0) ||
77998506Sjmallett		(strncmp(line, "======", 6) == 0) ||
78098506Sjmallett		(strncmp(line, ">>>>>>", 6) == 0))
781138232Sharti		Parse_Error(PARSE_FATAL,
78298506Sjmallett		    "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
78398506Sjmallett	    else
784138232Sharti	        Parse_Error(PARSE_FATAL, "Need an operator");
7851590Srgrimes	    return;
7861590Srgrimes	}
7871590Srgrimes	*cp = '\0';
7881590Srgrimes	/*
7891590Srgrimes	 * Have a word in line. See if it's a special target and set
7901590Srgrimes	 * specType to match it.
7911590Srgrimes	 */
792138264Sharti	if (*line == '.' && isupper((unsigned char)line[1])) {
7931590Srgrimes	    /*
7941590Srgrimes	     * See if the target is a special target that must have it
7958874Srgrimes	     * or its sources handled specially.
7961590Srgrimes	     */
7971590Srgrimes	    int keywd = ParseFindKeyword(line);
7981590Srgrimes	    if (keywd != -1) {
7991590Srgrimes		if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
8001590Srgrimes		    Parse_Error(PARSE_FATAL, "Mismatched special targets");
8011590Srgrimes		    return;
8021590Srgrimes		}
8038874Srgrimes
8041590Srgrimes		specType = parseKeywords[keywd].spec;
8051590Srgrimes		tOp = parseKeywords[keywd].op;
8061590Srgrimes
8071590Srgrimes		/*
8081590Srgrimes		 * Certain special targets have special semantics:
8091590Srgrimes		 *	.PATH		Have to set the dirSearchPath
8101590Srgrimes		 *			variable too
8111590Srgrimes		 *	.MAIN		Its sources are only used if
8121590Srgrimes		 *			nothing has been specified to
8131590Srgrimes		 *			create.
8141590Srgrimes		 *	.DEFAULT    	Need to create a node to hang
8151590Srgrimes		 *			commands on, but we don't want
8161590Srgrimes		 *			it in the graph, nor do we want
8171590Srgrimes		 *			it to be the Main Target, so we
8181590Srgrimes		 *			create it, set OP_NOTMAIN and
8191590Srgrimes		 *			add it to the list, setting
8201590Srgrimes		 *			DEFAULT to the new node for
8211590Srgrimes		 *			later use. We claim the node is
8221590Srgrimes		 *	    	    	A transformation rule to make
8231590Srgrimes		 *	    	    	life easier later, when we'll
8241590Srgrimes		 *	    	    	use Make_HandleUse to actually
8251590Srgrimes		 *	    	    	apply the .DEFAULT commands.
82618730Ssteve		 *	.PHONY		The list of targets
8271590Srgrimes		 *	.BEGIN
8281590Srgrimes		 *	.END
8291590Srgrimes		 *	.INTERRUPT  	Are not to be considered the
8301590Srgrimes		 *			main target.
8311590Srgrimes		 *  	.NOTPARALLEL	Make only one target at a time.
8321590Srgrimes		 *  	.SINGLESHELL	Create a shell for each command.
83369527Swill		 *  	.ORDER	    	Must set initial predecessor to NULL
8341590Srgrimes		 */
8351590Srgrimes		switch (specType) {
8361590Srgrimes		    case ExPath:
837138916Sharti			Lst_AtEnd(&paths, &dirSearchPath);
8381590Srgrimes			break;
8391590Srgrimes		    case Main:
840138916Sharti			if (!Lst_IsEmpty(&create)) {
8411590Srgrimes			    specType = Not;
8421590Srgrimes			}
8431590Srgrimes			break;
8441590Srgrimes		    case Begin:
8451590Srgrimes		    case End:
8461590Srgrimes		    case Interrupt:
8471590Srgrimes			gn = Targ_FindNode(line, TARG_CREATE);
8481590Srgrimes			gn->type |= OP_NOTMAIN;
849138916Sharti			Lst_AtEnd(&targets, gn);
8501590Srgrimes			break;
8511590Srgrimes		    case Default:
8521590Srgrimes			gn = Targ_NewGN(".DEFAULT");
8531590Srgrimes			gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
854138916Sharti			Lst_AtEnd(&targets, gn);
8551590Srgrimes			DEFAULT = gn;
8561590Srgrimes			break;
8571590Srgrimes		    case NotParallel:
8581590Srgrimes		    {
8591590Srgrimes			maxJobs = 1;
8601590Srgrimes			break;
8611590Srgrimes		    }
8621590Srgrimes		    case SingleShell:
8631590Srgrimes			compatMake = 1;
8641590Srgrimes			break;
8651590Srgrimes		    case Order:
86669527Swill			predecessor = NULL;
8671590Srgrimes			break;
8681590Srgrimes		    default:
8691590Srgrimes			break;
8701590Srgrimes		}
871138232Sharti	    } else if (strncmp(line, ".PATH", 5) == 0) {
8721590Srgrimes		/*
8731590Srgrimes		 * .PATH<suffix> has to be handled specially.
8741590Srgrimes		 * Call on the suffix module to give us a path to
8751590Srgrimes		 * modify.
8761590Srgrimes		 */
877138512Sharti		Lst *path;
8788874Srgrimes
8791590Srgrimes		specType = ExPath;
880138232Sharti		path = Suff_GetPath(&line[5]);
88169527Swill		if (path == NULL) {
882138232Sharti		    Parse_Error(PARSE_FATAL,
8831590Srgrimes				 "Suffix '%s' not defined (yet)",
8841590Srgrimes				 &line[5]);
8851590Srgrimes		    return;
886138916Sharti		} else
887138916Sharti		    Lst_AtEnd(&paths, path);
8881590Srgrimes	    }
8891590Srgrimes	}
8908874Srgrimes
8911590Srgrimes	/*
8921590Srgrimes	 * Have word in line. Get or create its node and stick it at
8938874Srgrimes	 * the end of the targets list
8941590Srgrimes	 */
8951590Srgrimes	if ((specType == Not) && (*line != '\0')) {
896138916Sharti	    /* target names to be found and added to targets list */
897138916Sharti	    Lst curTargs = Lst_Initializer(curTargs);
898138916Sharti
8991590Srgrimes	    if (Dir_HasWildcards(line)) {
9001590Srgrimes		/*
9011590Srgrimes		 * Targets are to be sought only in the current directory,
9021590Srgrimes		 * so create an empty path for the thing. Note we need to
9031590Srgrimes		 * use Dir_Destroy in the destruction of the path as the
9041590Srgrimes		 * Dir module could have added a directory to the path...
9051590Srgrimes		 */
906138916Sharti		Lst emptyPath = Lst_Initializer(emptyPath);
9078874Srgrimes
908138916Sharti		Dir_Expand(line, &emptyPath, &curTargs);
9098874Srgrimes
910138916Sharti		Lst_Destroy(&emptyPath, Dir_Destroy);
9111590Srgrimes	    } else {
9121590Srgrimes		/*
9131590Srgrimes		 * No wildcards, but we want to avoid code duplication,
9141590Srgrimes		 * so create a list with the word on it.
9151590Srgrimes		 */
916138916Sharti		Lst_AtEnd(&curTargs, line);
9171590Srgrimes	    }
9188874Srgrimes
919138916Sharti	    while (!Lst_IsEmpty(&curTargs)) {
920138916Sharti		char	*targName = Lst_DeQueue(&curTargs);
9218874Srgrimes
9221590Srgrimes		if (!Suff_IsTransform (targName)) {
923138232Sharti		    gn = Targ_FindNode(targName, TARG_CREATE);
9241590Srgrimes		} else {
925138232Sharti		    gn = Suff_AddTransform(targName);
9261590Srgrimes		}
9278874Srgrimes
928138916Sharti		Lst_AtEnd(&targets, gn);
9291590Srgrimes	    }
9301590Srgrimes	} else if (specType == ExPath && *line != '.' && *line != '\0') {
9311590Srgrimes	    Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
9321590Srgrimes	}
9338874Srgrimes
9341590Srgrimes	*cp = savec;
9351590Srgrimes	/*
9361590Srgrimes	 * If it is a special type and not .PATH, it's the only target we
9371590Srgrimes	 * allow on this line...
9381590Srgrimes	 */
9391590Srgrimes	if (specType != Not && specType != ExPath) {
940141252Sharti	    Boolean warnFlag = FALSE;
9418874Srgrimes
9421590Srgrimes	    while ((*cp != '!') && (*cp != ':') && *cp) {
9431590Srgrimes		if (*cp != ' ' && *cp != '\t') {
944141252Sharti		    warnFlag = TRUE;
9451590Srgrimes		}
9461590Srgrimes		cp++;
9471590Srgrimes	    }
948141252Sharti	    if (warnFlag) {
9491590Srgrimes		Parse_Error(PARSE_WARNING, "Extra target ignored");
9501590Srgrimes	    }
9511590Srgrimes	} else {
952138264Sharti	    while (*cp && isspace((unsigned char)*cp)) {
9531590Srgrimes		cp++;
9541590Srgrimes	    }
9551590Srgrimes	}
9561590Srgrimes	line = cp;
9571590Srgrimes    } while ((*line != '!') && (*line != ':') && *line);
9581590Srgrimes
959138916Sharti    if (!Lst_IsEmpty(&targets)) {
960138264Sharti	switch (specType) {
9611590Srgrimes	    default:
9621590Srgrimes		Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
9631590Srgrimes		break;
9641590Srgrimes	    case Default:
9651590Srgrimes	    case Begin:
9661590Srgrimes	    case End:
9671590Srgrimes	    case Interrupt:
9681590Srgrimes		/*
9691590Srgrimes		 * These four create nodes on which to hang commands, so
9701590Srgrimes		 * targets shouldn't be empty...
9711590Srgrimes		 */
9721590Srgrimes	    case Not:
9731590Srgrimes		/*
9741590Srgrimes		 * Nothing special here -- targets can be empty if it wants.
9751590Srgrimes		 */
9761590Srgrimes		break;
9771590Srgrimes	}
9781590Srgrimes    }
9791590Srgrimes
9801590Srgrimes    /*
9811590Srgrimes     * Have now parsed all the target names. Must parse the operator next. The
9821590Srgrimes     * result is left in  op .
9831590Srgrimes     */
9841590Srgrimes    if (*cp == '!') {
9851590Srgrimes	op = OP_FORCE;
9861590Srgrimes    } else if (*cp == ':') {
9871590Srgrimes	if (cp[1] == ':') {
9881590Srgrimes	    op = OP_DOUBLEDEP;
9891590Srgrimes	    cp++;
9901590Srgrimes	} else {
9911590Srgrimes	    op = OP_DEPENDS;
9921590Srgrimes	}
9931590Srgrimes    } else {
994138232Sharti	Parse_Error(PARSE_FATAL, "Missing dependency operator");
9951590Srgrimes	return;
9961590Srgrimes    }
9971590Srgrimes
9981590Srgrimes    cp++;			/* Advance beyond operator */
9991590Srgrimes
1000138916Sharti    Lst_ForEach(&targets, ParseDoOp, &op);
10011590Srgrimes
10021590Srgrimes    /*
10038874Srgrimes     * Get to the first source
10041590Srgrimes     */
1005138264Sharti    while (*cp && isspace((unsigned char)*cp)) {
10061590Srgrimes	cp++;
10071590Srgrimes    }
10081590Srgrimes    line = cp;
10091590Srgrimes
10101590Srgrimes    /*
10111590Srgrimes     * Several special targets take different actions if present with no
10121590Srgrimes     * sources:
10131590Srgrimes     *	a .SUFFIXES line with no sources clears out all old suffixes
10141590Srgrimes     *	a .PRECIOUS line makes all targets precious
10151590Srgrimes     *	a .IGNORE line ignores errors for all targets
10161590Srgrimes     *	a .SILENT line creates silence when making all targets
10171590Srgrimes     *	a .PATH removes all directories from the search path(s).
10181590Srgrimes     */
10191590Srgrimes    if (!*line) {
10201590Srgrimes	switch (specType) {
10211590Srgrimes	    case Suffixes:
1022138232Sharti		Suff_ClearSuffixes();
10231590Srgrimes		break;
10241590Srgrimes	    case Precious:
10251590Srgrimes		allPrecious = TRUE;
10261590Srgrimes		break;
10271590Srgrimes	    case Ignore:
10281590Srgrimes		ignoreErrors = TRUE;
10291590Srgrimes		break;
10301590Srgrimes	    case Silent:
10311590Srgrimes		beSilent = TRUE;
10321590Srgrimes		break;
10331590Srgrimes	    case ExPath:
1034138916Sharti		Lst_ForEach(&paths, ParseClearPath, NULL);
10351590Srgrimes		break;
103619344Ssteve	    case Posix:
103719344Ssteve		Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
103819344Ssteve		break;
10391590Srgrimes	    default:
10401590Srgrimes		break;
10411590Srgrimes	}
10421590Srgrimes    } else if (specType == MFlags) {
10431590Srgrimes	/*
10441590Srgrimes	 * Call on functions in main.c to deal with these arguments and
10451590Srgrimes	 * set the initial character to a null-character so the loop to
10461590Srgrimes	 * get sources won't get anything
10471590Srgrimes	 */
1048140870Sharti	Main_ParseArgLine(line, 0);
10491590Srgrimes	*line = '\0';
10501590Srgrimes    } else if (specType == ExShell) {
1051138232Sharti	if (Job_ParseShell(line) != SUCCESS) {
1052138232Sharti	    Parse_Error(PARSE_FATAL, "improper shell specification");
10531590Srgrimes	    return;
10541590Srgrimes	}
10551590Srgrimes	*line = '\0';
10561590Srgrimes    } else if ((specType == NotParallel) || (specType == SingleShell)) {
10571590Srgrimes	*line = '\0';
10581590Srgrimes    }
10598874Srgrimes
10601590Srgrimes    /*
10618874Srgrimes     * NOW GO FOR THE SOURCES
10621590Srgrimes     */
10631590Srgrimes    if ((specType == Suffixes) || (specType == ExPath) ||
10641590Srgrimes	(specType == Includes) || (specType == Libs) ||
10651590Srgrimes	(specType == Null))
10661590Srgrimes    {
10671590Srgrimes	while (*line) {
10681590Srgrimes	    /*
10691590Srgrimes	     * If the target was one that doesn't take files as its sources
10701590Srgrimes	     * but takes something like suffixes, we take each
10711590Srgrimes	     * space-separated word on the line as a something and deal
10721590Srgrimes	     * with it accordingly.
10731590Srgrimes	     *
10741590Srgrimes	     * If the target was .SUFFIXES, we take each source as a
10751590Srgrimes	     * suffix and add it to the list of suffixes maintained by the
10761590Srgrimes	     * Suff module.
10771590Srgrimes	     *
10781590Srgrimes	     * If the target was a .PATH, we add the source as a directory
10791590Srgrimes	     * to search on the search path.
10801590Srgrimes	     *
10811590Srgrimes	     * If it was .INCLUDES, the source is taken to be the suffix of
10821590Srgrimes	     * files which will be #included and whose search path should
10831590Srgrimes	     * be present in the .INCLUDES variable.
10841590Srgrimes	     *
10851590Srgrimes	     * If it was .LIBS, the source is taken to be the suffix of
10861590Srgrimes	     * files which are considered libraries and whose search path
10871590Srgrimes	     * should be present in the .LIBS variable.
10881590Srgrimes	     *
10891590Srgrimes	     * If it was .NULL, the source is the suffix to use when a file
10901590Srgrimes	     * has no valid suffix.
10911590Srgrimes	     */
1092104121Sjmallett	    char  savech;
1093138264Sharti	    while (*cp && !isspace((unsigned char)*cp)) {
10941590Srgrimes		cp++;
10951590Srgrimes	    }
1096104121Sjmallett	    savech = *cp;
10971590Srgrimes	    *cp = '\0';
10981590Srgrimes	    switch (specType) {
10991590Srgrimes		case Suffixes:
1100138232Sharti		    Suff_AddSuffix(line);
11011590Srgrimes		    break;
11021590Srgrimes		case ExPath:
1103138916Sharti		    Lst_ForEach(&paths, ParseAddDir, line);
11041590Srgrimes		    break;
11051590Srgrimes		case Includes:
1106138232Sharti		    Suff_AddInclude(line);
11071590Srgrimes		    break;
11081590Srgrimes		case Libs:
1109138232Sharti		    Suff_AddLib(line);
11101590Srgrimes		    break;
11111590Srgrimes		case Null:
1112138232Sharti		    Suff_SetNull(line);
11131590Srgrimes		    break;
11141590Srgrimes		default:
11151590Srgrimes		    break;
11161590Srgrimes	    }
1117104121Sjmallett	    *cp = savech;
1118104121Sjmallett	    if (savech != '\0') {
11191590Srgrimes		cp++;
11201590Srgrimes	    }
1121138264Sharti	    while (*cp && isspace((unsigned char)*cp)) {
11221590Srgrimes		cp++;
11231590Srgrimes	    }
11241590Srgrimes	    line = cp;
11251590Srgrimes	}
1126138916Sharti	Lst_Destroy(&paths, NOFREE);
1127138916Sharti
11281590Srgrimes    } else {
1129138916Sharti        Lst curSrcs = Lst_Initializer(curSrc);	/* list of sources in order */
1130141270Sharti
11311590Srgrimes	while (*line) {
11321590Srgrimes	    /*
11331590Srgrimes	     * The targets take real sources, so we must beware of archive
11341590Srgrimes	     * specifications (i.e. things with left parentheses in them)
11351590Srgrimes	     * and handle them accordingly.
11361590Srgrimes	     */
1137138264Sharti	    while (*cp && !isspace((unsigned char)*cp)) {
11381590Srgrimes		if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
11391590Srgrimes		    /*
11401590Srgrimes		     * Only stop for a left parenthesis if it isn't at the
11411590Srgrimes		     * start of a word (that'll be for variable changes
11421590Srgrimes		     * later) and isn't preceded by a dollar sign (a dynamic
11431590Srgrimes		     * source).
11441590Srgrimes		     */
11451590Srgrimes		    break;
11461590Srgrimes		} else {
11471590Srgrimes		    cp++;
11481590Srgrimes		}
11491590Srgrimes	    }
11501590Srgrimes
11511590Srgrimes	    if (*cp == '(') {
1152104121Sjmallett		GNode	  *gnp;
1153138916Sharti		/* list of archive source names after expansion */
1154138916Sharti		Lst sources = Lst_Initializer(sources);
11551590Srgrimes
1156138916Sharti		if (Arch_ParseArchive(&line, &sources, VAR_CMD) != SUCCESS) {
1157138232Sharti		    Parse_Error(PARSE_FATAL,
11581590Srgrimes				 "Error in source archive spec \"%s\"", line);
11591590Srgrimes		    return;
11601590Srgrimes		}
11611590Srgrimes
1162138916Sharti		while (!Lst_IsEmpty(&sources)) {
1163138916Sharti		    gnp = Lst_DeQueue(&sources);
1164138916Sharti		    ParseDoSrc(tOp, gnp->name, &curSrcs);
11651590Srgrimes		}
11661590Srgrimes		cp = line;
11671590Srgrimes	    } else {
11681590Srgrimes		if (*cp) {
11691590Srgrimes		    *cp = '\0';
11701590Srgrimes		    cp += 1;
11711590Srgrimes		}
11721590Srgrimes
1173138916Sharti		ParseDoSrc(tOp, line, &curSrcs);
11741590Srgrimes	    }
1175138264Sharti	    while (*cp && isspace((unsigned char)*cp)) {
11761590Srgrimes		cp++;
11771590Srgrimes	    }
11781590Srgrimes	    line = cp;
11791590Srgrimes	}
1180138916Sharti        Lst_Destroy(&curSrcs, NOFREE);
11811590Srgrimes    }
11828874Srgrimes
118369527Swill    if (mainNode == NULL) {
11841590Srgrimes	/*
11851590Srgrimes	 * If we have yet to decide on a main target to make, in the
11861590Srgrimes	 * absence of any user input, we want the first target on
11871590Srgrimes	 * the first dependency line that is actually a real target
11881590Srgrimes	 * (i.e. isn't a .USE or .EXEC rule) to be made.
11891590Srgrimes	 */
1190138916Sharti	Lst_ForEach(&targets, ParseFindMain, NULL);
11911590Srgrimes    }
11921590Srgrimes}
11931590Srgrimes
11941590Srgrimes/*-
11951590Srgrimes *---------------------------------------------------------------------
11961590Srgrimes * Parse_IsVar  --
11971590Srgrimes *	Return TRUE if the passed line is a variable assignment. A variable
11981590Srgrimes *	assignment consists of a single word followed by optional whitespace
11991590Srgrimes *	followed by either a += or an = operator.
12001590Srgrimes *	This function is used both by the Parse_File function and main when
12011590Srgrimes *	parsing the command-line arguments.
12021590Srgrimes *
12031590Srgrimes * Results:
12041590Srgrimes *	TRUE if it is. FALSE if it ain't
12051590Srgrimes *
12061590Srgrimes * Side Effects:
12071590Srgrimes *	none
12081590Srgrimes *---------------------------------------------------------------------
12091590Srgrimes */
12101590SrgrimesBoolean
1211138232ShartiParse_IsVar(char *line)
12121590Srgrimes{
121394584Sobrien    Boolean wasSpace = FALSE;	/* set TRUE if found a space */
121494584Sobrien    Boolean haveName = FALSE;	/* Set TRUE if have a variable name */
1215138232Sharti
121618730Ssteve    int level = 0;
1217103503Sjmallett#define	ISEQOPERATOR(c) \
121818730Ssteve	(((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
12191590Srgrimes
12201590Srgrimes    /*
12211590Srgrimes     * Skip to variable name
12221590Srgrimes     */
1223138232Sharti    for (; (*line == ' ') || (*line == '\t'); line++)
122418730Ssteve	continue;
12251590Srgrimes
122618730Ssteve    for (; *line != '=' || level != 0; line++)
122718730Ssteve	switch (*line) {
122818730Ssteve	case '\0':
12291590Srgrimes	    /*
12301590Srgrimes	     * end-of-line -- can't be a variable assignment.
12311590Srgrimes	     */
1232138232Sharti	    return (FALSE);
123318730Ssteve
123418730Ssteve	case ' ':
123518730Ssteve	case '\t':
12361590Srgrimes	    /*
12371590Srgrimes	     * there can be as much white space as desired so long as there is
12388874Srgrimes	     * only one word before the operator
12391590Srgrimes	     */
12401590Srgrimes	    wasSpace = TRUE;
124118730Ssteve	    break;
124218730Ssteve
124318730Ssteve	case '(':
124418730Ssteve	case '{':
124518730Ssteve	    level++;
124618730Ssteve	    break;
124718730Ssteve
124818730Ssteve	case '}':
124918730Ssteve	case ')':
125018730Ssteve	    level--;
125118730Ssteve	    break;
125218730Ssteve
125318730Ssteve	default:
125418730Ssteve	    if (wasSpace && haveName) {
125518730Ssteve		    if (ISEQOPERATOR(*line)) {
125618730Ssteve			/*
125718730Ssteve			 * We must have a finished word
125818730Ssteve			 */
125918730Ssteve			if (level != 0)
1260138232Sharti			    return (FALSE);
126118730Ssteve
126218730Ssteve			/*
126318730Ssteve			 * When an = operator [+?!:] is found, the next
126418730Ssteve			 * character must be an = or it ain't a valid
126518730Ssteve			 * assignment.
126618730Ssteve			 */
126718730Ssteve			if (line[1] == '=')
1268138232Sharti			    return (haveName);
126918730Ssteve#ifdef SUNSHCMD
127018730Ssteve			/*
127118730Ssteve			 * This is a shell command
127218730Ssteve			 */
127318730Ssteve			if (strncmp(line, ":sh", 3) == 0)
1274138232Sharti			    return (haveName);
127518730Ssteve#endif
127618730Ssteve		    }
127718730Ssteve		    /*
127818730Ssteve		     * This is the start of another word, so not assignment.
127918730Ssteve		     */
1280138232Sharti		    return (FALSE);
12811590Srgrimes	    }
128218730Ssteve	    else {
128318730Ssteve		haveName = TRUE;
128418730Ssteve		wasSpace = FALSE;
128518730Ssteve	    }
128618730Ssteve	    break;
12871590Srgrimes	}
12881590Srgrimes
1289138232Sharti    return (haveName);
12901590Srgrimes}
12911590Srgrimes
12921590Srgrimes/*-
12931590Srgrimes *---------------------------------------------------------------------
12941590Srgrimes * Parse_DoVar  --
12951590Srgrimes *	Take the variable assignment in the passed line and do it in the
12961590Srgrimes *	global context.
12971590Srgrimes *
12981590Srgrimes *	Note: There is a lexical ambiguity with assignment modifier characters
12991590Srgrimes *	in variable names. This routine interprets the character before the =
13001590Srgrimes *	as a modifier. Therefore, an assignment like
13011590Srgrimes *	    C++=/usr/bin/CC
13021590Srgrimes *	is interpreted as "C+ +=" instead of "C++ =".
13031590Srgrimes *
13041590Srgrimes * Results:
13051590Srgrimes *	none
13061590Srgrimes *
13071590Srgrimes * Side Effects:
13081590Srgrimes *	the variable structure of the given variable name is altered in the
13091590Srgrimes *	global context.
13101590Srgrimes *---------------------------------------------------------------------
13111590Srgrimes */
13121590Srgrimesvoid
1313138232ShartiParse_DoVar(char *line, GNode *ctxt)
13141590Srgrimes{
13155814Sjkh    char	   *cp;	/* pointer into line */
13161590Srgrimes    enum {
13171590Srgrimes	VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
13181590Srgrimes    }	    	    type;   	/* Type of assignment */
13198874Srgrimes    char            *opc;	/* ptr to operator character to
13201590Srgrimes				 * null-terminate the variable name */
1321142457Sharti    Buffer	    *buf;
1322142457Sharti
13238874Srgrimes    /*
13241590Srgrimes     * Avoid clobbered variable warnings by forcing the compiler
13251590Srgrimes     * to ``unregister'' variables
13265814Sjkh     */
13271590Srgrimes#if __GNUC__
1328138232Sharti    (void)&cp;
1329138232Sharti    (void)&line;
13305814Sjkh#endif
13311590Srgrimes
13321590Srgrimes    /*
13331590Srgrimes     * Skip to variable name
13341590Srgrimes     */
13351590Srgrimes    while ((*line == ' ') || (*line == '\t')) {
13361590Srgrimes	line++;
13371590Srgrimes    }
13381590Srgrimes
13391590Srgrimes    /*
13401590Srgrimes     * Skip to operator character, nulling out whitespace as we go
13411590Srgrimes     */
13421590Srgrimes    for (cp = line + 1; *cp != '='; cp++) {
1343138264Sharti	if (isspace((unsigned char)*cp)) {
13441590Srgrimes	    *cp = '\0';
13451590Srgrimes	}
13461590Srgrimes    }
1347138232Sharti    opc = cp - 1;	/* operator is the previous character */
13481590Srgrimes    *cp++ = '\0';	/* nuke the = */
13491590Srgrimes
13501590Srgrimes    /*
13511590Srgrimes     * Check operator type
13521590Srgrimes     */
13531590Srgrimes    switch (*opc) {
13541590Srgrimes	case '+':
13551590Srgrimes	    type = VAR_APPEND;
13561590Srgrimes	    *opc = '\0';
13571590Srgrimes	    break;
13581590Srgrimes
13591590Srgrimes	case '?':
13601590Srgrimes	    /*
13611590Srgrimes	     * If the variable already has a value, we don't do anything.
13621590Srgrimes	     */
13631590Srgrimes	    *opc = '\0';
13641590Srgrimes	    if (Var_Exists(line, ctxt)) {
13651590Srgrimes		return;
13661590Srgrimes	    } else {
13671590Srgrimes		type = VAR_NORMAL;
13681590Srgrimes	    }
13691590Srgrimes	    break;
13701590Srgrimes
13711590Srgrimes	case ':':
13721590Srgrimes	    type = VAR_SUBST;
13731590Srgrimes	    *opc = '\0';
13741590Srgrimes	    break;
13751590Srgrimes
13761590Srgrimes	case '!':
13771590Srgrimes	    type = VAR_SHELL;
13781590Srgrimes	    *opc = '\0';
13791590Srgrimes	    break;
13801590Srgrimes
13811590Srgrimes	default:
138218730Ssteve#ifdef SUNSHCMD
138318730Ssteve	    while (*opc != ':')
138442409Sjkh		if (opc == line)
138518730Ssteve		    break;
138642409Sjkh		else
138742409Sjkh		    --opc;
138818730Ssteve
138918730Ssteve	    if (strncmp(opc, ":sh", 3) == 0) {
139018730Ssteve		type = VAR_SHELL;
139118730Ssteve		*opc = '\0';
139218730Ssteve		break;
139318730Ssteve	    }
139418730Ssteve#endif
13951590Srgrimes	    type = VAR_NORMAL;
13961590Srgrimes	    break;
13971590Srgrimes    }
13981590Srgrimes
1399138264Sharti    while (isspace((unsigned char)*cp)) {
14001590Srgrimes	cp++;
14011590Srgrimes    }
14021590Srgrimes
14031590Srgrimes    if (type == VAR_APPEND) {
1404138232Sharti	Var_Append(line, cp, ctxt);
14051590Srgrimes    } else if (type == VAR_SUBST) {
14061590Srgrimes	/*
14071590Srgrimes	 * Allow variables in the old value to be undefined, but leave their
14081590Srgrimes	 * invocation alone -- this is done by forcing oldVars to be false.
14091590Srgrimes	 * XXX: This can cause recursive variables, but that's not hard to do,
14101590Srgrimes	 * and this allows someone to do something like
14111590Srgrimes	 *
14121590Srgrimes	 *  CFLAGS = $(.INCLUDES)
14131590Srgrimes	 *  CFLAGS := -I.. $(CFLAGS)
14141590Srgrimes	 *
14151590Srgrimes	 * And not get an error.
14161590Srgrimes	 */
14171590Srgrimes	Boolean	  oldOldVars = oldVars;
14181590Srgrimes
14191590Srgrimes	oldVars = FALSE;
142098509Sjmallett
142198509Sjmallett	/*
142298509Sjmallett	 * make sure that we set the variable the first time to nothing
142398509Sjmallett	 * so that it gets substituted!
142498509Sjmallett	 */
142598509Sjmallett	if (!Var_Exists(line, ctxt))
142698509Sjmallett	    Var_Set(line, "", ctxt);
142798509Sjmallett
1428142457Sharti	buf = Var_Subst(NULL, cp, ctxt, FALSE);
1429142457Sharti	cp = Buf_GetAll(buf, NULL);
1430142457Sharti	Buf_Destroy(buf, FALSE);
1431142457Sharti
14321590Srgrimes	oldVars = oldOldVars;
14331590Srgrimes
14341590Srgrimes	Var_Set(line, cp, ctxt);
14351590Srgrimes	free(cp);
14361590Srgrimes    } else if (type == VAR_SHELL) {
143718730Ssteve	Boolean	freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
143818730Ssteve				  * if any variable expansion was performed */
1439141454Sharti	Buffer *buf;
1440141252Sharti	const char *error;
14411590Srgrimes
144218730Ssteve	if (strchr(cp, '$') != NULL) {
14431590Srgrimes	    /*
14441590Srgrimes	     * There's a dollar sign in the command, so perform variable
14451590Srgrimes	     * expansion on the whole thing. The resulting string will need
14461590Srgrimes	     * freeing when we're done, so set freeCmd to TRUE.
14471590Srgrimes	     */
1448142457Sharti	    buf = Var_Subst(NULL, cp, VAR_CMD, TRUE);
1449142457Sharti	    cp = Buf_GetAll(buf, NULL);
1450142457Sharti	    Buf_Destroy(buf, FALSE);
14511590Srgrimes	    freeCmd = TRUE;
14521590Srgrimes	}
14531590Srgrimes
1454141454Sharti	buf = Cmd_Exec(cp, &error);
1455141454Sharti	Var_Set(line, Buf_GetAll(buf, NULL), ctxt);
1456141454Sharti	Buf_Destroy(buf, TRUE);
14571590Srgrimes
1458104121Sjmallett	if (error)
1459104121Sjmallett	    Parse_Error(PARSE_WARNING, error, cp);
14601590Srgrimes
146118730Ssteve	if (freeCmd)
146218730Ssteve	    free(cp);
14631590Srgrimes    } else {
14641590Srgrimes	/*
14651590Srgrimes	 * Normal assignment -- just do it.
14661590Srgrimes	 */
146718730Ssteve	Var_Set(line, cp, ctxt);
14681590Srgrimes    }
14691590Srgrimes}
14701590Srgrimes
14711590Srgrimes/*-
14721590Srgrimes * ParseAddCmd  --
14731590Srgrimes *	Lst_ForEach function to add a command line to all targets
14741590Srgrimes *
14751590Srgrimes * Results:
14761590Srgrimes *	Always 0
14771590Srgrimes *
14781590Srgrimes * Side Effects:
14791590Srgrimes *	A new element is added to the commands list of the node.
14801590Srgrimes */
14811590Srgrimesstatic int
1482104696SjmallettParseAddCmd(void *gnp, void *cmd)
14831590Srgrimes{
1484138264Sharti    GNode *gn = gnp;
1485138232Sharti
14865814Sjkh    /* if target already supplied, ignore commands */
14875814Sjkh    if (!(gn->type & OP_HAS_COMMANDS))
1488138916Sharti	Lst_AtEnd(&gn->commands, cmd);
1489100792Sjmallett    else
1490100792Sjmallett	Parse_Error(PARSE_WARNING,
1491100792Sjmallett		    "duplicate script for target \"%s\" ignored",
1492100792Sjmallett		    gn->name);
1493138232Sharti    return (0);
14941590Srgrimes}
14951590Srgrimes
14961590Srgrimes/*-
14971590Srgrimes *-----------------------------------------------------------------------
14981590Srgrimes * ParseHasCommands --
14991590Srgrimes *	Callback procedure for Parse_File when destroying the list of
15001590Srgrimes *	targets on the last dependency line. Marks a target as already
15011590Srgrimes *	having commands if it does, to keep from having shell commands
15021590Srgrimes *	on multiple dependency lines.
15031590Srgrimes *
15041590Srgrimes * Results:
15055814Sjkh *	None
15061590Srgrimes *
15071590Srgrimes * Side Effects:
15081590Srgrimes *	OP_HAS_COMMANDS may be set for the target.
15091590Srgrimes *
15101590Srgrimes *-----------------------------------------------------------------------
15111590Srgrimes */
15125814Sjkhstatic void
1513104696SjmallettParseHasCommands(void *gnp)
15141590Srgrimes{
1515138264Sharti    GNode *gn = gnp;
1516138232Sharti
1517138916Sharti    if (!Lst_IsEmpty(&gn->commands)) {
15181590Srgrimes	gn->type |= OP_HAS_COMMANDS;
15191590Srgrimes    }
15201590Srgrimes}
15211590Srgrimes
15221590Srgrimes/*-
15231590Srgrimes *-----------------------------------------------------------------------
15241590Srgrimes * Parse_AddIncludeDir --
15251590Srgrimes *	Add a directory to the path searched for included makefiles
15261590Srgrimes *	bracketed by double-quotes. Used by functions in main.c
15271590Srgrimes *
15281590Srgrimes * Results:
15291590Srgrimes *	None.
15301590Srgrimes *
15311590Srgrimes * Side Effects:
15321590Srgrimes *	The directory is appended to the list.
15331590Srgrimes *
15341590Srgrimes *-----------------------------------------------------------------------
15351590Srgrimes */
15361590Srgrimesvoid
1537138232ShartiParse_AddIncludeDir(char *dir)
15381590Srgrimes{
1539138232Sharti
1540138916Sharti    Dir_AddDir(&parseIncPath, dir);
15411590Srgrimes}
15421590Srgrimes
154336347Ssteve/*---------------------------------------------------------------------
154436347Ssteve * ParseDoError  --
154536347Ssteve *	Handle error directive
154636347Ssteve *
154736347Ssteve *	The input is the line minus the ".error".  We substitute variables,
154836347Ssteve *	print the message and exit(1) or just print a warning if the ".error"
154936347Ssteve *	directive is malformed.
155036347Ssteve *
155136347Ssteve *---------------------------------------------------------------------
155236347Ssteve */
155336347Sstevestatic void
1554104696SjmallettParseDoError(char *errmsg)
155536347Ssteve{
1556142457Sharti	Buffer *buf;
1557138232Sharti
1558138232Sharti	if (!isspace((unsigned char)*errmsg)) {
155936347Ssteve		Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg);
156036347Ssteve		return;
156136347Ssteve	}
1562138232Sharti
1563138232Sharti	while (isspace((unsigned char)*errmsg))
156436347Ssteve		errmsg++;
1565138232Sharti
1566142457Sharti	buf = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
1567142457Sharti	errmsg = Buf_GetAll(buf, NULL);
156836347Ssteve
1569128160Sru	Parse_Error(PARSE_FATAL, "%s", errmsg);
1570142457Sharti	Buf_Destroy(buf, TRUE);
1571142457Sharti
1572128160Sru	/* Terminate immediately. */
157336347Ssteve	exit(1);
157436347Ssteve}
157536347Ssteve
1576128160Sru/*---------------------------------------------------------------------
1577128160Sru * ParseDoWarning  --
1578128160Sru *	Handle warning directive
1579128160Sru *
1580128160Sru *	The input is the line minus the ".warning".  We substitute variables
1581128160Sru *	and print the message or just print a warning if the ".warning"
1582128160Sru *	directive is malformed.
1583128160Sru *
1584128160Sru *---------------------------------------------------------------------
1585128160Sru */
1586128160Srustatic void
1587128160SruParseDoWarning(char *warnmsg)
1588128160Sru{
1589142457Sharti	Buffer *buf;
1590138232Sharti
1591138232Sharti	if (!isspace((unsigned char)*warnmsg)) {
1592128160Sru		Parse_Error(PARSE_WARNING, "invalid syntax: .warning%s",
1593128160Sru		    warnmsg);
1594128160Sru		return;
1595128160Sru	}
1596138232Sharti
1597138232Sharti	while (isspace((unsigned char)*warnmsg))
1598128160Sru		warnmsg++;
1599138232Sharti
1600142457Sharti	buf = Var_Subst(NULL, warnmsg, VAR_GLOBAL, FALSE);
1601142457Sharti	warnmsg = Buf_GetAll(buf, NULL);
1602128160Sru
1603128160Sru	Parse_Error(PARSE_WARNING, "%s", warnmsg);
1604142457Sharti	Buf_Destroy(buf, TRUE);
1605128160Sru}
1606128160Sru
16071590Srgrimes/*-
16081590Srgrimes *---------------------------------------------------------------------
16091590Srgrimes * ParseDoInclude  --
16101590Srgrimes *	Push to another file.
16118874Srgrimes *
16121590Srgrimes *	The input is the line minus the #include. A file spec is a string
16131590Srgrimes *	enclosed in <> or "". The former is looked for only in sysIncPath.
16141590Srgrimes *	The latter in . and the directories specified by -I command line
16151590Srgrimes *	options
16161590Srgrimes *
16171590Srgrimes * Results:
16181590Srgrimes *	None
16191590Srgrimes *
16201590Srgrimes * Side Effects:
1621126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1622126824Sru *	curFile.fname and curFile.F are altered for the new file
16231590Srgrimes *---------------------------------------------------------------------
16241590Srgrimes */
16251590Srgrimesstatic void
1626141270ShartiParseDoInclude(char *file)
16271590Srgrimes{
16281590Srgrimes    char          *fullname;	/* full pathname of file */
16291590Srgrimes    IFile         *oldFile;	/* state associated with current file */
16301590Srgrimes    char          endc;	    	/* the character which ends the file spec */
16311590Srgrimes    char          *cp;		/* current position in file spec */
16321590Srgrimes    Boolean 	  isSystem; 	/* TRUE if makefile is a system makefile */
1633142457Sharti    Buffer	  *buf;
16341590Srgrimes
16351590Srgrimes    /*
16361590Srgrimes     * Skip to delimiter character so we know where to look
16371590Srgrimes     */
16381590Srgrimes    while ((*file == ' ') || (*file == '\t')) {
16391590Srgrimes	file++;
16401590Srgrimes    }
16411590Srgrimes
16421590Srgrimes    if ((*file != '"') && (*file != '<')) {
1643138232Sharti	Parse_Error(PARSE_FATAL,
16441590Srgrimes	    ".include filename must be delimited by '\"' or '<'");
16451590Srgrimes	return;
16461590Srgrimes    }
16471590Srgrimes
16481590Srgrimes    /*
16491590Srgrimes     * Set the search path on which to find the include file based on the
16501590Srgrimes     * characters which bracket its name. Angle-brackets imply it's
16511590Srgrimes     * a system Makefile while double-quotes imply it's a user makefile
16521590Srgrimes     */
16531590Srgrimes    if (*file == '<') {
16541590Srgrimes	isSystem = TRUE;
16551590Srgrimes	endc = '>';
16561590Srgrimes    } else {
16571590Srgrimes	isSystem = FALSE;
16581590Srgrimes	endc = '"';
16591590Srgrimes    }
16601590Srgrimes
16611590Srgrimes    /*
16621590Srgrimes     * Skip to matching delimiter
16631590Srgrimes     */
16641590Srgrimes    for (cp = ++file; *cp && *cp != endc; cp++) {
16651590Srgrimes	continue;
16661590Srgrimes    }
16671590Srgrimes
16681590Srgrimes    if (*cp != endc) {
1669138232Sharti	Parse_Error(PARSE_FATAL,
16701590Srgrimes		     "Unclosed %cinclude filename. '%c' expected",
16711590Srgrimes		     '.', endc);
16721590Srgrimes	return;
16731590Srgrimes    }
16741590Srgrimes    *cp = '\0';
16751590Srgrimes
16761590Srgrimes    /*
16771590Srgrimes     * Substitute for any variables in the file name before trying to
16781590Srgrimes     * find the thing.
16791590Srgrimes     */
1680142457Sharti    buf = Var_Subst(NULL, file, VAR_CMD, FALSE);
1681142457Sharti    file = Buf_GetAll(buf, NULL);
1682142457Sharti    Buf_Destroy(buf, FALSE);
16831590Srgrimes
16841590Srgrimes    /*
16851590Srgrimes     * Now we know the file's name and its search path, we attempt to
16861590Srgrimes     * find the durn thing. A return of NULL indicates the file don't
16871590Srgrimes     * exist.
16881590Srgrimes     */
16891590Srgrimes    if (!isSystem) {
16901590Srgrimes	/*
16911590Srgrimes	 * Include files contained in double-quotes are first searched for
16921590Srgrimes	 * relative to the including file's location. We don't want to
16931590Srgrimes	 * cd there, of course, so we just tack on the old file's
16941590Srgrimes	 * leading path components and call Dir_FindFile to see if
16951590Srgrimes	 * we can locate the beast.
16961590Srgrimes	 */
169718730Ssteve	char	  *prefEnd, *Fname;
16981590Srgrimes
169918730Ssteve	/* Make a temporary copy of this, to be safe. */
1700126824Sru	Fname = estrdup(curFile.fname);
170118730Ssteve
1702138232Sharti	prefEnd = strrchr(Fname, '/');
17031590Srgrimes	if (prefEnd != (char *)NULL) {
17041590Srgrimes	    char  	*newName;
17058874Srgrimes
17061590Srgrimes	    *prefEnd = '\0';
17075814Sjkh	    if (file[0] == '/')
170818730Ssteve		newName = estrdup(file);
17095814Sjkh	    else
1710138232Sharti		newName = str_concat(Fname, file, STR_ADDSLASH);
1711138916Sharti	    fullname = Dir_FindFile(newName, &parseIncPath);
1712138264Sharti	    if (fullname == NULL) {
1713138916Sharti		fullname = Dir_FindFile(newName, &dirSearchPath);
17141590Srgrimes	    }
1715138232Sharti	    free(newName);
17161590Srgrimes	    *prefEnd = '/';
17171590Srgrimes	} else {
1718138264Sharti	    fullname = NULL;
17191590Srgrimes	}
1720138232Sharti	free(Fname);
17211590Srgrimes    } else {
1722138264Sharti	fullname = NULL;
17231590Srgrimes    }
17241590Srgrimes
1725138264Sharti    if (fullname == NULL) {
17261590Srgrimes	/*
17271590Srgrimes	 * System makefile or makefile wasn't found in same directory as
17281590Srgrimes	 * included makefile. Search for it first on the -I search path,
17291590Srgrimes	 * then on the .PATH search path, if not found in a -I directory.
17301590Srgrimes	 * XXX: Suffix specific?
17311590Srgrimes	 */
1732138916Sharti	fullname = Dir_FindFile(file, &parseIncPath);
1733138264Sharti	if (fullname == NULL) {
1734138916Sharti	    fullname = Dir_FindFile(file, &dirSearchPath);
17351590Srgrimes	}
17361590Srgrimes    }
17371590Srgrimes
1738138264Sharti    if (fullname == NULL) {
17391590Srgrimes	/*
17401590Srgrimes	 * Still haven't found the makefile. Look for it on the system
17411590Srgrimes	 * path as a last resort.
17421590Srgrimes	 */
1743138916Sharti	fullname = Dir_FindFile(file, &sysIncPath);
17441590Srgrimes    }
17451590Srgrimes
1746138264Sharti    if (fullname == NULL) {
17471590Srgrimes	*cp = endc;
1748138232Sharti	Parse_Error(PARSE_FATAL, "Could not find %s", file);
1749142457Sharti	/* XXXHB free(file) */
17501590Srgrimes	return;
17511590Srgrimes    }
17521590Srgrimes
17535814Sjkh    free(file);
17545814Sjkh
17551590Srgrimes    /*
17561590Srgrimes     * Once we find the absolute path to the file, we get to save all the
17571590Srgrimes     * state from the current file before we can start reading this
17581590Srgrimes     * include file. The state is stored in an IFile structure which
17591590Srgrimes     * is placed on a list with other IFile structures. The list makes
17601590Srgrimes     * a very nice stack to track how we got here...
17611590Srgrimes     */
1762141270Sharti    oldFile = emalloc(sizeof(IFile));
1763138264Sharti    memcpy(oldFile, &curFile, sizeof(IFile));
17641590Srgrimes
1765138916Sharti    Lst_AtFront(&includes, oldFile);
17661590Srgrimes
17671590Srgrimes    /*
17681590Srgrimes     * Once the previous state has been saved, we can get down to reading
17691590Srgrimes     * the new file. We set up the name of the file to be the absolute
17701590Srgrimes     * name of the include file so error messages refer to the right
17711590Srgrimes     * place. Naturally enough, we start reading at line number 0.
17721590Srgrimes     */
1773126824Sru    curFile.fname = fullname;
1774126824Sru    curFile.lineno = 0;
17751590Srgrimes
1776138232Sharti    curFile.F = fopen(fullname, "r");
1777126824Sru    curFile.p = NULL;
1778138264Sharti    if (curFile.F == NULL) {
1779138232Sharti	Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
17801590Srgrimes	/*
17811590Srgrimes	 * Pop to previous file
17821590Srgrimes	 */
1783138232Sharti	ParseEOF(0);
1784131456Seik    } else {
1785131456Seik	Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
17861590Srgrimes    }
17871590Srgrimes}
17881590Srgrimes
17891590Srgrimes/*-
17901590Srgrimes *---------------------------------------------------------------------
17911590Srgrimes * Parse_FromString  --
17921590Srgrimes *	Start Parsing from the given string
17938874Srgrimes *
17941590Srgrimes * Results:
17951590Srgrimes *	None
17961590Srgrimes *
17971590Srgrimes * Side Effects:
1798126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1799126824Sru *	curFile.fname and curFile.F are altered for the new file
18001590Srgrimes *---------------------------------------------------------------------
18011590Srgrimes */
18021590Srgrimesvoid
1803126824SruParse_FromString(char *str, int lineno)
18041590Srgrimes{
18051590Srgrimes    IFile         *oldFile;	/* state associated with this file */
18061590Srgrimes
1807126824Sru    DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno));
18081590Srgrimes
1809138264Sharti    oldFile = emalloc(sizeof(IFile));
1810138232Sharti    memcpy(oldFile, &curFile, sizeof(IFile));
18118874Srgrimes
1812138916Sharti    Lst_AtFront(&includes, oldFile);
18131590Srgrimes
1814126824Sru    curFile.F = NULL;
1815141270Sharti    curFile.p = emalloc(sizeof(PTR));
1816126824Sru    curFile.p->str = curFile.p->ptr = str;
1817126824Sru    curFile.lineno = lineno;
1818126824Sru    curFile.fname = estrdup(curFile.fname);
18191590Srgrimes}
18201590Srgrimes
18211590Srgrimes#ifdef SYSVINCLUDE
18221590Srgrimes/*-
18231590Srgrimes *---------------------------------------------------------------------
18241590Srgrimes * ParseTraditionalInclude  --
18251590Srgrimes *	Push to another file.
18268874Srgrimes *
18271590Srgrimes *	The input is the line minus the "include".  The file name is
18281590Srgrimes *	the string following the "include".
18291590Srgrimes *
18301590Srgrimes * Results:
18311590Srgrimes *	None
18321590Srgrimes *
18331590Srgrimes * Side Effects:
1834126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1835126824Sru *	curFile.fname and curFile.F are altered for the new file
18361590Srgrimes *---------------------------------------------------------------------
18371590Srgrimes */
18381590Srgrimesstatic void
1839141270ShartiParseTraditionalInclude(char *file)
18401590Srgrimes{
18411590Srgrimes    char          *fullname;	/* full pathname of file */
18421590Srgrimes    IFile         *oldFile;	/* state associated with current file */
18431590Srgrimes    char          *cp;		/* current position in file spec */
1844142457Sharti    Buffer	  *buf;
18451590Srgrimes
18461590Srgrimes    /*
18471590Srgrimes     * Skip over whitespace
18481590Srgrimes     */
18491590Srgrimes    while ((*file == ' ') || (*file == '\t')) {
18501590Srgrimes	file++;
18511590Srgrimes    }
18521590Srgrimes
18531590Srgrimes    if (*file == '\0') {
1854138232Sharti	Parse_Error(PARSE_FATAL,
18551590Srgrimes		     "Filename missing from \"include\"");
18561590Srgrimes	return;
18571590Srgrimes    }
18581590Srgrimes
18591590Srgrimes    /*
18601590Srgrimes     * Skip to end of line or next whitespace
18611590Srgrimes     */
18621590Srgrimes    for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
18631590Srgrimes	continue;
18641590Srgrimes    }
18651590Srgrimes
18661590Srgrimes    *cp = '\0';
18671590Srgrimes
18681590Srgrimes    /*
18691590Srgrimes     * Substitute for any variables in the file name before trying to
18701590Srgrimes     * find the thing.
18711590Srgrimes     */
1872142457Sharti    buf = Var_Subst(NULL, file, VAR_CMD, FALSE);
1873142457Sharti    file = Buf_GetAll(buf, NULL);
1874142457Sharti    Buf_Destroy(buf, FALSE);
18751590Srgrimes
18761590Srgrimes    /*
18771590Srgrimes     * Now we know the file's name, we attempt to find the durn thing.
1878105754Sjmallett     * Search for it first on the -I search path, then on the .PATH
1879105754Sjmallett     * search path, if not found in a -I directory.
18801590Srgrimes     */
1881138916Sharti    fullname = Dir_FindFile(file, &parseIncPath);
1882138264Sharti    if (fullname == NULL) {
1883138916Sharti        fullname = Dir_FindFile(file, &dirSearchPath);
18841590Srgrimes    }
18851590Srgrimes
1886138264Sharti    if (fullname == NULL) {
18871590Srgrimes	/*
18881590Srgrimes	 * Still haven't found the makefile. Look for it on the system
18891590Srgrimes	 * path as a last resort.
18901590Srgrimes	 */
1891138916Sharti	fullname = Dir_FindFile(file, &sysIncPath);
18921590Srgrimes    }
18931590Srgrimes
1894138264Sharti    if (fullname == NULL) {
1895138232Sharti	Parse_Error(PARSE_FATAL, "Could not find %s", file);
1896142457Sharti	/* XXXHB free(file) */
18971590Srgrimes	return;
18981590Srgrimes    }
18991590Srgrimes
1900142457Sharti    /* XXXHB free(file) */
1901142457Sharti
19021590Srgrimes    /*
19031590Srgrimes     * Once we find the absolute path to the file, we get to save all the
19041590Srgrimes     * state from the current file before we can start reading this
19051590Srgrimes     * include file. The state is stored in an IFile structure which
19061590Srgrimes     * is placed on a list with other IFile structures. The list makes
19071590Srgrimes     * a very nice stack to track how we got here...
19081590Srgrimes     */
1909138264Sharti    oldFile = emalloc(sizeof(IFile));
1910138232Sharti    memcpy(oldFile, &curFile, sizeof(IFile));
19111590Srgrimes
1912138916Sharti    Lst_AtFront(&includes, oldFile);
19131590Srgrimes
19141590Srgrimes    /*
19151590Srgrimes     * Once the previous state has been saved, we can get down to reading
19161590Srgrimes     * the new file. We set up the name of the file to be the absolute
19171590Srgrimes     * name of the include file so error messages refer to the right
19181590Srgrimes     * place. Naturally enough, we start reading at line number 0.
19191590Srgrimes     */
1920126824Sru    curFile.fname = fullname;
1921126824Sru    curFile.lineno = 0;
19221590Srgrimes
1923138232Sharti    curFile.F = fopen(fullname, "r");
1924126824Sru    curFile.p = NULL;
1925138264Sharti    if (curFile.F == NULL) {
1926138232Sharti	Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
19271590Srgrimes	/*
19281590Srgrimes	 * Pop to previous file
19291590Srgrimes	 */
1930138232Sharti	ParseEOF(1);
1931131456Seik    } else {
1932131456Seik	Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
19331590Srgrimes    }
19341590Srgrimes}
19351590Srgrimes#endif
19361590Srgrimes
19371590Srgrimes/*-
19381590Srgrimes *---------------------------------------------------------------------
19391590Srgrimes * ParseEOF  --
19401590Srgrimes *	Called when EOF is reached in the current file. If we were reading
19411590Srgrimes *	an include file, the includes stack is popped and things set up
19421590Srgrimes *	to go back to reading the previous file at the previous location.
19431590Srgrimes *
19441590Srgrimes * Results:
19451590Srgrimes *	CONTINUE if there's more to do. DONE if not.
19461590Srgrimes *
19471590Srgrimes * Side Effects:
1948126824Sru *	The old curFile.F is closed. The includes list is shortened.
1949126824Sru *	curFile.lineno, curFile.F, and curFile.fname are changed if
1950126824Sru *	CONTINUE is returned.
19511590Srgrimes *---------------------------------------------------------------------
19521590Srgrimes */
19531590Srgrimesstatic int
1954138232ShartiParseEOF(int opened)
19551590Srgrimes{
19561590Srgrimes    IFile     *ifile;	/* the state on the top of the includes stack */
19571590Srgrimes
1958138916Sharti    if (Lst_IsEmpty(&includes)) {
1959131456Seik	Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
19601590Srgrimes	return (DONE);
19611590Srgrimes    }
19621590Srgrimes
1963138916Sharti    ifile = Lst_DeQueue(&includes);
1964138232Sharti    free(curFile.fname);
1965131456Seik    if (opened && curFile.F) {
1966138232Sharti	fclose(curFile.F);
1967131456Seik	Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
1968131456Seik    }
1969126824Sru    if (curFile.p) {
1970126824Sru	free(curFile.p->str);
1971126824Sru	free(curFile.p);
19721590Srgrimes    }
1973138232Sharti    memcpy(&curFile, ifile, sizeof(IFile));
1974138232Sharti    free(ifile);
19751590Srgrimes    return (CONTINUE);
19761590Srgrimes}
19771590Srgrimes
19781590Srgrimes/*-
19791590Srgrimes *---------------------------------------------------------------------
19801590Srgrimes * ParseReadc  --
19818874Srgrimes *	Read a character from the current file
19821590Srgrimes *
19831590Srgrimes * Results:
19841590Srgrimes *	The character that was read
19851590Srgrimes *
19861590Srgrimes * Side Effects:
19871590Srgrimes *---------------------------------------------------------------------
19881590Srgrimes */
19891590Srgrimesstatic int
1990104696SjmallettParseReadc(void)
19911590Srgrimes{
1992138232Sharti
1993126824Sru    if (curFile.F)
1994138232Sharti	return (fgetc(curFile.F));
19958874Srgrimes
1996126824Sru    if (curFile.p && *curFile.p->ptr)
1997138232Sharti	return (*curFile.p->ptr++);
1998138232Sharti    return (EOF);
19991590Srgrimes}
20001590Srgrimes
20011590Srgrimes
20021590Srgrimes/*-
20031590Srgrimes *---------------------------------------------------------------------
20041590Srgrimes * ParseUnreadc  --
20058874Srgrimes *	Put back a character to the current file
20061590Srgrimes *
20071590Srgrimes * Results:
20081590Srgrimes *	None.
20091590Srgrimes *
20101590Srgrimes * Side Effects:
20111590Srgrimes *---------------------------------------------------------------------
20121590Srgrimes */
20131590Srgrimesstatic void
2014104696SjmallettParseUnreadc(int c)
20151590Srgrimes{
2016138232Sharti
2017126824Sru    if (curFile.F) {
2018126824Sru	ungetc(c, curFile.F);
20191590Srgrimes	return;
20201590Srgrimes    }
2021126824Sru    if (curFile.p) {
2022126824Sru	*--(curFile.p->ptr) = c;
20231590Srgrimes	return;
20241590Srgrimes    }
20251590Srgrimes}
20261590Srgrimes
20271590Srgrimes
20281590Srgrimes/* ParseSkipLine():
2029104696Sjmallett *	Grab the next line unless it begins with a dot (`.') and we're told to
2030104696Sjmallett *	ignore such lines.
20311590Srgrimes */
20321590Srgrimesstatic char *
2033126824SruParseSkipLine(int skip, int keep_newline)
20341590Srgrimes{
20351590Srgrimes    char *line;
2036138346Sharti    int c, lastc;
2037141133Sharti    Buffer *buf;
20381590Srgrimes
203918456Ssteve    buf = Buf_Init(MAKE_BSIZE);
20401590Srgrimes
204118456Ssteve    do {
2042141275Sharti        Buf_Clear(buf);
204318456Ssteve        lastc = '\0';
20448874Srgrimes
204518456Ssteve        while (((c = ParseReadc()) != '\n' || lastc == '\\')
204618456Ssteve               && c != EOF) {
2047132540Sharti            if (skip && c == '#' && lastc != '\\') {
2048132540Sharti		/* let a comment be terminated even by an escaped \n.
2049132540Sharti		 * This is consistent to comment handling in ParseReadLine */
2050132540Sharti                while ((c = ParseReadc()) != '\n' && c != EOF)
2051132540Sharti		    ;
2052132540Sharti		break;
2053132540Sharti	    }
205474293Swill            if (c == '\n') {
2055126824Sru                if (keep_newline)
2056126824Sru                    Buf_AddByte(buf, (Byte)c);
2057126824Sru                else
2058126824Sru                    Buf_ReplaceLastByte(buf, (Byte)' ');
2059126824Sru                curFile.lineno++;
20608874Srgrimes
2061104108Sjmallett                while ((c = ParseReadc()) == ' ' || c == '\t')
2062104108Sjmallett		    continue;
20638874Srgrimes
206474293Swill                if (c == EOF)
206574293Swill                    break;
206674293Swill            }
206774272Swill
206874293Swill            Buf_AddByte(buf, (Byte)c);
206974293Swill            lastc = c;
207018456Ssteve        }
207118456Ssteve
207218456Ssteve        if (c == EOF) {
207318456Ssteve            Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
207418456Ssteve            Buf_Destroy(buf, TRUE);
2075138264Sharti            return (NULL);
207618456Ssteve        }
207718456Ssteve
2078126824Sru        curFile.lineno++;
207918456Ssteve        Buf_AddByte(buf, (Byte)'\0');
2080141291Sharti        line = (char *)Buf_GetAll(buf, NULL);
208118456Ssteve    } while (skip == 1 && line[0] != '.');
208218456Ssteve
208318456Ssteve    Buf_Destroy(buf, FALSE);
2084138232Sharti    return (line);
20851590Srgrimes}
20861590Srgrimes
20871590Srgrimes
20881590Srgrimes/*-
20891590Srgrimes *---------------------------------------------------------------------
20901590Srgrimes * ParseReadLine --
20911590Srgrimes *	Read an entire line from the input file. Called only by Parse_File.
20921590Srgrimes *	To facilitate escaped newlines and what have you, a character is
20931590Srgrimes *	buffered in 'lastc', which is '\0' when no characters have been
20941590Srgrimes *	read. When we break out of the loop, c holds the terminating
20951590Srgrimes *	character and lastc holds a character that should be added to
20961590Srgrimes *	the line (unless we don't read anything but a terminator).
20971590Srgrimes *
20981590Srgrimes * Results:
20991590Srgrimes *	A line w/o its newline
21001590Srgrimes *
21011590Srgrimes * Side Effects:
21021590Srgrimes *	Only those associated with reading a character
21031590Srgrimes *---------------------------------------------------------------------
21041590Srgrimes */
21051590Srgrimesstatic char *
2106138232ShartiParseReadLine(void)
21071590Srgrimes{
2108141133Sharti    Buffer  	  *buf;	    	/* Buffer for current line */
210994584Sobrien    int		  c;	      	/* the current character */
211094584Sobrien    int		  lastc;    	/* The most-recent character */
21111590Srgrimes    Boolean	  semiNL;     	/* treat semi-colons as newlines */
21121590Srgrimes    Boolean	  ignDepOp;   	/* TRUE if should ignore dependency operators
21131590Srgrimes				 * for the purposes of setting semiNL */
21141590Srgrimes    Boolean 	  ignComment;	/* TRUE if should ignore comments (in a
21151590Srgrimes				 * shell command */
21165814Sjkh    char 	  *line;    	/* Result */
21175814Sjkh    char          *ep;		/* to strip trailing blanks */
2118126824Sru    int		  lineno;	/* Saved line # */
21191590Srgrimes
21201590Srgrimes    semiNL = FALSE;
21211590Srgrimes    ignDepOp = FALSE;
21221590Srgrimes    ignComment = FALSE;
21231590Srgrimes
21241590Srgrimes    /*
21251590Srgrimes     * Handle special-characters at the beginning of the line. Either a
21261590Srgrimes     * leading tab (shell command) or pound-sign (possible conditional)
21271590Srgrimes     * forces us to ignore comments and dependency operators and treat
21281590Srgrimes     * semi-colons as semi-colons (by leaving semiNL FALSE). This also
21291590Srgrimes     * discards completely blank lines.
21301590Srgrimes     */
21311590Srgrimes    for (;;) {
21321590Srgrimes	c = ParseReadc();
21331590Srgrimes
21341590Srgrimes	if (c == '\t') {
21351590Srgrimes	    ignComment = ignDepOp = TRUE;
21361590Srgrimes	    break;
21371590Srgrimes	} else if (c == '\n') {
2138126824Sru	    curFile.lineno++;
21391590Srgrimes	} else if (c == '#') {
21401590Srgrimes	    ParseUnreadc(c);
21411590Srgrimes	    break;
21421590Srgrimes	} else {
21431590Srgrimes	    /*
21441590Srgrimes	     * Anything else breaks out without doing anything
21451590Srgrimes	     */
21461590Srgrimes	    break;
21471590Srgrimes	}
21481590Srgrimes    }
21498874Srgrimes
21501590Srgrimes    if (c != EOF) {
21511590Srgrimes	lastc = c;
21521590Srgrimes	buf = Buf_Init(MAKE_BSIZE);
21538874Srgrimes
2154138232Sharti	while (((c = ParseReadc()) != '\n' || (lastc == '\\')) &&
21551590Srgrimes	       (c != EOF))
21561590Srgrimes	{
21571590Srgrimestest_char:
2158138232Sharti	    switch (c) {
21591590Srgrimes	    case '\n':
21601590Srgrimes		/*
21611590Srgrimes		 * Escaped newline: read characters until a non-space or an
21621590Srgrimes		 * unescaped newline and replace them all by a single space.
21631590Srgrimes		 * This is done by storing the space over the backslash and
21641590Srgrimes		 * dropping through with the next nonspace. If it is a
21651590Srgrimes		 * semi-colon and semiNL is TRUE, it will be recognized as a
21661590Srgrimes		 * newline in the code below this...
21671590Srgrimes		 */
2168126824Sru		curFile.lineno++;
21691590Srgrimes		lastc = ' ';
2170138232Sharti		while ((c = ParseReadc()) == ' ' || c == '\t') {
21711590Srgrimes		    continue;
21721590Srgrimes		}
21731590Srgrimes		if (c == EOF || c == '\n') {
21741590Srgrimes		    goto line_read;
21751590Srgrimes		} else {
21761590Srgrimes		    /*
21771590Srgrimes		     * Check for comments, semiNL's, etc. -- easier than
21781590Srgrimes		     * ParseUnreadc(c); continue;
21791590Srgrimes		     */
21801590Srgrimes		    goto test_char;
21811590Srgrimes		}
21821590Srgrimes		/*NOTREACHED*/
21831590Srgrimes		break;
21841590Srgrimes
21851590Srgrimes	    case ';':
21861590Srgrimes		/*
21871590Srgrimes		 * Semi-colon: Need to see if it should be interpreted as a
21881590Srgrimes		 * newline
21891590Srgrimes		 */
21901590Srgrimes		if (semiNL) {
21911590Srgrimes		    /*
21921590Srgrimes		     * To make sure the command that may be following this
21931590Srgrimes		     * semi-colon begins with a tab, we push one back into the
21941590Srgrimes		     * input stream. This will overwrite the semi-colon in the
21951590Srgrimes		     * buffer. If there is no command following, this does no
21961590Srgrimes		     * harm, since the newline remains in the buffer and the
21971590Srgrimes		     * whole line is ignored.
21981590Srgrimes		     */
21991590Srgrimes		    ParseUnreadc('\t');
22001590Srgrimes		    goto line_read;
22018874Srgrimes		}
22021590Srgrimes		break;
22031590Srgrimes	    case '=':
22041590Srgrimes		if (!semiNL) {
22051590Srgrimes		    /*
22061590Srgrimes		     * Haven't seen a dependency operator before this, so this
22071590Srgrimes		     * must be a variable assignment -- don't pay attention to
22081590Srgrimes		     * dependency operators after this.
22091590Srgrimes		     */
22101590Srgrimes		    ignDepOp = TRUE;
22111590Srgrimes		} else if (lastc == ':' || lastc == '!') {
22121590Srgrimes		    /*
22131590Srgrimes		     * Well, we've seen a dependency operator already, but it
22141590Srgrimes		     * was the previous character, so this is really just an
22151590Srgrimes		     * expanded variable assignment. Revert semi-colons to
22161590Srgrimes		     * being just semi-colons again and ignore any more
22171590Srgrimes		     * dependency operators.
22181590Srgrimes		     *
22191590Srgrimes		     * XXX: Note that a line like "foo : a:=b" will blow up,
22201590Srgrimes		     * but who'd write a line like that anyway?
22211590Srgrimes		     */
2222138232Sharti		    ignDepOp = TRUE;
2223138232Sharti		    semiNL = FALSE;
22241590Srgrimes		}
22251590Srgrimes		break;
22261590Srgrimes	    case '#':
22271590Srgrimes		if (!ignComment) {
2228104374Sjmallett		    if (lastc != '\\') {
22291590Srgrimes			/*
22301590Srgrimes			 * If the character is a hash mark and it isn't escaped
22311590Srgrimes			 * (or we're being compatible), the thing is a comment.
22321590Srgrimes			 * Skip to the end of the line.
22331590Srgrimes			 */
22341590Srgrimes			do {
22351590Srgrimes			    c = ParseReadc();
22361590Srgrimes			} while ((c != '\n') && (c != EOF));
22371590Srgrimes			goto line_read;
22381590Srgrimes		    } else {
22391590Srgrimes			/*
22401590Srgrimes			 * Don't add the backslash. Just let the # get copied
22411590Srgrimes			 * over.
22421590Srgrimes			 */
22431590Srgrimes			lastc = c;
22441590Srgrimes			continue;
22451590Srgrimes		    }
22461590Srgrimes		}
22471590Srgrimes		break;
22481590Srgrimes	    case ':':
22491590Srgrimes	    case '!':
22501590Srgrimes		if (!ignDepOp && (c == ':' || c == '!')) {
22511590Srgrimes		    /*
22521590Srgrimes		     * A semi-colon is recognized as a newline only on
22531590Srgrimes		     * dependency lines. Dependency lines are lines with a
22541590Srgrimes		     * colon or an exclamation point. Ergo...
22551590Srgrimes		     */
22561590Srgrimes		    semiNL = TRUE;
22571590Srgrimes		}
22581590Srgrimes		break;
2259104108Sjmallett	    default:
2260104108Sjmallett		break;
22611590Srgrimes	    }
22621590Srgrimes	    /*
22631590Srgrimes	     * Copy in the previous character and save this one in lastc.
22641590Srgrimes	     */
2265138232Sharti	    Buf_AddByte(buf, (Byte)lastc);
22661590Srgrimes	    lastc = c;
22678874Srgrimes
22681590Srgrimes	}
22691590Srgrimes    line_read:
2270126824Sru	curFile.lineno++;
22718874Srgrimes
22721590Srgrimes	if (lastc != '\0') {
2273138232Sharti	    Buf_AddByte(buf, (Byte)lastc);
22741590Srgrimes	}
2275138232Sharti	Buf_AddByte(buf, (Byte)'\0');
2276141291Sharti	line = (char *)Buf_GetAll(buf, NULL);
2277138232Sharti	Buf_Destroy(buf, FALSE);
22785814Sjkh
22795814Sjkh	/*
22805814Sjkh	 * Strip trailing blanks and tabs from the line.
228172645Sasmodai	 * Do not strip a blank or tab that is preceded by
22825814Sjkh	 * a '\'
22835814Sjkh	 */
22845814Sjkh	ep = line;
22855814Sjkh	while (*ep)
22865814Sjkh	    ++ep;
22879298Sache	while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
228818730Ssteve	    if (ep > line + 1 && ep[-2] == '\\')
22895814Sjkh		break;
22905814Sjkh	    --ep;
22915814Sjkh	}
22925814Sjkh	*ep = 0;
22938874Srgrimes
22941590Srgrimes	if (line[0] == '.') {
22951590Srgrimes	    /*
22961590Srgrimes	     * The line might be a conditional. Ask the conditional module
22971590Srgrimes	     * about it and act accordingly
22981590Srgrimes	     */
2299138232Sharti	    switch (Cond_Eval(line)) {
23001590Srgrimes	    case COND_SKIP:
23011590Srgrimes		/*
23021590Srgrimes		 * Skip to next conditional that evaluates to COND_PARSE.
23031590Srgrimes		 */
23041590Srgrimes		do {
2305138232Sharti		    free(line);
2306126824Sru		    line = ParseSkipLine(1, 0);
23071590Srgrimes		} while (line && Cond_Eval(line) != COND_PARSE);
23081590Srgrimes		if (line == NULL)
23091590Srgrimes		    break;
23101590Srgrimes		/*FALLTHRU*/
23111590Srgrimes	    case COND_PARSE:
2312138232Sharti		free(line);
23131590Srgrimes		line = ParseReadLine();
23141590Srgrimes		break;
23151590Srgrimes	    case COND_INVALID:
23161590Srgrimes		if (For_Eval(line)) {
23171590Srgrimes		    int ok;
23181590Srgrimes		    free(line);
2319126824Sru		    lineno = curFile.lineno;
23201590Srgrimes		    do {
23211590Srgrimes			/*
23221590Srgrimes			 * Skip after the matching end
23231590Srgrimes			 */
2324126824Sru			line = ParseSkipLine(0, 1);
23251590Srgrimes			if (line == NULL) {
2326138232Sharti			    Parse_Error(PARSE_FATAL,
23271590Srgrimes				     "Unexpected end of file in for loop.\n");
23281590Srgrimes			    break;
23291590Srgrimes			}
23301590Srgrimes			ok = For_Eval(line);
23311590Srgrimes			free(line);
23321590Srgrimes		    }
23331590Srgrimes		    while (ok);
23341590Srgrimes		    if (line != NULL)
2335126824Sru			For_Run(lineno);
23361590Srgrimes		    line = ParseReadLine();
23371590Srgrimes		}
23381590Srgrimes		break;
2339104108Sjmallett	    default:
2340104108Sjmallett		break;
23411590Srgrimes	    }
23421590Srgrimes	}
23431590Srgrimes	return (line);
23441590Srgrimes
23451590Srgrimes    } else {
23461590Srgrimes	/*
23471590Srgrimes	 * Hit end-of-file, so return a NULL line to indicate this.
23481590Srgrimes	 */
2349138264Sharti	return (NULL);
23501590Srgrimes    }
23511590Srgrimes}
23521590Srgrimes
23531590Srgrimes/*-
23541590Srgrimes *-----------------------------------------------------------------------
23551590Srgrimes * ParseFinishLine --
23561590Srgrimes *	Handle the end of a dependency group.
23571590Srgrimes *
23581590Srgrimes * Results:
23591590Srgrimes *	Nothing.
23601590Srgrimes *
23611590Srgrimes * Side Effects:
23621590Srgrimes *	inLine set FALSE. 'targets' list destroyed.
23631590Srgrimes *
23641590Srgrimes *-----------------------------------------------------------------------
23651590Srgrimes */
23661590Srgrimesstatic void
2367104696SjmallettParseFinishLine(void)
23681590Srgrimes{
2369138232Sharti
23701590Srgrimes    if (inLine) {
2371138916Sharti	Lst_ForEach(&targets, Suff_EndTransform, NULL);
2372138916Sharti	Lst_Destroy(&targets, ParseHasCommands);
23731590Srgrimes	inLine = FALSE;
23741590Srgrimes    }
23751590Srgrimes}
23761590Srgrimes
23778874Srgrimes
23781590Srgrimes/*-
23791590Srgrimes *---------------------------------------------------------------------
23801590Srgrimes * Parse_File --
23811590Srgrimes *	Parse a file into its component parts, incorporating it into the
23821590Srgrimes *	current dependency graph. This is the main function and controls
23831590Srgrimes *	almost every other function in this module
23841590Srgrimes *
23851590Srgrimes * Results:
23861590Srgrimes *	None
23871590Srgrimes *
23881590Srgrimes * Side Effects:
23891590Srgrimes *	Loads. Nodes are added to the list of all targets, nodes and links
23901590Srgrimes *	are added to the dependency graph. etc. etc. etc.
23911590Srgrimes *---------------------------------------------------------------------
23921590Srgrimes */
23931590Srgrimesvoid
2394104696SjmallettParse_File(char *name, FILE *stream)
23951590Srgrimes{
239694584Sobrien    char	  *cp,		/* pointer into the line */
23971590Srgrimes                  *line;	/* the line we're working on */
2398142457Sharti    Buffer	  *buf;
23991590Srgrimes
24001590Srgrimes    inLine = FALSE;
2401126824Sru    curFile.fname = name;
2402126824Sru    curFile.F = stream;
2403126824Sru    curFile.lineno = 0;
24041590Srgrimes    fatals = 0;
24051590Srgrimes
2406131456Seik    Var_Append(".MAKEFILE_LIST", name, VAR_GLOBAL);
2407131456Seik
24081590Srgrimes    do {
2409138232Sharti	while ((line = ParseReadLine()) != NULL) {
24101590Srgrimes	    if (*line == '.') {
24111590Srgrimes		/*
24121590Srgrimes		 * Lines that begin with the special character are either
24131590Srgrimes		 * include or undef directives.
24141590Srgrimes		 */
2415138232Sharti		for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
24161590Srgrimes		    continue;
24171590Srgrimes		}
2418138232Sharti		if (strncmp(cp, "include", 7) == 0) {
2419141270Sharti		    ParseDoInclude(cp + 7);
24201590Srgrimes		    goto nextLine;
2421138232Sharti		} else if (strncmp(cp, "error", 5) == 0) {
242236347Ssteve		    ParseDoError(cp + 5);
2423138232Sharti	            goto nextLine;
2424138232Sharti		} else if (strncmp(cp, "warning", 7) == 0) {
2425128160Sru		    ParseDoWarning(cp + 7);
2426138232Sharti	            goto nextLine;
24271590Srgrimes		} else if (strncmp(cp, "undef", 5) == 0) {
24281590Srgrimes		    char *cp2;
2429138232Sharti		    for (cp += 5; isspace((unsigned char)*cp); cp++) {
24301590Srgrimes			continue;
24311590Srgrimes		    }
24321590Srgrimes
2433138232Sharti		    for (cp2 = cp; !isspace((unsigned char)*cp2) &&
24345814Sjkh				   (*cp2 != '\0'); cp2++) {
24351590Srgrimes			continue;
24361590Srgrimes		    }
24371590Srgrimes
24381590Srgrimes		    *cp2 = '\0';
24391590Srgrimes
2440142457Sharti		    buf = Var_Subst(NULL, cp, VAR_CMD, FALSE);
2441142457Sharti		    cp = Buf_GetAll(buf, NULL);
2442142457Sharti		    Buf_Destroy(buf, FALSE);
2443142457Sharti
24441590Srgrimes		    Var_Delete(cp, VAR_GLOBAL);
24451590Srgrimes		    goto nextLine;
24461590Srgrimes		}
24471590Srgrimes	    }
24489298Sache	    if (*line == '#') {
24491590Srgrimes		/* If we're this far, the line must be a comment. */
24501590Srgrimes		goto nextLine;
24511590Srgrimes	    }
24528874Srgrimes
24535814Sjkh	    if (*line == '\t') {
24541590Srgrimes		/*
24555814Sjkh		 * If a line starts with a tab, it can only hope to be
24565814Sjkh		 * a creation command.
24571590Srgrimes		 */
2458138232Sharti		for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
24591590Srgrimes		    continue;
24601590Srgrimes		}
24611590Srgrimes		if (*cp) {
24621590Srgrimes		    if (inLine) {
24631590Srgrimes			/*
24641590Srgrimes			 * So long as it's not a blank line and we're actually
24651590Srgrimes			 * in a dependency spec, add the command to the list of
24668874Srgrimes			 * commands of all targets in the dependency spec
24671590Srgrimes			 */
2468138916Sharti			Lst_ForEach(&targets, ParseAddCmd, cp);
24691590Srgrimes			continue;
24701590Srgrimes		    } else {
2471138232Sharti			Parse_Error(PARSE_FATAL,
247218730Ssteve				     "Unassociated shell command \"%s\"",
24731590Srgrimes				     cp);
24741590Srgrimes		    }
24751590Srgrimes		}
24761590Srgrimes#ifdef SYSVINCLUDE
2477138232Sharti	    } else if (strncmp(line, "include", 7) == 0 &&
2478138232Sharti		       isspace((unsigned char)line[7]) &&
24791590Srgrimes		       strchr(line, ':') == NULL) {
24801590Srgrimes		/*
24811590Srgrimes		 * It's an S3/S5-style "include".
24821590Srgrimes		 */
2483138232Sharti		ParseTraditionalInclude(line + 7);
24841590Srgrimes		goto nextLine;
24851590Srgrimes#endif
2486138232Sharti	    } else if (Parse_IsVar(line)) {
24871590Srgrimes		ParseFinishLine();
2488138232Sharti		Parse_DoVar(line, VAR_GLOBAL);
24891590Srgrimes	    } else {
24901590Srgrimes		/*
24911590Srgrimes		 * We now know it's a dependency line so it needs to have all
24921590Srgrimes		 * variables expanded before being parsed. Tell the variable
24931590Srgrimes		 * module to complain if some variable is undefined...
24941590Srgrimes		 * To make life easier on novices, if the line is indented we
24951590Srgrimes		 * first make sure the line has a dependency operator in it.
24961590Srgrimes		 * If it doesn't have an operator and we're in a dependency
24971590Srgrimes		 * line's script, we assume it's actually a shell command
24981590Srgrimes		 * and add it to the current list of targets.
24991590Srgrimes		 */
25001590Srgrimes		cp = line;
2501138232Sharti		if (isspace((unsigned char)line[0])) {
2502138232Sharti		    while ((*cp != '\0') && isspace((unsigned char)*cp)) {
25035814Sjkh			cp++;
25045814Sjkh		    }
25055814Sjkh		    if (*cp == '\0') {
25065814Sjkh			goto nextLine;
25075814Sjkh		    }
25081590Srgrimes		}
25098874Srgrimes
2510137810Sharti		ParseFinishLine();
25111590Srgrimes
2512142457Sharti		buf = Var_Subst(NULL, line, VAR_CMD, TRUE);
2513142457Sharti		cp = Buf_GetAll(buf, NULL);
2514142457Sharti		Buf_Destroy(buf, FALSE);
2515142457Sharti
2516138232Sharti		free(line);
2517137810Sharti		line = cp;
25188874Srgrimes
2519137810Sharti		/*
2520137810Sharti		 * Need a non-circular list for the target nodes
2521137810Sharti		 */
2522138916Sharti		Lst_Destroy(&targets, NOFREE);
2523137810Sharti		inLine = TRUE;
25248874Srgrimes
2525141270Sharti		ParseDoDependency(line);
25261590Srgrimes	    }
25271590Srgrimes
25281590Srgrimes	    nextLine:
25291590Srgrimes
2530138232Sharti	    free(line);
25311590Srgrimes	}
25321590Srgrimes	/*
25338874Srgrimes	 * Reached EOF, but it may be just EOF of an include file...
25341590Srgrimes	 */
25351590Srgrimes    } while (ParseEOF(1) == CONTINUE);
25361590Srgrimes
25371590Srgrimes    /*
25381590Srgrimes     * Make sure conditionals are clean
25391590Srgrimes     */
25401590Srgrimes    Cond_End();
25411590Srgrimes
254227644Scharnier    if (fatals)
254327644Scharnier	errx(1, "fatal errors encountered -- cannot continue");
25441590Srgrimes}
25451590Srgrimes
25461590Srgrimes/*-
25471590Srgrimes *---------------------------------------------------------------------
25481590Srgrimes * Parse_Init --
25491590Srgrimes *	initialize the parsing module
25501590Srgrimes *
25511590Srgrimes * Results:
25521590Srgrimes *	none
25531590Srgrimes *
25541590Srgrimes * Side Effects:
25551590Srgrimes *	the parseIncPath list is initialized...
25561590Srgrimes *---------------------------------------------------------------------
25571590Srgrimes */
25581590Srgrimesvoid
2559138232ShartiParse_Init(void)
25601590Srgrimes{
2561138232Sharti
256269527Swill    mainNode = NULL;
25631590Srgrimes}
25641590Srgrimes
25651590Srgrimes/*-
25661590Srgrimes *-----------------------------------------------------------------------
25671590Srgrimes * Parse_MainName --
25681590Srgrimes *	Return a Lst of the main target to create for main()'s sake. If
25691590Srgrimes *	no such target exists, we Punt with an obnoxious error message.
25701590Srgrimes *
25711590Srgrimes * Results:
25721590Srgrimes *	A Lst of the single node to create.
25731590Srgrimes *
25741590Srgrimes * Side Effects:
25751590Srgrimes *	None.
25761590Srgrimes *
25771590Srgrimes *-----------------------------------------------------------------------
25781590Srgrimes */
2579138916Shartivoid
2580138916ShartiParse_MainName(Lst *listmain)
25811590Srgrimes{
25821590Srgrimes
258369527Swill    if (mainNode == NULL) {
2584138232Sharti	Punt("no target to make.");
25851590Srgrimes    	/*NOTREACHED*/
25861590Srgrimes    } else if (mainNode->type & OP_DOUBLEDEP) {
2587138264Sharti	Lst_AtEnd(listmain, mainNode);
2588138916Sharti	Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW);
25891590Srgrimes    }
25901590Srgrimes    else
2591138264Sharti	Lst_AtEnd(listmain, mainNode);
25921590Srgrimes}
2593