parse.c revision 150595
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 150595 2005-09-26 20:31:00Z phk $");
431590Srgrimes
441590Srgrimes/*-
451590Srgrimes * parse.c --
461590Srgrimes *	Functions to parse a makefile.
471590Srgrimes *
481590Srgrimes *	Most important structures are kept in Lsts. Directories for
491590Srgrimes *	the #include "..." function are kept in the 'parseIncPath' Lst, while
501590Srgrimes *	those for the #include <...> are kept in the 'sysIncPath' Lst. The
511590Srgrimes *	targets currently being defined are kept in the 'targets' Lst.
521590Srgrimes *
531590Srgrimes * Interface:
541590Srgrimes *
55144026Sharti *	Parse_File	Function used to parse a makefile. It must
56144026Sharti *			be given the name of the file, which should
57144026Sharti *			already have been opened, and a function
58144026Sharti *			to call to read a character from the file.
591590Srgrimes *
60144026Sharti *	Parse_IsVar	Returns TRUE if the given line is a
61144026Sharti *			variable assignment. Used by MainParseArgs
62144026Sharti *			to determine if an argument is a target
63144026Sharti *			or a variable assignment. Used internally
64144026Sharti *			for pretty much the same thing...
651590Srgrimes *
66144026Sharti *	Parse_Error	Function called when an error occurs in
67144026Sharti *			parsing. Used by the variable and
68144026Sharti *			conditional modules.
69144026Sharti *
70144026Sharti *	Parse_MainName	Returns a Lst of the main target to create.
711590Srgrimes */
721590Srgrimes
73144341Sharti#include <assert.h>
74141104Sharti#include <ctype.h>
751590Srgrimes#include <stdarg.h>
76141104Sharti#include <string.h>
77141104Sharti#include <stdlib.h>
7827644Scharnier#include <err.h>
79141104Sharti
80141104Sharti#include "arch.h"
81141104Sharti#include "buf.h"
82141104Sharti#include "cond.h"
83141104Sharti#include "config.h"
841590Srgrimes#include "dir.h"
85141104Sharti#include "for.h"
86141104Sharti#include "globals.h"
87141104Sharti#include "GNode.h"
88145683Sharti#include "hash_tables.h"
891590Srgrimes#include "job.h"
90141104Sharti#include "make.h"
91141104Sharti#include "parse.h"
921590Srgrimes#include "pathnames.h"
93146572Sharti#include "shell.h"
94141104Sharti#include "str.h"
95141104Sharti#include "suff.h"
96141104Sharti#include "targ.h"
97141104Sharti#include "util.h"
98141104Sharti#include "var.h"
991590Srgrimes
1001590Srgrimes/*
101144341Sharti * These values are returned by ParsePopInput to tell Parse_File whether to
1021590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file,
1031590Srgrimes * or if it's DONE.
1041590Srgrimes */
1051590Srgrimes#define	CONTINUE	1
1061590Srgrimes#define	DONE		0
107138916Sharti
108138916Sharti/* targets we're working on */
109138916Shartistatic Lst targets = Lst_Initializer(targets);
110138916Sharti
111144026Sharti/* true if currently in a dependency line or its commands */
112144026Shartistatic Boolean inLine;
1131590Srgrimes
114144026Shartistatic int fatals = 0;
1151590Srgrimes
116144026Sharti/*
117144026Sharti * The main target to create. This is the first target on the
118144026Sharti * first dependency line in the first makefile.
119144026Sharti */
120144026Shartistatic GNode *mainNode;
121126824Sru
122144341Sharti/*
123144341Sharti * Definitions for handling #include specifications
124144341Sharti */
125144341Shartistruct IFile {
126144341Sharti	char	*fname;		/* name of previous file */
127144341Sharti	int	lineno;		/* saved line number */
128144341Sharti	FILE	*F;		/* the open stream */
129144341Sharti	char	*str;		/* the string when parsing a string */
130144341Sharti	char	*ptr;		/* the current pointer when parsing a string */
131144341Sharti	TAILQ_ENTRY(IFile) link;/* stack the files */
132144341Sharti};
133144026Sharti
134138916Sharti/* stack of IFiles generated by * #includes */
135144341Shartistatic TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes);
1361590Srgrimes
137144341Sharti/* access current file */
138144341Sharti#define	CURFILE	(TAILQ_FIRST(&includes))
139144341Sharti
140138916Sharti/* list of directories for "..." includes */
141144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath);
142138916Sharti
143138916Sharti/* list of directories for <...> includes */
144144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath);
145138916Sharti
146144026Sharti/*
1471590Srgrimes * specType contains the SPECial TYPE of the current target. It is
1481590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children
1491590Srgrimes * are linked as children of the parent but not vice versa. This variable is
1501590Srgrimes * set in ParseDoDependency
1511590Srgrimes */
1521590Srgrimestypedef enum {
153144026Sharti	Begin,		/* .BEGIN */
154144026Sharti	Default,	/* .DEFAULT */
155144026Sharti	End,		/* .END */
156145971Sharti	ExportVar,	/* .EXPORTVAR */
157144026Sharti	Ignore,		/* .IGNORE */
158144026Sharti	Includes,	/* .INCLUDES */
159144026Sharti	Interrupt,	/* .INTERRUPT */
160144026Sharti	Libs,		/* .LIBS */
161144026Sharti	MFlags,		/* .MFLAGS or .MAKEFLAGS */
162144026Sharti	Main,		/* .MAIN and we don't have anyth. user-spec. to make */
163144026Sharti	Not,		/* Not special */
164144026Sharti	NotParallel,	/* .NOTPARALELL */
165144026Sharti	Null,		/* .NULL */
166144026Sharti	Order,		/* .ORDER */
167144026Sharti	Parallel,	/* .PARALLEL */
168144026Sharti	ExPath,		/* .PATH */
169144026Sharti	Phony,		/* .PHONY */
170144026Sharti	Posix,		/* .POSIX */
171144026Sharti	Precious,	/* .PRECIOUS */
172144026Sharti	ExShell,	/* .SHELL */
173144026Sharti	Silent,		/* .SILENT */
174144026Sharti	SingleShell,	/* .SINGLESHELL */
175144026Sharti	Suffixes,	/* .SUFFIXES */
176144026Sharti	Wait,		/* .WAIT */
177145679Sharti	Warn,		/* .WARN */
178144026Sharti	Attribute	/* Generic attribute */
1791590Srgrimes} ParseSpecial;
1801590Srgrimes
1811590Srgrimesstatic ParseSpecial specType;
18218730Sstevestatic int waiting;
1831590Srgrimes
1841590Srgrimes/*
18569527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1861590Srgrimes * seen, then set to each successive source on the line.
1871590Srgrimes */
188144026Shartistatic GNode *predecessor;
1891590Srgrimes
1901590Srgrimes/*
1911590Srgrimes * The parseKeywords table is searched using binary search when deciding
1921590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial
1931590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while
1941590Srgrimes * the 'op' field is the operator to apply to the list of targets if the
1951590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source)
1961590Srgrimes */
197145616Shartistatic const struct keyword {
198144026Sharti	const char	*name;	/* Name of keyword */
199144026Sharti	ParseSpecial	spec;	/* Type when used as a target */
200144026Sharti	int		op;	/* Operator when used as a source */
2011590Srgrimes} parseKeywords[] = {
202145616Sharti	/* KEYWORD-START-TAG */
203144026Sharti	{ ".BEGIN",		Begin,		0 },
204144026Sharti	{ ".DEFAULT",		Default,	0 },
205144026Sharti	{ ".END",		End,		0 },
206144026Sharti	{ ".EXEC",		Attribute,	OP_EXEC },
207145971Sharti	{ ".EXPORTVAR",		ExportVar,	0 },
208144026Sharti	{ ".IGNORE",		Ignore,		OP_IGNORE },
209144026Sharti	{ ".INCLUDES",		Includes,	0 },
210144026Sharti	{ ".INTERRUPT",		Interrupt,	0 },
211144026Sharti	{ ".INVISIBLE",		Attribute,	OP_INVISIBLE },
212144026Sharti	{ ".JOIN",		Attribute,	OP_JOIN },
213144026Sharti	{ ".LIBS",		Libs,		0 },
214144026Sharti	{ ".MAIN",		Main,		0 },
215144026Sharti	{ ".MAKE",		Attribute,	OP_MAKE },
216144026Sharti	{ ".MAKEFLAGS",		MFlags,		0 },
217144026Sharti	{ ".MFLAGS",		MFlags,		0 },
218144026Sharti	{ ".NOTMAIN",		Attribute,	OP_NOTMAIN },
219144026Sharti	{ ".NOTPARALLEL",	NotParallel,	0 },
220144026Sharti	{ ".NO_PARALLEL",	NotParallel,	0 },
221144026Sharti	{ ".NULL",		Null,		0 },
222144026Sharti	{ ".OPTIONAL",		Attribute,	OP_OPTIONAL },
223144026Sharti	{ ".ORDER",		Order,		0 },
224144026Sharti	{ ".PARALLEL",		Parallel,	0 },
225144026Sharti	{ ".PATH",		ExPath,		0 },
226144026Sharti	{ ".PHONY",		Phony,		OP_PHONY },
227144026Sharti	{ ".POSIX",		Posix,		0 },
228144026Sharti	{ ".PRECIOUS",		Precious,	OP_PRECIOUS },
229144026Sharti	{ ".RECURSIVE",		Attribute,	OP_MAKE },
230144026Sharti	{ ".SHELL",		ExShell,	0 },
231144026Sharti	{ ".SILENT",		Silent,		OP_SILENT },
232144026Sharti	{ ".SINGLESHELL",	SingleShell,	0 },
233144026Sharti	{ ".SUFFIXES",		Suffixes,	0 },
234144026Sharti	{ ".USE",		Attribute,	OP_USE },
235144026Sharti	{ ".WAIT",		Wait,		0 },
236145679Sharti	{ ".WARN",		Warn,		0 },
237145616Sharti	/* KEYWORD-END-TAG */
2381590Srgrimes};
239145616Sharti#define	NKEYWORDS	(sizeof(parseKeywords) / sizeof(parseKeywords[0]))
2401590Srgrimes
241144894Shartistatic void parse_include(char *, int, int);
242150595Sphkstatic void parse_sinclude(char *, int, int);
243144894Shartistatic void parse_message(char *, int, int);
244144894Shartistatic void parse_undef(char *, int, int);
245144894Shartistatic void parse_for(char *, int, int);
246144894Shartistatic void parse_endfor(char *, int, int);
247144894Sharti
248144894Shartistatic const struct directive {
249144894Sharti	const char	*name;
250144894Sharti	int		code;
251144894Sharti	Boolean		skip_flag;	/* execute even when skipped */
252144894Sharti	void		(*func)(char *, int, int);
253144894Sharti} directives[] = {
254145612Sharti	/* DIRECTIVES-START-TAG */
255144894Sharti	{ "elif",	COND_ELIF,	TRUE,	Cond_If },
256144894Sharti	{ "elifdef",	COND_ELIFDEF,	TRUE,	Cond_If },
257144894Sharti	{ "elifmake",	COND_ELIFMAKE,	TRUE,	Cond_If },
258144894Sharti	{ "elifndef",	COND_ELIFNDEF,	TRUE,	Cond_If },
259144894Sharti	{ "elifnmake",	COND_ELIFNMAKE,	TRUE,	Cond_If },
260144894Sharti	{ "else",	COND_ELSE,	TRUE,	Cond_Else },
261144894Sharti	{ "endfor",	0,		FALSE,	parse_endfor },
262144894Sharti	{ "endif",	COND_ENDIF,	TRUE,	Cond_Endif },
263144894Sharti	{ "error",	1,		FALSE,	parse_message },
264144894Sharti	{ "for",	0,		FALSE,	parse_for },
265144894Sharti	{ "if",		COND_IF,	TRUE,	Cond_If },
266144894Sharti	{ "ifdef",	COND_IFDEF,	TRUE,	Cond_If },
267144894Sharti	{ "ifmake",	COND_IFMAKE,	TRUE,	Cond_If },
268144894Sharti	{ "ifndef",	COND_IFNDEF,	TRUE,	Cond_If },
269144894Sharti	{ "ifnmake",	COND_IFNMAKE,	TRUE,	Cond_If },
270144894Sharti	{ "include",	0,		FALSE,	parse_include },
271150595Sphk	{ "sinclude",	0,		FALSE,	parse_sinclude },
272144894Sharti	{ "undef",	0,		FALSE,	parse_undef },
273144894Sharti	{ "warning",	0,		FALSE,	parse_message },
274145612Sharti	/* DIRECTIVES-END-TAG */
275144894Sharti};
276144894Sharti#define	NDIRECTS	(sizeof(directives) / sizeof(directives[0]))
277144894Sharti
2781590Srgrimes/*-
279145616Sharti * ParseFindKeyword
2801590Srgrimes *	Look in the table of keywords for one matching the given string.
2811590Srgrimes *
2821590Srgrimes * Results:
283145616Sharti *	The pointer to keyword table entry or NULL.
2841590Srgrimes */
285145616Shartistatic const struct keyword *
286145616ShartiParseFindKeyword(const char *str)
2871590Srgrimes{
288145616Sharti	int kw;
2898874Srgrimes
290145616Sharti	kw = keyword_hash(str, strlen(str));
291145616Sharti	if (kw < 0 || kw >= (int)NKEYWORDS ||
292145616Sharti	    strcmp(str, parseKeywords[kw].name) != 0)
293145616Sharti		return (NULL);
294145616Sharti	return (&parseKeywords[kw]);
2951590Srgrimes}
2961590Srgrimes
2971590Srgrimes/*-
2981590Srgrimes * Parse_Error  --
2991590Srgrimes *	Error message abort function for parsing. Prints out the context
3001590Srgrimes *	of the error (line number and file) as well as the message with
3011590Srgrimes *	two optional arguments.
3021590Srgrimes *
3031590Srgrimes * Results:
3041590Srgrimes *	None
3051590Srgrimes *
3061590Srgrimes * Side Effects:
3071590Srgrimes *	"fatals" is incremented if the level is PARSE_FATAL.
3081590Srgrimes */
3091590Srgrimes/* VARARGS */
3101590Srgrimesvoid
31198136SjmallettParse_Error(int type, const char *fmt, ...)
3121590Srgrimes{
3131590Srgrimes	va_list ap;
31493056Simp
3151590Srgrimes	va_start(ap, fmt);
316144745Sharti	if (CURFILE != NULL)
317144745Sharti		fprintf(stderr, "\"%s\", line %d: ",
318144745Sharti		    CURFILE->fname, CURFILE->lineno);
3191590Srgrimes	if (type == PARSE_WARNING)
320138232Sharti		fprintf(stderr, "warning: ");
321138232Sharti	vfprintf(stderr, fmt, ap);
3221590Srgrimes	va_end(ap);
323138232Sharti	fprintf(stderr, "\n");
324138232Sharti	fflush(stderr);
3251590Srgrimes	if (type == PARSE_FATAL)
3261590Srgrimes		fatals += 1;
3271590Srgrimes}
3281590Srgrimes
329144341Sharti/**
330144341Sharti * ParsePushInput
331144341Sharti *
332144341Sharti * Push a new input source onto the input stack. If ptr is NULL
333144341Sharti * the fullname is used to fopen the file. If it is not NULL,
334144341Sharti * ptr is assumed to point to the string to be parsed. If opening the
335144341Sharti * file fails, the fullname is freed.
336144341Sharti */
337144341Shartistatic void
338144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno)
339144341Sharti{
340144341Sharti	struct IFile *nf;
341144341Sharti
342144341Sharti	nf = emalloc(sizeof(*nf));
343144341Sharti	nf->fname = fullname;
344144341Sharti	nf->lineno = lineno;
345144341Sharti
346144341Sharti	if (ptr == NULL) {
347144341Sharti		/* the input source is a file */
348144341Sharti		if ((nf->F = fp) == NULL) {
349144341Sharti			nf->F = fopen(fullname, "r");
350144341Sharti			if (nf->F == NULL) {
351144341Sharti				Parse_Error(PARSE_FATAL, "Cannot open %s",
352144341Sharti				    fullname);
353144341Sharti				free(fullname);
354144341Sharti				free(nf);
355144341Sharti				return;
356144341Sharti			}
357144341Sharti		}
358144341Sharti		nf->str = nf->ptr = NULL;
359144341Sharti		Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
360144341Sharti	} else {
361144341Sharti		nf->str = nf->ptr = ptr;
362144341Sharti		nf->F = NULL;
363144341Sharti	}
364144341Sharti	TAILQ_INSERT_HEAD(&includes, nf, link);
365144341Sharti}
366144341Sharti
367144341Sharti/**
368144341Sharti * ParsePopInput
369144341Sharti *	Called when EOF is reached in the current file. If we were reading
370144341Sharti *	an include file, the includes stack is popped and things set up
371144341Sharti *	to go back to reading the previous file at the previous location.
372144341Sharti *
373144341Sharti * Results:
374144341Sharti *	CONTINUE if there's more to do. DONE if not.
375144341Sharti *
376144341Sharti * Side Effects:
377144341Sharti *	The old curFile.F is closed. The includes list is shortened.
378144341Sharti *	curFile.lineno, curFile.F, and curFile.fname are changed if
379144341Sharti *	CONTINUE is returned.
380144341Sharti */
381144341Shartistatic int
382144341ShartiParsePopInput(void)
383144341Sharti{
384144341Sharti	struct IFile *ifile;	/* the state on the top of the includes stack */
385144341Sharti
386144341Sharti	assert(!TAILQ_EMPTY(&includes));
387144341Sharti
388144341Sharti	ifile = TAILQ_FIRST(&includes);
389144341Sharti	TAILQ_REMOVE(&includes, ifile, link);
390144341Sharti
391144341Sharti	free(ifile->fname);
392144341Sharti	if (ifile->F != NULL) {
393144341Sharti		fclose(ifile->F);
394144341Sharti		Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
395144341Sharti	}
396144341Sharti	if (ifile->str != NULL) {
397144341Sharti		free(ifile->str);
398144341Sharti	}
399144341Sharti	free(ifile);
400144341Sharti
401144341Sharti	return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE);
402144341Sharti}
403144341Sharti
404145679Sharti/**
405145679Sharti * parse_warn
406145679Sharti *	Parse the .WARN pseudo-target.
407145679Sharti */
408145679Shartistatic void
409145679Shartiparse_warn(char *line)
410145679Sharti{
411146345Sharti	ArgArray	aa;
412146345Sharti	int		i;
413145679Sharti
414146345Sharti	brk_string(&aa, line, TRUE);
415145679Sharti
416146345Sharti	for (i = 1; i < aa.argc; i++)
417146345Sharti		Main_ParseWarn(aa.argv[i], 0);
418145679Sharti}
419145679Sharti
4201590Srgrimes/*-
4211590Srgrimes *---------------------------------------------------------------------
4221590Srgrimes * ParseLinkSrc  --
423143100Sharti *	Link the parent nodes to their new child. Used by
4241590Srgrimes *	ParseDoDependency. If the specType isn't 'Not', the parent
4251590Srgrimes *	isn't linked as a parent of the child.
4261590Srgrimes *
4271590Srgrimes * Side Effects:
428143100Sharti *	New elements are added to the parents lists of cgn and the
4291590Srgrimes *	children list of cgn. the unmade field of pgn is updated
4301590Srgrimes *	to reflect the additional child.
4311590Srgrimes *---------------------------------------------------------------------
4321590Srgrimes */
433143027Shartistatic void
434143027ShartiParseLinkSrc(Lst *parents, GNode *cgn)
4351590Srgrimes{
436143027Sharti	LstNode	*ln;
437143027Sharti	GNode *pgn;
438138232Sharti
439143027Sharti	LST_FOREACH(ln, parents) {
440143027Sharti		pgn = Lst_Datum(ln);
441143027Sharti		if (Lst_Member(&pgn->children, cgn) == NULL) {
442143027Sharti			Lst_AtEnd(&pgn->children, cgn);
443143027Sharti			if (specType == Not) {
444143027Sharti				Lst_AtEnd(&cgn->parents, pgn);
445143027Sharti			}
446143027Sharti			pgn->unmade += 1;
447143027Sharti		}
4481590Srgrimes	}
4491590Srgrimes}
4501590Srgrimes
4511590Srgrimes/*-
4521590Srgrimes *---------------------------------------------------------------------
4531590Srgrimes * ParseDoOp  --
454143684Sharti *	Apply the parsed operator to all target nodes. Used in
455143684Sharti *	ParseDoDependency once all targets have been found and their
456143684Sharti *	operator parsed. If the previous and new operators are incompatible,
457143684Sharti *	a major error is taken.
4581590Srgrimes *
4591590Srgrimes * Side Effects:
4601590Srgrimes *	The type field of the node is altered to reflect any new bits in
4611590Srgrimes *	the op.
4621590Srgrimes *---------------------------------------------------------------------
4631590Srgrimes */
464143684Shartistatic void
465143684ShartiParseDoOp(int op)
4661590Srgrimes{
467143684Sharti	GNode	*cohort;
468143684Sharti	LstNode	*ln;
469143684Sharti	GNode	*gn;
470138232Sharti
471143684Sharti	LST_FOREACH(ln, &targets) {
472143684Sharti		gn = Lst_Datum(ln);
4731590Srgrimes
474143684Sharti		/*
475143684Sharti		 * If the dependency mask of the operator and the node don't
476143684Sharti		 * match and the node has actually had an operator applied to
477143684Sharti		 * it before, and the operator actually has some dependency
478143684Sharti		 * information in it, complain.
479143684Sharti		 */
480143684Sharti		if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) &&
481143684Sharti		    !OP_NOP(gn->type) && !OP_NOP(op)) {
482143684Sharti			Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
483143684Sharti			    gn->name);
484143684Sharti			return;
485143684Sharti		}
4868874Srgrimes
487143684Sharti		if (op == OP_DOUBLEDEP &&
488143684Sharti		    (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
489143684Sharti			/*
490143684Sharti			 * If the node was the object of a :: operator, we need
491143684Sharti			 * to create a new instance of it for the children and
492143684Sharti			 * commands on this dependency line. The new instance
493143684Sharti			 * is placed on the 'cohorts' list of the initial one
494143684Sharti			 * (note the initial one is not on its own cohorts list)
495143684Sharti			 * and the new instance is linked to all parents of the
496143684Sharti			 * initial instance.
497143684Sharti			 */
498143684Sharti			cohort = Targ_NewGN(gn->name);
4991590Srgrimes
500143684Sharti			/*
501143684Sharti			 * Duplicate links to parents so graph traversal is
502143684Sharti			 * simple. Perhaps some type bits should be duplicated?
503143684Sharti			 *
504143684Sharti			 * Make the cohort invisible as well to avoid
505143684Sharti			 * duplicating it into other variables. True, parents
506143684Sharti			 * of this target won't tend to do anything with their
507143684Sharti			 * local variables, but better safe than sorry.
508143684Sharti			 */
509143684Sharti			ParseLinkSrc(&gn->parents, cohort);
510143684Sharti			cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
511143684Sharti			Lst_AtEnd(&gn->cohorts, cohort);
5121590Srgrimes
513143684Sharti			/*
514143684Sharti			 * Replace the node in the targets list with the
515143684Sharti			 * new copy
516143684Sharti			 */
517143684Sharti			Lst_Replace(ln, cohort);
518143684Sharti			gn = cohort;
519143684Sharti		}
520143684Sharti		/*
521143684Sharti		 * We don't want to nuke any previous flags (whatever they were)
522143684Sharti		 * so we just OR the new operator into the old
523143684Sharti		 */
524143684Sharti		gn->type |= op;
525143684Sharti	}
5261590Srgrimes}
5271590Srgrimes
5281590Srgrimes/*-
5291590Srgrimes *---------------------------------------------------------------------
5301590Srgrimes * ParseDoSrc  --
5311590Srgrimes *	Given the name of a source, figure out if it is an attribute
5321590Srgrimes *	and apply it to the targets if it is. Else decide if there is
5331590Srgrimes *	some attribute which should be applied *to* the source because
5341590Srgrimes *	of some special target and apply it if so. Otherwise, make the
5351590Srgrimes *	source be a child of the targets in the list 'targets'
5361590Srgrimes *
5371590Srgrimes * Results:
5381590Srgrimes *	None
5391590Srgrimes *
5401590Srgrimes * Side Effects:
5411590Srgrimes *	Operator bits may be added to the list of targets or to the source.
5421590Srgrimes *	The targets may have a new source added to their lists of children.
5431590Srgrimes *---------------------------------------------------------------------
5441590Srgrimes */
5451590Srgrimesstatic void
546138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc)
5471590Srgrimes{
548144026Sharti	GNode	*gn = NULL;
549145616Sharti	const struct keyword *kw;
5501590Srgrimes
551145616Sharti	if (src[0] == '.' && isupper ((unsigned char)src[1])) {
552145616Sharti		if ((kw = ParseFindKeyword(src)) != NULL) {
553145616Sharti			if (kw->op != 0) {
554145616Sharti				ParseDoOp(kw->op);
555144026Sharti				return;
556144026Sharti			}
557145616Sharti			if (kw->spec == Wait) {
558144026Sharti				waiting++;
559144026Sharti				return;
560144026Sharti			}
561144026Sharti		}
5621590Srgrimes	}
56318730Ssteve
564144026Sharti	switch (specType) {
565144026Sharti	  case Main:
566144026Sharti		/*
567144026Sharti		 * If we have noted the existence of a .MAIN, it means we need
568144026Sharti		 * to add the sources of said target to the list of things
569144026Sharti		 * to create. The string 'src' is likely to be free, so we
570144026Sharti		 * must make a new copy of it. Note that this will only be
571144026Sharti		 * invoked if the user didn't specify a target on the command
572144026Sharti		 * line. This is to allow #ifmake's to succeed, or something...
573144026Sharti		 */
574144026Sharti		Lst_AtEnd(&create, estrdup(src));
575144026Sharti		/*
576144026Sharti		 * Add the name to the .TARGETS variable as well, so the user
577144026Sharti		 * can employ that, if desired.
578144026Sharti		 */
579144026Sharti		Var_Append(".TARGETS", src, VAR_GLOBAL);
580144026Sharti		return;
58118730Ssteve
582144026Sharti	  case Order:
583144026Sharti		/*
584144026Sharti		 * Create proper predecessor/successor links between the
585144026Sharti		 * previous source and the current one.
586144026Sharti		 */
587144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
588144026Sharti		if (predecessor != NULL) {
589144026Sharti			Lst_AtEnd(&predecessor->successors, gn);
590144026Sharti			Lst_AtEnd(&gn->preds, predecessor);
591144026Sharti		}
592144026Sharti		/*
593144026Sharti		 * The current source now becomes the predecessor for the next
594144026Sharti		 * one.
595144026Sharti		 */
596144026Sharti		predecessor = gn;
597144026Sharti		break;
59818730Ssteve
599144026Sharti	  default:
600144026Sharti		/*
601144026Sharti		 * If the source is not an attribute, we need to find/create
602144026Sharti		 * a node for it. After that we can apply any operator to it
603144026Sharti		 * from a special target or link it to its parents, as
604144026Sharti		 * appropriate.
605144026Sharti		 *
606144026Sharti		 * In the case of a source that was the object of a :: operator,
607144026Sharti		 * the attribute is applied to all of its instances (as kept in
608144026Sharti		 * the 'cohorts' list of the node) or all the cohorts are linked
609144026Sharti		 * to all the targets.
610144026Sharti		 */
611144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
6121590Srgrimes		if (tOp) {
613144026Sharti			gn->type |= tOp;
6141590Srgrimes		} else {
615144026Sharti			ParseLinkSrc(&targets, gn);
6161590Srgrimes		}
617144026Sharti		if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
618144026Sharti			GNode	*cohort;
619144026Sharti			LstNode	*ln;
620144026Sharti
621144026Sharti			for (ln = Lst_First(&gn->cohorts); ln != NULL;
622144026Sharti			    ln = Lst_Succ(ln)) {
623144026Sharti				cohort = Lst_Datum(ln);
624144026Sharti				if (tOp) {
625144026Sharti					cohort->type |= tOp;
626144026Sharti				} else {
627144026Sharti					ParseLinkSrc(&targets, cohort);
628144026Sharti				}
629144026Sharti			}
630144026Sharti		}
631144026Sharti		break;
6321590Srgrimes	}
63318730Ssteve
634144026Sharti	gn->order = waiting;
635144026Sharti	Lst_AtEnd(allsrc, gn);
636144026Sharti	if (waiting) {
637144026Sharti		LstNode	*ln;
638144026Sharti		GNode	*p;
6391590Srgrimes
640143684Sharti		/*
641144026Sharti		 * Check if GNodes needs to be synchronized.
642144026Sharti		 * This has to be when two nodes are on different sides of a
643144026Sharti		 * .WAIT directive.
644143684Sharti		 */
645144026Sharti		LST_FOREACH(ln, allsrc) {
646144026Sharti			p = Lst_Datum(ln);
647144026Sharti
648144026Sharti			if (p->order >= gn->order)
649144026Sharti				break;
650144026Sharti			/*
651144026Sharti			 * XXX: This can cause loops, and loops can cause
652144026Sharti			 * unmade targets, but checking is tedious, and the
653144026Sharti			 * debugging output can show the problem
654144026Sharti			 */
655144026Sharti			Lst_AtEnd(&p->successors, gn);
656144026Sharti			Lst_AtEnd(&gn->preds, p);
657144026Sharti		}
658143684Sharti	}
6591590Srgrimes}
6601590Srgrimes
661138232Sharti
6621590Srgrimes/*-
6631590Srgrimes *---------------------------------------------------------------------
6641590Srgrimes * ParseDoDependency  --
6651590Srgrimes *	Parse the dependency line in line.
6661590Srgrimes *
6671590Srgrimes * Results:
6681590Srgrimes *	None
6691590Srgrimes *
6701590Srgrimes * Side Effects:
6711590Srgrimes *	The nodes of the sources are linked as children to the nodes of the
6721590Srgrimes *	targets. Some nodes may be created.
6731590Srgrimes *
6741590Srgrimes *	We parse a dependency line by first extracting words from the line and
6751590Srgrimes * finding nodes in the list of all targets with that name. This is done
6761590Srgrimes * until a character is encountered which is an operator character. Currently
6771590Srgrimes * these are only ! and :. At this point the operator is parsed and the
6781590Srgrimes * pointer into the line advanced until the first source is encountered.
679144026Sharti *	The parsed operator is applied to each node in the 'targets' list,
6801590Srgrimes * which is where the nodes found for the targets are kept, by means of
6811590Srgrimes * the ParseDoOp function.
6821590Srgrimes *	The sources are read in much the same way as the targets were except
6831590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell
6841590Srgrimes * and all instances of the resulting words in the list of all targets
6851590Srgrimes * are found. Each of the resulting nodes is then linked to each of the
6861590Srgrimes * targets as one of its children.
6871590Srgrimes *	Certain targets are handled specially. These are the ones detailed
6881590Srgrimes * by the specType variable.
6891590Srgrimes *	The storing of transformation rules is also taken care of here.
6901590Srgrimes * A target is recognized as a transformation rule by calling
6911590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten
6921590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard
6931590Srgrimes * Targ_FindNode in the target module.
6941590Srgrimes *---------------------------------------------------------------------
6951590Srgrimes */
6961590Srgrimesstatic void
697141270ShartiParseDoDependency(char *line)
6981590Srgrimes{
699144026Sharti	char	*cp;	/* our current position */
700144026Sharti	GNode	*gn;	/* a general purpose temporary node */
701144026Sharti	int	op;	/* the operator on the line */
702144026Sharti	char	savec;	/* a place to save a character */
703144026Sharti	Lst	paths;	/* Search paths to alter when parsing .PATH targets */
704144026Sharti	int	tOp;	/* operator from special target */
705144026Sharti	LstNode	*ln;
706145616Sharti	const struct keyword *kw;
7071590Srgrimes
708144026Sharti	tOp = 0;
7091590Srgrimes
710144026Sharti	specType = Not;
711144026Sharti	waiting = 0;
712144026Sharti	Lst_Init(&paths);
7131590Srgrimes
714144026Sharti	do {
715144026Sharti		for (cp = line;
716144026Sharti		    *cp && !isspace((unsigned char)*cp) && *cp != '(';
717144026Sharti		    cp++) {
718144026Sharti			if (*cp == '$') {
719144026Sharti				/*
720144026Sharti				 * Must be a dynamic source (would have been
721144026Sharti				 * expanded otherwise), so call the Var module
722144026Sharti				 * to parse the puppy so we can safely advance
723144026Sharti				 * beyond it...There should be no errors in this
724144026Sharti				 * as they would have been discovered in the
725144026Sharti				 * initial Var_Subst and we wouldn't be here.
726144026Sharti				 */
727144026Sharti				size_t	length = 0;
728144026Sharti				Boolean	freeIt;
729144026Sharti				char	*result;
7301590Srgrimes
731144026Sharti				result = Var_Parse(cp, VAR_CMD, TRUE,
732144026Sharti				    &length, &freeIt);
7331590Srgrimes
734144026Sharti				if (freeIt) {
735144026Sharti					free(result);
736144026Sharti				}
737144026Sharti				cp += length - 1;
738102178Sru
739144026Sharti			} else if (*cp == '!' || *cp == ':') {
740144026Sharti				/*
741144026Sharti				 * We don't want to end a word on ':' or '!' if
742144026Sharti				 * there is a better match later on in the
743144026Sharti				 * string (greedy matching).
744144026Sharti				 * This allows the user to have targets like:
745144026Sharti				 *    fie::fi:fo: fum
746144026Sharti				 *    foo::bar:
747144026Sharti				 * where "fie::fi:fo" and "foo::bar" are the
748144026Sharti				 * targets. In real life this is used for perl5
749144026Sharti				 * library man pages where "::" separates an
750144026Sharti				 * object from its class. Ie:
751144026Sharti				 * "File::Spec::Unix". This behaviour is also
752144026Sharti				 * consistent with other versions of make.
753144026Sharti				 */
754144026Sharti				char *p = cp + 1;
755102178Sru
756144026Sharti				if (*cp == ':' && *p == ':')
757144026Sharti					p++;
758102178Sru
759144026Sharti				/* Found the best match already. */
760144026Sharti				if (*p == '\0' || isspace(*p))
761144026Sharti					break;
762102178Sru
763144026Sharti				p += strcspn(p, "!:");
7648874Srgrimes
765144026Sharti				/* No better match later on... */
766144026Sharti				if (*p == '\0')
767144026Sharti					break;
768144026Sharti			}
769144026Sharti			continue;
7701590Srgrimes		}
771144026Sharti		if (*cp == '(') {
772144026Sharti			/*
773144026Sharti			 * Archives must be handled specially to make sure the
774144026Sharti			 * OP_ARCHV flag is set in their 'type' field, for one
775144026Sharti			 * thing, and because things like "archive(file1.o
776144026Sharti			 * file2.o file3.o)" are permissible. Arch_ParseArchive
777144026Sharti			 * will set 'line' to be the first non-blank after the
778144026Sharti			 * archive-spec. It creates/finds nodes for the members
779146338Sharti			 * and places them on the given list, returning TRUE
780146338Sharti			 * if all went well and FALSE if there was an error in
781144026Sharti			 * the specification. On error, line should remain
782144026Sharti			 * untouched.
783144026Sharti			 */
784146338Sharti			if (!Arch_ParseArchive(&line, &targets, VAR_CMD)) {
785144026Sharti				Parse_Error(PARSE_FATAL,
786144026Sharti				    "Error in archive specification: \"%s\"",
787144026Sharti				    line);
788144026Sharti				return;
789144026Sharti			} else {
790144026Sharti				cp = line;
791144026Sharti				continue;
792144026Sharti			}
793144026Sharti		}
794144026Sharti		savec = *cp;
7958874Srgrimes
796144026Sharti		if (!*cp) {
797144026Sharti			/*
798144026Sharti			 * Ending a dependency line without an operator is a				 * Bozo no-no. As a heuristic, this is also often
799144026Sharti			 * triggered by undetected conflicts from cvs/rcs
800144026Sharti			 * merges.
801144026Sharti			 */
802144026Sharti			if (strncmp(line, "<<<<<<", 6) == 0 ||
803144026Sharti			    strncmp(line, "======", 6) == 0 ||
804144026Sharti			    strncmp(line, ">>>>>>", 6) == 0) {
805144026Sharti				Parse_Error(PARSE_FATAL, "Makefile appears to "
806144026Sharti				    "contain unresolved cvs/rcs/??? merge "
807144026Sharti				    "conflicts");
808144026Sharti			} else
809144026Sharti				Parse_Error(PARSE_FATAL, "Need an operator");
810144026Sharti			return;
811144026Sharti		}
812144026Sharti		*cp = '\0';
8131590Srgrimes		/*
814144026Sharti		 * Have a word in line. See if it's a special target and set
815144026Sharti		 * specType to match it.
8161590Srgrimes		 */
817144026Sharti		if (*line == '.' && isupper((unsigned char)line[1])) {
818144026Sharti			/*
819144026Sharti			 * See if the target is a special target that must have
820144026Sharti			 * it or its sources handled specially.
821144026Sharti			 */
822145616Sharti			if ((kw = ParseFindKeyword(line)) != NULL) {
823145616Sharti				if (specType == ExPath && kw->spec != ExPath) {
824144026Sharti					Parse_Error(PARSE_FATAL,
825144026Sharti					    "Mismatched special targets");
826144026Sharti					return;
827144026Sharti				}
828144026Sharti
829145616Sharti				specType = kw->spec;
830145616Sharti				tOp = kw->op;
831144026Sharti
832144026Sharti				/*
833144026Sharti				 * Certain special targets have special
834144026Sharti				 * semantics:
835144026Sharti				 *  .PATH	Have to set the dirSearchPath
836144026Sharti				 *		variable too
837144026Sharti				 *  .MAIN	Its sources are only used if
838144026Sharti				 *		nothing has been specified to
839144026Sharti				 *		create.
840144026Sharti				 *  .DEFAULT    Need to create a node to hang
841144026Sharti				 *		commands on, but we don't want
842144026Sharti				 *		it in the graph, nor do we want
843144026Sharti				 *		it to be the Main Target, so we
844144026Sharti				 *		create it, set OP_NOTMAIN and
845144026Sharti				 *		add it to the list, setting
846144026Sharti				 *		DEFAULT to the new node for
847144026Sharti				 *		later use. We claim the node is
848144026Sharti				 *		A transformation rule to make
849144026Sharti				 *		life easier later, when we'll
850144026Sharti				 *		use Make_HandleUse to actually
851144026Sharti				 *		apply the .DEFAULT commands.
852144026Sharti				 *  .PHONY	The list of targets
853144026Sharti				 *  .BEGIN
854144026Sharti				 *  .END
855144026Sharti				 *  .INTERRUPT	Are not to be considered the
856144026Sharti				 *		main target.
857144026Sharti				 *  .NOTPARALLEL Make only one target at a time.
858144026Sharti				 *  .SINGLESHELL Create a shell for each
859144026Sharti				 *		command.
860144026Sharti				 *  .ORDER	Must set initial predecessor
861144026Sharti				 *		to NULL
862144026Sharti				 */
863144026Sharti				switch (specType) {
864144026Sharti				  case ExPath:
865144026Sharti					Lst_AtEnd(&paths, &dirSearchPath);
866144026Sharti					break;
867144026Sharti				  case Main:
868144026Sharti					if (!Lst_IsEmpty(&create)) {
869144026Sharti						specType = Not;
870144026Sharti					}
871144026Sharti					break;
872144026Sharti				  case Begin:
873144026Sharti				  case End:
874144026Sharti				  case Interrupt:
875144026Sharti					gn = Targ_FindNode(line, TARG_CREATE);
876144026Sharti					gn->type |= OP_NOTMAIN;
877144026Sharti					Lst_AtEnd(&targets, gn);
878144026Sharti					break;
879144026Sharti				  case Default:
880144026Sharti					gn = Targ_NewGN(".DEFAULT");
881144026Sharti					gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
882144026Sharti					Lst_AtEnd(&targets, gn);
883144026Sharti					DEFAULT = gn;
884144026Sharti					break;
885144026Sharti				  case NotParallel:
886146140Sharti					jobLimit = 1;
887144026Sharti					break;
888144026Sharti				  case SingleShell:
889144026Sharti					compatMake = 1;
890144026Sharti					break;
891144026Sharti				  case Order:
892144026Sharti					predecessor = NULL;
893144026Sharti					break;
894144026Sharti				  default:
895144026Sharti					break;
896144026Sharti				}
897144026Sharti
898144026Sharti			} else if (strncmp(line, ".PATH", 5) == 0) {
899144026Sharti				/*
900144026Sharti				 * .PATH<suffix> has to be handled specially.
901144026Sharti				 * Call on the suffix module to give us a path
902144026Sharti				 * to modify.
903144026Sharti				 */
904144026Sharti				struct Path *path;
905144026Sharti
906144026Sharti				specType = ExPath;
907144026Sharti				path = Suff_GetPath(&line[5]);
908144026Sharti				if (path == NULL) {
909144026Sharti					Parse_Error(PARSE_FATAL, "Suffix '%s' "
910144026Sharti					    "not defined (yet)", &line[5]);
911144026Sharti					return;
912144026Sharti				} else
913144026Sharti					Lst_AtEnd(&paths, path);
9141590Srgrimes			}
9151590Srgrimes		}
916144026Sharti
9171590Srgrimes		/*
918144026Sharti		 * Have word in line. Get or create its node and stick it at
919144026Sharti		 * the end of the targets list
9201590Srgrimes		 */
921144029Sharti		if (specType == Not && *line != '\0') {
9228874Srgrimes
923144026Sharti			/* target names to be found and added to targets list */
924144026Sharti			Lst curTargs = Lst_Initializer(curTargs);
9258874Srgrimes
926144026Sharti			if (Dir_HasWildcards(line)) {
927144026Sharti				/*
928144026Sharti				 * Targets are to be sought only in the current
929144026Sharti				 * directory, so create an empty path for the
930144026Sharti				 * thing. Note we need to use Path_Clear in the
931144026Sharti				 * destruction of the path as the Dir module
932144026Sharti				 * could have added a directory to the path...
933144026Sharti				 */
934144026Sharti				struct Path emptyPath =
935144026Sharti				    TAILQ_HEAD_INITIALIZER(emptyPath);
936138916Sharti
937144026Sharti				Path_Expand(line, &emptyPath, &curTargs);
938144026Sharti				Path_Clear(&emptyPath);
9398874Srgrimes
940144026Sharti			} else {
941144026Sharti				/*
942144026Sharti				 * No wildcards, but we want to avoid code
943144026Sharti				 * duplication, so create a list with the word
944144026Sharti				 * on it.
945144026Sharti				 */
946144026Sharti				Lst_AtEnd(&curTargs, line);
947144026Sharti			}
9488874Srgrimes
949144026Sharti			while (!Lst_IsEmpty(&curTargs)) {
950144026Sharti				char	*targName = Lst_DeQueue(&curTargs);
951144026Sharti
952144026Sharti				if (!Suff_IsTransform (targName)) {
953144026Sharti					gn = Targ_FindNode(targName,
954144026Sharti					    TARG_CREATE);
955144026Sharti				} else {
956144026Sharti					gn = Suff_AddTransform(targName);
957144026Sharti				}
958144026Sharti
959144026Sharti				Lst_AtEnd(&targets, gn);
960144026Sharti			}
961144026Sharti		} else if (specType == ExPath && *line != '.' && *line != '\0'){
962144026Sharti			Parse_Error(PARSE_WARNING, "Extra target (%s) ignored",
963144026Sharti			    line);
964144026Sharti		}
965144026Sharti
966144026Sharti		*cp = savec;
9671590Srgrimes		/*
968144026Sharti		 * If it is a special type and not .PATH, it's the only
969144026Sharti		 * target we allow on this line...
9701590Srgrimes		 */
971144026Sharti		if (specType != Not && specType != ExPath) {
972144026Sharti			Boolean warnFlag = FALSE;
9738874Srgrimes
974144029Sharti			while (*cp != '!' && *cp != ':' && *cp) {
975144026Sharti				if (*cp != ' ' && *cp != '\t') {
976144026Sharti					warnFlag = TRUE;
977144026Sharti				}
978144026Sharti				cp++;
979144026Sharti			}
980144026Sharti			if (warnFlag) {
981144026Sharti				Parse_Error(PARSE_WARNING,
982144026Sharti				    "Extra target ignored");
983144026Sharti			}
9841590Srgrimes		} else {
985144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
986144026Sharti				cp++;
987144026Sharti			}
9881590Srgrimes		}
989144026Sharti		line = cp;
990144029Sharti	} while (*line != '!' && *line != ':' && *line);
9918874Srgrimes
992144026Sharti	if (!Lst_IsEmpty(&targets)) {
993144026Sharti		switch (specType) {
994144026Sharti		  default:
995144026Sharti			Parse_Error(PARSE_WARNING, "Special and mundane "
996144026Sharti			    "targets don't mix. Mundane ones ignored");
997144026Sharti			break;
998144026Sharti		  case Default:
999144026Sharti		  case Begin:
1000144026Sharti		  case End:
1001144026Sharti		  case Interrupt:
1002144026Sharti			/*
1003144026Sharti			 * These four create nodes on which to hang commands, so
1004144026Sharti			 * targets shouldn't be empty...
1005144026Sharti			 */
1006144026Sharti		  case Not:
1007144026Sharti			/*
1008144026Sharti			 * Nothing special here -- targets can be empty if it
1009144026Sharti			 * wants.
1010144026Sharti			 */
1011144026Sharti			break;
1012144026Sharti		}
10131590Srgrimes	}
10148874Srgrimes
10151590Srgrimes	/*
1016144026Sharti	 * Have now parsed all the target names. Must parse the operator next.
1017144026Sharti	 * The result is left in op.
10181590Srgrimes	 */
1019144026Sharti	if (*cp == '!') {
1020144026Sharti		op = OP_FORCE;
1021144026Sharti	} else if (*cp == ':') {
1022144026Sharti		if (cp[1] == ':') {
1023144026Sharti			op = OP_DOUBLEDEP;
1024144026Sharti			cp++;
1025144026Sharti		} else {
1026144026Sharti			op = OP_DEPENDS;
10271590Srgrimes		}
10281590Srgrimes	} else {
1029144026Sharti		Parse_Error(PARSE_FATAL, "Missing dependency operator");
1030144026Sharti		return;
1031144026Sharti	}
1032144026Sharti
1033144026Sharti	cp++;			/* Advance beyond operator */
1034144026Sharti
1035144026Sharti	ParseDoOp(op);
1036144026Sharti
1037144026Sharti	/*
1038144026Sharti	 * Get to the first source
1039144026Sharti	 */
1040144026Sharti	while (*cp && isspace((unsigned char)*cp)) {
10411590Srgrimes		cp++;
10421590Srgrimes	}
10431590Srgrimes	line = cp;
10441590Srgrimes
1045144026Sharti	/*
1046144026Sharti	 * Several special targets take different actions if present with no
1047144026Sharti	 * sources:
1048144026Sharti	 *	a .SUFFIXES line with no sources clears out all old suffixes
1049144026Sharti	 *	a .PRECIOUS line makes all targets precious
1050144026Sharti	 *	a .IGNORE line ignores errors for all targets
1051144026Sharti	 *	a .SILENT line creates silence when making all targets
1052144026Sharti	 *	a .PATH removes all directories from the search path(s).
1053144026Sharti	 */
1054144026Sharti	if (!*line) {
1055144026Sharti		switch (specType) {
1056144026Sharti		  case Suffixes:
1057144026Sharti			Suff_ClearSuffixes();
1058144026Sharti			break;
1059144026Sharti		  case Precious:
1060144026Sharti			allPrecious = TRUE;
1061144026Sharti			break;
1062144026Sharti		  case Ignore:
1063144026Sharti			ignoreErrors = TRUE;
1064144026Sharti			break;
1065144026Sharti		  case Silent:
1066144026Sharti			beSilent = TRUE;
1067144026Sharti			break;
1068144026Sharti		  case ExPath:
1069144026Sharti			LST_FOREACH(ln, &paths)
1070144026Sharti			Path_Clear(Lst_Datum(ln));
1071144026Sharti			break;
1072144026Sharti		  case Posix:
1073144026Sharti			Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1074144026Sharti			break;
1075144026Sharti		  default:
1076144026Sharti			break;
1077144026Sharti		}
1078144026Sharti
1079144026Sharti	} else if (specType == MFlags) {
10801590Srgrimes		/*
1081144026Sharti		 * Call on functions in main.c to deal with these arguments and
1082144026Sharti		 * set the initial character to a null-character so the loop to
1083144026Sharti		 * get sources won't get anything
10841590Srgrimes		 */
1085144026Sharti		Main_ParseArgLine(line, 0);
1086144026Sharti		*line = '\0';
10871590Srgrimes
1088145679Sharti	} else if (specType == Warn) {
1089145679Sharti		parse_warn(line);
1090145679Sharti		*line = '\0';
1091145679Sharti
1092144026Sharti	} else if (specType == ExShell) {
1093146572Sharti		if (!Shell_Parse(line)) {
1094144026Sharti			Parse_Error(PARSE_FATAL,
1095144026Sharti			    "improper shell specification");
1096144026Sharti			return;
1097144026Sharti		}
1098144026Sharti		*line = '\0';
1099144026Sharti
1100144029Sharti	} else if (specType == NotParallel || specType == SingleShell) {
1101144026Sharti		*line = '\0';
11021590Srgrimes	}
11031590Srgrimes
1104144026Sharti	/*
1105144026Sharti	* NOW GO FOR THE SOURCES
1106144026Sharti	*/
1107144029Sharti	if (specType == Suffixes || specType == ExPath ||
1108144029Sharti	    specType == Includes || specType == Libs ||
1109144029Sharti	    specType == Null) {
1110144026Sharti		while (*line) {
1111144026Sharti			/*
1112144026Sharti			 * If the target was one that doesn't take files as its
1113144026Sharti			 * sources but takes something like suffixes, we take
1114144026Sharti			 * each space-separated word on the line as a something
1115144026Sharti			 * and deal with it accordingly.
1116144026Sharti			 *
1117144026Sharti			 * If the target was .SUFFIXES, we take each source as
1118144026Sharti			 * a suffix and add it to the list of suffixes
1119144026Sharti			 * maintained by the Suff module.
1120144026Sharti			 *
1121144026Sharti			 * If the target was a .PATH, we add the source as a
1122144026Sharti			 * directory to search on the search path.
1123144026Sharti			 *
1124144026Sharti			 * If it was .INCLUDES, the source is taken to be the
1125144026Sharti			 * suffix of files which will be #included and whose
1126144026Sharti			 * search path should be present in the .INCLUDES
1127144026Sharti			 * variable.
1128144026Sharti			 *
1129144026Sharti			 * If it was .LIBS, the source is taken to be the
1130144026Sharti			 * suffix of files which are considered libraries and
1131144026Sharti			 * whose search path should be present in the .LIBS
1132144026Sharti			 * variable.
1133144026Sharti			 *
1134144026Sharti			 * If it was .NULL, the source is the suffix to use
1135144026Sharti			 * when a file has no valid suffix.
1136144026Sharti			 */
1137144026Sharti			char  savech;
1138144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1139144026Sharti				cp++;
1140144026Sharti			}
1141144026Sharti			savech = *cp;
1142144026Sharti			*cp = '\0';
1143144026Sharti			switch (specType) {
1144144026Sharti			  case Suffixes:
1145144026Sharti				Suff_AddSuffix(line);
1146144026Sharti				break;
1147144026Sharti			  case ExPath:
1148144026Sharti				LST_FOREACH(ln, &paths)
1149144026Sharti					Path_AddDir(Lst_Datum(ln), line);
1150144026Sharti				break;
1151144026Sharti			  case Includes:
1152144026Sharti				Suff_AddInclude(line);
1153144026Sharti				break;
1154144026Sharti			  case Libs:
1155144026Sharti				Suff_AddLib(line);
1156144026Sharti				break;
1157144026Sharti			  case Null:
1158144026Sharti				Suff_SetNull(line);
1159144026Sharti				break;
1160144026Sharti			  default:
1161144026Sharti				break;
1162144026Sharti			}
1163144026Sharti			*cp = savech;
1164144026Sharti			if (savech != '\0') {
1165144026Sharti				cp++;
1166144026Sharti			}
1167144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1168144026Sharti				cp++;
1169144026Sharti			}
1170144026Sharti			line = cp;
1171144026Sharti		}
1172144026Sharti		Lst_Destroy(&paths, NOFREE);
11731590Srgrimes
1174145971Sharti	} else if (specType == ExportVar) {
1175145971Sharti		Var_SetEnv(line, VAR_GLOBAL);
1176145971Sharti
1177144026Sharti	} else {
1178144026Sharti		/* list of sources in order */
1179144026Sharti		Lst curSrcs = Lst_Initializer(curSrc);
11801590Srgrimes
1181144026Sharti		while (*line) {
1182144026Sharti			/*
1183144026Sharti			 * The targets take real sources, so we must beware of
1184144026Sharti			 * archive specifications (i.e. things with left
1185144026Sharti			 * parentheses in them) and handle them accordingly.
1186144026Sharti			 */
1187144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1188144026Sharti				if (*cp == '(' && cp > line && cp[-1] != '$') {
1189144026Sharti					/*
1190144026Sharti					 * Only stop for a left parenthesis if
1191144026Sharti					 * it isn't at the start of a word
1192144026Sharti					 * (that'll be for variable changes
1193144026Sharti					 * later) and isn't preceded by a dollar
1194144026Sharti					 * sign (a dynamic source).
1195144026Sharti					 */
1196144026Sharti					break;
1197144026Sharti				} else {
1198144026Sharti					cp++;
1199144026Sharti				}
1200144026Sharti			}
12011590Srgrimes
1202144026Sharti			if (*cp == '(') {
1203144026Sharti				GNode	  *gnp;
12048874Srgrimes
1205144026Sharti				/* list of archive source names after exp. */
1206144026Sharti				Lst sources = Lst_Initializer(sources);
1207138916Sharti
1208146338Sharti				if (!Arch_ParseArchive(&line, &sources,
1209146338Sharti				    VAR_CMD)) {
1210144026Sharti					Parse_Error(PARSE_FATAL, "Error in "
1211144026Sharti					    "source archive spec \"%s\"", line);
1212144026Sharti					return;
1213144026Sharti				}
1214141270Sharti
1215144026Sharti				while (!Lst_IsEmpty(&sources)) {
1216144026Sharti					gnp = Lst_DeQueue(&sources);
1217144026Sharti					ParseDoSrc(tOp, gnp->name, &curSrcs);
1218144026Sharti				}
1219144026Sharti				cp = line;
1220144026Sharti			} else {
1221144026Sharti				if (*cp) {
1222144026Sharti					*cp = '\0';
1223144026Sharti					cp += 1;
1224144026Sharti				}
12251590Srgrimes
1226144026Sharti				ParseDoSrc(tOp, line, &curSrcs);
1227144026Sharti			}
1228144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1229144026Sharti				cp++;
1230144026Sharti			}
1231144026Sharti			line = cp;
12321590Srgrimes		}
1233144026Sharti		Lst_Destroy(&curSrcs, NOFREE);
1234144026Sharti	}
12351590Srgrimes
1236144026Sharti	if (mainNode == NULL) {
1237144026Sharti		/*
1238144026Sharti		 * If we have yet to decide on a main target to make, in the
1239144026Sharti		 * absence of any user input, we want the first target on
1240144026Sharti		 * the first dependency line that is actually a real target
1241144026Sharti		 * (i.e. isn't a .USE or .EXEC rule) to be made.
1242144026Sharti		 */
1243144026Sharti		LST_FOREACH(ln, &targets) {
1244144026Sharti			gn = Lst_Datum(ln);
1245144026Sharti			if ((gn->type & (OP_NOTMAIN | OP_USE |
1246144026Sharti			    OP_EXEC | OP_TRANSFORM)) == 0) {
1247144026Sharti				mainNode = gn;
1248144026Sharti				Targ_SetMain(gn);
1249144026Sharti				break;
1250144026Sharti			}
12511590Srgrimes		}
12521590Srgrimes	}
12531590Srgrimes}
12541590Srgrimes
12551590Srgrimes/*-
12561590Srgrimes *---------------------------------------------------------------------
12571590Srgrimes * Parse_IsVar  --
12581590Srgrimes *	Return TRUE if the passed line is a variable assignment. A variable
12591590Srgrimes *	assignment consists of a single word followed by optional whitespace
12601590Srgrimes *	followed by either a += or an = operator.
12611590Srgrimes *	This function is used both by the Parse_File function and main when
12621590Srgrimes *	parsing the command-line arguments.
12631590Srgrimes *
12641590Srgrimes * Results:
12651590Srgrimes *	TRUE if it is. FALSE if it ain't
12661590Srgrimes *
12671590Srgrimes * Side Effects:
12681590Srgrimes *	none
12691590Srgrimes *---------------------------------------------------------------------
12701590Srgrimes */
12711590SrgrimesBoolean
1272138232ShartiParse_IsVar(char *line)
12731590Srgrimes{
1274144026Sharti	Boolean wasSpace = FALSE;	/* set TRUE if found a space */
1275144026Sharti	Boolean haveName = FALSE;	/* Set TRUE if have a variable name */
1276138232Sharti
1277144026Sharti	int level = 0;
1278103503Sjmallett#define	ISEQOPERATOR(c) \
1279144029Sharti	((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!')
12801590Srgrimes
1281144026Sharti	/*
1282144026Sharti	 * Skip to variable name
1283144026Sharti	 */
1284144029Sharti	for (; *line == ' ' || *line == '\t'; line++)
1285144026Sharti		continue;
12861590Srgrimes
1287144026Sharti	for (; *line != '=' || level != 0; line++) {
1288144026Sharti		switch (*line) {
1289144026Sharti		  case '\0':
1290144026Sharti			/*
1291144026Sharti			 * end-of-line -- can't be a variable assignment.
1292144026Sharti			 */
1293144026Sharti			return (FALSE);
129418730Ssteve
1295144026Sharti		  case ' ':
1296144026Sharti		  case '\t':
1297144026Sharti			/*
1298144026Sharti			 * there can be as much white space as desired so long
1299144026Sharti			 * as there is only one word before the operator
1300144026Sharti			*/
1301144026Sharti			wasSpace = TRUE;
1302144026Sharti			break;
130318730Ssteve
1304144026Sharti		  case '(':
1305144026Sharti		  case '{':
1306144026Sharti			level++;
1307144026Sharti			break;
130818730Ssteve
1309144026Sharti		  case '}':
1310144026Sharti		  case ')':
1311144026Sharti			level--;
1312144026Sharti			break;
131318730Ssteve
1314144026Sharti		  default:
1315144026Sharti			if (wasSpace && haveName) {
1316144026Sharti				if (ISEQOPERATOR(*line)) {
1317144026Sharti					/*
1318144026Sharti					 * We must have a finished word
1319144026Sharti					 */
1320144026Sharti					if (level != 0)
1321144026Sharti						return (FALSE);
132218730Ssteve
1323144026Sharti					/*
1324144026Sharti					 * When an = operator [+?!:] is found,
1325144026Sharti					 * the next character must be an = or
1326144026Sharti					 * it ain't a valid assignment.
1327144026Sharti					 */
1328144026Sharti					if (line[1] == '=')
1329144026Sharti						return (haveName);
133018730Ssteve#ifdef SUNSHCMD
1331144026Sharti					/*
1332144026Sharti					 * This is a shell command
1333144026Sharti					 */
1334144026Sharti					if (strncmp(line, ":sh", 3) == 0)
1335144026Sharti						return (haveName);
133618730Ssteve#endif
1337144026Sharti				}
1338144026Sharti				/*
1339144026Sharti				 * This is the start of another word, so not
1340144026Sharti				 * assignment.
1341144026Sharti				 */
1342144026Sharti				return (FALSE);
1343144026Sharti
1344144026Sharti			} else {
1345144026Sharti				haveName = TRUE;
1346144026Sharti				wasSpace = FALSE;
1347144026Sharti			}
1348144026Sharti			break;
1349144026Sharti		}
13501590Srgrimes	}
13511590Srgrimes
1352144026Sharti	return (haveName);
13531590Srgrimes}
13541590Srgrimes
13551590Srgrimes/*-
13561590Srgrimes *---------------------------------------------------------------------
13571590Srgrimes * Parse_DoVar  --
13581590Srgrimes *	Take the variable assignment in the passed line and do it in the
13591590Srgrimes *	global context.
13601590Srgrimes *
13611590Srgrimes *	Note: There is a lexical ambiguity with assignment modifier characters
13621590Srgrimes *	in variable names. This routine interprets the character before the =
13631590Srgrimes *	as a modifier. Therefore, an assignment like
13641590Srgrimes *	    C++=/usr/bin/CC
13651590Srgrimes *	is interpreted as "C+ +=" instead of "C++ =".
13661590Srgrimes *
13671590Srgrimes * Results:
13681590Srgrimes *	none
13691590Srgrimes *
13701590Srgrimes * Side Effects:
13711590Srgrimes *	the variable structure of the given variable name is altered in the
13721590Srgrimes *	global context.
13731590Srgrimes *---------------------------------------------------------------------
13741590Srgrimes */
13751590Srgrimesvoid
1376138232ShartiParse_DoVar(char *line, GNode *ctxt)
13771590Srgrimes{
1378144026Sharti	char	*cp;	/* pointer into line */
1379144026Sharti	enum {
1380144026Sharti		VAR_SUBST,
1381144026Sharti		VAR_APPEND,
1382144026Sharti		VAR_SHELL,
1383144026Sharti		VAR_NORMAL
1384144026Sharti	}	type;	/* Type of assignment */
1385144026Sharti	char	*opc;	/* ptr to operator character to
1386144026Sharti			 * null-terminate the variable name */
1387144026Sharti
1388144026Sharti	/*
1389144026Sharti	 * Skip to variable name
1390144026Sharti	 */
1391144029Sharti	while (*line == ' ' || *line == '\t') {
1392144026Sharti		line++;
1393144026Sharti	}
13941590Srgrimes
1395144026Sharti	/*
1396144026Sharti	 * Skip to operator character, nulling out whitespace as we go
1397144026Sharti	 */
1398144026Sharti	for (cp = line + 1; *cp != '='; cp++) {
1399144026Sharti		if (isspace((unsigned char)*cp)) {
1400144026Sharti			*cp = '\0';
1401144026Sharti		}
14021590Srgrimes	}
1403144026Sharti	opc = cp - 1;		/* operator is the previous character */
1404144026Sharti	*cp++ = '\0';		/* nuke the = */
14051590Srgrimes
1406144026Sharti	/*
1407144026Sharti	 * Check operator type
1408144026Sharti	 */
1409144026Sharti	switch (*opc) {
1410144026Sharti	  case '+':
1411144026Sharti		type = VAR_APPEND;
1412144026Sharti		*opc = '\0';
1413144026Sharti		break;
14141590Srgrimes
1415144026Sharti	  case '?':
1416144026Sharti		/*
1417144026Sharti		 * If the variable already has a value, we don't do anything.
1418144026Sharti		 */
1419144026Sharti		*opc = '\0';
1420144026Sharti		if (Var_Exists(line, ctxt)) {
1421144026Sharti			return;
1422144026Sharti		} else {
1423144026Sharti			type = VAR_NORMAL;
1424144026Sharti		}
1425144026Sharti		break;
14261590Srgrimes
1427144026Sharti	  case ':':
1428144026Sharti		type = VAR_SUBST;
1429144026Sharti		*opc = '\0';
1430144026Sharti		break;
14311590Srgrimes
1432144026Sharti	  case '!':
1433144026Sharti		type = VAR_SHELL;
1434144026Sharti		*opc = '\0';
1435144026Sharti		break;
14361590Srgrimes
1437144026Sharti	  default:
143818730Ssteve#ifdef SUNSHCMD
1439144026Sharti		while (*opc != ':') {
1440144026Sharti			if (opc == line)
1441144026Sharti				break;
1442144026Sharti			else
1443144026Sharti				--opc;
1444144026Sharti		}
144518730Ssteve
1446144026Sharti		if (strncmp(opc, ":sh", 3) == 0) {
1447144026Sharti			type = VAR_SHELL;
1448144026Sharti			*opc = '\0';
1449144026Sharti			break;
1450144026Sharti		}
1451144026Sharti#endif
1452144026Sharti		type = VAR_NORMAL;
145318730Ssteve		break;
1454144026Sharti	}
14551590Srgrimes
1456144026Sharti	while (isspace((unsigned char)*cp)) {
1457144026Sharti		cp++;
1458144026Sharti	}
14591590Srgrimes
1460144026Sharti	if (type == VAR_APPEND) {
1461144026Sharti		Var_Append(line, cp, ctxt);
14621590Srgrimes
1463144026Sharti	} else if (type == VAR_SUBST) {
1464144026Sharti		/*
1465144026Sharti		 * Allow variables in the old value to be undefined, but leave
1466144026Sharti		 * their invocation alone -- this is done by forcing oldVars
1467144026Sharti		 * to be false.
1468144026Sharti		 * XXX: This can cause recursive variables, but that's not
1469144026Sharti		 * hard to do, and this allows someone to do something like
1470144026Sharti		 *
1471144026Sharti		 *  CFLAGS = $(.INCLUDES)
1472144026Sharti		 *  CFLAGS := -I.. $(CFLAGS)
1473144026Sharti		 *
1474144026Sharti		 * And not get an error.
1475144026Sharti		 */
1476144026Sharti		Boolean oldOldVars = oldVars;
147798509Sjmallett
1478144026Sharti		oldVars = FALSE;
147998509Sjmallett
1480144026Sharti		/*
1481144026Sharti		 * make sure that we set the variable the first time to nothing
1482144026Sharti		 * so that it gets substituted!
1483144026Sharti		 */
1484144026Sharti		if (!Var_Exists(line, ctxt))
1485144026Sharti			Var_Set(line, "", ctxt);
1486142457Sharti
1487146027Sharti		cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE));
14881590Srgrimes
1489144026Sharti		oldVars = oldOldVars;
14901590Srgrimes
1491144026Sharti		Var_Set(line, cp, ctxt);
1492144026Sharti		free(cp);
14931590Srgrimes
1494144026Sharti	} else if (type == VAR_SHELL) {
1495144026Sharti		/*
1496144026Sharti		 * TRUE if the command needs to be freed, i.e.
1497144026Sharti		 * if any variable expansion was performed
1498144026Sharti		 */
1499144026Sharti		Boolean	freeCmd = FALSE;
1500144026Sharti		Buffer *buf;
1501144026Sharti		const char *error;
15021590Srgrimes
1503144026Sharti		if (strchr(cp, '$') != NULL) {
1504144026Sharti			/*
1505144026Sharti			 * There's a dollar sign in the command, so perform
1506144026Sharti			 * variable expansion on the whole thing. The
1507144026Sharti			 * resulting string will need freeing when we're done,
1508144026Sharti			 * so set freeCmd to TRUE.
1509144026Sharti			 */
1510146027Sharti			cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE));
1511144026Sharti			freeCmd = TRUE;
1512144026Sharti		}
15131590Srgrimes
1514144026Sharti		buf = Cmd_Exec(cp, &error);
1515144026Sharti		Var_Set(line, Buf_Data(buf), ctxt);
1516144026Sharti		Buf_Destroy(buf, TRUE);
1517144026Sharti
1518144026Sharti		if (error)
1519144026Sharti			Parse_Error(PARSE_WARNING, error, cp);
1520144026Sharti
1521144026Sharti		if (freeCmd)
1522144026Sharti			free(cp);
1523144026Sharti
1524144026Sharti	} else {
1525144026Sharti		/*
1526144026Sharti		 * Normal assignment -- just do it.
1527144026Sharti		 */
1528144026Sharti		Var_Set(line, cp, ctxt);
1529144026Sharti	}
15301590Srgrimes}
15311590Srgrimes
15321590Srgrimes/*-
15331590Srgrimes *-----------------------------------------------------------------------
15341590Srgrimes * ParseHasCommands --
15351590Srgrimes *	Callback procedure for Parse_File when destroying the list of
15361590Srgrimes *	targets on the last dependency line. Marks a target as already
15371590Srgrimes *	having commands if it does, to keep from having shell commands
15381590Srgrimes *	on multiple dependency lines.
15391590Srgrimes *
15401590Srgrimes * Results:
15415814Sjkh *	None
15421590Srgrimes *
15431590Srgrimes * Side Effects:
15441590Srgrimes *	OP_HAS_COMMANDS may be set for the target.
15451590Srgrimes *
15461590Srgrimes *-----------------------------------------------------------------------
15471590Srgrimes */
15485814Sjkhstatic void
1549104696SjmallettParseHasCommands(void *gnp)
15501590Srgrimes{
1551144026Sharti	GNode *gn = gnp;
1552138232Sharti
1553144026Sharti	if (!Lst_IsEmpty(&gn->commands)) {
1554144026Sharti		gn->type |= OP_HAS_COMMANDS;
1555144026Sharti	}
15561590Srgrimes}
15571590Srgrimes
15581590Srgrimes/*-
15591590Srgrimes *-----------------------------------------------------------------------
15601590Srgrimes * Parse_AddIncludeDir --
15611590Srgrimes *	Add a directory to the path searched for included makefiles
15621590Srgrimes *	bracketed by double-quotes. Used by functions in main.c
15631590Srgrimes *
15641590Srgrimes * Results:
15651590Srgrimes *	None.
15661590Srgrimes *
15671590Srgrimes * Side Effects:
15681590Srgrimes *	The directory is appended to the list.
15691590Srgrimes *
15701590Srgrimes *-----------------------------------------------------------------------
15711590Srgrimes */
15721590Srgrimesvoid
1573138232ShartiParse_AddIncludeDir(char *dir)
15741590Srgrimes{
1575138232Sharti
1576144026Sharti	Path_AddDir(&parseIncPath, dir);
15771590Srgrimes}
15781590Srgrimes
15791590Srgrimes/*-
15801590Srgrimes *---------------------------------------------------------------------
15811590Srgrimes * Parse_FromString  --
15821590Srgrimes *	Start Parsing from the given string
15838874Srgrimes *
15841590Srgrimes * Results:
15851590Srgrimes *	None
15861590Srgrimes *
15871590Srgrimes * Side Effects:
1588126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1589126824Sru *	curFile.fname and curFile.F are altered for the new file
15901590Srgrimes *---------------------------------------------------------------------
15911590Srgrimes */
15921590Srgrimesvoid
1593126824SruParse_FromString(char *str, int lineno)
15941590Srgrimes{
15951590Srgrimes
1596144026Sharti	DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno));
15971590Srgrimes
1598144341Sharti	ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno);
15991590Srgrimes}
16001590Srgrimes
16011590Srgrimes#ifdef SYSVINCLUDE
16021590Srgrimes/*-
16031590Srgrimes *---------------------------------------------------------------------
16041590Srgrimes * ParseTraditionalInclude  --
16051590Srgrimes *	Push to another file.
16068874Srgrimes *
16071590Srgrimes *	The input is the line minus the "include".  The file name is
16081590Srgrimes *	the string following the "include".
16091590Srgrimes *
16101590Srgrimes * Results:
16111590Srgrimes *	None
16121590Srgrimes *
16131590Srgrimes * Side Effects:
1614126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1615126824Sru *	curFile.fname and curFile.F are altered for the new file
16161590Srgrimes *---------------------------------------------------------------------
16171590Srgrimes */
16181590Srgrimesstatic void
1619141270ShartiParseTraditionalInclude(char *file)
16201590Srgrimes{
1621144026Sharti	char	*fullname;	/* full pathname of file */
1622144026Sharti	char	*cp;		/* current position in file spec */
16231590Srgrimes
1624144026Sharti	/*
1625144026Sharti	 * Skip over whitespace
1626144026Sharti	 */
1627144029Sharti	while (*file == ' ' || *file == '\t') {
1628144026Sharti		file++;
1629144026Sharti	}
16301590Srgrimes
1631144026Sharti	if (*file == '\0') {
1632144026Sharti		Parse_Error(PARSE_FATAL, "Filename missing from \"include\"");
1633144026Sharti		return;
1634144026Sharti	}
16351590Srgrimes
1636144026Sharti	/*
1637144026Sharti	* Skip to end of line or next whitespace
1638144026Sharti	*/
1639144026Sharti	for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1640144026Sharti		continue;
1641144026Sharti	}
16421590Srgrimes
1643144026Sharti	*cp = '\0';
16441590Srgrimes
1645144026Sharti	/*
1646144026Sharti	 * Substitute for any variables in the file name before trying to
1647144026Sharti	 * find the thing.
1648144026Sharti	 */
1649146027Sharti	file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE));
16501590Srgrimes
16511590Srgrimes	/*
1652144026Sharti	 * Now we know the file's name, we attempt to find the durn thing.
1653144026Sharti	 * Search for it first on the -I search path, then on the .PATH
1654144026Sharti	 * search path, if not found in a -I directory.
16551590Srgrimes	 */
1656144026Sharti	fullname = Path_FindFile(file, &parseIncPath);
1657144026Sharti	if (fullname == NULL) {
1658144026Sharti		fullname = Path_FindFile(file, &dirSearchPath);
1659144026Sharti	}
16601590Srgrimes
1661144026Sharti	if (fullname == NULL) {
1662144026Sharti		/*
1663144026Sharti		 * Still haven't found the makefile. Look for it on the system
1664144026Sharti		 * path as a last resort.
1665144026Sharti		 */
1666144026Sharti		fullname = Path_FindFile(file, &sysIncPath);
1667144026Sharti	}
16681590Srgrimes
1669144026Sharti	if (fullname == NULL) {
1670144026Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
1671144026Sharti		/* XXXHB free(file) */
1672144026Sharti		return;
1673144026Sharti	}
1674142457Sharti
1675144026Sharti	/* XXXHB free(file) */
16761590Srgrimes
1677144026Sharti	/*
1678144341Sharti	 * We set up the name of the file to be the absolute
1679144026Sharti	 * name of the include file so error messages refer to the right
1680144341Sharti	 * place.
16811590Srgrimes	 */
1682144341Sharti	ParsePushInput(fullname, NULL, NULL, 0);
16831590Srgrimes}
16841590Srgrimes#endif
16851590Srgrimes
16861590Srgrimes/*-
16871590Srgrimes *---------------------------------------------------------------------
16881590Srgrimes * ParseReadc  --
16898874Srgrimes *	Read a character from the current file
16901590Srgrimes *
16911590Srgrimes * Results:
16921590Srgrimes *	The character that was read
16931590Srgrimes *
16941590Srgrimes * Side Effects:
16951590Srgrimes *---------------------------------------------------------------------
16961590Srgrimes */
16971590Srgrimesstatic int
1698104696SjmallettParseReadc(void)
16991590Srgrimes{
1700138232Sharti
1701144341Sharti	if (CURFILE->F != NULL)
1702144341Sharti		return (fgetc(CURFILE->F));
17038874Srgrimes
1704144341Sharti	if (CURFILE->str != NULL && *CURFILE->ptr != '\0')
1705144341Sharti		return (*CURFILE->ptr++);
1706144341Sharti
1707144026Sharti	return (EOF);
17081590Srgrimes}
17091590Srgrimes
17101590Srgrimes
17111590Srgrimes/*-
17121590Srgrimes *---------------------------------------------------------------------
17131590Srgrimes * ParseUnreadc  --
17148874Srgrimes *	Put back a character to the current file
17151590Srgrimes *
17161590Srgrimes * Results:
17171590Srgrimes *	None.
17181590Srgrimes *
17191590Srgrimes * Side Effects:
17201590Srgrimes *---------------------------------------------------------------------
17211590Srgrimes */
17221590Srgrimesstatic void
1723104696SjmallettParseUnreadc(int c)
17241590Srgrimes{
1725138232Sharti
1726144341Sharti	if (CURFILE->F != NULL) {
1727144341Sharti		ungetc(c, CURFILE->F);
1728144026Sharti		return;
1729144026Sharti	}
1730144341Sharti	if (CURFILE->str != NULL) {
1731144341Sharti		*--(CURFILE->ptr) = c;
1732144026Sharti		return;
1733144026Sharti	}
17341590Srgrimes}
17351590Srgrimes
17361590Srgrimes/* ParseSkipLine():
1737104696Sjmallett *	Grab the next line unless it begins with a dot (`.') and we're told to
1738104696Sjmallett *	ignore such lines.
17391590Srgrimes */
17401590Srgrimesstatic char *
1741126824SruParseSkipLine(int skip, int keep_newline)
17421590Srgrimes{
1743144026Sharti	char *line;
1744144026Sharti	int c, lastc;
1745144026Sharti	Buffer *buf;
17461590Srgrimes
1747144026Sharti	buf = Buf_Init(MAKE_BSIZE);
17481590Srgrimes
1749144026Sharti	do {
1750144026Sharti		Buf_Clear(buf);
1751144026Sharti		lastc = '\0';
17528874Srgrimes
1753144026Sharti		while (((c = ParseReadc()) != '\n' || lastc == '\\')
1754144026Sharti		    && c != EOF) {
1755144026Sharti			if (skip && c == '#' && lastc != '\\') {
1756144026Sharti				/*
1757144026Sharti				 * let a comment be terminated even by an
1758144026Sharti				 * escaped \n. This is consistent to comment
1759144026Sharti				 * handling in ParseReadLine
1760144026Sharti				 */
1761144026Sharti				while ((c = ParseReadc()) != '\n' && c != EOF)
1762144026Sharti					;
1763144026Sharti				break;
1764144026Sharti			}
1765144026Sharti			if (c == '\n') {
1766144026Sharti				if (keep_newline)
1767144026Sharti					Buf_AddByte(buf, (Byte)c);
1768144026Sharti				else
1769144026Sharti					Buf_ReplaceLastByte(buf, (Byte)' ');
1770144341Sharti				CURFILE->lineno++;
17718874Srgrimes
1772144026Sharti				while ((c = ParseReadc()) == ' ' || c == '\t')
1773144026Sharti					continue;
17748874Srgrimes
1775144026Sharti				if (c == EOF)
1776144026Sharti					break;
1777144026Sharti			}
177874272Swill
1779144026Sharti			Buf_AddByte(buf, (Byte)c);
1780144026Sharti			lastc = c;
1781144026Sharti		}
178218456Ssteve
1783144026Sharti		if (c == EOF) {
1784144026Sharti			Parse_Error(PARSE_FATAL,
1785144026Sharti			    "Unclosed conditional/for loop");
1786144026Sharti			Buf_Destroy(buf, TRUE);
1787144026Sharti			return (NULL);
1788144026Sharti		}
178918456Ssteve
1790144341Sharti		CURFILE->lineno++;
1791144026Sharti		Buf_AddByte(buf, (Byte)'\0');
1792144026Sharti		line = Buf_Data(buf);
1793144026Sharti	} while (skip == 1 && line[0] != '.');
179418456Ssteve
1795144026Sharti	Buf_Destroy(buf, FALSE);
1796144026Sharti	return (line);
17971590Srgrimes}
17981590Srgrimes
17991590Srgrimes/*-
18001590Srgrimes *---------------------------------------------------------------------
18011590Srgrimes * ParseReadLine --
18021590Srgrimes *	Read an entire line from the input file. Called only by Parse_File.
18031590Srgrimes *	To facilitate escaped newlines and what have you, a character is
18041590Srgrimes *	buffered in 'lastc', which is '\0' when no characters have been
18051590Srgrimes *	read. When we break out of the loop, c holds the terminating
18061590Srgrimes *	character and lastc holds a character that should be added to
18071590Srgrimes *	the line (unless we don't read anything but a terminator).
18081590Srgrimes *
18091590Srgrimes * Results:
18101590Srgrimes *	A line w/o its newline
18111590Srgrimes *
18121590Srgrimes * Side Effects:
18131590Srgrimes *	Only those associated with reading a character
18141590Srgrimes *---------------------------------------------------------------------
18151590Srgrimes */
18161590Srgrimesstatic char *
1817138232ShartiParseReadLine(void)
18181590Srgrimes{
1819144026Sharti	Buffer	*buf;		/* Buffer for current line */
1820144026Sharti	int	c;		/* the current character */
1821144026Sharti	int	lastc;		/* The most-recent character */
1822144026Sharti	Boolean	semiNL;		/* treat semi-colons as newlines */
1823144026Sharti	Boolean	ignDepOp;	/* TRUE if should ignore dependency operators
18241590Srgrimes				 * for the purposes of setting semiNL */
1825144026Sharti	Boolean	ignComment;	/* TRUE if should ignore comments (in a
18261590Srgrimes				 * shell command */
1827144026Sharti	char	*line;		/* Result */
1828144026Sharti	char	*ep;		/* to strip trailing blanks */
18291590Srgrimes
1830144742Sharti  again:
1831144026Sharti	semiNL = FALSE;
1832144026Sharti	ignDepOp = FALSE;
1833144026Sharti	ignComment = FALSE;
18341590Srgrimes
1835144742Sharti	lastc = '\0';
1836144742Sharti
1837144026Sharti	/*
1838144742Sharti	 * Handle tab at the beginning of the line. A leading tab (shell
1839144742Sharti	 * command) forces us to ignore comments and dependency operators and
1840144742Sharti	 * treat semi-colons as semi-colons (by leaving semiNL FALSE).
1841144742Sharti	 * This also discards completely blank lines.
1842144026Sharti	 */
1843144026Sharti	for (;;) {
1844144026Sharti		c = ParseReadc();
1845144742Sharti		if (c == EOF) {
1846144742Sharti			if (ParsePopInput() == DONE) {
1847144742Sharti				/* End of all inputs - return NULL */
1848144742Sharti				return (NULL);
1849144742Sharti			}
1850144742Sharti			continue;
1851144742Sharti		}
18521590Srgrimes
1853144026Sharti		if (c == '\t') {
1854144026Sharti			ignComment = ignDepOp = TRUE;
1855144742Sharti			lastc = c;
1856144026Sharti			break;
1857144742Sharti		}
1858144742Sharti		if (c != '\n') {
1859144026Sharti			ParseUnreadc(c);
1860144026Sharti			break;
1861144026Sharti		}
1862144742Sharti		CURFILE->lineno++;
18631590Srgrimes	}
18648874Srgrimes
1865144742Sharti	buf = Buf_Init(MAKE_BSIZE);
18668874Srgrimes
1867144742Sharti	while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) {
1868144026Sharti  test_char:
1869144742Sharti		switch (c) {
1870144742Sharti		  case '\n':
1871144742Sharti			/*
1872144742Sharti			 * Escaped newline: read characters until a
1873144742Sharti			 * non-space or an unescaped newline and
1874144742Sharti			 * replace them all by a single space. This is
1875144742Sharti			 * done by storing the space over the backslash
1876144742Sharti			 * and dropping through with the next nonspace.
1877144742Sharti			 * If it is a semi-colon and semiNL is TRUE,
1878144742Sharti			 * it will be recognized as a newline in the
1879144742Sharti			 * code below this...
1880144742Sharti			 */
1881144742Sharti			CURFILE->lineno++;
1882144742Sharti			lastc = ' ';
1883144742Sharti			while ((c = ParseReadc()) == ' ' || c == '\t') {
1884144742Sharti				continue;
1885144742Sharti			}
1886144742Sharti			if (c == EOF || c == '\n') {
1887144742Sharti				goto line_read;
1888144742Sharti			} else {
1889144026Sharti				/*
1890144742Sharti				 * Check for comments, semiNL's, etc. --
1891144742Sharti				 * easier than ParseUnreadc(c);
1892144742Sharti				 * continue;
1893144026Sharti				 */
1894144742Sharti				goto test_char;
1895144742Sharti			}
1896144742Sharti			/*NOTREACHED*/
1897144742Sharti			break;
1898144026Sharti
1899144742Sharti		  case ';':
1900144742Sharti			/*
1901144742Sharti			 * Semi-colon: Need to see if it should be
1902144742Sharti			 * interpreted as a newline
1903144742Sharti			 */
1904144742Sharti			if (semiNL) {
1905144026Sharti				/*
1906144742Sharti				 * To make sure the command that may
1907144742Sharti				 * be following this semi-colon begins
1908144742Sharti				 * with a tab, we push one back into the
1909144742Sharti				 * input stream. This will overwrite the
1910144742Sharti				 * semi-colon in the buffer. If there is
1911144742Sharti				 * no command following, this does no
1912144742Sharti				 * harm, since the newline remains in
1913144742Sharti				 * the buffer and the
1914144742Sharti				 * whole line is ignored.
1915144026Sharti				 */
1916144742Sharti				ParseUnreadc('\t');
1917144742Sharti				goto line_read;
1918144742Sharti			}
1919144742Sharti			break;
1920144742Sharti		  case '=':
1921144742Sharti			if (!semiNL) {
1922144742Sharti				/*
1923144742Sharti				 * Haven't seen a dependency operator
1924144742Sharti				 * before this, so this must be a
1925144742Sharti				 * variable assignment -- don't pay
1926144742Sharti				 * attention to dependency operators
1927144742Sharti				 * after this.
1928144742Sharti				 */
1929144742Sharti				ignDepOp = TRUE;
1930144742Sharti			} else if (lastc == ':' || lastc == '!') {
1931144742Sharti				/*
1932144742Sharti				 * Well, we've seen a dependency
1933144742Sharti				 * operator already, but it was the
1934144742Sharti				 * previous character, so this is really
1935144742Sharti				 * just an expanded variable assignment.
1936144742Sharti				 * Revert semi-colons to being just
1937144742Sharti				 * semi-colons again and ignore any more
1938144742Sharti				 * dependency operators.
1939144742Sharti				 *
1940144742Sharti				 * XXX: Note that a line like
1941144742Sharti				 * "foo : a:=b" will blow up, but who'd
1942144742Sharti				 * write a line like that anyway?
1943144742Sharti				 */
1944144742Sharti				ignDepOp = TRUE;
1945144742Sharti				semiNL = FALSE;
1946144742Sharti			}
1947144742Sharti			break;
1948144742Sharti		  case '#':
1949144742Sharti			if (!ignComment) {
1950144742Sharti				if (lastc != '\\') {
1951144026Sharti					/*
1952144742Sharti					 * If the character is a hash
1953144742Sharti					 * mark and it isn't escaped
1954144742Sharti					 * (or we're being compatible),
1955144742Sharti					 * the thing is a comment.
1956144742Sharti					 * Skip to the end of the line.
1957144026Sharti					 */
1958144742Sharti					do {
1959144742Sharti						c = ParseReadc();
1960144742Sharti					} while (c != '\n' && c != EOF);
1961144026Sharti					goto line_read;
1962144742Sharti				} else {
1963144026Sharti					/*
1964144742Sharti					 * Don't add the backslash.
1965144742Sharti					 * Just let the # get copied
1966144742Sharti					 * over.
1967144026Sharti					 */
1968144742Sharti					lastc = c;
1969144742Sharti					continue;
1970144026Sharti				}
1971144742Sharti			}
1972144742Sharti			break;
1973144026Sharti
1974144742Sharti		  case ':':
1975144742Sharti		  case '!':
1976144742Sharti			if (!ignDepOp) {
1977144742Sharti				/*
1978144742Sharti				 * A semi-colon is recognized as a
1979144742Sharti				 * newline only on dependency lines.
1980144742Sharti				 * Dependency lines are lines with a
1981144742Sharti				 * colon or an exclamation point.
1982144742Sharti				 * Ergo...
1983144742Sharti				 */
1984144742Sharti				semiNL = TRUE;
1985144742Sharti			}
1986144742Sharti			break;
1987144026Sharti
1988144742Sharti		  default:
1989144742Sharti			break;
1990144742Sharti		}
1991144742Sharti		/*
1992144742Sharti		 * Copy in the previous character (there may be none if this
1993144742Sharti		 * was the first character) and save this one in
1994144742Sharti		 * lastc.
1995144742Sharti		 */
1996144742Sharti		if (lastc != '\0')
1997144026Sharti			Buf_AddByte(buf, (Byte)lastc);
1998144742Sharti		lastc = c;
1999144742Sharti	}
2000144026Sharti  line_read:
2001144742Sharti	CURFILE->lineno++;
2002144026Sharti
2003144742Sharti	if (lastc != '\0') {
2004144742Sharti		Buf_AddByte(buf, (Byte)lastc);
2005144742Sharti	}
2006144742Sharti	Buf_AddByte(buf, (Byte)'\0');
2007144742Sharti	line = Buf_Peel(buf);
20081590Srgrimes
2009144742Sharti	/*
2010144742Sharti	 * Strip trailing blanks and tabs from the line.
2011144742Sharti	 * Do not strip a blank or tab that is preceded by
2012144742Sharti	 * a '\'
2013144742Sharti	 */
2014144742Sharti	ep = line;
2015144742Sharti	while (*ep)
2016144742Sharti		++ep;
2017144742Sharti	while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
2018144742Sharti		if (ep > line + 1 && ep[-2] == '\\')
2019144742Sharti			break;
2020144742Sharti		--ep;
2021144742Sharti	}
2022144742Sharti	*ep = 0;
2023144742Sharti
2024144742Sharti	if (line[0] == '\0') {
2025144742Sharti		/* empty line - just ignore */
2026144742Sharti		free(line);
2027144742Sharti		goto again;
2028144742Sharti	}
2029144742Sharti
2030144742Sharti	return (line);
20311590Srgrimes}
20321590Srgrimes
20331590Srgrimes/*-
20341590Srgrimes *-----------------------------------------------------------------------
20351590Srgrimes * ParseFinishLine --
20361590Srgrimes *	Handle the end of a dependency group.
20371590Srgrimes *
20381590Srgrimes * Results:
20391590Srgrimes *	Nothing.
20401590Srgrimes *
20411590Srgrimes * Side Effects:
20421590Srgrimes *	inLine set FALSE. 'targets' list destroyed.
20431590Srgrimes *
20441590Srgrimes *-----------------------------------------------------------------------
20451590Srgrimes */
20461590Srgrimesstatic void
2047104696SjmallettParseFinishLine(void)
20481590Srgrimes{
2049143372Sharti	const LstNode	*ln;
2050138232Sharti
2051143372Sharti	if (inLine) {
2052143372Sharti		LST_FOREACH(ln, &targets) {
2053143372Sharti			if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM)
2054143372Sharti				Suff_EndTransform(Lst_Datum(ln));
2055143372Sharti		}
2056143372Sharti		Lst_Destroy(&targets, ParseHasCommands);
2057143372Sharti		inLine = FALSE;
2058143372Sharti	}
20591590Srgrimes}
20601590Srgrimes
2061144894Sharti/**
2062144894Sharti * parse_include
2063144894Sharti *	Parse an .include directive and push the file onto the input stack.
2064144894Sharti *	The input is the line minus the .include. A file spec is a string
2065144894Sharti *	enclosed in <> or "". The former is looked for only in sysIncPath.
2066144894Sharti *	The latter in . and the directories specified by -I command line
2067144894Sharti *	options
2068144894Sharti */
2069144894Shartistatic void
2070150595Sphkxparse_include(char *file, int sinclude)
2071144894Sharti{
2072144894Sharti	char	*fullname;	/* full pathname of file */
2073144894Sharti	char	endc;		/* the character which ends the file spec */
2074144894Sharti	char	*cp;		/* current position in file spec */
2075144894Sharti	Boolean	isSystem;	/* TRUE if makefile is a system makefile */
2076144894Sharti	char	*prefEnd, *Fname;
2077144894Sharti	char	*newName;
20788874Srgrimes
2079144894Sharti	/*
2080144894Sharti	 * Skip to delimiter character so we know where to look
2081144894Sharti	 */
2082144894Sharti	while (*file == ' ' || *file == '\t') {
2083144894Sharti		file++;
2084144894Sharti	}
2085144894Sharti
2086144894Sharti	if (*file != '"' && *file != '<') {
2087144894Sharti		Parse_Error(PARSE_FATAL,
2088144894Sharti		    ".include filename must be delimited by '\"' or '<'");
2089144894Sharti		return;
2090144894Sharti	}
2091144894Sharti
2092144894Sharti	/*
2093144894Sharti	 * Set the search path on which to find the include file based on the
2094144894Sharti	 * characters which bracket its name. Angle-brackets imply it's
2095144894Sharti	 * a system Makefile while double-quotes imply it's a user makefile
2096144894Sharti	 */
2097144894Sharti	if (*file == '<') {
2098144894Sharti		isSystem = TRUE;
2099144894Sharti		endc = '>';
2100144894Sharti	} else {
2101144894Sharti		isSystem = FALSE;
2102144894Sharti		endc = '"';
2103144894Sharti	}
2104144894Sharti
2105144894Sharti	/*
2106144894Sharti	* Skip to matching delimiter
2107144894Sharti	*/
2108144894Sharti	for (cp = ++file; *cp != endc; cp++) {
2109144894Sharti		if (*cp == '\0') {
2110144894Sharti			Parse_Error(PARSE_FATAL,
2111144894Sharti			    "Unclosed .include filename. '%c' expected", endc);
2112144894Sharti			return;
2113144894Sharti		}
2114144894Sharti	}
2115144894Sharti	*cp = '\0';
2116144894Sharti
2117144894Sharti	/*
2118144894Sharti	 * Substitute for any variables in the file name before trying to
2119144894Sharti	 * find the thing.
2120144894Sharti	 */
2121146027Sharti	file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE));
2122144894Sharti
2123144894Sharti	/*
2124144894Sharti	 * Now we know the file's name and its search path, we attempt to
2125144894Sharti	 * find the durn thing. A return of NULL indicates the file don't
2126144894Sharti	 * exist.
2127144894Sharti	 */
2128144894Sharti	if (!isSystem) {
2129144894Sharti		/*
2130144894Sharti		 * Include files contained in double-quotes are first searched
2131144894Sharti		 * for relative to the including file's location. We don't want
2132144894Sharti		 * to cd there, of course, so we just tack on the old file's
2133144894Sharti		 * leading path components and call Dir_FindFile to see if
2134144894Sharti		 * we can locate the beast.
2135144894Sharti		 */
2136144894Sharti
2137144894Sharti		/* Make a temporary copy of this, to be safe. */
2138144894Sharti		Fname = estrdup(CURFILE->fname);
2139144894Sharti
2140144894Sharti		prefEnd = strrchr(Fname, '/');
2141144894Sharti		if (prefEnd != NULL) {
2142144894Sharti			*prefEnd = '\0';
2143144894Sharti			if (file[0] == '/')
2144144894Sharti				newName = estrdup(file);
2145144894Sharti			else
2146144894Sharti				newName = str_concat(Fname, file, STR_ADDSLASH);
2147144894Sharti			fullname = Path_FindFile(newName, &parseIncPath);
2148144894Sharti			if (fullname == NULL) {
2149144894Sharti				fullname = Path_FindFile(newName,
2150144894Sharti				    &dirSearchPath);
2151144894Sharti			}
2152144894Sharti			free(newName);
2153144894Sharti			*prefEnd = '/';
2154144894Sharti		} else {
2155144894Sharti			fullname = NULL;
2156144894Sharti		}
2157144894Sharti		free(Fname);
2158144894Sharti	} else {
2159144894Sharti		fullname = NULL;
2160144894Sharti	}
2161144894Sharti
2162144894Sharti	if (fullname == NULL) {
2163144894Sharti		/*
2164144894Sharti		 * System makefile or makefile wasn't found in same directory as
2165144894Sharti		 * included makefile. Search for it first on the -I search path,
2166144894Sharti		 * then on the .PATH search path, if not found in a -I
2167144894Sharti		 * directory.
2168144894Sharti		 * XXX: Suffix specific?
2169144894Sharti		 */
2170144894Sharti		fullname = Path_FindFile(file, &parseIncPath);
2171144894Sharti		if (fullname == NULL) {
2172144894Sharti			fullname = Path_FindFile(file, &dirSearchPath);
2173144894Sharti		}
2174144894Sharti	}
2175144894Sharti
2176144894Sharti	if (fullname == NULL) {
2177144894Sharti		/*
2178144894Sharti		 * Still haven't found the makefile. Look for it on the system
2179144894Sharti		 * path as a last resort.
2180144894Sharti		 */
2181144894Sharti		fullname = Path_FindFile(file, &sysIncPath);
2182144894Sharti	}
2183144894Sharti
2184144894Sharti	if (fullname == NULL) {
2185144894Sharti		*cp = endc;
2186150595Sphk		if (!sinclude)
2187150595Sphk			Parse_Error(PARSE_FATAL, "Could not find %s", file);
2188144894Sharti		free(file);
2189144894Sharti		return;
2190144894Sharti	}
2191144894Sharti	free(file);
2192144894Sharti
2193144894Sharti	/*
2194144894Sharti	 * We set up the name of the file to be the absolute
2195144894Sharti	 * name of the include file so error messages refer to the right
2196144894Sharti	 * place.
2197144894Sharti	 */
2198144894Sharti	ParsePushInput(fullname, NULL, NULL, 0);
2199144894Sharti}
2200144894Sharti
2201150595Sphkstatic void
2202150595Sphkparse_include(char *file, int code __unused, int lineno __unused)
2203150595Sphk{
2204150595Sphk	xparse_include(file, 0);
2205150595Sphk}
2206150595Sphk
2207150595Sphkstatic void
2208150595Sphkparse_sinclude(char *file, int code __unused, int lineno __unused)
2209150595Sphk{
2210150595Sphk	xparse_include(file, 1);
2211150595Sphk}
2212150595Sphk
2213144894Sharti/**
2214144894Sharti * parse_message
2215144894Sharti *	Parse a .warning or .error directive
2216144894Sharti *
2217144894Sharti *	The input is the line minus the ".error"/".warning".  We substitute
2218144894Sharti *	variables, print the message and exit(1) (for .error) or just print
2219144894Sharti *	a warning if the directive is malformed.
2220144894Sharti */
2221144894Shartistatic void
2222144894Shartiparse_message(char *line, int iserror, int lineno __unused)
2223144894Sharti{
2224144894Sharti
2225144894Sharti	if (!isspace((u_char)*line)) {
2226144894Sharti		Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s",
2227144894Sharti		    iserror ? "error" : "warning", line);
2228144894Sharti		return;
2229144894Sharti	}
2230144894Sharti
2231144894Sharti	while (isspace((u_char)*line))
2232144894Sharti		line++;
2233144894Sharti
2234146027Sharti	line = Buf_Peel(Var_Subst(line, VAR_GLOBAL, FALSE));
2235144894Sharti	Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line);
2236144894Sharti	free(line);
2237144894Sharti
2238144894Sharti	if (iserror) {
2239144894Sharti		/* Terminate immediately. */
2240144894Sharti		exit(1);
2241144894Sharti	}
2242144894Sharti}
2243144894Sharti
2244144894Sharti/**
2245144894Sharti * parse_undef
2246144894Sharti *	Parse an .undef directive.
2247144894Sharti */
2248144894Shartistatic void
2249144894Shartiparse_undef(char *line, int code __unused, int lineno __unused)
2250144894Sharti{
2251144894Sharti	char *cp;
2252144894Sharti
2253144894Sharti	while (isspace((u_char)*line))
2254144894Sharti		line++;
2255144894Sharti
2256144894Sharti	for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) {
2257144894Sharti		;
2258144894Sharti	}
2259144894Sharti	*cp = '\0';
2260144894Sharti
2261146027Sharti	cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE));
2262144894Sharti	Var_Delete(cp, VAR_GLOBAL);
2263144894Sharti	free(cp);
2264144894Sharti}
2265144894Sharti
2266144894Sharti/**
2267144894Sharti * parse_for
2268144894Sharti *	Parse a .for directive.
2269144894Sharti */
2270144894Shartistatic void
2271144894Shartiparse_for(char *line, int code __unused, int lineno)
2272144894Sharti{
2273144894Sharti
2274144894Sharti	if (!For_For(line)) {
2275144894Sharti		/* syntax error */
2276144894Sharti		return;
2277144894Sharti	}
2278144894Sharti	line = NULL;
2279144894Sharti
2280144894Sharti	/*
2281144894Sharti	 * Skip after the matching endfor.
2282144894Sharti	 */
2283144894Sharti	do {
2284144894Sharti		free(line);
2285144894Sharti		line = ParseSkipLine(0, 1);
2286144894Sharti		if (line == NULL) {
2287144894Sharti			Parse_Error(PARSE_FATAL,
2288144894Sharti			    "Unexpected end of file in for loop.\n");
2289144894Sharti			return;
2290144894Sharti		}
2291144894Sharti	} while (For_Eval(line));
2292144894Sharti	free(line);
2293144894Sharti
2294144894Sharti	/* execute */
2295144894Sharti	For_Run(lineno);
2296144894Sharti}
2297144894Sharti
2298144894Sharti/**
2299144894Sharti * parse_endfor
2300144894Sharti *	Parse endfor. This may only happen if there was no matching .for.
2301144894Sharti */
2302144894Shartistatic void
2303144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused)
2304144894Sharti{
2305144894Sharti
2306144894Sharti	Parse_Error(PARSE_FATAL, "for-less endfor");
2307144894Sharti}
2308144894Sharti
2309144894Sharti/**
2310144894Sharti * parse_directive
2311144894Sharti *	Got a line starting with a '.'. Check if this is a directive
2312144894Sharti *	and parse it.
2313144894Sharti *
2314144894Sharti * return:
2315144894Sharti *	TRUE if line was a directive, FALSE otherwise.
2316144894Sharti */
2317144894Shartistatic Boolean
2318144894Shartiparse_directive(char *line)
2319144894Sharti{
2320144894Sharti	char	*start;
2321144894Sharti	char	*cp;
2322144894Sharti	int	dir;
2323144894Sharti
2324144894Sharti	/*
2325144894Sharti	 * Get the keyword:
2326144894Sharti	 *	.[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).*
2327144894Sharti	 * \1 is the keyword.
2328144894Sharti	 */
2329144894Sharti	for (start = line; isspace((u_char)*start); start++) {
2330144894Sharti		;
2331144894Sharti	}
2332144894Sharti
2333144894Sharti	if (!isalpha((u_char)*start)) {
2334144894Sharti		return (FALSE);
2335144894Sharti	}
2336144894Sharti
2337144894Sharti	cp = start + 1;
2338144894Sharti	while (isalnum((u_char)*cp) || *cp == '_') {
2339144894Sharti		cp++;
2340144894Sharti	}
2341144894Sharti
2342144894Sharti	dir = directive_hash(start, cp - start);
2343144894Sharti	if (dir < 0 || dir >= (int)NDIRECTS ||
2344144894Sharti	    (size_t)(cp - start) != strlen(directives[dir].name) ||
2345144894Sharti	    strncmp(start, directives[dir].name, cp - start) != 0) {
2346144894Sharti		/* not actually matched */
2347144894Sharti		return (FALSE);
2348144894Sharti	}
2349144894Sharti
2350144894Sharti	if (!skipLine || directives[dir].skip_flag)
2351144894Sharti		(*directives[dir].func)(cp, directives[dir].code,
2352144894Sharti		    CURFILE->lineno);
2353144894Sharti	return (TRUE);
2354144894Sharti}
2355144894Sharti
23561590Srgrimes/*-
23571590Srgrimes *---------------------------------------------------------------------
23581590Srgrimes * Parse_File --
23591590Srgrimes *	Parse a file into its component parts, incorporating it into the
23601590Srgrimes *	current dependency graph. This is the main function and controls
23611590Srgrimes *	almost every other function in this module
23621590Srgrimes *
23631590Srgrimes * Results:
23641590Srgrimes *	None
23651590Srgrimes *
23661590Srgrimes * Side Effects:
23671590Srgrimes *	Loads. Nodes are added to the list of all targets, nodes and links
23681590Srgrimes *	are added to the dependency graph. etc. etc. etc.
23691590Srgrimes *---------------------------------------------------------------------
23701590Srgrimes */
23711590Srgrimesvoid
2372144341ShartiParse_File(const char *name, FILE *stream)
23731590Srgrimes{
2374144026Sharti	char	*cp;	/* pointer into the line */
2375144026Sharti	char	*line;	/* the line we're working on */
23761590Srgrimes
2377144026Sharti	inLine = FALSE;
2378144026Sharti	fatals = 0;
23791590Srgrimes
2380144341Sharti	ParsePushInput(estrdup(name), stream, NULL, 0);
2381131456Seik
2382144742Sharti	while ((line = ParseReadLine()) != NULL) {
2383144894Sharti		if (*line == '.' && parse_directive(line + 1)) {
2384144894Sharti			/* directive consumed */
2385144894Sharti			goto nextLine;
2386144742Sharti		}
2387144894Sharti		if (skipLine || *line == '#') {
2388144894Sharti			/* Skipping .if block or comment. */
2389144742Sharti			goto nextLine;
2390144742Sharti		}
23918874Srgrimes
2392144742Sharti		if (*line == '\t') {
2393144742Sharti			/*
2394144742Sharti			 * If a line starts with a tab, it can only
2395144742Sharti			 * hope to be a creation command.
2396144742Sharti			 */
2397144742Sharti			for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
2398144742Sharti				continue;
2399144742Sharti			}
2400144742Sharti			if (*cp) {
2401144742Sharti				if (inLine) {
2402144742Sharti					LstNode	*ln;
2403144742Sharti					GNode	*gn;
2404143684Sharti
2405144742Sharti					/*
2406144742Sharti					 * So long as it's not a blank
2407144742Sharti					 * line and we're actually in a
2408144742Sharti					 * dependency spec, add the
2409144742Sharti					 * command to the list of
2410144742Sharti					 * commands of all targets in
2411144742Sharti					 * the dependency spec.
2412144742Sharti					 */
2413144742Sharti					LST_FOREACH(ln, &targets) {
2414144742Sharti						gn = Lst_Datum(ln);
2415144742Sharti
2416144026Sharti						/*
2417144742Sharti						 * if target already
2418144742Sharti						 * supplied, ignore
2419144742Sharti						 * commands
2420144026Sharti						 */
2421144742Sharti						if (!(gn->type & OP_HAS_COMMANDS))
2422144742Sharti							Lst_AtEnd(&gn->commands, cp);
2423144742Sharti						else
2424144742Sharti							Parse_Error(PARSE_WARNING, "duplicate script "
2425144742Sharti							    "for target \"%s\" ignored", gn->name);
2426144026Sharti					}
2427144742Sharti					continue;
2428144742Sharti				} else {
2429144742Sharti					Parse_Error(PARSE_FATAL,
2430144742Sharti					     "Unassociated shell command \"%s\"",
2431144742Sharti					     cp);
2432144026Sharti				}
2433144742Sharti			}
24341590Srgrimes#ifdef SYSVINCLUDE
2435144742Sharti		} else if (strncmp(line, "include", 7) == 0 &&
2436144742Sharti		    isspace((unsigned char)line[7]) &&
2437144742Sharti		    strchr(line, ':') == NULL) {
2438144742Sharti			/*
2439144742Sharti			 * It's an S3/S5-style "include".
2440144742Sharti			 */
2441144742Sharti			ParseTraditionalInclude(line + 7);
2442144742Sharti			goto nextLine;
24431590Srgrimes#endif
2444144742Sharti		} else if (Parse_IsVar(line)) {
2445144742Sharti			ParseFinishLine();
2446144742Sharti			Parse_DoVar(line, VAR_GLOBAL);
24478874Srgrimes
2448144742Sharti		} else {
2449144742Sharti			/*
2450144742Sharti			 * We now know it's a dependency line so it
2451144742Sharti			 * needs to have all variables expanded before
2452144742Sharti			 * being parsed. Tell the variable module to
2453144742Sharti			 * complain if some variable is undefined...
2454144742Sharti			 * To make life easier on novices, if the line
2455144742Sharti			 * is indented we first make sure the line has
2456144742Sharti			 * a dependency operator in it. If it doesn't
2457144742Sharti			 * have an operator and we're in a dependency
2458144742Sharti			 * line's script, we assume it's actually a
2459144742Sharti			 * shell command and add it to the current
2460144894Sharti			 * list of targets. XXX this comment seems wrong.
2461144742Sharti			 */
2462144742Sharti			cp = line;
2463144742Sharti			if (isspace((unsigned char)line[0])) {
2464144742Sharti				while (*cp != '\0' &&
2465144742Sharti				    isspace((unsigned char)*cp)) {
2466144742Sharti					cp++;
2467144026Sharti				}
2468144742Sharti				if (*cp == '\0') {
2469144742Sharti					goto nextLine;
2470144742Sharti				}
2471144742Sharti			}
24721590Srgrimes
2473144742Sharti			ParseFinishLine();
2474142457Sharti
2475146027Sharti			cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE));
24768874Srgrimes
2477144742Sharti			free(line);
2478144742Sharti			line = cp;
2479144026Sharti
2480144742Sharti			/*
2481144742Sharti			 * Need a non-circular list for the target nodes
2482144742Sharti			 */
2483144742Sharti			Lst_Destroy(&targets, NOFREE);
2484144742Sharti			inLine = TRUE;
2485144026Sharti
2486144742Sharti			ParseDoDependency(line);
2487144026Sharti		}
2488144026Sharti
2489144742Sharti  nextLine:
2490144742Sharti		free(line);
2491144742Sharti	}
24928874Srgrimes
2493144026Sharti	ParseFinishLine();
24941590Srgrimes
24951590Srgrimes	/*
2496144026Sharti	 * Make sure conditionals are clean
24971590Srgrimes	 */
2498144026Sharti	Cond_End();
24991590Srgrimes
2500144026Sharti	if (fatals)
2501144026Sharti		errx(1, "fatal errors encountered -- cannot continue");
25021590Srgrimes}
25031590Srgrimes
25041590Srgrimes/*-
25051590Srgrimes *-----------------------------------------------------------------------
25061590Srgrimes * Parse_MainName --
25071590Srgrimes *	Return a Lst of the main target to create for main()'s sake. If
25081590Srgrimes *	no such target exists, we Punt with an obnoxious error message.
25091590Srgrimes *
25101590Srgrimes * Results:
25111590Srgrimes *	A Lst of the single node to create.
25121590Srgrimes *
25131590Srgrimes * Side Effects:
25141590Srgrimes *	None.
25151590Srgrimes *
25161590Srgrimes *-----------------------------------------------------------------------
25171590Srgrimes */
2518138916Shartivoid
2519138916ShartiParse_MainName(Lst *listmain)
25201590Srgrimes{
25211590Srgrimes
2522144026Sharti	if (mainNode == NULL) {
2523144026Sharti		Punt("no target to make.");
2524144026Sharti		/*NOTREACHED*/
2525144026Sharti	} else if (mainNode->type & OP_DOUBLEDEP) {
2526144026Sharti		Lst_AtEnd(listmain, mainNode);
2527144026Sharti		Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW);
2528144026Sharti	} else
2529144026Sharti		Lst_AtEnd(listmain, mainNode);
25301590Srgrimes}
2531