parse.c revision 144026
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 144026 2005-03-23 16:14:41Z 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:
63144026Sharti *	Parse_Init	Initialization function which must be
64144026Sharti *			called before anything else in this module is used.
651590Srgrimes *
66144026Sharti *	Parse_File	Function used to parse a makefile. It must
67144026Sharti *			be given the name of the file, which should
68144026Sharti *			already have been opened, and a function
69144026Sharti *			to call to read a character from the file.
701590Srgrimes *
71144026Sharti *	Parse_IsVar	Returns TRUE if the given line is a
72144026Sharti *			variable assignment. Used by MainParseArgs
73144026Sharti *			to determine if an argument is a target
74144026Sharti *			or a variable assignment. Used internally
75144026Sharti *			for pretty much the same thing...
761590Srgrimes *
77144026Sharti *	Parse_Error	Function called when an error occurs in
78144026Sharti *			parsing. Used by the variable and
79144026Sharti *			conditional modules.
80144026Sharti *
81144026Sharti *	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
120144026Sharti/* true if currently in a dependency line or its commands */
121144026Shartistatic Boolean inLine;
1221590Srgrimes
123144026Shartistatic int fatals = 0;
1241590Srgrimes
125144026Sharti/*
126144026Sharti * The main target to create. This is the first target on the
127144026Sharti * first dependency line in the first makefile.
128144026Sharti */
129144026Shartistatic GNode *mainNode;
130126824Sru
131144026ShartiIFile curFile;			/* current makefile */
132144026Sharti
133138916Sharti/* stack of IFiles generated by * #includes */
134138916Shartistatic Lst includes = Lst_Initializer(includes);
1351590Srgrimes
136138916Sharti/* list of directories for "..." includes */
137144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath);
138138916Sharti
139138916Sharti/* list of directories for <...> includes */
140144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath);
141138916Sharti
142144026Sharti/*
1431590Srgrimes * specType contains the SPECial TYPE of the current target. It is
1441590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children
1451590Srgrimes * are linked as children of the parent but not vice versa. This variable is
1461590Srgrimes * set in ParseDoDependency
1471590Srgrimes */
1481590Srgrimestypedef enum {
149144026Sharti	Begin,		/* .BEGIN */
150144026Sharti	Default,	/* .DEFAULT */
151144026Sharti	End,		/* .END */
152144026Sharti	Ignore,		/* .IGNORE */
153144026Sharti	Includes,	/* .INCLUDES */
154144026Sharti	Interrupt,	/* .INTERRUPT */
155144026Sharti	Libs,		/* .LIBS */
156144026Sharti	MFlags,		/* .MFLAGS or .MAKEFLAGS */
157144026Sharti	Main,		/* .MAIN and we don't have anyth. user-spec. to make */
158144026Sharti	NoExport,	/* .NOEXPORT */
159144026Sharti	Not,		/* Not special */
160144026Sharti	NotParallel,	/* .NOTPARALELL */
161144026Sharti	Null,		/* .NULL */
162144026Sharti	Order,		/* .ORDER */
163144026Sharti	Parallel,	/* .PARALLEL */
164144026Sharti	ExPath,		/* .PATH */
165144026Sharti	Phony,		/* .PHONY */
166144026Sharti	Posix,		/* .POSIX */
167144026Sharti	Precious,	/* .PRECIOUS */
168144026Sharti	ExShell,	/* .SHELL */
169144026Sharti	Silent,		/* .SILENT */
170144026Sharti	SingleShell,	/* .SINGLESHELL */
171144026Sharti	Suffixes,	/* .SUFFIXES */
172144026Sharti	Wait,		/* .WAIT */
173144026Sharti	Attribute	/* Generic attribute */
1741590Srgrimes} ParseSpecial;
1751590Srgrimes
1761590Srgrimesstatic ParseSpecial specType;
17718730Sstevestatic int waiting;
1781590Srgrimes
1791590Srgrimes/*
18069527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1811590Srgrimes * seen, then set to each successive source on the line.
1821590Srgrimes */
183144026Shartistatic GNode *predecessor;
1841590Srgrimes
1851590Srgrimes/*
1861590Srgrimes * The parseKeywords table is searched using binary search when deciding
1871590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial
1881590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while
1891590Srgrimes * the 'op' field is the operator to apply to the list of targets if the
1901590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source)
1911590Srgrimes */
1921590Srgrimesstatic struct {
193144026Sharti	const char	*name;	/* Name of keyword */
194144026Sharti	ParseSpecial	spec;	/* Type when used as a target */
195144026Sharti	int		op;	/* Operator when used as a source */
1961590Srgrimes} parseKeywords[] = {
197144026Sharti	{ ".BEGIN",		Begin,		0 },
198144026Sharti	{ ".DEFAULT",		Default,	0 },
199144026Sharti	{ ".END",		End,		0 },
200144026Sharti	{ ".EXEC",		Attribute,	OP_EXEC },
201144026Sharti	{ ".IGNORE",		Ignore,		OP_IGNORE },
202144026Sharti	{ ".INCLUDES",		Includes,	0 },
203144026Sharti	{ ".INTERRUPT",		Interrupt,	0 },
204144026Sharti	{ ".INVISIBLE",		Attribute,	OP_INVISIBLE },
205144026Sharti	{ ".JOIN",		Attribute,	OP_JOIN },
206144026Sharti	{ ".LIBS",		Libs,		0 },
207144026Sharti	{ ".MAIN",		Main,		0 },
208144026Sharti	{ ".MAKE",		Attribute,	OP_MAKE },
209144026Sharti	{ ".MAKEFLAGS",		MFlags,		0 },
210144026Sharti	{ ".MFLAGS",		MFlags,		0 },
211144026Sharti	{ ".NOTMAIN",		Attribute,	OP_NOTMAIN },
212144026Sharti	{ ".NOTPARALLEL",	NotParallel,	0 },
213144026Sharti	{ ".NO_PARALLEL",	NotParallel,	0 },
214144026Sharti	{ ".NULL",		Null,		0 },
215144026Sharti	{ ".OPTIONAL",		Attribute,	OP_OPTIONAL },
216144026Sharti	{ ".ORDER",		Order,		0 },
217144026Sharti	{ ".PARALLEL",		Parallel,	0 },
218144026Sharti	{ ".PATH",		ExPath,		0 },
219144026Sharti	{ ".PHONY",		Phony,		OP_PHONY },
220144026Sharti	{ ".POSIX",		Posix,		0 },
221144026Sharti	{ ".PRECIOUS",		Precious,	OP_PRECIOUS },
222144026Sharti	{ ".RECURSIVE",		Attribute,	OP_MAKE },
223144026Sharti	{ ".SHELL",		ExShell,	0 },
224144026Sharti	{ ".SILENT",		Silent,		OP_SILENT },
225144026Sharti	{ ".SINGLESHELL",	SingleShell,	0 },
226144026Sharti	{ ".SUFFIXES",		Suffixes,	0 },
227144026Sharti	{ ".USE",		Attribute,	OP_USE },
228144026Sharti	{ ".WAIT",		Wait,		0 },
2291590Srgrimes};
2301590Srgrimes
23192921Simpstatic int ParseEOF(int);
2321590Srgrimes
2331590Srgrimes/*-
2341590Srgrimes *----------------------------------------------------------------------
2351590Srgrimes * ParseFindKeyword --
2361590Srgrimes *	Look in the table of keywords for one matching the given string.
2371590Srgrimes *
2381590Srgrimes * Results:
2391590Srgrimes *	The index of the keyword, or -1 if it isn't there.
2401590Srgrimes *
2411590Srgrimes * Side Effects:
2421590Srgrimes *	None
2431590Srgrimes *----------------------------------------------------------------------
2441590Srgrimes */
2451590Srgrimesstatic int
246138232ShartiParseFindKeyword(char *str)
2471590Srgrimes{
248144026Sharti	int	start;
249144026Sharti	int	end;
250144026Sharti	int	cur;
251144026Sharti	int	diff;
2528874Srgrimes
253144026Sharti	start = 0;
254144026Sharti	end = (sizeof(parseKeywords) / sizeof(parseKeywords[0])) - 1;
2551590Srgrimes
256144026Sharti	do {
257144026Sharti		cur = start + (end - start) / 2;
258144026Sharti		diff = strcmp(str, parseKeywords[cur].name);
259144026Sharti		if (diff == 0) {
260144026Sharti			return (cur);
261144026Sharti		} else if (diff < 0) {
262144026Sharti			end = cur - 1;
263144026Sharti		} else {
264144026Sharti			start = cur + 1;
265144026Sharti		}
266144026Sharti	} while (start <= end);
2671590Srgrimes
268144026Sharti	return (-1);
2691590Srgrimes}
2701590Srgrimes
2711590Srgrimes/*-
2721590Srgrimes * Parse_Error  --
2731590Srgrimes *	Error message abort function for parsing. Prints out the context
2741590Srgrimes *	of the error (line number and file) as well as the message with
2751590Srgrimes *	two optional arguments.
2761590Srgrimes *
2771590Srgrimes * Results:
2781590Srgrimes *	None
2791590Srgrimes *
2801590Srgrimes * Side Effects:
2811590Srgrimes *	"fatals" is incremented if the level is PARSE_FATAL.
2821590Srgrimes */
2831590Srgrimes/* VARARGS */
2841590Srgrimesvoid
28598136SjmallettParse_Error(int type, const char *fmt, ...)
2861590Srgrimes{
2871590Srgrimes	va_list ap;
28893056Simp
2891590Srgrimes	va_start(ap, fmt);
290138232Sharti	fprintf(stderr, "\"%s\", line %d: ",
291126824Sru	    curFile.fname, curFile.lineno);
2921590Srgrimes	if (type == PARSE_WARNING)
293138232Sharti		fprintf(stderr, "warning: ");
294138232Sharti	vfprintf(stderr, fmt, ap);
2951590Srgrimes	va_end(ap);
296138232Sharti	fprintf(stderr, "\n");
297138232Sharti	fflush(stderr);
2981590Srgrimes	if (type == PARSE_FATAL)
2991590Srgrimes		fatals += 1;
3001590Srgrimes}
3011590Srgrimes
3021590Srgrimes/*-
3031590Srgrimes *---------------------------------------------------------------------
3041590Srgrimes * ParseLinkSrc  --
305143100Sharti *	Link the parent nodes to their new child. Used by
3061590Srgrimes *	ParseDoDependency. If the specType isn't 'Not', the parent
3071590Srgrimes *	isn't linked as a parent of the child.
3081590Srgrimes *
3091590Srgrimes * Side Effects:
310143100Sharti *	New elements are added to the parents lists of cgn and the
3111590Srgrimes *	children list of cgn. the unmade field of pgn is updated
3121590Srgrimes *	to reflect the additional child.
3131590Srgrimes *---------------------------------------------------------------------
3141590Srgrimes */
315143027Shartistatic void
316143027ShartiParseLinkSrc(Lst *parents, GNode *cgn)
3171590Srgrimes{
318143027Sharti	LstNode	*ln;
319143027Sharti	GNode *pgn;
320138232Sharti
321143027Sharti	LST_FOREACH(ln, parents) {
322143027Sharti		pgn = Lst_Datum(ln);
323143027Sharti		if (Lst_Member(&pgn->children, cgn) == NULL) {
324143027Sharti			Lst_AtEnd(&pgn->children, cgn);
325143027Sharti			if (specType == Not) {
326143027Sharti				Lst_AtEnd(&cgn->parents, pgn);
327143027Sharti			}
328143027Sharti			pgn->unmade += 1;
329143027Sharti		}
3301590Srgrimes	}
3311590Srgrimes}
3321590Srgrimes
3331590Srgrimes/*-
3341590Srgrimes *---------------------------------------------------------------------
3351590Srgrimes * ParseDoOp  --
336143684Sharti *	Apply the parsed operator to all target nodes. Used in
337143684Sharti *	ParseDoDependency once all targets have been found and their
338143684Sharti *	operator parsed. If the previous and new operators are incompatible,
339143684Sharti *	a major error is taken.
3401590Srgrimes *
3411590Srgrimes * Side Effects:
3421590Srgrimes *	The type field of the node is altered to reflect any new bits in
3431590Srgrimes *	the op.
3441590Srgrimes *---------------------------------------------------------------------
3451590Srgrimes */
346143684Shartistatic void
347143684ShartiParseDoOp(int op)
3481590Srgrimes{
349143684Sharti	GNode	*cohort;
350143684Sharti	LstNode	*ln;
351143684Sharti	GNode	*gn;
352138232Sharti
353143684Sharti	LST_FOREACH(ln, &targets) {
354143684Sharti		gn = Lst_Datum(ln);
3551590Srgrimes
356143684Sharti		/*
357143684Sharti		 * If the dependency mask of the operator and the node don't
358143684Sharti		 * match and the node has actually had an operator applied to
359143684Sharti		 * it before, and the operator actually has some dependency
360143684Sharti		 * information in it, complain.
361143684Sharti		 */
362143684Sharti		if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) &&
363143684Sharti		    !OP_NOP(gn->type) && !OP_NOP(op)) {
364143684Sharti			Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
365143684Sharti			    gn->name);
366143684Sharti			return;
367143684Sharti		}
3688874Srgrimes
369143684Sharti		if (op == OP_DOUBLEDEP &&
370143684Sharti		    (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
371143684Sharti			/*
372143684Sharti			 * If the node was the object of a :: operator, we need
373143684Sharti			 * to create a new instance of it for the children and
374143684Sharti			 * commands on this dependency line. The new instance
375143684Sharti			 * is placed on the 'cohorts' list of the initial one
376143684Sharti			 * (note the initial one is not on its own cohorts list)
377143684Sharti			 * and the new instance is linked to all parents of the
378143684Sharti			 * initial instance.
379143684Sharti			 */
380143684Sharti			cohort = Targ_NewGN(gn->name);
3811590Srgrimes
382143684Sharti			/*
383143684Sharti			 * Duplicate links to parents so graph traversal is
384143684Sharti			 * simple. Perhaps some type bits should be duplicated?
385143684Sharti			 *
386143684Sharti			 * Make the cohort invisible as well to avoid
387143684Sharti			 * duplicating it into other variables. True, parents
388143684Sharti			 * of this target won't tend to do anything with their
389143684Sharti			 * local variables, but better safe than sorry.
390143684Sharti			 */
391143684Sharti			ParseLinkSrc(&gn->parents, cohort);
392143684Sharti			cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
393143684Sharti			Lst_AtEnd(&gn->cohorts, cohort);
3941590Srgrimes
395143684Sharti			/*
396143684Sharti			 * Replace the node in the targets list with the
397143684Sharti			 * new copy
398143684Sharti			 */
399143684Sharti			Lst_Replace(ln, cohort);
400143684Sharti			gn = cohort;
401143684Sharti		}
402143684Sharti		/*
403143684Sharti		 * We don't want to nuke any previous flags (whatever they were)
404143684Sharti		 * so we just OR the new operator into the old
405143684Sharti		 */
406143684Sharti		gn->type |= op;
407143684Sharti	}
4081590Srgrimes}
4091590Srgrimes
4101590Srgrimes/*-
4111590Srgrimes *---------------------------------------------------------------------
4121590Srgrimes * ParseDoSrc  --
4131590Srgrimes *	Given the name of a source, figure out if it is an attribute
4141590Srgrimes *	and apply it to the targets if it is. Else decide if there is
4151590Srgrimes *	some attribute which should be applied *to* the source because
4161590Srgrimes *	of some special target and apply it if so. Otherwise, make the
4171590Srgrimes *	source be a child of the targets in the list 'targets'
4181590Srgrimes *
4191590Srgrimes * Results:
4201590Srgrimes *	None
4211590Srgrimes *
4221590Srgrimes * Side Effects:
4231590Srgrimes *	Operator bits may be added to the list of targets or to the source.
4241590Srgrimes *	The targets may have a new source added to their lists of children.
4251590Srgrimes *---------------------------------------------------------------------
4261590Srgrimes */
4271590Srgrimesstatic void
428138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc)
4291590Srgrimes{
430144026Sharti	GNode	*gn = NULL;
4311590Srgrimes
432144026Sharti	if (*src == '.' && isupper ((unsigned char) src[1])) {
433144026Sharti		int keywd = ParseFindKeyword(src);
434144026Sharti		if (keywd != -1) {
435144026Sharti			if(parseKeywords[keywd].op != 0) {
436144026Sharti				ParseDoOp(parseKeywords[keywd].op);
437144026Sharti				return;
438144026Sharti			}
439144026Sharti			if (parseKeywords[keywd].spec == Wait) {
440144026Sharti				waiting++;
441144026Sharti				return;
442144026Sharti			}
443144026Sharti		}
4441590Srgrimes	}
44518730Ssteve
446144026Sharti	switch (specType) {
447144026Sharti	  case Main:
448144026Sharti		/*
449144026Sharti		 * If we have noted the existence of a .MAIN, it means we need
450144026Sharti		 * to add the sources of said target to the list of things
451144026Sharti		 * to create. The string 'src' is likely to be free, so we
452144026Sharti		 * must make a new copy of it. Note that this will only be
453144026Sharti		 * invoked if the user didn't specify a target on the command
454144026Sharti		 * line. This is to allow #ifmake's to succeed, or something...
455144026Sharti		 */
456144026Sharti		Lst_AtEnd(&create, estrdup(src));
457144026Sharti		/*
458144026Sharti		 * Add the name to the .TARGETS variable as well, so the user
459144026Sharti		 * can employ that, if desired.
460144026Sharti		 */
461144026Sharti		Var_Append(".TARGETS", src, VAR_GLOBAL);
462144026Sharti		return;
46318730Ssteve
464144026Sharti	  case Order:
465144026Sharti		/*
466144026Sharti		 * Create proper predecessor/successor links between the
467144026Sharti		 * previous source and the current one.
468144026Sharti		 */
469144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
470144026Sharti		if (predecessor != NULL) {
471144026Sharti			Lst_AtEnd(&predecessor->successors, gn);
472144026Sharti			Lst_AtEnd(&gn->preds, predecessor);
473144026Sharti		}
474144026Sharti		/*
475144026Sharti		 * The current source now becomes the predecessor for the next
476144026Sharti		 * one.
477144026Sharti		 */
478144026Sharti		predecessor = gn;
479144026Sharti		break;
48018730Ssteve
481144026Sharti	  default:
482144026Sharti		/*
483144026Sharti		 * If the source is not an attribute, we need to find/create
484144026Sharti		 * a node for it. After that we can apply any operator to it
485144026Sharti		 * from a special target or link it to its parents, as
486144026Sharti		 * appropriate.
487144026Sharti		 *
488144026Sharti		 * In the case of a source that was the object of a :: operator,
489144026Sharti		 * the attribute is applied to all of its instances (as kept in
490144026Sharti		 * the 'cohorts' list of the node) or all the cohorts are linked
491144026Sharti		 * to all the targets.
492144026Sharti		 */
493144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
4941590Srgrimes		if (tOp) {
495144026Sharti			gn->type |= tOp;
4961590Srgrimes		} else {
497144026Sharti			ParseLinkSrc(&targets, gn);
4981590Srgrimes		}
499144026Sharti		if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
500144026Sharti			GNode	*cohort;
501144026Sharti			LstNode	*ln;
502144026Sharti
503144026Sharti			for (ln = Lst_First(&gn->cohorts); ln != NULL;
504144026Sharti			    ln = Lst_Succ(ln)) {
505144026Sharti				cohort = Lst_Datum(ln);
506144026Sharti				if (tOp) {
507144026Sharti					cohort->type |= tOp;
508144026Sharti				} else {
509144026Sharti					ParseLinkSrc(&targets, cohort);
510144026Sharti				}
511144026Sharti			}
512144026Sharti		}
513144026Sharti		break;
5141590Srgrimes	}
51518730Ssteve
516144026Sharti	gn->order = waiting;
517144026Sharti	Lst_AtEnd(allsrc, gn);
518144026Sharti	if (waiting) {
519144026Sharti		LstNode	*ln;
520144026Sharti		GNode	*p;
5211590Srgrimes
522143684Sharti		/*
523144026Sharti		 * Check if GNodes needs to be synchronized.
524144026Sharti		 * This has to be when two nodes are on different sides of a
525144026Sharti		 * .WAIT directive.
526143684Sharti		 */
527144026Sharti		LST_FOREACH(ln, allsrc) {
528144026Sharti			p = Lst_Datum(ln);
529144026Sharti
530144026Sharti			if (p->order >= gn->order)
531144026Sharti				break;
532144026Sharti			/*
533144026Sharti			 * XXX: This can cause loops, and loops can cause
534144026Sharti			 * unmade targets, but checking is tedious, and the
535144026Sharti			 * debugging output can show the problem
536144026Sharti			 */
537144026Sharti			Lst_AtEnd(&p->successors, gn);
538144026Sharti			Lst_AtEnd(&gn->preds, p);
539144026Sharti		}
540143684Sharti	}
5411590Srgrimes}
5421590Srgrimes
543138232Sharti
5441590Srgrimes/*-
5451590Srgrimes *---------------------------------------------------------------------
5461590Srgrimes * ParseDoDependency  --
5471590Srgrimes *	Parse the dependency line in line.
5481590Srgrimes *
5491590Srgrimes * Results:
5501590Srgrimes *	None
5511590Srgrimes *
5521590Srgrimes * Side Effects:
5531590Srgrimes *	The nodes of the sources are linked as children to the nodes of the
5541590Srgrimes *	targets. Some nodes may be created.
5551590Srgrimes *
5561590Srgrimes *	We parse a dependency line by first extracting words from the line and
5571590Srgrimes * finding nodes in the list of all targets with that name. This is done
5581590Srgrimes * until a character is encountered which is an operator character. Currently
5591590Srgrimes * these are only ! and :. At this point the operator is parsed and the
5601590Srgrimes * pointer into the line advanced until the first source is encountered.
561144026Sharti *	The parsed operator is applied to each node in the 'targets' list,
5621590Srgrimes * which is where the nodes found for the targets are kept, by means of
5631590Srgrimes * the ParseDoOp function.
5641590Srgrimes *	The sources are read in much the same way as the targets were except
5651590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell
5661590Srgrimes * and all instances of the resulting words in the list of all targets
5671590Srgrimes * are found. Each of the resulting nodes is then linked to each of the
5681590Srgrimes * targets as one of its children.
5691590Srgrimes *	Certain targets are handled specially. These are the ones detailed
5701590Srgrimes * by the specType variable.
5711590Srgrimes *	The storing of transformation rules is also taken care of here.
5721590Srgrimes * A target is recognized as a transformation rule by calling
5731590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten
5741590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard
5751590Srgrimes * Targ_FindNode in the target module.
5761590Srgrimes *---------------------------------------------------------------------
5771590Srgrimes */
5781590Srgrimesstatic void
579141270ShartiParseDoDependency(char *line)
5801590Srgrimes{
581144026Sharti	char	*cp;	/* our current position */
582144026Sharti	GNode	*gn;	/* a general purpose temporary node */
583144026Sharti	int	op;	/* the operator on the line */
584144026Sharti	char	savec;	/* a place to save a character */
585144026Sharti	Lst	paths;	/* Search paths to alter when parsing .PATH targets */
586144026Sharti	int	tOp;	/* operator from special target */
587144026Sharti	LstNode	*ln;
5881590Srgrimes
589144026Sharti	tOp = 0;
5901590Srgrimes
591144026Sharti	specType = Not;
592144026Sharti	waiting = 0;
593144026Sharti	Lst_Init(&paths);
5941590Srgrimes
595144026Sharti	do {
596144026Sharti		for (cp = line;
597144026Sharti		    *cp && !isspace((unsigned char)*cp) && *cp != '(';
598144026Sharti		    cp++) {
599144026Sharti			if (*cp == '$') {
600144026Sharti				/*
601144026Sharti				 * Must be a dynamic source (would have been
602144026Sharti				 * expanded otherwise), so call the Var module
603144026Sharti				 * to parse the puppy so we can safely advance
604144026Sharti				 * beyond it...There should be no errors in this
605144026Sharti				 * as they would have been discovered in the
606144026Sharti				 * initial Var_Subst and we wouldn't be here.
607144026Sharti				 */
608144026Sharti				size_t	length = 0;
609144026Sharti				Boolean	freeIt;
610144026Sharti				char	*result;
6111590Srgrimes
612144026Sharti				result = Var_Parse(cp, VAR_CMD, TRUE,
613144026Sharti				    &length, &freeIt);
6141590Srgrimes
615144026Sharti				if (freeIt) {
616144026Sharti					free(result);
617144026Sharti				}
618144026Sharti				cp += length - 1;
619102178Sru
620144026Sharti			} else if (*cp == '!' || *cp == ':') {
621144026Sharti				/*
622144026Sharti				 * We don't want to end a word on ':' or '!' if
623144026Sharti				 * there is a better match later on in the
624144026Sharti				 * string (greedy matching).
625144026Sharti				 * This allows the user to have targets like:
626144026Sharti				 *    fie::fi:fo: fum
627144026Sharti				 *    foo::bar:
628144026Sharti				 * where "fie::fi:fo" and "foo::bar" are the
629144026Sharti				 * targets. In real life this is used for perl5
630144026Sharti				 * library man pages where "::" separates an
631144026Sharti				 * object from its class. Ie:
632144026Sharti				 * "File::Spec::Unix". This behaviour is also
633144026Sharti				 * consistent with other versions of make.
634144026Sharti				 */
635144026Sharti				char *p = cp + 1;
636102178Sru
637144026Sharti				if (*cp == ':' && *p == ':')
638144026Sharti					p++;
639102178Sru
640144026Sharti				/* Found the best match already. */
641144026Sharti				if (*p == '\0' || isspace(*p))
642144026Sharti					break;
643102178Sru
644144026Sharti				p += strcspn(p, "!:");
6458874Srgrimes
646144026Sharti				/* No better match later on... */
647144026Sharti				if (*p == '\0')
648144026Sharti					break;
649144026Sharti			}
650144026Sharti			continue;
6511590Srgrimes		}
652144026Sharti		if (*cp == '(') {
653144026Sharti			/*
654144026Sharti			 * Archives must be handled specially to make sure the
655144026Sharti			 * OP_ARCHV flag is set in their 'type' field, for one
656144026Sharti			 * thing, and because things like "archive(file1.o
657144026Sharti			 * file2.o file3.o)" are permissible. Arch_ParseArchive
658144026Sharti			 * will set 'line' to be the first non-blank after the
659144026Sharti			 * archive-spec. It creates/finds nodes for the members
660144026Sharti			 * and places them on the given list, returning SUCCESS
661144026Sharti			 * if all went well and FAILURE if there was an error in
662144026Sharti			 * the specification. On error, line should remain
663144026Sharti			 * untouched.
664144026Sharti			 */
665144026Sharti			if (Arch_ParseArchive(&line, &targets, VAR_CMD) !=
666144026Sharti			    SUCCESS) {
667144026Sharti				Parse_Error(PARSE_FATAL,
668144026Sharti				    "Error in archive specification: \"%s\"",
669144026Sharti				    line);
670144026Sharti				return;
671144026Sharti			} else {
672144026Sharti				cp = line;
673144026Sharti				continue;
674144026Sharti			}
675144026Sharti		}
676144026Sharti		savec = *cp;
6778874Srgrimes
678144026Sharti		if (!*cp) {
679144026Sharti			/*
680144026Sharti			 * Ending a dependency line without an operator is a				 * Bozo no-no. As a heuristic, this is also often
681144026Sharti			 * triggered by undetected conflicts from cvs/rcs
682144026Sharti			 * merges.
683144026Sharti			 */
684144026Sharti			if (strncmp(line, "<<<<<<", 6) == 0 ||
685144026Sharti			    strncmp(line, "======", 6) == 0 ||
686144026Sharti			    strncmp(line, ">>>>>>", 6) == 0) {
687144026Sharti				Parse_Error(PARSE_FATAL, "Makefile appears to "
688144026Sharti				    "contain unresolved cvs/rcs/??? merge "
689144026Sharti				    "conflicts");
690144026Sharti			} else
691144026Sharti				Parse_Error(PARSE_FATAL, "Need an operator");
692144026Sharti			return;
693144026Sharti		}
694144026Sharti		*cp = '\0';
6951590Srgrimes		/*
696144026Sharti		 * Have a word in line. See if it's a special target and set
697144026Sharti		 * specType to match it.
6981590Srgrimes		 */
699144026Sharti		if (*line == '.' && isupper((unsigned char)line[1])) {
700144026Sharti			/*
701144026Sharti			 * See if the target is a special target that must have
702144026Sharti			 * it or its sources handled specially.
703144026Sharti			 */
704144026Sharti			int keywd = ParseFindKeyword(line);
705144026Sharti
706144026Sharti			if (keywd != -1) {
707144026Sharti				if (specType == ExPath &&
708144026Sharti				    parseKeywords[keywd].spec != ExPath) {
709144026Sharti					Parse_Error(PARSE_FATAL,
710144026Sharti					    "Mismatched special targets");
711144026Sharti					return;
712144026Sharti				}
713144026Sharti
714144026Sharti				specType = parseKeywords[keywd].spec;
715144026Sharti				tOp = parseKeywords[keywd].op;
716144026Sharti
717144026Sharti				/*
718144026Sharti				 * Certain special targets have special
719144026Sharti				 * semantics:
720144026Sharti				 *  .PATH	Have to set the dirSearchPath
721144026Sharti				 *		variable too
722144026Sharti				 *  .MAIN	Its sources are only used if
723144026Sharti				 *		nothing has been specified to
724144026Sharti				 *		create.
725144026Sharti				 *  .DEFAULT    Need to create a node to hang
726144026Sharti				 *		commands on, but we don't want
727144026Sharti				 *		it in the graph, nor do we want
728144026Sharti				 *		it to be the Main Target, so we
729144026Sharti				 *		create it, set OP_NOTMAIN and
730144026Sharti				 *		add it to the list, setting
731144026Sharti				 *		DEFAULT to the new node for
732144026Sharti				 *		later use. We claim the node is
733144026Sharti				 *		A transformation rule to make
734144026Sharti				 *		life easier later, when we'll
735144026Sharti				 *		use Make_HandleUse to actually
736144026Sharti				 *		apply the .DEFAULT commands.
737144026Sharti				 *  .PHONY	The list of targets
738144026Sharti				 *  .BEGIN
739144026Sharti				 *  .END
740144026Sharti				 *  .INTERRUPT	Are not to be considered the
741144026Sharti				 *		main target.
742144026Sharti				 *  .NOTPARALLEL Make only one target at a time.
743144026Sharti				 *  .SINGLESHELL Create a shell for each
744144026Sharti				 *		command.
745144026Sharti				 *  .ORDER	Must set initial predecessor
746144026Sharti				 *		to NULL
747144026Sharti				 */
748144026Sharti				switch (specType) {
749144026Sharti				  case ExPath:
750144026Sharti					Lst_AtEnd(&paths, &dirSearchPath);
751144026Sharti					break;
752144026Sharti				  case Main:
753144026Sharti					if (!Lst_IsEmpty(&create)) {
754144026Sharti						specType = Not;
755144026Sharti					}
756144026Sharti					break;
757144026Sharti				  case Begin:
758144026Sharti				  case End:
759144026Sharti				  case Interrupt:
760144026Sharti					gn = Targ_FindNode(line, TARG_CREATE);
761144026Sharti					gn->type |= OP_NOTMAIN;
762144026Sharti					Lst_AtEnd(&targets, gn);
763144026Sharti					break;
764144026Sharti				  case Default:
765144026Sharti					gn = Targ_NewGN(".DEFAULT");
766144026Sharti					gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
767144026Sharti					Lst_AtEnd(&targets, gn);
768144026Sharti					DEFAULT = gn;
769144026Sharti					break;
770144026Sharti				  case NotParallel:
771144026Sharti					maxJobs = 1;
772144026Sharti					break;
773144026Sharti				  case SingleShell:
774144026Sharti					compatMake = 1;
775144026Sharti					break;
776144026Sharti				  case Order:
777144026Sharti					predecessor = NULL;
778144026Sharti					break;
779144026Sharti				  default:
780144026Sharti					break;
781144026Sharti				}
782144026Sharti
783144026Sharti			} else if (strncmp(line, ".PATH", 5) == 0) {
784144026Sharti				/*
785144026Sharti				 * .PATH<suffix> has to be handled specially.
786144026Sharti				 * Call on the suffix module to give us a path
787144026Sharti				 * to modify.
788144026Sharti				 */
789144026Sharti				struct Path *path;
790144026Sharti
791144026Sharti				specType = ExPath;
792144026Sharti				path = Suff_GetPath(&line[5]);
793144026Sharti				if (path == NULL) {
794144026Sharti					Parse_Error(PARSE_FATAL, "Suffix '%s' "
795144026Sharti					    "not defined (yet)", &line[5]);
796144026Sharti					return;
797144026Sharti				} else
798144026Sharti					Lst_AtEnd(&paths, path);
7991590Srgrimes			}
8001590Srgrimes		}
801144026Sharti
8021590Srgrimes		/*
803144026Sharti		 * Have word in line. Get or create its node and stick it at
804144026Sharti		 * the end of the targets list
8051590Srgrimes		 */
806144026Sharti		if ((specType == Not) && (*line != '\0')) {
8078874Srgrimes
808144026Sharti			/* target names to be found and added to targets list */
809144026Sharti			Lst curTargs = Lst_Initializer(curTargs);
8108874Srgrimes
811144026Sharti			if (Dir_HasWildcards(line)) {
812144026Sharti				/*
813144026Sharti				 * Targets are to be sought only in the current
814144026Sharti				 * directory, so create an empty path for the
815144026Sharti				 * thing. Note we need to use Path_Clear in the
816144026Sharti				 * destruction of the path as the Dir module
817144026Sharti				 * could have added a directory to the path...
818144026Sharti				 */
819144026Sharti				struct Path emptyPath =
820144026Sharti				    TAILQ_HEAD_INITIALIZER(emptyPath);
821138916Sharti
822144026Sharti				Path_Expand(line, &emptyPath, &curTargs);
823144026Sharti				Path_Clear(&emptyPath);
8248874Srgrimes
825144026Sharti			} else {
826144026Sharti				/*
827144026Sharti				 * No wildcards, but we want to avoid code
828144026Sharti				 * duplication, so create a list with the word
829144026Sharti				 * on it.
830144026Sharti				 */
831144026Sharti				Lst_AtEnd(&curTargs, line);
832144026Sharti			}
8338874Srgrimes
834144026Sharti			while (!Lst_IsEmpty(&curTargs)) {
835144026Sharti				char	*targName = Lst_DeQueue(&curTargs);
836144026Sharti
837144026Sharti				if (!Suff_IsTransform (targName)) {
838144026Sharti					gn = Targ_FindNode(targName,
839144026Sharti					    TARG_CREATE);
840144026Sharti				} else {
841144026Sharti					gn = Suff_AddTransform(targName);
842144026Sharti				}
843144026Sharti
844144026Sharti				Lst_AtEnd(&targets, gn);
845144026Sharti			}
846144026Sharti		} else if (specType == ExPath && *line != '.' && *line != '\0'){
847144026Sharti			Parse_Error(PARSE_WARNING, "Extra target (%s) ignored",
848144026Sharti			    line);
849144026Sharti		}
850144026Sharti
851144026Sharti		*cp = savec;
8521590Srgrimes		/*
853144026Sharti		 * If it is a special type and not .PATH, it's the only
854144026Sharti		 * target we allow on this line...
8551590Srgrimes		 */
856144026Sharti		if (specType != Not && specType != ExPath) {
857144026Sharti			Boolean warnFlag = FALSE;
8588874Srgrimes
859144026Sharti			while ((*cp != '!') && (*cp != ':') && *cp) {
860144026Sharti				if (*cp != ' ' && *cp != '\t') {
861144026Sharti					warnFlag = TRUE;
862144026Sharti				}
863144026Sharti				cp++;
864144026Sharti			}
865144026Sharti			if (warnFlag) {
866144026Sharti				Parse_Error(PARSE_WARNING,
867144026Sharti				    "Extra target ignored");
868144026Sharti			}
8691590Srgrimes		} else {
870144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
871144026Sharti				cp++;
872144026Sharti			}
8731590Srgrimes		}
874144026Sharti		line = cp;
875144026Sharti	} while ((*line != '!') && (*line != ':') && *line);
8768874Srgrimes
877144026Sharti	if (!Lst_IsEmpty(&targets)) {
878144026Sharti		switch (specType) {
879144026Sharti		  default:
880144026Sharti			Parse_Error(PARSE_WARNING, "Special and mundane "
881144026Sharti			    "targets don't mix. Mundane ones ignored");
882144026Sharti			break;
883144026Sharti		  case Default:
884144026Sharti		  case Begin:
885144026Sharti		  case End:
886144026Sharti		  case Interrupt:
887144026Sharti			/*
888144026Sharti			 * These four create nodes on which to hang commands, so
889144026Sharti			 * targets shouldn't be empty...
890144026Sharti			 */
891144026Sharti		  case Not:
892144026Sharti			/*
893144026Sharti			 * Nothing special here -- targets can be empty if it
894144026Sharti			 * wants.
895144026Sharti			 */
896144026Sharti			break;
897144026Sharti		}
8981590Srgrimes	}
8998874Srgrimes
9001590Srgrimes	/*
901144026Sharti	 * Have now parsed all the target names. Must parse the operator next.
902144026Sharti	 * The result is left in op.
9031590Srgrimes	 */
904144026Sharti	if (*cp == '!') {
905144026Sharti		op = OP_FORCE;
906144026Sharti	} else if (*cp == ':') {
907144026Sharti		if (cp[1] == ':') {
908144026Sharti			op = OP_DOUBLEDEP;
909144026Sharti			cp++;
910144026Sharti		} else {
911144026Sharti			op = OP_DEPENDS;
9121590Srgrimes		}
9131590Srgrimes	} else {
914144026Sharti		Parse_Error(PARSE_FATAL, "Missing dependency operator");
915144026Sharti		return;
916144026Sharti	}
917144026Sharti
918144026Sharti	cp++;			/* Advance beyond operator */
919144026Sharti
920144026Sharti	ParseDoOp(op);
921144026Sharti
922144026Sharti	/*
923144026Sharti	 * Get to the first source
924144026Sharti	 */
925144026Sharti	while (*cp && isspace((unsigned char)*cp)) {
9261590Srgrimes		cp++;
9271590Srgrimes	}
9281590Srgrimes	line = cp;
9291590Srgrimes
930144026Sharti	/*
931144026Sharti	 * Several special targets take different actions if present with no
932144026Sharti	 * sources:
933144026Sharti	 *	a .SUFFIXES line with no sources clears out all old suffixes
934144026Sharti	 *	a .PRECIOUS line makes all targets precious
935144026Sharti	 *	a .IGNORE line ignores errors for all targets
936144026Sharti	 *	a .SILENT line creates silence when making all targets
937144026Sharti	 *	a .PATH removes all directories from the search path(s).
938144026Sharti	 */
939144026Sharti	if (!*line) {
940144026Sharti		switch (specType) {
941144026Sharti		  case Suffixes:
942144026Sharti			Suff_ClearSuffixes();
943144026Sharti			break;
944144026Sharti		  case Precious:
945144026Sharti			allPrecious = TRUE;
946144026Sharti			break;
947144026Sharti		  case Ignore:
948144026Sharti			ignoreErrors = TRUE;
949144026Sharti			break;
950144026Sharti		  case Silent:
951144026Sharti			beSilent = TRUE;
952144026Sharti			break;
953144026Sharti		  case ExPath:
954144026Sharti			LST_FOREACH(ln, &paths)
955144026Sharti			Path_Clear(Lst_Datum(ln));
956144026Sharti			break;
957144026Sharti		  case Posix:
958144026Sharti			Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
959144026Sharti			break;
960144026Sharti		  default:
961144026Sharti			break;
962144026Sharti		}
963144026Sharti
964144026Sharti	} else if (specType == MFlags) {
9651590Srgrimes		/*
966144026Sharti		 * Call on functions in main.c to deal with these arguments and
967144026Sharti		 * set the initial character to a null-character so the loop to
968144026Sharti		 * get sources won't get anything
9691590Srgrimes		 */
970144026Sharti		Main_ParseArgLine(line, 0);
971144026Sharti		*line = '\0';
9721590Srgrimes
973144026Sharti	} else if (specType == ExShell) {
974144026Sharti		if (Job_ParseShell(line) != SUCCESS) {
975144026Sharti			Parse_Error(PARSE_FATAL,
976144026Sharti			    "improper shell specification");
977144026Sharti			return;
978144026Sharti		}
979144026Sharti		*line = '\0';
980144026Sharti
981144026Sharti	} else if ((specType == NotParallel) || (specType == SingleShell)) {
982144026Sharti		*line = '\0';
9831590Srgrimes	}
9841590Srgrimes
985144026Sharti	/*
986144026Sharti	* NOW GO FOR THE SOURCES
987144026Sharti	*/
988144026Sharti	if ((specType == Suffixes) || (specType == ExPath) ||
989144026Sharti	    (specType == Includes) || (specType == Libs) ||
990144026Sharti	    (specType == Null)) {
991144026Sharti		while (*line) {
992144026Sharti			/*
993144026Sharti			 * If the target was one that doesn't take files as its
994144026Sharti			 * sources but takes something like suffixes, we take
995144026Sharti			 * each space-separated word on the line as a something
996144026Sharti			 * and deal with it accordingly.
997144026Sharti			 *
998144026Sharti			 * If the target was .SUFFIXES, we take each source as
999144026Sharti			 * a suffix and add it to the list of suffixes
1000144026Sharti			 * maintained by the Suff module.
1001144026Sharti			 *
1002144026Sharti			 * If the target was a .PATH, we add the source as a
1003144026Sharti			 * directory to search on the search path.
1004144026Sharti			 *
1005144026Sharti			 * If it was .INCLUDES, the source is taken to be the
1006144026Sharti			 * suffix of files which will be #included and whose
1007144026Sharti			 * search path should be present in the .INCLUDES
1008144026Sharti			 * variable.
1009144026Sharti			 *
1010144026Sharti			 * If it was .LIBS, the source is taken to be the
1011144026Sharti			 * suffix of files which are considered libraries and
1012144026Sharti			 * whose search path should be present in the .LIBS
1013144026Sharti			 * variable.
1014144026Sharti			 *
1015144026Sharti			 * If it was .NULL, the source is the suffix to use
1016144026Sharti			 * when a file has no valid suffix.
1017144026Sharti			 */
1018144026Sharti			char  savech;
1019144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1020144026Sharti				cp++;
1021144026Sharti			}
1022144026Sharti			savech = *cp;
1023144026Sharti			*cp = '\0';
1024144026Sharti			switch (specType) {
1025144026Sharti			  case Suffixes:
1026144026Sharti				Suff_AddSuffix(line);
1027144026Sharti				break;
1028144026Sharti			  case ExPath:
1029144026Sharti				LST_FOREACH(ln, &paths)
1030144026Sharti					Path_AddDir(Lst_Datum(ln), line);
1031144026Sharti				break;
1032144026Sharti			  case Includes:
1033144026Sharti				Suff_AddInclude(line);
1034144026Sharti				break;
1035144026Sharti			  case Libs:
1036144026Sharti				Suff_AddLib(line);
1037144026Sharti				break;
1038144026Sharti			  case Null:
1039144026Sharti				Suff_SetNull(line);
1040144026Sharti				break;
1041144026Sharti			  default:
1042144026Sharti				break;
1043144026Sharti			}
1044144026Sharti			*cp = savech;
1045144026Sharti			if (savech != '\0') {
1046144026Sharti				cp++;
1047144026Sharti			}
1048144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1049144026Sharti				cp++;
1050144026Sharti			}
1051144026Sharti			line = cp;
1052144026Sharti		}
1053144026Sharti		Lst_Destroy(&paths, NOFREE);
10541590Srgrimes
1055144026Sharti	} else {
1056144026Sharti		/* list of sources in order */
1057144026Sharti		Lst curSrcs = Lst_Initializer(curSrc);
10581590Srgrimes
1059144026Sharti		while (*line) {
1060144026Sharti			/*
1061144026Sharti			 * The targets take real sources, so we must beware of
1062144026Sharti			 * archive specifications (i.e. things with left
1063144026Sharti			 * parentheses in them) and handle them accordingly.
1064144026Sharti			 */
1065144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1066144026Sharti				if (*cp == '(' && cp > line && cp[-1] != '$') {
1067144026Sharti					/*
1068144026Sharti					 * Only stop for a left parenthesis if
1069144026Sharti					 * it isn't at the start of a word
1070144026Sharti					 * (that'll be for variable changes
1071144026Sharti					 * later) and isn't preceded by a dollar
1072144026Sharti					 * sign (a dynamic source).
1073144026Sharti					 */
1074144026Sharti					break;
1075144026Sharti				} else {
1076144026Sharti					cp++;
1077144026Sharti				}
1078144026Sharti			}
10791590Srgrimes
1080144026Sharti			if (*cp == '(') {
1081144026Sharti				GNode	  *gnp;
10828874Srgrimes
1083144026Sharti				/* list of archive source names after exp. */
1084144026Sharti				Lst sources = Lst_Initializer(sources);
1085138916Sharti
1086144026Sharti				if (Arch_ParseArchive(&line, &sources,
1087144026Sharti				    VAR_CMD) != SUCCESS) {
1088144026Sharti					Parse_Error(PARSE_FATAL, "Error in "
1089144026Sharti					    "source archive spec \"%s\"", line);
1090144026Sharti					return;
1091144026Sharti				}
1092141270Sharti
1093144026Sharti				while (!Lst_IsEmpty(&sources)) {
1094144026Sharti					gnp = Lst_DeQueue(&sources);
1095144026Sharti					ParseDoSrc(tOp, gnp->name, &curSrcs);
1096144026Sharti				}
1097144026Sharti				cp = line;
1098144026Sharti			} else {
1099144026Sharti				if (*cp) {
1100144026Sharti					*cp = '\0';
1101144026Sharti					cp += 1;
1102144026Sharti				}
11031590Srgrimes
1104144026Sharti				ParseDoSrc(tOp, line, &curSrcs);
1105144026Sharti			}
1106144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1107144026Sharti				cp++;
1108144026Sharti			}
1109144026Sharti			line = cp;
11101590Srgrimes		}
1111144026Sharti		Lst_Destroy(&curSrcs, NOFREE);
1112144026Sharti	}
11131590Srgrimes
1114144026Sharti	if (mainNode == NULL) {
1115144026Sharti		/*
1116144026Sharti		 * If we have yet to decide on a main target to make, in the
1117144026Sharti		 * absence of any user input, we want the first target on
1118144026Sharti		 * the first dependency line that is actually a real target
1119144026Sharti		 * (i.e. isn't a .USE or .EXEC rule) to be made.
1120144026Sharti		 */
1121144026Sharti		LST_FOREACH(ln, &targets) {
1122144026Sharti			gn = Lst_Datum(ln);
1123144026Sharti			if ((gn->type & (OP_NOTMAIN | OP_USE |
1124144026Sharti			    OP_EXEC | OP_TRANSFORM)) == 0) {
1125144026Sharti				mainNode = gn;
1126144026Sharti				Targ_SetMain(gn);
1127144026Sharti				break;
1128144026Sharti			}
11291590Srgrimes		}
11301590Srgrimes	}
11311590Srgrimes}
11321590Srgrimes
11331590Srgrimes/*-
11341590Srgrimes *---------------------------------------------------------------------
11351590Srgrimes * Parse_IsVar  --
11361590Srgrimes *	Return TRUE if the passed line is a variable assignment. A variable
11371590Srgrimes *	assignment consists of a single word followed by optional whitespace
11381590Srgrimes *	followed by either a += or an = operator.
11391590Srgrimes *	This function is used both by the Parse_File function and main when
11401590Srgrimes *	parsing the command-line arguments.
11411590Srgrimes *
11421590Srgrimes * Results:
11431590Srgrimes *	TRUE if it is. FALSE if it ain't
11441590Srgrimes *
11451590Srgrimes * Side Effects:
11461590Srgrimes *	none
11471590Srgrimes *---------------------------------------------------------------------
11481590Srgrimes */
11491590SrgrimesBoolean
1150138232ShartiParse_IsVar(char *line)
11511590Srgrimes{
1152144026Sharti	Boolean wasSpace = FALSE;	/* set TRUE if found a space */
1153144026Sharti	Boolean haveName = FALSE;	/* Set TRUE if have a variable name */
1154138232Sharti
1155144026Sharti	int level = 0;
1156103503Sjmallett#define	ISEQOPERATOR(c) \
115718730Ssteve	(((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
11581590Srgrimes
1159144026Sharti	/*
1160144026Sharti	 * Skip to variable name
1161144026Sharti	 */
1162144026Sharti	for (; (*line == ' ') || (*line == '\t'); line++)
1163144026Sharti		continue;
11641590Srgrimes
1165144026Sharti	for (; *line != '=' || level != 0; line++) {
1166144026Sharti		switch (*line) {
1167144026Sharti		  case '\0':
1168144026Sharti			/*
1169144026Sharti			 * end-of-line -- can't be a variable assignment.
1170144026Sharti			 */
1171144026Sharti			return (FALSE);
117218730Ssteve
1173144026Sharti		  case ' ':
1174144026Sharti		  case '\t':
1175144026Sharti			/*
1176144026Sharti			 * there can be as much white space as desired so long
1177144026Sharti			 * as there is only one word before the operator
1178144026Sharti			*/
1179144026Sharti			wasSpace = TRUE;
1180144026Sharti			break;
118118730Ssteve
1182144026Sharti		  case '(':
1183144026Sharti		  case '{':
1184144026Sharti			level++;
1185144026Sharti			break;
118618730Ssteve
1187144026Sharti		  case '}':
1188144026Sharti		  case ')':
1189144026Sharti			level--;
1190144026Sharti			break;
119118730Ssteve
1192144026Sharti		  default:
1193144026Sharti			if (wasSpace && haveName) {
1194144026Sharti				if (ISEQOPERATOR(*line)) {
1195144026Sharti					/*
1196144026Sharti					 * We must have a finished word
1197144026Sharti					 */
1198144026Sharti					if (level != 0)
1199144026Sharti						return (FALSE);
120018730Ssteve
1201144026Sharti					/*
1202144026Sharti					 * When an = operator [+?!:] is found,
1203144026Sharti					 * the next character must be an = or
1204144026Sharti					 * it ain't a valid assignment.
1205144026Sharti					 */
1206144026Sharti					if (line[1] == '=')
1207144026Sharti						return (haveName);
120818730Ssteve#ifdef SUNSHCMD
1209144026Sharti					/*
1210144026Sharti					 * This is a shell command
1211144026Sharti					 */
1212144026Sharti					if (strncmp(line, ":sh", 3) == 0)
1213144026Sharti						return (haveName);
121418730Ssteve#endif
1215144026Sharti				}
1216144026Sharti				/*
1217144026Sharti				 * This is the start of another word, so not
1218144026Sharti				 * assignment.
1219144026Sharti				 */
1220144026Sharti				return (FALSE);
1221144026Sharti
1222144026Sharti			} else {
1223144026Sharti				haveName = TRUE;
1224144026Sharti				wasSpace = FALSE;
1225144026Sharti			}
1226144026Sharti			break;
1227144026Sharti		}
12281590Srgrimes	}
12291590Srgrimes
1230144026Sharti	return (haveName);
12311590Srgrimes}
12321590Srgrimes
12331590Srgrimes/*-
12341590Srgrimes *---------------------------------------------------------------------
12351590Srgrimes * Parse_DoVar  --
12361590Srgrimes *	Take the variable assignment in the passed line and do it in the
12371590Srgrimes *	global context.
12381590Srgrimes *
12391590Srgrimes *	Note: There is a lexical ambiguity with assignment modifier characters
12401590Srgrimes *	in variable names. This routine interprets the character before the =
12411590Srgrimes *	as a modifier. Therefore, an assignment like
12421590Srgrimes *	    C++=/usr/bin/CC
12431590Srgrimes *	is interpreted as "C+ +=" instead of "C++ =".
12441590Srgrimes *
12451590Srgrimes * Results:
12461590Srgrimes *	none
12471590Srgrimes *
12481590Srgrimes * Side Effects:
12491590Srgrimes *	the variable structure of the given variable name is altered in the
12501590Srgrimes *	global context.
12511590Srgrimes *---------------------------------------------------------------------
12521590Srgrimes */
12531590Srgrimesvoid
1254138232ShartiParse_DoVar(char *line, GNode *ctxt)
12551590Srgrimes{
1256144026Sharti	char	*cp;	/* pointer into line */
1257144026Sharti	enum {
1258144026Sharti		VAR_SUBST,
1259144026Sharti		VAR_APPEND,
1260144026Sharti		VAR_SHELL,
1261144026Sharti		VAR_NORMAL
1262144026Sharti	}	type;	/* Type of assignment */
1263144026Sharti	char	*opc;	/* ptr to operator character to
1264144026Sharti			 * null-terminate the variable name */
1265144026Sharti
1266144026Sharti	/*
1267144026Sharti	 * Avoid clobbered variable warnings by forcing the compiler
1268144026Sharti	 * to ``unregister'' variables
1269144026Sharti	 */
12701590Srgrimes#if __GNUC__
1271144026Sharti	(void)&cp;
1272144026Sharti	(void)&line;
12735814Sjkh#endif
12741590Srgrimes
1275144026Sharti	/*
1276144026Sharti	 * Skip to variable name
1277144026Sharti	 */
1278144026Sharti	while ((*line == ' ') || (*line == '\t')) {
1279144026Sharti		line++;
1280144026Sharti	}
12811590Srgrimes
1282144026Sharti	/*
1283144026Sharti	 * Skip to operator character, nulling out whitespace as we go
1284144026Sharti	 */
1285144026Sharti	for (cp = line + 1; *cp != '='; cp++) {
1286144026Sharti		if (isspace((unsigned char)*cp)) {
1287144026Sharti			*cp = '\0';
1288144026Sharti		}
12891590Srgrimes	}
1290144026Sharti	opc = cp - 1;		/* operator is the previous character */
1291144026Sharti	*cp++ = '\0';		/* nuke the = */
12921590Srgrimes
1293144026Sharti	/*
1294144026Sharti	 * Check operator type
1295144026Sharti	 */
1296144026Sharti	switch (*opc) {
1297144026Sharti	  case '+':
1298144026Sharti		type = VAR_APPEND;
1299144026Sharti		*opc = '\0';
1300144026Sharti		break;
13011590Srgrimes
1302144026Sharti	  case '?':
1303144026Sharti		/*
1304144026Sharti		 * If the variable already has a value, we don't do anything.
1305144026Sharti		 */
1306144026Sharti		*opc = '\0';
1307144026Sharti		if (Var_Exists(line, ctxt)) {
1308144026Sharti			return;
1309144026Sharti		} else {
1310144026Sharti			type = VAR_NORMAL;
1311144026Sharti		}
1312144026Sharti		break;
13131590Srgrimes
1314144026Sharti	  case ':':
1315144026Sharti		type = VAR_SUBST;
1316144026Sharti		*opc = '\0';
1317144026Sharti		break;
13181590Srgrimes
1319144026Sharti	  case '!':
1320144026Sharti		type = VAR_SHELL;
1321144026Sharti		*opc = '\0';
1322144026Sharti		break;
13231590Srgrimes
1324144026Sharti	  default:
132518730Ssteve#ifdef SUNSHCMD
1326144026Sharti		while (*opc != ':') {
1327144026Sharti			if (opc == line)
1328144026Sharti				break;
1329144026Sharti			else
1330144026Sharti				--opc;
1331144026Sharti		}
133218730Ssteve
1333144026Sharti		if (strncmp(opc, ":sh", 3) == 0) {
1334144026Sharti			type = VAR_SHELL;
1335144026Sharti			*opc = '\0';
1336144026Sharti			break;
1337144026Sharti		}
1338144026Sharti#endif
1339144026Sharti		type = VAR_NORMAL;
134018730Ssteve		break;
1341144026Sharti	}
13421590Srgrimes
1343144026Sharti	while (isspace((unsigned char)*cp)) {
1344144026Sharti		cp++;
1345144026Sharti	}
13461590Srgrimes
1347144026Sharti	if (type == VAR_APPEND) {
1348144026Sharti		Var_Append(line, cp, ctxt);
13491590Srgrimes
1350144026Sharti	} else if (type == VAR_SUBST) {
1351144026Sharti		/*
1352144026Sharti		 * Allow variables in the old value to be undefined, but leave
1353144026Sharti		 * their invocation alone -- this is done by forcing oldVars
1354144026Sharti		 * to be false.
1355144026Sharti		 * XXX: This can cause recursive variables, but that's not
1356144026Sharti		 * hard to do, and this allows someone to do something like
1357144026Sharti		 *
1358144026Sharti		 *  CFLAGS = $(.INCLUDES)
1359144026Sharti		 *  CFLAGS := -I.. $(CFLAGS)
1360144026Sharti		 *
1361144026Sharti		 * And not get an error.
1362144026Sharti		 */
1363144026Sharti		Boolean oldOldVars = oldVars;
136498509Sjmallett
1365144026Sharti		oldVars = FALSE;
136698509Sjmallett
1367144026Sharti		/*
1368144026Sharti		 * make sure that we set the variable the first time to nothing
1369144026Sharti		 * so that it gets substituted!
1370144026Sharti		 */
1371144026Sharti		if (!Var_Exists(line, ctxt))
1372144026Sharti			Var_Set(line, "", ctxt);
1373142457Sharti
1374144026Sharti		cp = Buf_Peel(Var_Subst(NULL, cp, ctxt, FALSE));
13751590Srgrimes
1376144026Sharti		oldVars = oldOldVars;
13771590Srgrimes
1378144026Sharti		Var_Set(line, cp, ctxt);
1379144026Sharti		free(cp);
13801590Srgrimes
1381144026Sharti	} else if (type == VAR_SHELL) {
1382144026Sharti		/*
1383144026Sharti		 * TRUE if the command needs to be freed, i.e.
1384144026Sharti		 * if any variable expansion was performed
1385144026Sharti		 */
1386144026Sharti		Boolean	freeCmd = FALSE;
1387144026Sharti		Buffer *buf;
1388144026Sharti		const char *error;
13891590Srgrimes
1390144026Sharti		if (strchr(cp, '$') != NULL) {
1391144026Sharti			/*
1392144026Sharti			 * There's a dollar sign in the command, so perform
1393144026Sharti			 * variable expansion on the whole thing. The
1394144026Sharti			 * resulting string will need freeing when we're done,
1395144026Sharti			 * so set freeCmd to TRUE.
1396144026Sharti			 */
1397144026Sharti			cp = Buf_Peel(Var_Subst(NULL, cp, VAR_CMD, TRUE));
1398144026Sharti			freeCmd = TRUE;
1399144026Sharti		}
14001590Srgrimes
1401144026Sharti		buf = Cmd_Exec(cp, &error);
1402144026Sharti		Var_Set(line, Buf_Data(buf), ctxt);
1403144026Sharti		Buf_Destroy(buf, TRUE);
1404144026Sharti
1405144026Sharti		if (error)
1406144026Sharti			Parse_Error(PARSE_WARNING, error, cp);
1407144026Sharti
1408144026Sharti		if (freeCmd)
1409144026Sharti			free(cp);
1410144026Sharti
1411144026Sharti	} else {
1412144026Sharti		/*
1413144026Sharti		 * Normal assignment -- just do it.
1414144026Sharti		 */
1415144026Sharti		Var_Set(line, cp, ctxt);
1416144026Sharti	}
14171590Srgrimes}
14181590Srgrimes
14191590Srgrimes/*-
14201590Srgrimes *-----------------------------------------------------------------------
14211590Srgrimes * ParseHasCommands --
14221590Srgrimes *	Callback procedure for Parse_File when destroying the list of
14231590Srgrimes *	targets on the last dependency line. Marks a target as already
14241590Srgrimes *	having commands if it does, to keep from having shell commands
14251590Srgrimes *	on multiple dependency lines.
14261590Srgrimes *
14271590Srgrimes * Results:
14285814Sjkh *	None
14291590Srgrimes *
14301590Srgrimes * Side Effects:
14311590Srgrimes *	OP_HAS_COMMANDS may be set for the target.
14321590Srgrimes *
14331590Srgrimes *-----------------------------------------------------------------------
14341590Srgrimes */
14355814Sjkhstatic void
1436104696SjmallettParseHasCommands(void *gnp)
14371590Srgrimes{
1438144026Sharti	GNode *gn = gnp;
1439138232Sharti
1440144026Sharti	if (!Lst_IsEmpty(&gn->commands)) {
1441144026Sharti		gn->type |= OP_HAS_COMMANDS;
1442144026Sharti	}
14431590Srgrimes}
14441590Srgrimes
14451590Srgrimes/*-
14461590Srgrimes *-----------------------------------------------------------------------
14471590Srgrimes * Parse_AddIncludeDir --
14481590Srgrimes *	Add a directory to the path searched for included makefiles
14491590Srgrimes *	bracketed by double-quotes. Used by functions in main.c
14501590Srgrimes *
14511590Srgrimes * Results:
14521590Srgrimes *	None.
14531590Srgrimes *
14541590Srgrimes * Side Effects:
14551590Srgrimes *	The directory is appended to the list.
14561590Srgrimes *
14571590Srgrimes *-----------------------------------------------------------------------
14581590Srgrimes */
14591590Srgrimesvoid
1460138232ShartiParse_AddIncludeDir(char *dir)
14611590Srgrimes{
1462138232Sharti
1463144026Sharti	Path_AddDir(&parseIncPath, dir);
14641590Srgrimes}
14651590Srgrimes
146636347Ssteve/*---------------------------------------------------------------------
146736347Ssteve * ParseDoError  --
146836347Ssteve *	Handle error directive
146936347Ssteve *
147036347Ssteve *	The input is the line minus the ".error".  We substitute variables,
147136347Ssteve *	print the message and exit(1) or just print a warning if the ".error"
147236347Ssteve *	directive is malformed.
147336347Ssteve *
147436347Ssteve *---------------------------------------------------------------------
147536347Ssteve */
147636347Sstevestatic void
1477104696SjmallettParseDoError(char *errmsg)
147836347Ssteve{
1479142457Sharti	Buffer *buf;
1480138232Sharti
1481138232Sharti	if (!isspace((unsigned char)*errmsg)) {
148236347Ssteve		Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg);
148336347Ssteve		return;
148436347Ssteve	}
1485138232Sharti
1486138232Sharti	while (isspace((unsigned char)*errmsg))
148736347Ssteve		errmsg++;
1488138232Sharti
1489142457Sharti	buf = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
1490143959Sharti	Parse_Error(PARSE_FATAL, "%s", Buf_Data(buf));
1491142457Sharti	Buf_Destroy(buf, TRUE);
1492142457Sharti
1493128160Sru	/* Terminate immediately. */
149436347Ssteve	exit(1);
149536347Ssteve}
149636347Ssteve
1497128160Sru/*---------------------------------------------------------------------
1498128160Sru * ParseDoWarning  --
1499128160Sru *	Handle warning directive
1500128160Sru *
1501128160Sru *	The input is the line minus the ".warning".  We substitute variables
1502128160Sru *	and print the message or just print a warning if the ".warning"
1503128160Sru *	directive is malformed.
1504128160Sru *
1505128160Sru *---------------------------------------------------------------------
1506128160Sru */
1507128160Srustatic void
1508128160SruParseDoWarning(char *warnmsg)
1509128160Sru{
1510142457Sharti	Buffer *buf;
1511138232Sharti
1512138232Sharti	if (!isspace((unsigned char)*warnmsg)) {
1513128160Sru		Parse_Error(PARSE_WARNING, "invalid syntax: .warning%s",
1514128160Sru		    warnmsg);
1515128160Sru		return;
1516128160Sru	}
1517138232Sharti
1518138232Sharti	while (isspace((unsigned char)*warnmsg))
1519128160Sru		warnmsg++;
1520138232Sharti
1521142457Sharti	buf = Var_Subst(NULL, warnmsg, VAR_GLOBAL, FALSE);
1522143959Sharti	Parse_Error(PARSE_WARNING, "%s", Buf_Data(buf));
1523142457Sharti	Buf_Destroy(buf, TRUE);
1524128160Sru}
1525128160Sru
15261590Srgrimes/*-
15271590Srgrimes *---------------------------------------------------------------------
15281590Srgrimes * ParseDoInclude  --
15291590Srgrimes *	Push to another file.
15308874Srgrimes *
15311590Srgrimes *	The input is the line minus the #include. A file spec is a string
15321590Srgrimes *	enclosed in <> or "". The former is looked for only in sysIncPath.
15331590Srgrimes *	The latter in . and the directories specified by -I command line
15341590Srgrimes *	options
15351590Srgrimes *
15361590Srgrimes * Results:
15371590Srgrimes *	None
15381590Srgrimes *
15391590Srgrimes * Side Effects:
1540126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1541126824Sru *	curFile.fname and curFile.F are altered for the new file
15421590Srgrimes *---------------------------------------------------------------------
15431590Srgrimes */
15441590Srgrimesstatic void
1545141270ShartiParseDoInclude(char *file)
15461590Srgrimes{
1547144026Sharti	char	*fullname;	/* full pathname of file */
1548144026Sharti	IFile	*oldFile;	/* state associated with current file */
1549144026Sharti	char	endc;		/* the character which ends the file spec */
1550144026Sharti	char	*cp;		/* current position in file spec */
1551144026Sharti	Boolean	isSystem;	/* TRUE if makefile is a system makefile */
1552144026Sharti	Buffer	*buf;
15531590Srgrimes
1554144026Sharti	/*
1555144026Sharti	 * Skip to delimiter character so we know where to look
1556144026Sharti	 */
1557144026Sharti	while ((*file == ' ') || (*file == '\t')) {
1558144026Sharti		file++;
1559144026Sharti	}
15601590Srgrimes
1561144026Sharti	if ((*file != '"') && (*file != '<')) {
1562144026Sharti		Parse_Error(PARSE_FATAL,
1563144026Sharti		    ".include filename must be delimited by '\"' or '<'");
1564144026Sharti		return;
1565144026Sharti	}
15661590Srgrimes
1567144026Sharti	/*
1568144026Sharti	 * Set the search path on which to find the include file based on the
1569144026Sharti	 * characters which bracket its name. Angle-brackets imply it's
1570144026Sharti	 * a system Makefile while double-quotes imply it's a user makefile
1571144026Sharti	 */
1572144026Sharti	if (*file == '<') {
1573144026Sharti		isSystem = TRUE;
1574144026Sharti		endc = '>';
1575144026Sharti	} else {
1576144026Sharti		isSystem = FALSE;
1577144026Sharti		endc = '"';
1578144026Sharti	}
15791590Srgrimes
1580144026Sharti	/*
1581144026Sharti	* Skip to matching delimiter
1582144026Sharti	*/
1583144026Sharti	for (cp = ++file; *cp && *cp != endc; cp++) {
1584144026Sharti		continue;
1585144026Sharti	}
15861590Srgrimes
1587144026Sharti	if (*cp != endc) {
1588144026Sharti		Parse_Error(PARSE_FATAL,
1589144026Sharti		    "Unclosed %cinclude filename. '%c' expected", '.', endc);
1590144026Sharti		return;
1591144026Sharti	}
1592144026Sharti	*cp = '\0';
15931590Srgrimes
1594144026Sharti	/*
1595144026Sharti	 * Substitute for any variables in the file name before trying to
1596144026Sharti	 * find the thing.
1597144026Sharti	 */
1598144026Sharti	buf = Var_Subst(NULL, file, VAR_CMD, FALSE);
1599144026Sharti	file = Buf_Peel(buf);
16001590Srgrimes
16011590Srgrimes	/*
1602144026Sharti	 * Now we know the file's name and its search path, we attempt to
1603144026Sharti	 * find the durn thing. A return of NULL indicates the file don't
1604144026Sharti	 * exist.
16051590Srgrimes	 */
1606144026Sharti	if (!isSystem) {
1607144026Sharti		/*
1608144026Sharti		 * Include files contained in double-quotes are first searched
1609144026Sharti		 * for relative to the including file's location. We don't want
1610144026Sharti		 * to cd there, of course, so we just tack on the old file's
1611144026Sharti		 * leading path components and call Dir_FindFile to see if
1612144026Sharti		 * we can locate the beast.
1613144026Sharti		 */
1614144026Sharti		char	*prefEnd, *Fname;
16151590Srgrimes
1616144026Sharti		/* Make a temporary copy of this, to be safe. */
1617144026Sharti		Fname = estrdup(curFile.fname);
161818730Ssteve
1619144026Sharti		prefEnd = strrchr(Fname, '/');
1620144026Sharti		if (prefEnd != (char *)NULL) {
1621144026Sharti			char	*newName;
16228874Srgrimes
1623144026Sharti			*prefEnd = '\0';
1624144026Sharti			if (file[0] == '/')
1625144026Sharti				newName = estrdup(file);
1626144026Sharti			else
1627144026Sharti				newName = str_concat(Fname, file, STR_ADDSLASH);
1628144026Sharti			fullname = Path_FindFile(newName, &parseIncPath);
1629144026Sharti			if (fullname == NULL) {
1630144026Sharti				fullname = Path_FindFile(newName,
1631144026Sharti				    &dirSearchPath);
1632144026Sharti			}
1633144026Sharti			free(newName);
1634144026Sharti			*prefEnd = '/';
1635144026Sharti		} else {
1636144026Sharti			fullname = NULL;
1637144026Sharti		}
1638144026Sharti		free(Fname);
16391590Srgrimes	} else {
1640144026Sharti		fullname = NULL;
16411590Srgrimes	}
16421590Srgrimes
1643138264Sharti	if (fullname == NULL) {
1644144026Sharti		/*
1645144026Sharti		 * System makefile or makefile wasn't found in same directory as
1646144026Sharti		 * included makefile. Search for it first on the -I search path,
1647144026Sharti		 * then on the .PATH search path, if not found in a -I
1648144026Sharti		 * directory.
1649144026Sharti		 * XXX: Suffix specific?
1650144026Sharti		 */
1651144026Sharti		fullname = Path_FindFile(file, &parseIncPath);
1652144026Sharti		if (fullname == NULL) {
1653144026Sharti			fullname = Path_FindFile(file, &dirSearchPath);
1654144026Sharti		}
16551590Srgrimes	}
16561590Srgrimes
1657144026Sharti	if (fullname == NULL) {
1658144026Sharti		/*
1659144026Sharti		 * Still haven't found the makefile. Look for it on the system
1660144026Sharti		 * path as a last resort.
1661144026Sharti		 */
1662144026Sharti		fullname = Path_FindFile(file, &sysIncPath);
1663144026Sharti	}
16641590Srgrimes
1665144026Sharti	if (fullname == NULL) {
1666144026Sharti		*cp = endc;
1667144026Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
1668144026Sharti		/* XXXHB free(file) */
1669144026Sharti		return;
1670144026Sharti	}
16711590Srgrimes
1672144026Sharti	free(file);
16735814Sjkh
1674144026Sharti	/*
1675144026Sharti	* Once we find the absolute path to the file, we get to save all the
1676144026Sharti	* state from the current file before we can start reading this
1677144026Sharti	* include file. The state is stored in an IFile structure which
1678144026Sharti	* is placed on a list with other IFile structures. The list makes
1679144026Sharti	* a very nice stack to track how we got here...
1680144026Sharti	*/
1681144026Sharti	oldFile = emalloc(sizeof(IFile));
1682144026Sharti	memcpy(oldFile, &curFile, sizeof(IFile));
16831590Srgrimes
1684144026Sharti	Lst_AtFront(&includes, oldFile);
16851590Srgrimes
16861590Srgrimes	/*
1687144026Sharti	 * Once the previous state has been saved, we can get down to reading
1688144026Sharti	 * the new file. We set up the name of the file to be the absolute
1689144026Sharti	 * name of the include file so error messages refer to the right
1690144026Sharti	 * place. Naturally enough, we start reading at line number 0.
16911590Srgrimes	 */
1692144026Sharti	curFile.fname = fullname;
1693144026Sharti	curFile.lineno = 0;
1694144026Sharti
1695144026Sharti	curFile.F = fopen(fullname, "r");
1696144026Sharti	curFile.p = NULL;
1697144026Sharti	if (curFile.F == NULL) {
1698144026Sharti		Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1699144026Sharti		/*
1700144026Sharti		 * Pop to previous file
1701144026Sharti		 */
1702144026Sharti		ParseEOF(0);
1703144026Sharti	} else {
1704144026Sharti		Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
1705144026Sharti	}
17061590Srgrimes}
17071590Srgrimes
17081590Srgrimes/*-
17091590Srgrimes *---------------------------------------------------------------------
17101590Srgrimes * Parse_FromString  --
17111590Srgrimes *	Start Parsing from the given string
17128874Srgrimes *
17131590Srgrimes * Results:
17141590Srgrimes *	None
17151590Srgrimes *
17161590Srgrimes * Side Effects:
1717126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1718126824Sru *	curFile.fname and curFile.F are altered for the new file
17191590Srgrimes *---------------------------------------------------------------------
17201590Srgrimes */
17211590Srgrimesvoid
1722126824SruParse_FromString(char *str, int lineno)
17231590Srgrimes{
1724144026Sharti	IFile	*oldFile;	/* state associated with this file */
17251590Srgrimes
1726144026Sharti	DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno));
17271590Srgrimes
1728144026Sharti	oldFile = emalloc(sizeof(IFile));
1729144026Sharti	memcpy(oldFile, &curFile, sizeof(IFile));
17308874Srgrimes
1731144026Sharti	Lst_AtFront(&includes, oldFile);
17321590Srgrimes
1733144026Sharti	curFile.F = NULL;
1734144026Sharti	curFile.p = emalloc(sizeof(PTR));
1735144026Sharti	curFile.p->str = curFile.p->ptr = str;
1736144026Sharti	curFile.lineno = lineno;
1737144026Sharti	curFile.fname = estrdup(curFile.fname);
17381590Srgrimes}
17391590Srgrimes
17401590Srgrimes#ifdef SYSVINCLUDE
17411590Srgrimes/*-
17421590Srgrimes *---------------------------------------------------------------------
17431590Srgrimes * ParseTraditionalInclude  --
17441590Srgrimes *	Push to another file.
17458874Srgrimes *
17461590Srgrimes *	The input is the line minus the "include".  The file name is
17471590Srgrimes *	the string following the "include".
17481590Srgrimes *
17491590Srgrimes * Results:
17501590Srgrimes *	None
17511590Srgrimes *
17521590Srgrimes * Side Effects:
1753126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1754126824Sru *	curFile.fname and curFile.F are altered for the new file
17551590Srgrimes *---------------------------------------------------------------------
17561590Srgrimes */
17571590Srgrimesstatic void
1758141270ShartiParseTraditionalInclude(char *file)
17591590Srgrimes{
1760144026Sharti	char	*fullname;	/* full pathname of file */
1761144026Sharti	IFile	*oldFile;	/* state associated with current file */
1762144026Sharti	char	*cp;		/* current position in file spec */
1763144026Sharti	Buffer	*buf;
17641590Srgrimes
1765144026Sharti	/*
1766144026Sharti	 * Skip over whitespace
1767144026Sharti	 */
1768144026Sharti	while ((*file == ' ') || (*file == '\t')) {
1769144026Sharti		file++;
1770144026Sharti	}
17711590Srgrimes
1772144026Sharti	if (*file == '\0') {
1773144026Sharti		Parse_Error(PARSE_FATAL, "Filename missing from \"include\"");
1774144026Sharti		return;
1775144026Sharti	}
17761590Srgrimes
1777144026Sharti	/*
1778144026Sharti	* Skip to end of line or next whitespace
1779144026Sharti	*/
1780144026Sharti	for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1781144026Sharti		continue;
1782144026Sharti	}
17831590Srgrimes
1784144026Sharti	*cp = '\0';
17851590Srgrimes
1786144026Sharti	/*
1787144026Sharti	 * Substitute for any variables in the file name before trying to
1788144026Sharti	 * find the thing.
1789144026Sharti	 */
1790144026Sharti	buf = Var_Subst(NULL, file, VAR_CMD, FALSE);
1791144026Sharti	file = Buf_Peel(buf);
17921590Srgrimes
17931590Srgrimes	/*
1794144026Sharti	 * Now we know the file's name, we attempt to find the durn thing.
1795144026Sharti	 * Search for it first on the -I search path, then on the .PATH
1796144026Sharti	 * search path, if not found in a -I directory.
17971590Srgrimes	 */
1798144026Sharti	fullname = Path_FindFile(file, &parseIncPath);
1799144026Sharti	if (fullname == NULL) {
1800144026Sharti		fullname = Path_FindFile(file, &dirSearchPath);
1801144026Sharti	}
18021590Srgrimes
1803144026Sharti	if (fullname == NULL) {
1804144026Sharti		/*
1805144026Sharti		 * Still haven't found the makefile. Look for it on the system
1806144026Sharti		 * path as a last resort.
1807144026Sharti		 */
1808144026Sharti		fullname = Path_FindFile(file, &sysIncPath);
1809144026Sharti	}
18101590Srgrimes
1811144026Sharti	if (fullname == NULL) {
1812144026Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
1813144026Sharti		/* XXXHB free(file) */
1814144026Sharti		return;
1815144026Sharti	}
1816142457Sharti
1817144026Sharti	/* XXXHB free(file) */
18181590Srgrimes
1819144026Sharti	/*
1820144026Sharti	 * Once we find the absolute path to the file, we get to save all the
1821144026Sharti	 * state from the current file before we can start reading this
1822144026Sharti	 * include file. The state is stored in an IFile structure which
1823144026Sharti	 * is placed on a list with other IFile structures. The list makes
1824144026Sharti	 * a very nice stack to track how we got here...
1825144026Sharti	 */
1826144026Sharti	oldFile = emalloc(sizeof(IFile));
1827144026Sharti	memcpy(oldFile, &curFile, sizeof(IFile));
18281590Srgrimes
1829144026Sharti	Lst_AtFront(&includes, oldFile);
18301590Srgrimes
18311590Srgrimes	/*
1832144026Sharti	 * Once the previous state has been saved, we can get down to reading
1833144026Sharti	 * the new file. We set up the name of the file to be the absolute
1834144026Sharti	 * name of the include file so error messages refer to the right
1835144026Sharti	 * place. Naturally enough, we start reading at line number 0.
18361590Srgrimes	 */
1837144026Sharti	curFile.fname = fullname;
1838144026Sharti	curFile.lineno = 0;
1839144026Sharti
1840144026Sharti	curFile.F = fopen(fullname, "r");
1841144026Sharti	curFile.p = NULL;
1842144026Sharti	if (curFile.F == NULL) {
1843144026Sharti		Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1844144026Sharti		/*
1845144026Sharti		 * Pop to previous file
1846144026Sharti		 */
1847144026Sharti		 ParseEOF(1);
1848144026Sharti	} else {
1849144026Sharti		Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
1850144026Sharti	}
18511590Srgrimes}
18521590Srgrimes#endif
18531590Srgrimes
18541590Srgrimes/*-
18551590Srgrimes *---------------------------------------------------------------------
18561590Srgrimes * ParseEOF  --
18571590Srgrimes *	Called when EOF is reached in the current file. If we were reading
18581590Srgrimes *	an include file, the includes stack is popped and things set up
18591590Srgrimes *	to go back to reading the previous file at the previous location.
18601590Srgrimes *
18611590Srgrimes * Results:
18621590Srgrimes *	CONTINUE if there's more to do. DONE if not.
18631590Srgrimes *
18641590Srgrimes * Side Effects:
1865126824Sru *	The old curFile.F is closed. The includes list is shortened.
1866126824Sru *	curFile.lineno, curFile.F, and curFile.fname are changed if
1867126824Sru *	CONTINUE is returned.
18681590Srgrimes *---------------------------------------------------------------------
18691590Srgrimes */
18701590Srgrimesstatic int
1871138232ShartiParseEOF(int opened)
18721590Srgrimes{
1873144026Sharti	IFile	*ifile;		/* the state on the top of the includes stack */
18741590Srgrimes
1875144026Sharti	if (Lst_IsEmpty(&includes)) {
1876144026Sharti		Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
1877144026Sharti		return (DONE);
1878144026Sharti	}
18791590Srgrimes
1880144026Sharti	ifile = Lst_DeQueue(&includes);
1881144026Sharti	free(curFile.fname);
1882144026Sharti	if (opened && curFile.F) {
1883144026Sharti		fclose(curFile.F);
1884144026Sharti		Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
1885144026Sharti	}
1886144026Sharti	if (curFile.p) {
1887144026Sharti		free(curFile.p->str);
1888144026Sharti		free(curFile.p);
1889144026Sharti	}
1890144026Sharti	memcpy(&curFile, ifile, sizeof(IFile));
1891144026Sharti	free(ifile);
1892144026Sharti	return (CONTINUE);
18931590Srgrimes}
18941590Srgrimes
18951590Srgrimes/*-
18961590Srgrimes *---------------------------------------------------------------------
18971590Srgrimes * ParseReadc  --
18988874Srgrimes *	Read a character from the current file
18991590Srgrimes *
19001590Srgrimes * Results:
19011590Srgrimes *	The character that was read
19021590Srgrimes *
19031590Srgrimes * Side Effects:
19041590Srgrimes *---------------------------------------------------------------------
19051590Srgrimes */
19061590Srgrimesstatic int
1907104696SjmallettParseReadc(void)
19081590Srgrimes{
1909138232Sharti
1910144026Sharti	if (curFile.F)
1911144026Sharti		return (fgetc(curFile.F));
19128874Srgrimes
1913144026Sharti	if (curFile.p && *curFile.p->ptr)
1914144026Sharti		return (*curFile.p->ptr++);
1915144026Sharti	return (EOF);
19161590Srgrimes}
19171590Srgrimes
19181590Srgrimes
19191590Srgrimes/*-
19201590Srgrimes *---------------------------------------------------------------------
19211590Srgrimes * ParseUnreadc  --
19228874Srgrimes *	Put back a character to the current file
19231590Srgrimes *
19241590Srgrimes * Results:
19251590Srgrimes *	None.
19261590Srgrimes *
19271590Srgrimes * Side Effects:
19281590Srgrimes *---------------------------------------------------------------------
19291590Srgrimes */
19301590Srgrimesstatic void
1931104696SjmallettParseUnreadc(int c)
19321590Srgrimes{
1933138232Sharti
1934144026Sharti	if (curFile.F) {
1935144026Sharti		ungetc(c, curFile.F);
1936144026Sharti		return;
1937144026Sharti	}
1938144026Sharti	if (curFile.p) {
1939144026Sharti		*--(curFile.p->ptr) = c;
1940144026Sharti		return;
1941144026Sharti	}
19421590Srgrimes}
19431590Srgrimes
19441590Srgrimes/* ParseSkipLine():
1945104696Sjmallett *	Grab the next line unless it begins with a dot (`.') and we're told to
1946104696Sjmallett *	ignore such lines.
19471590Srgrimes */
19481590Srgrimesstatic char *
1949126824SruParseSkipLine(int skip, int keep_newline)
19501590Srgrimes{
1951144026Sharti	char *line;
1952144026Sharti	int c, lastc;
1953144026Sharti	Buffer *buf;
19541590Srgrimes
1955144026Sharti	buf = Buf_Init(MAKE_BSIZE);
19561590Srgrimes
1957144026Sharti	do {
1958144026Sharti		Buf_Clear(buf);
1959144026Sharti		lastc = '\0';
19608874Srgrimes
1961144026Sharti		while (((c = ParseReadc()) != '\n' || lastc == '\\')
1962144026Sharti		    && c != EOF) {
1963144026Sharti			if (skip && c == '#' && lastc != '\\') {
1964144026Sharti				/*
1965144026Sharti				 * let a comment be terminated even by an
1966144026Sharti				 * escaped \n. This is consistent to comment
1967144026Sharti				 * handling in ParseReadLine
1968144026Sharti				 */
1969144026Sharti				while ((c = ParseReadc()) != '\n' && c != EOF)
1970144026Sharti					;
1971144026Sharti				break;
1972144026Sharti			}
1973144026Sharti			if (c == '\n') {
1974144026Sharti				if (keep_newline)
1975144026Sharti					Buf_AddByte(buf, (Byte)c);
1976144026Sharti				else
1977144026Sharti					Buf_ReplaceLastByte(buf, (Byte)' ');
1978144026Sharti				curFile.lineno++;
19798874Srgrimes
1980144026Sharti				while ((c = ParseReadc()) == ' ' || c == '\t')
1981144026Sharti					continue;
19828874Srgrimes
1983144026Sharti				if (c == EOF)
1984144026Sharti					break;
1985144026Sharti			}
198674272Swill
1987144026Sharti			Buf_AddByte(buf, (Byte)c);
1988144026Sharti			lastc = c;
1989144026Sharti		}
199018456Ssteve
1991144026Sharti		if (c == EOF) {
1992144026Sharti			Parse_Error(PARSE_FATAL,
1993144026Sharti			    "Unclosed conditional/for loop");
1994144026Sharti			Buf_Destroy(buf, TRUE);
1995144026Sharti			return (NULL);
1996144026Sharti		}
199718456Ssteve
1998144026Sharti		curFile.lineno++;
1999144026Sharti		Buf_AddByte(buf, (Byte)'\0');
2000144026Sharti		line = Buf_Data(buf);
2001144026Sharti	} while (skip == 1 && line[0] != '.');
200218456Ssteve
2003144026Sharti	Buf_Destroy(buf, FALSE);
2004144026Sharti	return (line);
20051590Srgrimes}
20061590Srgrimes
20071590Srgrimes/*-
20081590Srgrimes *---------------------------------------------------------------------
20091590Srgrimes * ParseReadLine --
20101590Srgrimes *	Read an entire line from the input file. Called only by Parse_File.
20111590Srgrimes *	To facilitate escaped newlines and what have you, a character is
20121590Srgrimes *	buffered in 'lastc', which is '\0' when no characters have been
20131590Srgrimes *	read. When we break out of the loop, c holds the terminating
20141590Srgrimes *	character and lastc holds a character that should be added to
20151590Srgrimes *	the line (unless we don't read anything but a terminator).
20161590Srgrimes *
20171590Srgrimes * Results:
20181590Srgrimes *	A line w/o its newline
20191590Srgrimes *
20201590Srgrimes * Side Effects:
20211590Srgrimes *	Only those associated with reading a character
20221590Srgrimes *---------------------------------------------------------------------
20231590Srgrimes */
20241590Srgrimesstatic char *
2025138232ShartiParseReadLine(void)
20261590Srgrimes{
2027144026Sharti	Buffer	*buf;		/* Buffer for current line */
2028144026Sharti	int	c;		/* the current character */
2029144026Sharti	int	lastc;		/* The most-recent character */
2030144026Sharti	Boolean	semiNL;		/* treat semi-colons as newlines */
2031144026Sharti	Boolean	ignDepOp;	/* TRUE if should ignore dependency operators
20321590Srgrimes				 * for the purposes of setting semiNL */
2033144026Sharti	Boolean	ignComment;	/* TRUE if should ignore comments (in a
20341590Srgrimes				 * shell command */
2035144026Sharti	char	*line;		/* Result */
2036144026Sharti	char	*ep;		/* to strip trailing blanks */
2037144026Sharti	int	lineno;		/* Saved line # */
20381590Srgrimes
2039144026Sharti	semiNL = FALSE;
2040144026Sharti	ignDepOp = FALSE;
2041144026Sharti	ignComment = FALSE;
20421590Srgrimes
2043144026Sharti	/*
2044144026Sharti	 * Handle special-characters at the beginning of the line. Either a
2045144026Sharti	 * leading tab (shell command) or pound-sign (possible conditional)
2046144026Sharti	 * forces us to ignore comments and dependency operators and treat
2047144026Sharti	 * semi-colons as semi-colons (by leaving semiNL FALSE). This also
2048144026Sharti	 * discards completely blank lines.
2049144026Sharti	 */
2050144026Sharti	for (;;) {
2051144026Sharti		c = ParseReadc();
20521590Srgrimes
2053144026Sharti		if (c == '\t') {
2054144026Sharti			ignComment = ignDepOp = TRUE;
2055144026Sharti			break;
2056144026Sharti		} else if (c == '\n') {
2057144026Sharti			curFile.lineno++;
2058144026Sharti		} else if (c == '#') {
2059144026Sharti			ParseUnreadc(c);
2060144026Sharti			break;
2061144026Sharti		} else {
2062144026Sharti			/*
2063144026Sharti			 * Anything else breaks out without doing anything
2064144026Sharti			 */
2065144026Sharti			break;
2066144026Sharti		}
20671590Srgrimes	}
20688874Srgrimes
2069144026Sharti	if (c != EOF) {
2070144026Sharti		lastc = c;
2071144026Sharti		buf = Buf_Init(MAKE_BSIZE);
20728874Srgrimes
2073144026Sharti		while (((c = ParseReadc()) != '\n' || (lastc == '\\')) &&
2074144026Sharti		    (c != EOF)) {
2075144026Sharti  test_char:
2076144026Sharti			switch (c) {
2077144026Sharti			  case '\n':
2078144026Sharti				/*
2079144026Sharti				 * Escaped newline: read characters until a
2080144026Sharti				 * non-space or an unescaped newline and
2081144026Sharti				 * replace them all by a single space. This is
2082144026Sharti				 * done by storing the space over the backslash
2083144026Sharti				 * and dropping through with the next nonspace.
2084144026Sharti				 * If it is a semi-colon and semiNL is TRUE,
2085144026Sharti				 * it will be recognized as a newline in the
2086144026Sharti				 * code below this...
2087144026Sharti				 */
2088144026Sharti				curFile.lineno++;
2089144026Sharti				lastc = ' ';
2090144026Sharti				while ((c = ParseReadc()) == ' ' || c == '\t') {
2091144026Sharti					continue;
2092144026Sharti				}
2093144026Sharti				if (c == EOF || c == '\n') {
2094144026Sharti					goto line_read;
2095144026Sharti				} else {
2096144026Sharti					/*
2097144026Sharti					 * Check for comments, semiNL's, etc. --
2098144026Sharti					 * easier than ParseUnreadc(c);
2099144026Sharti					 * continue;
2100144026Sharti					 */
2101144026Sharti					goto test_char;
2102144026Sharti				}
2103144026Sharti				/*NOTREACHED*/
2104144026Sharti				break;
2105144026Sharti
2106144026Sharti			  case ';':
2107144026Sharti				/*
2108144026Sharti				 * Semi-colon: Need to see if it should be
2109144026Sharti				 * interpreted as a newline
2110144026Sharti				 */
2111144026Sharti				if (semiNL) {
2112144026Sharti					/*
2113144026Sharti					 * To make sure the command that may
2114144026Sharti					 * be following this semi-colon begins
2115144026Sharti					 * with a tab, we push one back into the
2116144026Sharti					 * input stream. This will overwrite the
2117144026Sharti					 * semi-colon in the buffer. If there is
2118144026Sharti					 * no command following, this does no
2119144026Sharti					 * harm, since the newline remains in
2120144026Sharti					 * the buffer and the
2121144026Sharti					 * whole line is ignored.
2122144026Sharti					 */
2123144026Sharti					ParseUnreadc('\t');
2124144026Sharti					goto line_read;
2125144026Sharti				}
2126144026Sharti				break;
2127144026Sharti			  case '=':
2128144026Sharti				if (!semiNL) {
2129144026Sharti					/*
2130144026Sharti					 * Haven't seen a dependency operator
2131144026Sharti					 * before this, so this must be a
2132144026Sharti					 * variable assignment -- don't pay
2133144026Sharti					 * attention to dependency operators
2134144026Sharti					 * after this.
2135144026Sharti					 */
2136144026Sharti					ignDepOp = TRUE;
2137144026Sharti				} else if (lastc == ':' || lastc == '!') {
2138144026Sharti					/*
2139144026Sharti					 * Well, we've seen a dependency
2140144026Sharti					 * operator already, but it was the
2141144026Sharti					 * previous character, so this is really
2142144026Sharti					 * just an expanded variable assignment.
2143144026Sharti					 * Revert semi-colons to being just
2144144026Sharti					 * semi-colons again and ignore any more
2145144026Sharti					 * dependency operators.
2146144026Sharti					 *
2147144026Sharti					 * XXX: Note that a line like
2148144026Sharti					 * "foo : a:=b" will blow up, but who'd
2149144026Sharti					 * write a line like that anyway?
2150144026Sharti					 */
2151144026Sharti					ignDepOp = TRUE;
2152144026Sharti					semiNL = FALSE;
2153144026Sharti				}
2154144026Sharti				break;
2155144026Sharti			  case '#':
2156144026Sharti				if (!ignComment) {
2157144026Sharti					if (lastc != '\\') {
2158144026Sharti						/*
2159144026Sharti						 * If the character is a hash
2160144026Sharti						 * mark and it isn't escaped
2161144026Sharti						 * (or we're being compatible),
2162144026Sharti						 * the thing is a comment.
2163144026Sharti						 * Skip to the end of the line.
2164144026Sharti						 */
2165144026Sharti						do {
2166144026Sharti							c = ParseReadc();
2167144026Sharti						} while (c != '\n' && c != EOF);
2168144026Sharti						goto line_read;
2169144026Sharti					} else {
2170144026Sharti						/*
2171144026Sharti						 * Don't add the backslash.
2172144026Sharti						 * Just let the # get copied
2173144026Sharti						 * over.
2174144026Sharti						 */
2175144026Sharti						lastc = c;
2176144026Sharti						continue;
2177144026Sharti					}
2178144026Sharti				}
2179144026Sharti				break;
2180144026Sharti
2181144026Sharti			  case ':':
2182144026Sharti			  case '!':
2183144026Sharti				if (!ignDepOp && (c == ':' || c == '!')) {
2184144026Sharti					/*
2185144026Sharti					 * A semi-colon is recognized as a
2186144026Sharti					 * newline only on dependency lines.
2187144026Sharti					 * Dependency lines are lines with a
2188144026Sharti					 * colon or an exclamation point.
2189144026Sharti					 * Ergo...
2190144026Sharti					 */
2191144026Sharti					semiNL = TRUE;
2192144026Sharti				}
2193144026Sharti				break;
2194144026Sharti
2195144026Sharti			  default:
2196144026Sharti				break;
2197144026Sharti			}
2198144026Sharti			/*
2199144026Sharti			 * Copy in the previous character and save this one in
2200144026Sharti			 * lastc.
2201144026Sharti			 */
2202144026Sharti			Buf_AddByte(buf, (Byte)lastc);
2203144026Sharti			lastc = c;
2204144026Sharti		}
2205144026Sharti  line_read:
2206126824Sru		curFile.lineno++;
2207144026Sharti
2208144026Sharti		if (lastc != '\0') {
2209144026Sharti			Buf_AddByte(buf, (Byte)lastc);
22101590Srgrimes		}
2211144026Sharti		Buf_AddByte(buf, (Byte)'\0');
2212144026Sharti		line = Buf_Peel(buf);
22131590Srgrimes
22141590Srgrimes		/*
2215144026Sharti		 * Strip trailing blanks and tabs from the line.
2216144026Sharti		 * Do not strip a blank or tab that is preceded by
2217144026Sharti		 * a '\'
22181590Srgrimes		 */
2219144026Sharti		ep = line;
2220144026Sharti		while (*ep)
2221144026Sharti			++ep;
2222144026Sharti		while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
2223144026Sharti			if (ep > line + 1 && ep[-2] == '\\')
2224144026Sharti				break;
2225144026Sharti			--ep;
22268874Srgrimes		}
2227144026Sharti		*ep = 0;
2228144026Sharti
2229144026Sharti		if (line[0] == '.') {
22301590Srgrimes			/*
2231144026Sharti			 * The line might be a conditional. Ask the
2232144026Sharti			 * conditional module about it and act accordingly
22331590Srgrimes			 */
2234144026Sharti			switch (Cond_Eval(line)) {
2235144026Sharti			  case COND_SKIP:
2236144026Sharti				/*
2237144026Sharti				 * Skip to next conditional that evaluates to
2238144026Sharti				 * COND_PARSE.
2239144026Sharti				 */
2240144026Sharti				do {
2241144026Sharti					free(line);
2242144026Sharti					line = ParseSkipLine(1, 0);
2243144026Sharti				} while (line && Cond_Eval(line) != COND_PARSE);
2244144026Sharti				if (line == NULL)
2245144026Sharti					break;
2246144026Sharti				/*FALLTHRU*/
22478874Srgrimes
2248144026Sharti			  case COND_PARSE:
2249144026Sharti				free(line);
2250144026Sharti				line = ParseReadLine();
2251144026Sharti				break;
22528874Srgrimes
2253144026Sharti			  case COND_INVALID:
2254144026Sharti				if (For_Eval(line)) {
2255144026Sharti					int ok;
2256144026Sharti					free(line);
2257144026Sharti					lineno = curFile.lineno;
2258144026Sharti					do {
2259144026Sharti						/*
2260144026Sharti						 * Skip after the matching end
2261144026Sharti						 */
2262144026Sharti						line = ParseSkipLine(0, 1);
2263144026Sharti						if (line == NULL) {
2264144026Sharti							Parse_Error(PARSE_FATAL,
2265144026Sharti							    "Unexpected end of"
2266144026Sharti							    " file in for "
2267144026Sharti							    "loop.\n");
2268144026Sharti							break;
2269144026Sharti						}
2270144026Sharti						ok = For_Eval(line);
2271144026Sharti						free(line);
2272144026Sharti					} while (ok);
2273144026Sharti					if (line != NULL)
2274144026Sharti						For_Run(lineno);
2275144026Sharti					line = ParseReadLine();
2276144026Sharti				}
2277144026Sharti				break;
22785814Sjkh
2279144026Sharti			  default:
2280144026Sharti				break;
2281144026Sharti			}
2282144026Sharti		}
2283144026Sharti		return (line);
22848874Srgrimes
2285144026Sharti	} else {
22861590Srgrimes		/*
2287144026Sharti		 * Hit end-of-file, so return a NULL line to indicate this.
22881590Srgrimes		 */
2289144026Sharti		return (NULL);
22901590Srgrimes	}
22911590Srgrimes}
22921590Srgrimes
22931590Srgrimes/*-
22941590Srgrimes *-----------------------------------------------------------------------
22951590Srgrimes * ParseFinishLine --
22961590Srgrimes *	Handle the end of a dependency group.
22971590Srgrimes *
22981590Srgrimes * Results:
22991590Srgrimes *	Nothing.
23001590Srgrimes *
23011590Srgrimes * Side Effects:
23021590Srgrimes *	inLine set FALSE. 'targets' list destroyed.
23031590Srgrimes *
23041590Srgrimes *-----------------------------------------------------------------------
23051590Srgrimes */
23061590Srgrimesstatic void
2307104696SjmallettParseFinishLine(void)
23081590Srgrimes{
2309143372Sharti	const LstNode	*ln;
2310138232Sharti
2311143372Sharti	if (inLine) {
2312143372Sharti		LST_FOREACH(ln, &targets) {
2313143372Sharti			if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM)
2314143372Sharti				Suff_EndTransform(Lst_Datum(ln));
2315143372Sharti		}
2316143372Sharti		Lst_Destroy(&targets, ParseHasCommands);
2317143372Sharti		inLine = FALSE;
2318143372Sharti	}
23191590Srgrimes}
23201590Srgrimes
23218874Srgrimes
23221590Srgrimes/*-
23231590Srgrimes *---------------------------------------------------------------------
23241590Srgrimes * Parse_File --
23251590Srgrimes *	Parse a file into its component parts, incorporating it into the
23261590Srgrimes *	current dependency graph. This is the main function and controls
23271590Srgrimes *	almost every other function in this module
23281590Srgrimes *
23291590Srgrimes * Results:
23301590Srgrimes *	None
23311590Srgrimes *
23321590Srgrimes * Side Effects:
23331590Srgrimes *	Loads. Nodes are added to the list of all targets, nodes and links
23341590Srgrimes *	are added to the dependency graph. etc. etc. etc.
23351590Srgrimes *---------------------------------------------------------------------
23361590Srgrimes */
23371590Srgrimesvoid
2338104696SjmallettParse_File(char *name, FILE *stream)
23391590Srgrimes{
2340144026Sharti	char	*cp;	/* pointer into the line */
2341144026Sharti	char	*line;	/* the line we're working on */
2342144026Sharti	Buffer	*buf;
23431590Srgrimes
2344144026Sharti	inLine = FALSE;
2345144026Sharti	curFile.fname = name;
2346144026Sharti	curFile.F = stream;
2347144026Sharti	curFile.lineno = 0;
2348144026Sharti	fatals = 0;
23491590Srgrimes
2350144026Sharti	Var_Append(".MAKEFILE_LIST", name, VAR_GLOBAL);
2351131456Seik
2352144026Sharti	do {
2353144026Sharti		while ((line = ParseReadLine()) != NULL) {
2354144026Sharti			if (*line == '.') {
2355144026Sharti				/*
2356144026Sharti				 * Lines that begin with the special character
2357144026Sharti				 * are either include or undef directives.
2358144026Sharti				 */
2359144026Sharti				for (cp = line + 1; isspace((unsigned char)*cp);
2360144026Sharti				    cp++) {
2361144026Sharti					continue;
2362144026Sharti				}
2363144026Sharti				if (strncmp(cp, "include", 7) == 0) {
2364144026Sharti					ParseDoInclude(cp + 7);
2365144026Sharti					goto nextLine;
2366144026Sharti				} else if (strncmp(cp, "error", 5) == 0) {
2367144026Sharti					ParseDoError(cp + 5);
2368144026Sharti					goto nextLine;
2369144026Sharti				} else if (strncmp(cp, "warning", 7) == 0) {
2370144026Sharti					ParseDoWarning(cp + 7);
2371144026Sharti					goto nextLine;
2372144026Sharti				} else if (strncmp(cp, "undef", 5) == 0) {
2373144026Sharti					char *cp2;
2374144026Sharti					for (cp += 5;
2375144026Sharti					    isspace((unsigned char)*cp);
2376144026Sharti					    cp++) {
2377144026Sharti						continue;
2378144026Sharti					}
23791590Srgrimes
2380144026Sharti					for (cp2 = cp;
2381144026Sharti					    !isspace((unsigned char)*cp2) &&
2382144026Sharti					   (*cp2 != '\0'); cp2++) {
2383144026Sharti						continue;
2384144026Sharti					}
23851590Srgrimes
2386144026Sharti					*cp2 = '\0';
23871590Srgrimes
2388144026Sharti					buf = Var_Subst(NULL, cp, VAR_CMD,
2389144026Sharti					    FALSE);
2390144026Sharti					cp = Buf_Peel(buf);
2391142457Sharti
2392144026Sharti					Var_Delete(cp, VAR_GLOBAL);
2393144026Sharti					goto nextLine;
2394144026Sharti				}
2395144026Sharti			}
2396144026Sharti			if (*line == '#') {
2397144026Sharti				/*
2398144026Sharti				 * If we're this far, the line must be
2399144026Sharti				 * a comment.
2400144026Sharti				 */
2401144026Sharti				goto nextLine;
2402144026Sharti			}
24038874Srgrimes
2404144026Sharti			if (*line == '\t') {
2405144026Sharti				/*
2406144026Sharti				 * If a line starts with a tab, it can only
2407144026Sharti				 * hope to be a creation command.
2408144026Sharti				 */
2409144026Sharti				for (cp = line + 1;
2410144026Sharti				    isspace((unsigned char)*cp); cp++) {
2411144026Sharti					continue;
2412144026Sharti				}
2413144026Sharti				if (*cp) {
2414144026Sharti					if (inLine) {
2415144026Sharti						LstNode	*ln;
2416144026Sharti						GNode	*gn;
2417143684Sharti
2418144026Sharti						/*
2419144026Sharti						 * So long as it's not a blank
2420144026Sharti						 * line and we're actually in a
2421144026Sharti						 * dependency spec, add the
2422144026Sharti						 * command to the list of
2423144026Sharti						 * commands of all targets in
2424144026Sharti						 * the dependency spec.
2425144026Sharti						 */
2426144026Sharti						LST_FOREACH(ln, &targets) {
2427144026Sharti							gn = Lst_Datum(ln);
2428143684Sharti
2429144026Sharti							/*
2430144026Sharti							 * if target already
2431144026Sharti							 * supplied, ignore
2432144026Sharti							 * commands
2433144026Sharti							 */
2434144026Sharti							if (!(gn->type &
2435144026Sharti							    OP_HAS_COMMANDS))
2436144026Sharti								Lst_AtEnd(&gn->commands, cp);
2437144026Sharti							else
2438144026Sharti								Parse_Error(PARSE_WARNING, "duplicate script "
2439144026Sharti								    "for target \"%s\" ignored", gn->name);
2440144026Sharti						}
2441144026Sharti						continue;
2442144026Sharti					} else {
2443144026Sharti						Parse_Error(PARSE_FATAL,
2444144026Sharti						     "Unassociated shell command \"%s\"",
2445144026Sharti						     cp);
2446144026Sharti					}
2447144026Sharti				}
24481590Srgrimes#ifdef SYSVINCLUDE
2449144026Sharti			} else if (strncmp(line, "include", 7) == 0 &&
2450144026Sharti			    isspace((unsigned char)line[7]) &&
2451144026Sharti			    strchr(line, ':') == NULL) {
2452144026Sharti				/*
2453144026Sharti				 * It's an S3/S5-style "include".
2454144026Sharti				 */
2455144026Sharti				ParseTraditionalInclude(line + 7);
2456144026Sharti				goto nextLine;
24571590Srgrimes#endif
2458144026Sharti			} else if (Parse_IsVar(line)) {
2459144026Sharti				ParseFinishLine();
2460144026Sharti				Parse_DoVar(line, VAR_GLOBAL);
24618874Srgrimes
2462144026Sharti			} else {
2463144026Sharti				/*
2464144026Sharti				 * We now know it's a dependency line so it
2465144026Sharti				 * needs to have all variables expanded before
2466144026Sharti				 * being parsed. Tell the variable module to
2467144026Sharti				 * complain if some variable is undefined...
2468144026Sharti				 * To make life easier on novices, if the line
2469144026Sharti				 * is indented we first make sure the line has
2470144026Sharti				 * a dependency operator in it. If it doesn't
2471144026Sharti				 * have an operator and we're in a dependency
2472144026Sharti				 * line's script, we assume it's actually a
2473144026Sharti				 * shell command and add it to the current
2474144026Sharti				 * list of targets.
2475144026Sharti				 */
2476144026Sharti				cp = line;
2477144026Sharti				if (isspace((unsigned char)line[0])) {
2478144026Sharti					while ((*cp != '\0') &&
2479144026Sharti					    isspace((unsigned char)*cp)) {
2480144026Sharti						cp++;
2481144026Sharti					}
2482144026Sharti					if (*cp == '\0') {
2483144026Sharti						goto nextLine;
2484144026Sharti					}
2485144026Sharti				}
24861590Srgrimes
2487144026Sharti				ParseFinishLine();
2488142457Sharti
2489144026Sharti				buf = Var_Subst(NULL, line, VAR_CMD, TRUE);
2490144026Sharti				cp = Buf_Peel(buf);
24918874Srgrimes
2492144026Sharti				free(line);
2493144026Sharti				line = cp;
2494144026Sharti
2495144026Sharti				/*
2496144026Sharti				 * Need a non-circular list for the target nodes
2497144026Sharti				 */
2498144026Sharti				Lst_Destroy(&targets, NOFREE);
2499144026Sharti				inLine = TRUE;
2500144026Sharti
2501144026Sharti				ParseDoDependency(line);
2502144026Sharti			}
2503144026Sharti
2504144026Sharti    nextLine:
2505144026Sharti			free(line);
2506144026Sharti		}
2507144026Sharti
2508137810Sharti		/*
2509144026Sharti		 * Reached EOF, but it may be just EOF of an include file...
2510137810Sharti		 */
2511144026Sharti	} while (ParseEOF(1) == CONTINUE);
25128874Srgrimes
2513144026Sharti	ParseFinishLine();
25141590Srgrimes
25151590Srgrimes	/*
2516144026Sharti	 * Make sure conditionals are clean
25171590Srgrimes	 */
2518144026Sharti	Cond_End();
25191590Srgrimes
2520144026Sharti	if (fatals)
2521144026Sharti		errx(1, "fatal errors encountered -- cannot continue");
25221590Srgrimes}
25231590Srgrimes
25241590Srgrimes/*-
25251590Srgrimes *---------------------------------------------------------------------
25261590Srgrimes * Parse_Init --
25271590Srgrimes *	initialize the parsing module
25281590Srgrimes *
25291590Srgrimes * Results:
25301590Srgrimes *	none
25311590Srgrimes *
25321590Srgrimes * Side Effects:
25331590Srgrimes *	the parseIncPath list is initialized...
25341590Srgrimes *---------------------------------------------------------------------
25351590Srgrimes */
25361590Srgrimesvoid
2537138232ShartiParse_Init(void)
25381590Srgrimes{
2539138232Sharti
2540144026Sharti	mainNode = NULL;
25411590Srgrimes}
25421590Srgrimes
25431590Srgrimes/*-
25441590Srgrimes *-----------------------------------------------------------------------
25451590Srgrimes * Parse_MainName --
25461590Srgrimes *	Return a Lst of the main target to create for main()'s sake. If
25471590Srgrimes *	no such target exists, we Punt with an obnoxious error message.
25481590Srgrimes *
25491590Srgrimes * Results:
25501590Srgrimes *	A Lst of the single node to create.
25511590Srgrimes *
25521590Srgrimes * Side Effects:
25531590Srgrimes *	None.
25541590Srgrimes *
25551590Srgrimes *-----------------------------------------------------------------------
25561590Srgrimes */
2557138916Shartivoid
2558138916ShartiParse_MainName(Lst *listmain)
25591590Srgrimes{
25601590Srgrimes
2561144026Sharti	if (mainNode == NULL) {
2562144026Sharti		Punt("no target to make.");
2563144026Sharti		/*NOTREACHED*/
2564144026Sharti	} else if (mainNode->type & OP_DOUBLEDEP) {
2565144026Sharti		Lst_AtEnd(listmain, mainNode);
2566144026Sharti		Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW);
2567144026Sharti	} else
2568144026Sharti		Lst_AtEnd(listmain, mainNode);
25691590Srgrimes}
2570