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$");
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 */
171177101Sobrien	MakefileDeps,	/* .MAKEFILEDEPS */
172144026Sharti	Precious,	/* .PRECIOUS */
173144026Sharti	ExShell,	/* .SHELL */
174144026Sharti	Silent,		/* .SILENT */
175144026Sharti	SingleShell,	/* .SINGLESHELL */
176144026Sharti	Suffixes,	/* .SUFFIXES */
177144026Sharti	Wait,		/* .WAIT */
178145679Sharti	Warn,		/* .WARN */
179144026Sharti	Attribute	/* Generic attribute */
1801590Srgrimes} ParseSpecial;
1811590Srgrimes
1821590Srgrimesstatic ParseSpecial specType;
18318730Sstevestatic int waiting;
1841590Srgrimes
1851590Srgrimes/*
18669527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1871590Srgrimes * seen, then set to each successive source on the line.
1881590Srgrimes */
189144026Shartistatic GNode *predecessor;
1901590Srgrimes
1911590Srgrimes/*
1921590Srgrimes * The parseKeywords table is searched using binary search when deciding
1931590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial
1941590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while
1951590Srgrimes * the 'op' field is the operator to apply to the list of targets if the
1961590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source)
1971590Srgrimes */
198145616Shartistatic const struct keyword {
199144026Sharti	const char	*name;	/* Name of keyword */
200144026Sharti	ParseSpecial	spec;	/* Type when used as a target */
201144026Sharti	int		op;	/* Operator when used as a source */
2021590Srgrimes} parseKeywords[] = {
203145616Sharti	/* KEYWORD-START-TAG */
204144026Sharti	{ ".BEGIN",		Begin,		0 },
205144026Sharti	{ ".DEFAULT",		Default,	0 },
206144026Sharti	{ ".END",		End,		0 },
207144026Sharti	{ ".EXEC",		Attribute,	OP_EXEC },
208145971Sharti	{ ".EXPORTVAR",		ExportVar,	0 },
209144026Sharti	{ ".IGNORE",		Ignore,		OP_IGNORE },
210144026Sharti	{ ".INCLUDES",		Includes,	0 },
211144026Sharti	{ ".INTERRUPT",		Interrupt,	0 },
212144026Sharti	{ ".INVISIBLE",		Attribute,	OP_INVISIBLE },
213144026Sharti	{ ".JOIN",		Attribute,	OP_JOIN },
214144026Sharti	{ ".LIBS",		Libs,		0 },
215144026Sharti	{ ".MAIN",		Main,		0 },
216144026Sharti	{ ".MAKE",		Attribute,	OP_MAKE },
217177101Sobrien	{ ".MAKEFILEDEPS",	MakefileDeps,	0 },
218144026Sharti	{ ".MAKEFLAGS",		MFlags,		0 },
219144026Sharti	{ ".MFLAGS",		MFlags,		0 },
220144026Sharti	{ ".NOTMAIN",		Attribute,	OP_NOTMAIN },
221144026Sharti	{ ".NOTPARALLEL",	NotParallel,	0 },
222144026Sharti	{ ".NO_PARALLEL",	NotParallel,	0 },
223144026Sharti	{ ".NULL",		Null,		0 },
224144026Sharti	{ ".OPTIONAL",		Attribute,	OP_OPTIONAL },
225144026Sharti	{ ".ORDER",		Order,		0 },
226144026Sharti	{ ".PARALLEL",		Parallel,	0 },
227144026Sharti	{ ".PATH",		ExPath,		0 },
228144026Sharti	{ ".PHONY",		Phony,		OP_PHONY },
229144026Sharti	{ ".POSIX",		Posix,		0 },
230144026Sharti	{ ".PRECIOUS",		Precious,	OP_PRECIOUS },
231144026Sharti	{ ".RECURSIVE",		Attribute,	OP_MAKE },
232144026Sharti	{ ".SHELL",		ExShell,	0 },
233144026Sharti	{ ".SILENT",		Silent,		OP_SILENT },
234144026Sharti	{ ".SINGLESHELL",	SingleShell,	0 },
235144026Sharti	{ ".SUFFIXES",		Suffixes,	0 },
236144026Sharti	{ ".USE",		Attribute,	OP_USE },
237144026Sharti	{ ".WAIT",		Wait,		0 },
238145679Sharti	{ ".WARN",		Warn,		0 },
239145616Sharti	/* KEYWORD-END-TAG */
2401590Srgrimes};
241145616Sharti#define	NKEYWORDS	(sizeof(parseKeywords) / sizeof(parseKeywords[0]))
2421590Srgrimes
243144894Shartistatic void parse_include(char *, int, int);
244150595Sphkstatic void parse_sinclude(char *, int, int);
245144894Shartistatic void parse_message(char *, int, int);
246144894Shartistatic void parse_undef(char *, int, int);
247144894Shartistatic void parse_for(char *, int, int);
248144894Shartistatic void parse_endfor(char *, int, int);
249144894Sharti
250144894Shartistatic const struct directive {
251144894Sharti	const char	*name;
252144894Sharti	int		code;
253144894Sharti	Boolean		skip_flag;	/* execute even when skipped */
254144894Sharti	void		(*func)(char *, int, int);
255144894Sharti} directives[] = {
256145612Sharti	/* DIRECTIVES-START-TAG */
257144894Sharti	{ "elif",	COND_ELIF,	TRUE,	Cond_If },
258144894Sharti	{ "elifdef",	COND_ELIFDEF,	TRUE,	Cond_If },
259144894Sharti	{ "elifmake",	COND_ELIFMAKE,	TRUE,	Cond_If },
260144894Sharti	{ "elifndef",	COND_ELIFNDEF,	TRUE,	Cond_If },
261144894Sharti	{ "elifnmake",	COND_ELIFNMAKE,	TRUE,	Cond_If },
262144894Sharti	{ "else",	COND_ELSE,	TRUE,	Cond_Else },
263144894Sharti	{ "endfor",	0,		FALSE,	parse_endfor },
264144894Sharti	{ "endif",	COND_ENDIF,	TRUE,	Cond_Endif },
265144894Sharti	{ "error",	1,		FALSE,	parse_message },
266144894Sharti	{ "for",	0,		FALSE,	parse_for },
267144894Sharti	{ "if",		COND_IF,	TRUE,	Cond_If },
268144894Sharti	{ "ifdef",	COND_IFDEF,	TRUE,	Cond_If },
269144894Sharti	{ "ifmake",	COND_IFMAKE,	TRUE,	Cond_If },
270144894Sharti	{ "ifndef",	COND_IFNDEF,	TRUE,	Cond_If },
271144894Sharti	{ "ifnmake",	COND_IFNMAKE,	TRUE,	Cond_If },
272144894Sharti	{ "include",	0,		FALSE,	parse_include },
273150595Sphk	{ "sinclude",	0,		FALSE,	parse_sinclude },
274144894Sharti	{ "undef",	0,		FALSE,	parse_undef },
275144894Sharti	{ "warning",	0,		FALSE,	parse_message },
276145612Sharti	/* DIRECTIVES-END-TAG */
277144894Sharti};
278144894Sharti#define	NDIRECTS	(sizeof(directives) / sizeof(directives[0]))
279144894Sharti
2801590Srgrimes/*-
281145616Sharti * ParseFindKeyword
2821590Srgrimes *	Look in the table of keywords for one matching the given string.
2831590Srgrimes *
2841590Srgrimes * Results:
285145616Sharti *	The pointer to keyword table entry or NULL.
2861590Srgrimes */
287145616Shartistatic const struct keyword *
288145616ShartiParseFindKeyword(const char *str)
2891590Srgrimes{
290145616Sharti	int kw;
2918874Srgrimes
292145616Sharti	kw = keyword_hash(str, strlen(str));
293145616Sharti	if (kw < 0 || kw >= (int)NKEYWORDS ||
294145616Sharti	    strcmp(str, parseKeywords[kw].name) != 0)
295145616Sharti		return (NULL);
296145616Sharti	return (&parseKeywords[kw]);
2971590Srgrimes}
2981590Srgrimes
2991590Srgrimes/*-
3001590Srgrimes * Parse_Error  --
3011590Srgrimes *	Error message abort function for parsing. Prints out the context
3021590Srgrimes *	of the error (line number and file) as well as the message with
3031590Srgrimes *	two optional arguments.
3041590Srgrimes *
3051590Srgrimes * Results:
3061590Srgrimes *	None
3071590Srgrimes *
3081590Srgrimes * Side Effects:
3091590Srgrimes *	"fatals" is incremented if the level is PARSE_FATAL.
3101590Srgrimes */
3111590Srgrimes/* VARARGS */
3121590Srgrimesvoid
31398136SjmallettParse_Error(int type, const char *fmt, ...)
3141590Srgrimes{
3151590Srgrimes	va_list ap;
31693056Simp
3171590Srgrimes	va_start(ap, fmt);
318144745Sharti	if (CURFILE != NULL)
319144745Sharti		fprintf(stderr, "\"%s\", line %d: ",
320144745Sharti		    CURFILE->fname, CURFILE->lineno);
3211590Srgrimes	if (type == PARSE_WARNING)
322138232Sharti		fprintf(stderr, "warning: ");
323138232Sharti	vfprintf(stderr, fmt, ap);
3241590Srgrimes	va_end(ap);
325138232Sharti	fprintf(stderr, "\n");
326138232Sharti	fflush(stderr);
3271590Srgrimes	if (type == PARSE_FATAL)
3281590Srgrimes		fatals += 1;
3291590Srgrimes}
3301590Srgrimes
331144341Sharti/**
332144341Sharti * ParsePushInput
333144341Sharti *
334144341Sharti * Push a new input source onto the input stack. If ptr is NULL
335144341Sharti * the fullname is used to fopen the file. If it is not NULL,
336144341Sharti * ptr is assumed to point to the string to be parsed. If opening the
337144341Sharti * file fails, the fullname is freed.
338144341Sharti */
339144341Shartistatic void
340144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno)
341144341Sharti{
342144341Sharti	struct IFile *nf;
343144341Sharti
344144341Sharti	nf = emalloc(sizeof(*nf));
345144341Sharti	nf->fname = fullname;
346144341Sharti	nf->lineno = lineno;
347144341Sharti
348144341Sharti	if (ptr == NULL) {
349144341Sharti		/* the input source is a file */
350144341Sharti		if ((nf->F = fp) == NULL) {
351144341Sharti			nf->F = fopen(fullname, "r");
352144341Sharti			if (nf->F == NULL) {
353144341Sharti				Parse_Error(PARSE_FATAL, "Cannot open %s",
354144341Sharti				    fullname);
355144341Sharti				free(fullname);
356144341Sharti				free(nf);
357144341Sharti				return;
358144341Sharti			}
359144341Sharti		}
360144341Sharti		nf->str = nf->ptr = NULL;
361144341Sharti		Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
362144341Sharti	} else {
363144341Sharti		nf->str = nf->ptr = ptr;
364144341Sharti		nf->F = NULL;
365144341Sharti	}
366144341Sharti	TAILQ_INSERT_HEAD(&includes, nf, link);
367144341Sharti}
368144341Sharti
369144341Sharti/**
370144341Sharti * ParsePopInput
371144341Sharti *	Called when EOF is reached in the current file. If we were reading
372144341Sharti *	an include file, the includes stack is popped and things set up
373144341Sharti *	to go back to reading the previous file at the previous location.
374144341Sharti *
375144341Sharti * Results:
376144341Sharti *	CONTINUE if there's more to do. DONE if not.
377144341Sharti *
378144341Sharti * Side Effects:
379144341Sharti *	The old curFile.F is closed. The includes list is shortened.
380144341Sharti *	curFile.lineno, curFile.F, and curFile.fname are changed if
381144341Sharti *	CONTINUE is returned.
382144341Sharti */
383144341Shartistatic int
384144341ShartiParsePopInput(void)
385144341Sharti{
386144341Sharti	struct IFile *ifile;	/* the state on the top of the includes stack */
387144341Sharti
388144341Sharti	assert(!TAILQ_EMPTY(&includes));
389144341Sharti
390144341Sharti	ifile = TAILQ_FIRST(&includes);
391144341Sharti	TAILQ_REMOVE(&includes, ifile, link);
392144341Sharti
393144341Sharti	free(ifile->fname);
394144341Sharti	if (ifile->F != NULL) {
395144341Sharti		fclose(ifile->F);
396144341Sharti		Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
397144341Sharti	}
398144341Sharti	if (ifile->str != NULL) {
399144341Sharti		free(ifile->str);
400144341Sharti	}
401144341Sharti	free(ifile);
402144341Sharti
403144341Sharti	return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE);
404144341Sharti}
405144341Sharti
406145679Sharti/**
407145679Sharti * parse_warn
408145679Sharti *	Parse the .WARN pseudo-target.
409145679Sharti */
410145679Shartistatic void
411145679Shartiparse_warn(char *line)
412145679Sharti{
413146345Sharti	ArgArray	aa;
414146345Sharti	int		i;
415145679Sharti
416146345Sharti	brk_string(&aa, line, TRUE);
417145679Sharti
418146345Sharti	for (i = 1; i < aa.argc; i++)
419146345Sharti		Main_ParseWarn(aa.argv[i], 0);
420145679Sharti}
421145679Sharti
4221590Srgrimes/*-
4231590Srgrimes *---------------------------------------------------------------------
4241590Srgrimes * ParseLinkSrc  --
425143100Sharti *	Link the parent nodes to their new child. Used by
4261590Srgrimes *	ParseDoDependency. If the specType isn't 'Not', the parent
4271590Srgrimes *	isn't linked as a parent of the child.
4281590Srgrimes *
4291590Srgrimes * Side Effects:
430143100Sharti *	New elements are added to the parents lists of cgn and the
4311590Srgrimes *	children list of cgn. the unmade field of pgn is updated
4321590Srgrimes *	to reflect the additional child.
4331590Srgrimes *---------------------------------------------------------------------
4341590Srgrimes */
435143027Shartistatic void
436143027ShartiParseLinkSrc(Lst *parents, GNode *cgn)
4371590Srgrimes{
438143027Sharti	LstNode	*ln;
439143027Sharti	GNode *pgn;
440138232Sharti
441143027Sharti	LST_FOREACH(ln, parents) {
442143027Sharti		pgn = Lst_Datum(ln);
443143027Sharti		if (Lst_Member(&pgn->children, cgn) == NULL) {
444143027Sharti			Lst_AtEnd(&pgn->children, cgn);
445143027Sharti			if (specType == Not) {
446143027Sharti				Lst_AtEnd(&cgn->parents, pgn);
447143027Sharti			}
448143027Sharti			pgn->unmade += 1;
449143027Sharti		}
4501590Srgrimes	}
4511590Srgrimes}
4521590Srgrimes
4531590Srgrimes/*-
4541590Srgrimes *---------------------------------------------------------------------
4551590Srgrimes * ParseDoOp  --
456143684Sharti *	Apply the parsed operator to all target nodes. Used in
457143684Sharti *	ParseDoDependency once all targets have been found and their
458143684Sharti *	operator parsed. If the previous and new operators are incompatible,
459143684Sharti *	a major error is taken.
4601590Srgrimes *
4611590Srgrimes * Side Effects:
4621590Srgrimes *	The type field of the node is altered to reflect any new bits in
4631590Srgrimes *	the op.
4641590Srgrimes *---------------------------------------------------------------------
4651590Srgrimes */
466143684Shartistatic void
467143684ShartiParseDoOp(int op)
4681590Srgrimes{
469143684Sharti	GNode	*cohort;
470143684Sharti	LstNode	*ln;
471143684Sharti	GNode	*gn;
472138232Sharti
473143684Sharti	LST_FOREACH(ln, &targets) {
474143684Sharti		gn = Lst_Datum(ln);
4751590Srgrimes
476143684Sharti		/*
477143684Sharti		 * If the dependency mask of the operator and the node don't
478143684Sharti		 * match and the node has actually had an operator applied to
479143684Sharti		 * it before, and the operator actually has some dependency
480143684Sharti		 * information in it, complain.
481143684Sharti		 */
482143684Sharti		if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) &&
483143684Sharti		    !OP_NOP(gn->type) && !OP_NOP(op)) {
484143684Sharti			Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
485143684Sharti			    gn->name);
486143684Sharti			return;
487143684Sharti		}
4888874Srgrimes
489143684Sharti		if (op == OP_DOUBLEDEP &&
490143684Sharti		    (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
491143684Sharti			/*
492143684Sharti			 * If the node was the object of a :: operator, we need
493143684Sharti			 * to create a new instance of it for the children and
494143684Sharti			 * commands on this dependency line. The new instance
495143684Sharti			 * is placed on the 'cohorts' list of the initial one
496143684Sharti			 * (note the initial one is not on its own cohorts list)
497143684Sharti			 * and the new instance is linked to all parents of the
498143684Sharti			 * initial instance.
499143684Sharti			 */
500143684Sharti			cohort = Targ_NewGN(gn->name);
5011590Srgrimes
502143684Sharti			/*
503143684Sharti			 * Duplicate links to parents so graph traversal is
504143684Sharti			 * simple. Perhaps some type bits should be duplicated?
505143684Sharti			 *
506143684Sharti			 * Make the cohort invisible as well to avoid
507143684Sharti			 * duplicating it into other variables. True, parents
508143684Sharti			 * of this target won't tend to do anything with their
509143684Sharti			 * local variables, but better safe than sorry.
510143684Sharti			 */
511143684Sharti			ParseLinkSrc(&gn->parents, cohort);
512143684Sharti			cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
513143684Sharti			Lst_AtEnd(&gn->cohorts, cohort);
5141590Srgrimes
515143684Sharti			/*
516143684Sharti			 * Replace the node in the targets list with the
517143684Sharti			 * new copy
518143684Sharti			 */
519143684Sharti			Lst_Replace(ln, cohort);
520143684Sharti			gn = cohort;
521143684Sharti		}
522143684Sharti		/*
523143684Sharti		 * We don't want to nuke any previous flags (whatever they were)
524143684Sharti		 * so we just OR the new operator into the old
525143684Sharti		 */
526143684Sharti		gn->type |= op;
527143684Sharti	}
5281590Srgrimes}
5291590Srgrimes
5301590Srgrimes/*-
5311590Srgrimes *---------------------------------------------------------------------
5321590Srgrimes * ParseDoSrc  --
5331590Srgrimes *	Given the name of a source, figure out if it is an attribute
5341590Srgrimes *	and apply it to the targets if it is. Else decide if there is
5351590Srgrimes *	some attribute which should be applied *to* the source because
5361590Srgrimes *	of some special target and apply it if so. Otherwise, make the
5371590Srgrimes *	source be a child of the targets in the list 'targets'
5381590Srgrimes *
5391590Srgrimes * Results:
5401590Srgrimes *	None
5411590Srgrimes *
5421590Srgrimes * Side Effects:
5431590Srgrimes *	Operator bits may be added to the list of targets or to the source.
5441590Srgrimes *	The targets may have a new source added to their lists of children.
5451590Srgrimes *---------------------------------------------------------------------
5461590Srgrimes */
5471590Srgrimesstatic void
548138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc)
5491590Srgrimes{
550144026Sharti	GNode	*gn = NULL;
551145616Sharti	const struct keyword *kw;
5521590Srgrimes
553145616Sharti	if (src[0] == '.' && isupper ((unsigned char)src[1])) {
554145616Sharti		if ((kw = ParseFindKeyword(src)) != NULL) {
555145616Sharti			if (kw->op != 0) {
556145616Sharti				ParseDoOp(kw->op);
557144026Sharti				return;
558144026Sharti			}
559145616Sharti			if (kw->spec == Wait) {
560144026Sharti				waiting++;
561144026Sharti				return;
562144026Sharti			}
563144026Sharti		}
5641590Srgrimes	}
56518730Ssteve
566144026Sharti	switch (specType) {
567144026Sharti	  case Main:
568144026Sharti		/*
569144026Sharti		 * If we have noted the existence of a .MAIN, it means we need
570144026Sharti		 * to add the sources of said target to the list of things
571144026Sharti		 * to create. The string 'src' is likely to be free, so we
572144026Sharti		 * must make a new copy of it. Note that this will only be
573144026Sharti		 * invoked if the user didn't specify a target on the command
574144026Sharti		 * line. This is to allow #ifmake's to succeed, or something...
575144026Sharti		 */
576144026Sharti		Lst_AtEnd(&create, estrdup(src));
577144026Sharti		/*
578144026Sharti		 * Add the name to the .TARGETS variable as well, so the user
579144026Sharti		 * can employ that, if desired.
580144026Sharti		 */
581144026Sharti		Var_Append(".TARGETS", src, VAR_GLOBAL);
582144026Sharti		return;
58318730Ssteve
584144026Sharti	  case Order:
585144026Sharti		/*
586144026Sharti		 * Create proper predecessor/successor links between the
587144026Sharti		 * previous source and the current one.
588144026Sharti		 */
589144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
590144026Sharti		if (predecessor != NULL) {
591144026Sharti			Lst_AtEnd(&predecessor->successors, gn);
592144026Sharti			Lst_AtEnd(&gn->preds, predecessor);
593144026Sharti		}
594144026Sharti		/*
595144026Sharti		 * The current source now becomes the predecessor for the next
596144026Sharti		 * one.
597144026Sharti		 */
598144026Sharti		predecessor = gn;
599144026Sharti		break;
60018730Ssteve
601144026Sharti	  default:
602144026Sharti		/*
603144026Sharti		 * If the source is not an attribute, we need to find/create
604144026Sharti		 * a node for it. After that we can apply any operator to it
605144026Sharti		 * from a special target or link it to its parents, as
606144026Sharti		 * appropriate.
607144026Sharti		 *
608144026Sharti		 * In the case of a source that was the object of a :: operator,
609144026Sharti		 * the attribute is applied to all of its instances (as kept in
610144026Sharti		 * the 'cohorts' list of the node) or all the cohorts are linked
611144026Sharti		 * to all the targets.
612144026Sharti		 */
613144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
6141590Srgrimes		if (tOp) {
615144026Sharti			gn->type |= tOp;
6161590Srgrimes		} else {
617144026Sharti			ParseLinkSrc(&targets, gn);
6181590Srgrimes		}
619144026Sharti		if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
620144026Sharti			GNode	*cohort;
621144026Sharti			LstNode	*ln;
622144026Sharti
623144026Sharti			for (ln = Lst_First(&gn->cohorts); ln != NULL;
624144026Sharti			    ln = Lst_Succ(ln)) {
625144026Sharti				cohort = Lst_Datum(ln);
626144026Sharti				if (tOp) {
627144026Sharti					cohort->type |= tOp;
628144026Sharti				} else {
629144026Sharti					ParseLinkSrc(&targets, cohort);
630144026Sharti				}
631144026Sharti			}
632144026Sharti		}
633144026Sharti		break;
6341590Srgrimes	}
63518730Ssteve
636144026Sharti	gn->order = waiting;
637144026Sharti	Lst_AtEnd(allsrc, gn);
638144026Sharti	if (waiting) {
639144026Sharti		LstNode	*ln;
640144026Sharti		GNode	*p;
6411590Srgrimes
642143684Sharti		/*
643144026Sharti		 * Check if GNodes needs to be synchronized.
644144026Sharti		 * This has to be when two nodes are on different sides of a
645144026Sharti		 * .WAIT directive.
646143684Sharti		 */
647144026Sharti		LST_FOREACH(ln, allsrc) {
648144026Sharti			p = Lst_Datum(ln);
649144026Sharti
650144026Sharti			if (p->order >= gn->order)
651144026Sharti				break;
652144026Sharti			/*
653144026Sharti			 * XXX: This can cause loops, and loops can cause
654144026Sharti			 * unmade targets, but checking is tedious, and the
655144026Sharti			 * debugging output can show the problem
656144026Sharti			 */
657144026Sharti			Lst_AtEnd(&p->successors, gn);
658144026Sharti			Lst_AtEnd(&gn->preds, p);
659144026Sharti		}
660143684Sharti	}
6611590Srgrimes}
6621590Srgrimes
663138232Sharti
6641590Srgrimes/*-
6651590Srgrimes *---------------------------------------------------------------------
6661590Srgrimes * ParseDoDependency  --
6671590Srgrimes *	Parse the dependency line in line.
6681590Srgrimes *
6691590Srgrimes * Results:
6701590Srgrimes *	None
6711590Srgrimes *
6721590Srgrimes * Side Effects:
6731590Srgrimes *	The nodes of the sources are linked as children to the nodes of the
6741590Srgrimes *	targets. Some nodes may be created.
6751590Srgrimes *
6761590Srgrimes *	We parse a dependency line by first extracting words from the line and
6771590Srgrimes * finding nodes in the list of all targets with that name. This is done
6781590Srgrimes * until a character is encountered which is an operator character. Currently
6791590Srgrimes * these are only ! and :. At this point the operator is parsed and the
6801590Srgrimes * pointer into the line advanced until the first source is encountered.
681144026Sharti *	The parsed operator is applied to each node in the 'targets' list,
6821590Srgrimes * which is where the nodes found for the targets are kept, by means of
6831590Srgrimes * the ParseDoOp function.
6841590Srgrimes *	The sources are read in much the same way as the targets were except
6851590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell
6861590Srgrimes * and all instances of the resulting words in the list of all targets
6871590Srgrimes * are found. Each of the resulting nodes is then linked to each of the
6881590Srgrimes * targets as one of its children.
6891590Srgrimes *	Certain targets are handled specially. These are the ones detailed
6901590Srgrimes * by the specType variable.
6911590Srgrimes *	The storing of transformation rules is also taken care of here.
6921590Srgrimes * A target is recognized as a transformation rule by calling
6931590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten
6941590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard
6951590Srgrimes * Targ_FindNode in the target module.
6961590Srgrimes *---------------------------------------------------------------------
6971590Srgrimes */
6981590Srgrimesstatic void
699141270ShartiParseDoDependency(char *line)
7001590Srgrimes{
701144026Sharti	char	*cp;	/* our current position */
702201456Sobrien	char	*lstart = line;	/* original input line */
703144026Sharti	GNode	*gn;	/* a general purpose temporary node */
704144026Sharti	int	op;	/* the operator on the line */
705144026Sharti	char	savec;	/* a place to save a character */
706144026Sharti	Lst	paths;	/* Search paths to alter when parsing .PATH targets */
707144026Sharti	int	tOp;	/* operator from special target */
708144026Sharti	LstNode	*ln;
709145616Sharti	const struct keyword *kw;
7101590Srgrimes
711144026Sharti	tOp = 0;
7121590Srgrimes
713144026Sharti	specType = Not;
714144026Sharti	waiting = 0;
715144026Sharti	Lst_Init(&paths);
7161590Srgrimes
717144026Sharti	do {
718144026Sharti		for (cp = line;
719144026Sharti		    *cp && !isspace((unsigned char)*cp) && *cp != '(';
720144026Sharti		    cp++) {
721144026Sharti			if (*cp == '$') {
722144026Sharti				/*
723144026Sharti				 * Must be a dynamic source (would have been
724144026Sharti				 * expanded otherwise), so call the Var module
725144026Sharti				 * to parse the puppy so we can safely advance
726144026Sharti				 * beyond it...There should be no errors in this
727144026Sharti				 * as they would have been discovered in the
728144026Sharti				 * initial Var_Subst and we wouldn't be here.
729144026Sharti				 */
730144026Sharti				size_t	length = 0;
731144026Sharti				Boolean	freeIt;
732144026Sharti				char	*result;
7331590Srgrimes
734144026Sharti				result = Var_Parse(cp, VAR_CMD, TRUE,
735144026Sharti				    &length, &freeIt);
7361590Srgrimes
737144026Sharti				if (freeIt) {
738144026Sharti					free(result);
739144026Sharti				}
740144026Sharti				cp += length - 1;
741102178Sru
742144026Sharti			} else if (*cp == '!' || *cp == ':') {
743144026Sharti				/*
744144026Sharti				 * We don't want to end a word on ':' or '!' if
745144026Sharti				 * there is a better match later on in the
746144026Sharti				 * string (greedy matching).
747144026Sharti				 * This allows the user to have targets like:
748144026Sharti				 *    fie::fi:fo: fum
749144026Sharti				 *    foo::bar:
750144026Sharti				 * where "fie::fi:fo" and "foo::bar" are the
751144026Sharti				 * targets. In real life this is used for perl5
752144026Sharti				 * library man pages where "::" separates an
753144026Sharti				 * object from its class. Ie:
754144026Sharti				 * "File::Spec::Unix". This behaviour is also
755144026Sharti				 * consistent with other versions of make.
756144026Sharti				 */
757144026Sharti				char *p = cp + 1;
758102178Sru
759144026Sharti				if (*cp == ':' && *p == ':')
760144026Sharti					p++;
761102178Sru
762144026Sharti				/* Found the best match already. */
763144026Sharti				if (*p == '\0' || isspace(*p))
764144026Sharti					break;
765102178Sru
766144026Sharti				p += strcspn(p, "!:");
7678874Srgrimes
768144026Sharti				/* No better match later on... */
769144026Sharti				if (*p == '\0')
770144026Sharti					break;
771144026Sharti			}
772144026Sharti			continue;
7731590Srgrimes		}
774144026Sharti		if (*cp == '(') {
775144026Sharti			/*
776144026Sharti			 * Archives must be handled specially to make sure the
777144026Sharti			 * OP_ARCHV flag is set in their 'type' field, for one
778144026Sharti			 * thing, and because things like "archive(file1.o
779144026Sharti			 * file2.o file3.o)" are permissible. Arch_ParseArchive
780144026Sharti			 * will set 'line' to be the first non-blank after the
781144026Sharti			 * archive-spec. It creates/finds nodes for the members
782146338Sharti			 * and places them on the given list, returning TRUE
783146338Sharti			 * if all went well and FALSE if there was an error in
784144026Sharti			 * the specification. On error, line should remain
785144026Sharti			 * untouched.
786144026Sharti			 */
787146338Sharti			if (!Arch_ParseArchive(&line, &targets, VAR_CMD)) {
788144026Sharti				Parse_Error(PARSE_FATAL,
789144026Sharti				    "Error in archive specification: \"%s\"",
790144026Sharti				    line);
791144026Sharti				return;
792144026Sharti			} else {
793144026Sharti				cp = line;
794144026Sharti				continue;
795144026Sharti			}
796144026Sharti		}
797144026Sharti		savec = *cp;
7988874Srgrimes
799144026Sharti		if (!*cp) {
800144026Sharti			/*
801144026Sharti			 * Ending a dependency line without an operator is a				 * Bozo no-no. As a heuristic, this is also often
802144026Sharti			 * triggered by undetected conflicts from cvs/rcs
803144026Sharti			 * merges.
804144026Sharti			 */
805144026Sharti			if (strncmp(line, "<<<<<<", 6) == 0 ||
806201455Sobrien			    strncmp(line, "||||||", 6) == 0 ||
807144026Sharti			    strncmp(line, "======", 6) == 0 ||
808144026Sharti			    strncmp(line, ">>>>>>", 6) == 0) {
809144026Sharti				Parse_Error(PARSE_FATAL, "Makefile appears to "
810144026Sharti				    "contain unresolved cvs/rcs/??? merge "
811144026Sharti				    "conflicts");
812144026Sharti			} else
813201456Sobrien				Parse_Error(PARSE_FATAL, lstart[0] == '.' ?
814201456Sobrien				    "Unknown directive" : "Need an operator");
815144026Sharti			return;
816144026Sharti		}
817144026Sharti		*cp = '\0';
8181590Srgrimes		/*
819144026Sharti		 * Have a word in line. See if it's a special target and set
820144026Sharti		 * specType to match it.
8211590Srgrimes		 */
822144026Sharti		if (*line == '.' && isupper((unsigned char)line[1])) {
823144026Sharti			/*
824144026Sharti			 * See if the target is a special target that must have
825144026Sharti			 * it or its sources handled specially.
826144026Sharti			 */
827145616Sharti			if ((kw = ParseFindKeyword(line)) != NULL) {
828145616Sharti				if (specType == ExPath && kw->spec != ExPath) {
829144026Sharti					Parse_Error(PARSE_FATAL,
830144026Sharti					    "Mismatched special targets");
831144026Sharti					return;
832144026Sharti				}
833144026Sharti
834145616Sharti				specType = kw->spec;
835145616Sharti				tOp = kw->op;
836144026Sharti
837144026Sharti				/*
838144026Sharti				 * Certain special targets have special
839144026Sharti				 * semantics:
840144026Sharti				 *  .PATH	Have to set the dirSearchPath
841144026Sharti				 *		variable too
842144026Sharti				 *  .MAIN	Its sources are only used if
843144026Sharti				 *		nothing has been specified to
844144026Sharti				 *		create.
845144026Sharti				 *  .DEFAULT    Need to create a node to hang
846144026Sharti				 *		commands on, but we don't want
847144026Sharti				 *		it in the graph, nor do we want
848144026Sharti				 *		it to be the Main Target, so we
849144026Sharti				 *		create it, set OP_NOTMAIN and
850144026Sharti				 *		add it to the list, setting
851144026Sharti				 *		DEFAULT to the new node for
852144026Sharti				 *		later use. We claim the node is
853144026Sharti				 *		A transformation rule to make
854144026Sharti				 *		life easier later, when we'll
855144026Sharti				 *		use Make_HandleUse to actually
856144026Sharti				 *		apply the .DEFAULT commands.
857144026Sharti				 *  .PHONY	The list of targets
858144026Sharti				 *  .BEGIN
859144026Sharti				 *  .END
860144026Sharti				 *  .INTERRUPT	Are not to be considered the
861144026Sharti				 *		main target.
862144026Sharti				 *  .NOTPARALLEL Make only one target at a time.
863144026Sharti				 *  .SINGLESHELL Create a shell for each
864144026Sharti				 *		command.
865144026Sharti				 *  .ORDER	Must set initial predecessor
866144026Sharti				 *		to NULL
867144026Sharti				 */
868144026Sharti				switch (specType) {
869144026Sharti				  case ExPath:
870144026Sharti					Lst_AtEnd(&paths, &dirSearchPath);
871144026Sharti					break;
872144026Sharti				  case Main:
873144026Sharti					if (!Lst_IsEmpty(&create)) {
874144026Sharti						specType = Not;
875144026Sharti					}
876144026Sharti					break;
877144026Sharti				  case Begin:
878144026Sharti				  case End:
879144026Sharti				  case Interrupt:
880144026Sharti					gn = Targ_FindNode(line, TARG_CREATE);
881144026Sharti					gn->type |= OP_NOTMAIN;
882144026Sharti					Lst_AtEnd(&targets, gn);
883144026Sharti					break;
884144026Sharti				  case Default:
885144026Sharti					gn = Targ_NewGN(".DEFAULT");
886144026Sharti					gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
887144026Sharti					Lst_AtEnd(&targets, gn);
888144026Sharti					DEFAULT = gn;
889144026Sharti					break;
890144026Sharti				  case NotParallel:
891146140Sharti					jobLimit = 1;
892144026Sharti					break;
893144026Sharti				  case SingleShell:
894144026Sharti					compatMake = 1;
895144026Sharti					break;
896144026Sharti				  case Order:
897144026Sharti					predecessor = NULL;
898144026Sharti					break;
899144026Sharti				  default:
900144026Sharti					break;
901144026Sharti				}
902144026Sharti
903144026Sharti			} else if (strncmp(line, ".PATH", 5) == 0) {
904144026Sharti				/*
905144026Sharti				 * .PATH<suffix> has to be handled specially.
906144026Sharti				 * Call on the suffix module to give us a path
907144026Sharti				 * to modify.
908144026Sharti				 */
909144026Sharti				struct Path *path;
910144026Sharti
911144026Sharti				specType = ExPath;
912144026Sharti				path = Suff_GetPath(&line[5]);
913144026Sharti				if (path == NULL) {
914144026Sharti					Parse_Error(PARSE_FATAL, "Suffix '%s' "
915144026Sharti					    "not defined (yet)", &line[5]);
916144026Sharti					return;
917144026Sharti				} else
918144026Sharti					Lst_AtEnd(&paths, path);
9191590Srgrimes			}
9201590Srgrimes		}
921144026Sharti
9221590Srgrimes		/*
923144026Sharti		 * Have word in line. Get or create its node and stick it at
924144026Sharti		 * the end of the targets list
9251590Srgrimes		 */
926144029Sharti		if (specType == Not && *line != '\0') {
9278874Srgrimes
928144026Sharti			/* target names to be found and added to targets list */
929144026Sharti			Lst curTargs = Lst_Initializer(curTargs);
9308874Srgrimes
931144026Sharti			if (Dir_HasWildcards(line)) {
932144026Sharti				/*
933144026Sharti				 * Targets are to be sought only in the current
934144026Sharti				 * directory, so create an empty path for the
935144026Sharti				 * thing. Note we need to use Path_Clear in the
936144026Sharti				 * destruction of the path as the Dir module
937144026Sharti				 * could have added a directory to the path...
938144026Sharti				 */
939144026Sharti				struct Path emptyPath =
940144026Sharti				    TAILQ_HEAD_INITIALIZER(emptyPath);
941138916Sharti
942144026Sharti				Path_Expand(line, &emptyPath, &curTargs);
943144026Sharti				Path_Clear(&emptyPath);
9448874Srgrimes
945144026Sharti			} else {
946144026Sharti				/*
947144026Sharti				 * No wildcards, but we want to avoid code
948144026Sharti				 * duplication, so create a list with the word
949144026Sharti				 * on it.
950144026Sharti				 */
951144026Sharti				Lst_AtEnd(&curTargs, line);
952144026Sharti			}
9538874Srgrimes
954144026Sharti			while (!Lst_IsEmpty(&curTargs)) {
955144026Sharti				char	*targName = Lst_DeQueue(&curTargs);
956144026Sharti
957144026Sharti				if (!Suff_IsTransform (targName)) {
958144026Sharti					gn = Targ_FindNode(targName,
959144026Sharti					    TARG_CREATE);
960144026Sharti				} else {
961144026Sharti					gn = Suff_AddTransform(targName);
962144026Sharti				}
963144026Sharti
964144026Sharti				Lst_AtEnd(&targets, gn);
965144026Sharti			}
966144026Sharti		} else if (specType == ExPath && *line != '.' && *line != '\0'){
967144026Sharti			Parse_Error(PARSE_WARNING, "Extra target (%s) ignored",
968144026Sharti			    line);
969144026Sharti		}
970144026Sharti
971144026Sharti		*cp = savec;
9721590Srgrimes		/*
973144026Sharti		 * If it is a special type and not .PATH, it's the only
974144026Sharti		 * target we allow on this line...
9751590Srgrimes		 */
976144026Sharti		if (specType != Not && specType != ExPath) {
977144026Sharti			Boolean warnFlag = FALSE;
9788874Srgrimes
979144029Sharti			while (*cp != '!' && *cp != ':' && *cp) {
980144026Sharti				if (*cp != ' ' && *cp != '\t') {
981144026Sharti					warnFlag = TRUE;
982144026Sharti				}
983144026Sharti				cp++;
984144026Sharti			}
985144026Sharti			if (warnFlag) {
986144026Sharti				Parse_Error(PARSE_WARNING,
987144026Sharti				    "Extra target ignored");
988144026Sharti			}
9891590Srgrimes		} else {
990144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
991144026Sharti				cp++;
992144026Sharti			}
9931590Srgrimes		}
994144026Sharti		line = cp;
995144029Sharti	} while (*line != '!' && *line != ':' && *line);
9968874Srgrimes
997144026Sharti	if (!Lst_IsEmpty(&targets)) {
998144026Sharti		switch (specType) {
999144026Sharti		  default:
1000144026Sharti			Parse_Error(PARSE_WARNING, "Special and mundane "
1001144026Sharti			    "targets don't mix. Mundane ones ignored");
1002144026Sharti			break;
1003144026Sharti		  case Default:
1004144026Sharti		  case Begin:
1005144026Sharti		  case End:
1006144026Sharti		  case Interrupt:
1007144026Sharti			/*
1008144026Sharti			 * These four create nodes on which to hang commands, so
1009144026Sharti			 * targets shouldn't be empty...
1010144026Sharti			 */
1011144026Sharti		  case Not:
1012144026Sharti			/*
1013144026Sharti			 * Nothing special here -- targets can be empty if it
1014144026Sharti			 * wants.
1015144026Sharti			 */
1016144026Sharti			break;
1017144026Sharti		}
10181590Srgrimes	}
10198874Srgrimes
10201590Srgrimes	/*
1021144026Sharti	 * Have now parsed all the target names. Must parse the operator next.
1022144026Sharti	 * The result is left in op.
10231590Srgrimes	 */
1024144026Sharti	if (*cp == '!') {
1025144026Sharti		op = OP_FORCE;
1026144026Sharti	} else if (*cp == ':') {
1027144026Sharti		if (cp[1] == ':') {
1028144026Sharti			op = OP_DOUBLEDEP;
1029144026Sharti			cp++;
1030144026Sharti		} else {
1031144026Sharti			op = OP_DEPENDS;
10321590Srgrimes		}
10331590Srgrimes	} else {
1034201456Sobrien		Parse_Error(PARSE_FATAL, lstart[0] == '.' ?
1035201456Sobrien		    "Unknown directive" : "Missing dependency operator");
1036144026Sharti		return;
1037144026Sharti	}
1038144026Sharti
1039144026Sharti	cp++;			/* Advance beyond operator */
1040144026Sharti
1041144026Sharti	ParseDoOp(op);
1042144026Sharti
1043144026Sharti	/*
1044144026Sharti	 * Get to the first source
1045144026Sharti	 */
1046144026Sharti	while (*cp && isspace((unsigned char)*cp)) {
10471590Srgrimes		cp++;
10481590Srgrimes	}
10491590Srgrimes	line = cp;
10501590Srgrimes
1051144026Sharti	/*
1052144026Sharti	 * Several special targets take different actions if present with no
1053144026Sharti	 * sources:
1054144026Sharti	 *	a .SUFFIXES line with no sources clears out all old suffixes
1055144026Sharti	 *	a .PRECIOUS line makes all targets precious
1056144026Sharti	 *	a .IGNORE line ignores errors for all targets
1057144026Sharti	 *	a .SILENT line creates silence when making all targets
1058144026Sharti	 *	a .PATH removes all directories from the search path(s).
1059144026Sharti	 */
1060144026Sharti	if (!*line) {
1061144026Sharti		switch (specType) {
1062144026Sharti		  case Suffixes:
1063144026Sharti			Suff_ClearSuffixes();
1064144026Sharti			break;
1065144026Sharti		  case Precious:
1066144026Sharti			allPrecious = TRUE;
1067144026Sharti			break;
1068144026Sharti		  case Ignore:
1069144026Sharti			ignoreErrors = TRUE;
1070144026Sharti			break;
1071144026Sharti		  case Silent:
1072144026Sharti			beSilent = TRUE;
1073144026Sharti			break;
1074144026Sharti		  case ExPath:
1075144026Sharti			LST_FOREACH(ln, &paths)
1076144026Sharti			Path_Clear(Lst_Datum(ln));
1077144026Sharti			break;
1078177101Sobrien		  case MakefileDeps:
1079177101Sobrien			mfAutoDeps = TRUE;
1080177101Sobrien			break;
1081144026Sharti		  case Posix:
1082167330Sfjoe			is_posix = TRUE;
1083186558Sobrien			Var_SetGlobal("%POSIX", "1003.2");
1084144026Sharti			break;
1085144026Sharti		  default:
1086144026Sharti			break;
1087144026Sharti		}
1088144026Sharti
1089144026Sharti	} else if (specType == MFlags) {
10901590Srgrimes		/*
1091144026Sharti		 * Call on functions in main.c to deal with these arguments and
1092144026Sharti		 * set the initial character to a null-character so the loop to
1093144026Sharti		 * get sources won't get anything
10941590Srgrimes		 */
1095144026Sharti		Main_ParseArgLine(line, 0);
1096144026Sharti		*line = '\0';
10971590Srgrimes
1098145679Sharti	} else if (specType == Warn) {
1099145679Sharti		parse_warn(line);
1100145679Sharti		*line = '\0';
1101145679Sharti
1102144026Sharti	} else if (specType == ExShell) {
1103146572Sharti		if (!Shell_Parse(line)) {
1104144026Sharti			Parse_Error(PARSE_FATAL,
1105144026Sharti			    "improper shell specification");
1106144026Sharti			return;
1107144026Sharti		}
1108144026Sharti		*line = '\0';
1109144026Sharti
1110144029Sharti	} else if (specType == NotParallel || specType == SingleShell) {
1111144026Sharti		*line = '\0';
11121590Srgrimes	}
11131590Srgrimes
1114144026Sharti	/*
1115144026Sharti	* NOW GO FOR THE SOURCES
1116144026Sharti	*/
1117144029Sharti	if (specType == Suffixes || specType == ExPath ||
1118144029Sharti	    specType == Includes || specType == Libs ||
1119144029Sharti	    specType == Null) {
1120144026Sharti		while (*line) {
1121144026Sharti			/*
1122144026Sharti			 * If the target was one that doesn't take files as its
1123144026Sharti			 * sources but takes something like suffixes, we take
1124144026Sharti			 * each space-separated word on the line as a something
1125144026Sharti			 * and deal with it accordingly.
1126144026Sharti			 *
1127144026Sharti			 * If the target was .SUFFIXES, we take each source as
1128144026Sharti			 * a suffix and add it to the list of suffixes
1129144026Sharti			 * maintained by the Suff module.
1130144026Sharti			 *
1131144026Sharti			 * If the target was a .PATH, we add the source as a
1132144026Sharti			 * directory to search on the search path.
1133144026Sharti			 *
1134144026Sharti			 * If it was .INCLUDES, the source is taken to be the
1135144026Sharti			 * suffix of files which will be #included and whose
1136144026Sharti			 * search path should be present in the .INCLUDES
1137144026Sharti			 * variable.
1138144026Sharti			 *
1139144026Sharti			 * If it was .LIBS, the source is taken to be the
1140144026Sharti			 * suffix of files which are considered libraries and
1141144026Sharti			 * whose search path should be present in the .LIBS
1142144026Sharti			 * variable.
1143144026Sharti			 *
1144144026Sharti			 * If it was .NULL, the source is the suffix to use
1145144026Sharti			 * when a file has no valid suffix.
1146144026Sharti			 */
1147144026Sharti			char  savech;
1148144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1149144026Sharti				cp++;
1150144026Sharti			}
1151144026Sharti			savech = *cp;
1152144026Sharti			*cp = '\0';
1153144026Sharti			switch (specType) {
1154144026Sharti			  case Suffixes:
1155144026Sharti				Suff_AddSuffix(line);
1156144026Sharti				break;
1157144026Sharti			  case ExPath:
1158144026Sharti				LST_FOREACH(ln, &paths)
1159144026Sharti					Path_AddDir(Lst_Datum(ln), line);
1160144026Sharti				break;
1161144026Sharti			  case Includes:
1162144026Sharti				Suff_AddInclude(line);
1163144026Sharti				break;
1164144026Sharti			  case Libs:
1165144026Sharti				Suff_AddLib(line);
1166144026Sharti				break;
1167144026Sharti			  case Null:
1168144026Sharti				Suff_SetNull(line);
1169144026Sharti				break;
1170144026Sharti			  default:
1171144026Sharti				break;
1172144026Sharti			}
1173144026Sharti			*cp = savech;
1174144026Sharti			if (savech != '\0') {
1175144026Sharti				cp++;
1176144026Sharti			}
1177144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1178144026Sharti				cp++;
1179144026Sharti			}
1180144026Sharti			line = cp;
1181144026Sharti		}
1182144026Sharti		Lst_Destroy(&paths, NOFREE);
11831590Srgrimes
1184145971Sharti	} else if (specType == ExportVar) {
1185145971Sharti		Var_SetEnv(line, VAR_GLOBAL);
1186145971Sharti
1187144026Sharti	} else {
1188144026Sharti		/* list of sources in order */
1189144026Sharti		Lst curSrcs = Lst_Initializer(curSrc);
11901590Srgrimes
1191144026Sharti		while (*line) {
1192144026Sharti			/*
1193144026Sharti			 * The targets take real sources, so we must beware of
1194144026Sharti			 * archive specifications (i.e. things with left
1195144026Sharti			 * parentheses in them) and handle them accordingly.
1196144026Sharti			 */
1197144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1198144026Sharti				if (*cp == '(' && cp > line && cp[-1] != '$') {
1199144026Sharti					/*
1200144026Sharti					 * Only stop for a left parenthesis if
1201144026Sharti					 * it isn't at the start of a word
1202144026Sharti					 * (that'll be for variable changes
1203144026Sharti					 * later) and isn't preceded by a dollar
1204144026Sharti					 * sign (a dynamic source).
1205144026Sharti					 */
1206144026Sharti					break;
1207144026Sharti				} else {
1208144026Sharti					cp++;
1209144026Sharti				}
1210144026Sharti			}
12111590Srgrimes
1212144026Sharti			if (*cp == '(') {
1213144026Sharti				GNode	  *gnp;
12148874Srgrimes
1215144026Sharti				/* list of archive source names after exp. */
1216144026Sharti				Lst sources = Lst_Initializer(sources);
1217138916Sharti
1218146338Sharti				if (!Arch_ParseArchive(&line, &sources,
1219146338Sharti				    VAR_CMD)) {
1220144026Sharti					Parse_Error(PARSE_FATAL, "Error in "
1221144026Sharti					    "source archive spec \"%s\"", line);
1222144026Sharti					return;
1223144026Sharti				}
1224141270Sharti
1225144026Sharti				while (!Lst_IsEmpty(&sources)) {
1226144026Sharti					gnp = Lst_DeQueue(&sources);
1227144026Sharti					ParseDoSrc(tOp, gnp->name, &curSrcs);
1228144026Sharti				}
1229144026Sharti				cp = line;
1230144026Sharti			} else {
1231144026Sharti				if (*cp) {
1232144026Sharti					*cp = '\0';
1233144026Sharti					cp += 1;
1234144026Sharti				}
12351590Srgrimes
1236144026Sharti				ParseDoSrc(tOp, line, &curSrcs);
1237144026Sharti			}
1238144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1239144026Sharti				cp++;
1240144026Sharti			}
1241144026Sharti			line = cp;
12421590Srgrimes		}
1243144026Sharti		Lst_Destroy(&curSrcs, NOFREE);
1244144026Sharti	}
12451590Srgrimes
1246144026Sharti	if (mainNode == NULL) {
1247144026Sharti		/*
1248144026Sharti		 * If we have yet to decide on a main target to make, in the
1249144026Sharti		 * absence of any user input, we want the first target on
1250144026Sharti		 * the first dependency line that is actually a real target
1251144026Sharti		 * (i.e. isn't a .USE or .EXEC rule) to be made.
1252144026Sharti		 */
1253144026Sharti		LST_FOREACH(ln, &targets) {
1254144026Sharti			gn = Lst_Datum(ln);
1255144026Sharti			if ((gn->type & (OP_NOTMAIN | OP_USE |
1256144026Sharti			    OP_EXEC | OP_TRANSFORM)) == 0) {
1257144026Sharti				mainNode = gn;
1258144026Sharti				Targ_SetMain(gn);
1259144026Sharti				break;
1260144026Sharti			}
12611590Srgrimes		}
12621590Srgrimes	}
12631590Srgrimes}
12641590Srgrimes
12651590Srgrimes/*-
12661590Srgrimes *---------------------------------------------------------------------
12671590Srgrimes * Parse_IsVar  --
12681590Srgrimes *	Return TRUE if the passed line is a variable assignment. A variable
12691590Srgrimes *	assignment consists of a single word followed by optional whitespace
12701590Srgrimes *	followed by either a += or an = operator.
12711590Srgrimes *	This function is used both by the Parse_File function and main when
12721590Srgrimes *	parsing the command-line arguments.
12731590Srgrimes *
12741590Srgrimes * Results:
12751590Srgrimes *	TRUE if it is. FALSE if it ain't
12761590Srgrimes *
12771590Srgrimes * Side Effects:
12781590Srgrimes *	none
12791590Srgrimes *---------------------------------------------------------------------
12801590Srgrimes */
12811590SrgrimesBoolean
1282138232ShartiParse_IsVar(char *line)
12831590Srgrimes{
1284144026Sharti	Boolean wasSpace = FALSE;	/* set TRUE if found a space */
1285144026Sharti	Boolean haveName = FALSE;	/* Set TRUE if have a variable name */
1286138232Sharti
1287144026Sharti	int level = 0;
1288103503Sjmallett#define	ISEQOPERATOR(c) \
1289144029Sharti	((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!')
12901590Srgrimes
1291144026Sharti	/*
1292144026Sharti	 * Skip to variable name
1293144026Sharti	 */
1294144029Sharti	for (; *line == ' ' || *line == '\t'; line++)
1295144026Sharti		continue;
12961590Srgrimes
1297144026Sharti	for (; *line != '=' || level != 0; line++) {
1298144026Sharti		switch (*line) {
1299144026Sharti		  case '\0':
1300144026Sharti			/*
1301144026Sharti			 * end-of-line -- can't be a variable assignment.
1302144026Sharti			 */
1303144026Sharti			return (FALSE);
130418730Ssteve
1305144026Sharti		  case ' ':
1306144026Sharti		  case '\t':
1307144026Sharti			/*
1308144026Sharti			 * there can be as much white space as desired so long
1309144026Sharti			 * as there is only one word before the operator
1310144026Sharti			*/
1311144026Sharti			wasSpace = TRUE;
1312144026Sharti			break;
131318730Ssteve
1314144026Sharti		  case '(':
1315144026Sharti		  case '{':
1316144026Sharti			level++;
1317144026Sharti			break;
131818730Ssteve
1319144026Sharti		  case '}':
1320144026Sharti		  case ')':
1321144026Sharti			level--;
1322144026Sharti			break;
132318730Ssteve
1324144026Sharti		  default:
1325144026Sharti			if (wasSpace && haveName) {
1326144026Sharti				if (ISEQOPERATOR(*line)) {
1327144026Sharti					/*
1328144026Sharti					 * We must have a finished word
1329144026Sharti					 */
1330144026Sharti					if (level != 0)
1331144026Sharti						return (FALSE);
133218730Ssteve
1333144026Sharti					/*
1334144026Sharti					 * When an = operator [+?!:] is found,
1335144026Sharti					 * the next character must be an = or
1336144026Sharti					 * it ain't a valid assignment.
1337144026Sharti					 */
1338144026Sharti					if (line[1] == '=')
1339144026Sharti						return (haveName);
134018730Ssteve#ifdef SUNSHCMD
1341144026Sharti					/*
1342144026Sharti					 * This is a shell command
1343144026Sharti					 */
1344144026Sharti					if (strncmp(line, ":sh", 3) == 0)
1345144026Sharti						return (haveName);
134618730Ssteve#endif
1347144026Sharti				}
1348144026Sharti				/*
1349144026Sharti				 * This is the start of another word, so not
1350144026Sharti				 * assignment.
1351144026Sharti				 */
1352144026Sharti				return (FALSE);
1353144026Sharti
1354144026Sharti			} else {
1355144026Sharti				haveName = TRUE;
1356144026Sharti				wasSpace = FALSE;
1357144026Sharti			}
1358144026Sharti			break;
1359144026Sharti		}
13601590Srgrimes	}
13611590Srgrimes
1362144026Sharti	return (haveName);
13631590Srgrimes}
13641590Srgrimes
13651590Srgrimes/*-
13661590Srgrimes *---------------------------------------------------------------------
13671590Srgrimes * Parse_DoVar  --
13681590Srgrimes *	Take the variable assignment in the passed line and do it in the
13691590Srgrimes *	global context.
13701590Srgrimes *
13711590Srgrimes *	Note: There is a lexical ambiguity with assignment modifier characters
13721590Srgrimes *	in variable names. This routine interprets the character before the =
13731590Srgrimes *	as a modifier. Therefore, an assignment like
13741590Srgrimes *	    C++=/usr/bin/CC
13751590Srgrimes *	is interpreted as "C+ +=" instead of "C++ =".
13761590Srgrimes *
13771590Srgrimes * Results:
13781590Srgrimes *	none
13791590Srgrimes *
13801590Srgrimes * Side Effects:
13811590Srgrimes *	the variable structure of the given variable name is altered in the
13821590Srgrimes *	global context.
13831590Srgrimes *---------------------------------------------------------------------
13841590Srgrimes */
13851590Srgrimesvoid
1386138232ShartiParse_DoVar(char *line, GNode *ctxt)
13871590Srgrimes{
1388144026Sharti	char	*cp;	/* pointer into line */
1389144026Sharti	enum {
1390144026Sharti		VAR_SUBST,
1391144026Sharti		VAR_APPEND,
1392144026Sharti		VAR_SHELL,
1393144026Sharti		VAR_NORMAL
1394144026Sharti	}	type;	/* Type of assignment */
1395144026Sharti	char	*opc;	/* ptr to operator character to
1396144026Sharti			 * null-terminate the variable name */
1397144026Sharti
1398144026Sharti	/*
1399144026Sharti	 * Skip to variable name
1400144026Sharti	 */
1401144029Sharti	while (*line == ' ' || *line == '\t') {
1402144026Sharti		line++;
1403144026Sharti	}
14041590Srgrimes
1405144026Sharti	/*
1406144026Sharti	 * Skip to operator character, nulling out whitespace as we go
1407144026Sharti	 */
1408144026Sharti	for (cp = line + 1; *cp != '='; cp++) {
1409144026Sharti		if (isspace((unsigned char)*cp)) {
1410144026Sharti			*cp = '\0';
1411144026Sharti		}
14121590Srgrimes	}
1413144026Sharti	opc = cp - 1;		/* operator is the previous character */
1414144026Sharti	*cp++ = '\0';		/* nuke the = */
14151590Srgrimes
1416144026Sharti	/*
1417144026Sharti	 * Check operator type
1418144026Sharti	 */
1419144026Sharti	switch (*opc) {
1420144026Sharti	  case '+':
1421144026Sharti		type = VAR_APPEND;
1422144026Sharti		*opc = '\0';
1423144026Sharti		break;
14241590Srgrimes
1425144026Sharti	  case '?':
1426144026Sharti		/*
1427144026Sharti		 * If the variable already has a value, we don't do anything.
1428144026Sharti		 */
1429144026Sharti		*opc = '\0';
1430144026Sharti		if (Var_Exists(line, ctxt)) {
1431144026Sharti			return;
1432144026Sharti		} else {
1433144026Sharti			type = VAR_NORMAL;
1434144026Sharti		}
1435144026Sharti		break;
14361590Srgrimes
1437144026Sharti	  case ':':
1438144026Sharti		type = VAR_SUBST;
1439144026Sharti		*opc = '\0';
1440144026Sharti		break;
14411590Srgrimes
1442144026Sharti	  case '!':
1443144026Sharti		type = VAR_SHELL;
1444144026Sharti		*opc = '\0';
1445144026Sharti		break;
14461590Srgrimes
1447144026Sharti	  default:
144818730Ssteve#ifdef SUNSHCMD
1449144026Sharti		while (*opc != ':') {
1450144026Sharti			if (opc == line)
1451144026Sharti				break;
1452144026Sharti			else
1453144026Sharti				--opc;
1454144026Sharti		}
145518730Ssteve
1456144026Sharti		if (strncmp(opc, ":sh", 3) == 0) {
1457144026Sharti			type = VAR_SHELL;
1458144026Sharti			*opc = '\0';
1459144026Sharti			break;
1460144026Sharti		}
1461144026Sharti#endif
1462144026Sharti		type = VAR_NORMAL;
146318730Ssteve		break;
1464144026Sharti	}
14651590Srgrimes
1466144026Sharti	while (isspace((unsigned char)*cp)) {
1467144026Sharti		cp++;
1468144026Sharti	}
14691590Srgrimes
1470144026Sharti	if (type == VAR_APPEND) {
1471144026Sharti		Var_Append(line, cp, ctxt);
14721590Srgrimes
1473144026Sharti	} else if (type == VAR_SUBST) {
1474144026Sharti		/*
1475144026Sharti		 * Allow variables in the old value to be undefined, but leave
1476144026Sharti		 * their invocation alone -- this is done by forcing oldVars
1477144026Sharti		 * to be false.
1478144026Sharti		 * XXX: This can cause recursive variables, but that's not
1479144026Sharti		 * hard to do, and this allows someone to do something like
1480144026Sharti		 *
1481144026Sharti		 *  CFLAGS = $(.INCLUDES)
1482144026Sharti		 *  CFLAGS := -I.. $(CFLAGS)
1483144026Sharti		 *
1484144026Sharti		 * And not get an error.
1485144026Sharti		 */
1486144026Sharti		Boolean oldOldVars = oldVars;
148798509Sjmallett
1488144026Sharti		oldVars = FALSE;
148998509Sjmallett
1490144026Sharti		/*
1491144026Sharti		 * make sure that we set the variable the first time to nothing
1492144026Sharti		 * so that it gets substituted!
1493144026Sharti		 */
1494144026Sharti		if (!Var_Exists(line, ctxt))
1495144026Sharti			Var_Set(line, "", ctxt);
1496142457Sharti
1497146027Sharti		cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE));
14981590Srgrimes
1499144026Sharti		oldVars = oldOldVars;
15001590Srgrimes
1501144026Sharti		Var_Set(line, cp, ctxt);
1502144026Sharti		free(cp);
15031590Srgrimes
1504144026Sharti	} else if (type == VAR_SHELL) {
1505144026Sharti		/*
1506144026Sharti		 * TRUE if the command needs to be freed, i.e.
1507144026Sharti		 * if any variable expansion was performed
1508144026Sharti		 */
1509144026Sharti		Boolean	freeCmd = FALSE;
1510144026Sharti		Buffer *buf;
1511144026Sharti		const char *error;
15121590Srgrimes
1513144026Sharti		if (strchr(cp, '$') != NULL) {
1514144026Sharti			/*
1515144026Sharti			 * There's a dollar sign in the command, so perform
1516144026Sharti			 * variable expansion on the whole thing. The
1517144026Sharti			 * resulting string will need freeing when we're done,
1518144026Sharti			 * so set freeCmd to TRUE.
1519144026Sharti			 */
1520146027Sharti			cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE));
1521144026Sharti			freeCmd = TRUE;
1522144026Sharti		}
15231590Srgrimes
1524144026Sharti		buf = Cmd_Exec(cp, &error);
1525144026Sharti		Var_Set(line, Buf_Data(buf), ctxt);
1526144026Sharti		Buf_Destroy(buf, TRUE);
1527144026Sharti
1528144026Sharti		if (error)
1529144026Sharti			Parse_Error(PARSE_WARNING, error, cp);
1530144026Sharti
1531144026Sharti		if (freeCmd)
1532144026Sharti			free(cp);
1533144026Sharti
1534144026Sharti	} else {
1535144026Sharti		/*
1536144026Sharti		 * Normal assignment -- just do it.
1537144026Sharti		 */
1538144026Sharti		Var_Set(line, cp, ctxt);
1539144026Sharti	}
1540186559Sobrien	if (strcmp(line, MAKE_JOB_PREFIX) == 0)
1541186559Sobrien		Job_SetPrefix();
15421590Srgrimes}
15431590Srgrimes
15441590Srgrimes/*-
15451590Srgrimes *-----------------------------------------------------------------------
15461590Srgrimes * ParseHasCommands --
15471590Srgrimes *	Callback procedure for Parse_File when destroying the list of
15481590Srgrimes *	targets on the last dependency line. Marks a target as already
15491590Srgrimes *	having commands if it does, to keep from having shell commands
15501590Srgrimes *	on multiple dependency lines.
15511590Srgrimes *
15521590Srgrimes * Results:
15535814Sjkh *	None
15541590Srgrimes *
15551590Srgrimes * Side Effects:
15561590Srgrimes *	OP_HAS_COMMANDS may be set for the target.
15571590Srgrimes *
15581590Srgrimes *-----------------------------------------------------------------------
15591590Srgrimes */
15605814Sjkhstatic void
1561104696SjmallettParseHasCommands(void *gnp)
15621590Srgrimes{
1563144026Sharti	GNode *gn = gnp;
1564138232Sharti
1565144026Sharti	if (!Lst_IsEmpty(&gn->commands)) {
1566144026Sharti		gn->type |= OP_HAS_COMMANDS;
1567144026Sharti	}
15681590Srgrimes}
15691590Srgrimes
15701590Srgrimes/*-
15711590Srgrimes *-----------------------------------------------------------------------
15721590Srgrimes * Parse_AddIncludeDir --
15731590Srgrimes *	Add a directory to the path searched for included makefiles
15741590Srgrimes *	bracketed by double-quotes. Used by functions in main.c
15751590Srgrimes *
15761590Srgrimes * Results:
15771590Srgrimes *	None.
15781590Srgrimes *
15791590Srgrimes * Side Effects:
15801590Srgrimes *	The directory is appended to the list.
15811590Srgrimes *
15821590Srgrimes *-----------------------------------------------------------------------
15831590Srgrimes */
15841590Srgrimesvoid
1585138232ShartiParse_AddIncludeDir(char *dir)
15861590Srgrimes{
1587138232Sharti
1588144026Sharti	Path_AddDir(&parseIncPath, dir);
15891590Srgrimes}
15901590Srgrimes
15911590Srgrimes/*-
15921590Srgrimes *---------------------------------------------------------------------
15931590Srgrimes * Parse_FromString  --
15941590Srgrimes *	Start Parsing from the given string
15958874Srgrimes *
15961590Srgrimes * Results:
15971590Srgrimes *	None
15981590Srgrimes *
15991590Srgrimes * Side Effects:
1600126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1601126824Sru *	curFile.fname and curFile.F are altered for the new file
16021590Srgrimes *---------------------------------------------------------------------
16031590Srgrimes */
16041590Srgrimesvoid
1605126824SruParse_FromString(char *str, int lineno)
16061590Srgrimes{
16071590Srgrimes
1608144026Sharti	DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno));
16091590Srgrimes
1610144341Sharti	ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno);
16111590Srgrimes}
16121590Srgrimes
16131590Srgrimes#ifdef SYSVINCLUDE
16141590Srgrimes/*-
16151590Srgrimes *---------------------------------------------------------------------
16161590Srgrimes * ParseTraditionalInclude  --
16171590Srgrimes *	Push to another file.
16188874Srgrimes *
16191590Srgrimes *	The input is the line minus the "include".  The file name is
16201590Srgrimes *	the string following the "include".
16211590Srgrimes *
16221590Srgrimes * Results:
16231590Srgrimes *	None
16241590Srgrimes *
16251590Srgrimes * Side Effects:
1626126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1627126824Sru *	curFile.fname and curFile.F are altered for the new file
16281590Srgrimes *---------------------------------------------------------------------
16291590Srgrimes */
16301590Srgrimesstatic void
1631141270ShartiParseTraditionalInclude(char *file)
16321590Srgrimes{
1633144026Sharti	char	*fullname;	/* full pathname of file */
1634144026Sharti	char	*cp;		/* current position in file spec */
16351590Srgrimes
1636144026Sharti	/*
1637144026Sharti	 * Skip over whitespace
1638144026Sharti	 */
1639144029Sharti	while (*file == ' ' || *file == '\t') {
1640144026Sharti		file++;
1641144026Sharti	}
16421590Srgrimes
1643144026Sharti	if (*file == '\0') {
1644144026Sharti		Parse_Error(PARSE_FATAL, "Filename missing from \"include\"");
1645144026Sharti		return;
1646144026Sharti	}
16471590Srgrimes
1648144026Sharti	/*
1649144026Sharti	* Skip to end of line or next whitespace
1650144026Sharti	*/
1651144026Sharti	for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1652144026Sharti		continue;
1653144026Sharti	}
16541590Srgrimes
1655144026Sharti	*cp = '\0';
16561590Srgrimes
1657144026Sharti	/*
1658144026Sharti	 * Substitute for any variables in the file name before trying to
1659144026Sharti	 * find the thing.
1660144026Sharti	 */
1661146027Sharti	file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE));
16621590Srgrimes
16631590Srgrimes	/*
1664144026Sharti	 * Now we know the file's name, we attempt to find the durn thing.
1665144026Sharti	 * Search for it first on the -I search path, then on the .PATH
1666144026Sharti	 * search path, if not found in a -I directory.
16671590Srgrimes	 */
1668144026Sharti	fullname = Path_FindFile(file, &parseIncPath);
1669144026Sharti	if (fullname == NULL) {
1670144026Sharti		fullname = Path_FindFile(file, &dirSearchPath);
1671144026Sharti	}
16721590Srgrimes
1673144026Sharti	if (fullname == NULL) {
1674144026Sharti		/*
1675144026Sharti		 * Still haven't found the makefile. Look for it on the system
1676144026Sharti		 * path as a last resort.
1677144026Sharti		 */
1678144026Sharti		fullname = Path_FindFile(file, &sysIncPath);
1679144026Sharti	}
16801590Srgrimes
1681144026Sharti	if (fullname == NULL) {
1682144026Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
1683144026Sharti		/* XXXHB free(file) */
1684144026Sharti		return;
1685144026Sharti	}
1686142457Sharti
1687144026Sharti	/* XXXHB free(file) */
16881590Srgrimes
1689144026Sharti	/*
1690144341Sharti	 * We set up the name of the file to be the absolute
1691144026Sharti	 * name of the include file so error messages refer to the right
1692144341Sharti	 * place.
16931590Srgrimes	 */
1694144341Sharti	ParsePushInput(fullname, NULL, NULL, 0);
16951590Srgrimes}
16961590Srgrimes#endif
16971590Srgrimes
16981590Srgrimes/*-
16991590Srgrimes *---------------------------------------------------------------------
17001590Srgrimes * ParseReadc  --
17018874Srgrimes *	Read a character from the current file
17021590Srgrimes *
17031590Srgrimes * Results:
17041590Srgrimes *	The character that was read
17051590Srgrimes *
17061590Srgrimes * Side Effects:
17071590Srgrimes *---------------------------------------------------------------------
17081590Srgrimes */
17091590Srgrimesstatic int
1710104696SjmallettParseReadc(void)
17111590Srgrimes{
1712138232Sharti
1713144341Sharti	if (CURFILE->F != NULL)
1714144341Sharti		return (fgetc(CURFILE->F));
17158874Srgrimes
1716144341Sharti	if (CURFILE->str != NULL && *CURFILE->ptr != '\0')
1717144341Sharti		return (*CURFILE->ptr++);
1718144341Sharti
1719144026Sharti	return (EOF);
17201590Srgrimes}
17211590Srgrimes
17221590Srgrimes
17231590Srgrimes/*-
17241590Srgrimes *---------------------------------------------------------------------
17251590Srgrimes * ParseUnreadc  --
17268874Srgrimes *	Put back a character to the current file
17271590Srgrimes *
17281590Srgrimes * Results:
17291590Srgrimes *	None.
17301590Srgrimes *
17311590Srgrimes * Side Effects:
17321590Srgrimes *---------------------------------------------------------------------
17331590Srgrimes */
17341590Srgrimesstatic void
1735104696SjmallettParseUnreadc(int c)
17361590Srgrimes{
1737138232Sharti
1738144341Sharti	if (CURFILE->F != NULL) {
1739144341Sharti		ungetc(c, CURFILE->F);
1740144026Sharti		return;
1741144026Sharti	}
1742144341Sharti	if (CURFILE->str != NULL) {
1743144341Sharti		*--(CURFILE->ptr) = c;
1744144026Sharti		return;
1745144026Sharti	}
17461590Srgrimes}
17471590Srgrimes
17481590Srgrimes/* ParseSkipLine():
1749104696Sjmallett *	Grab the next line unless it begins with a dot (`.') and we're told to
1750104696Sjmallett *	ignore such lines.
17511590Srgrimes */
17521590Srgrimesstatic char *
1753126824SruParseSkipLine(int skip, int keep_newline)
17541590Srgrimes{
1755144026Sharti	char *line;
1756144026Sharti	int c, lastc;
1757144026Sharti	Buffer *buf;
17581590Srgrimes
1759144026Sharti	buf = Buf_Init(MAKE_BSIZE);
17601590Srgrimes
1761144026Sharti	do {
1762144026Sharti		Buf_Clear(buf);
1763144026Sharti		lastc = '\0';
17648874Srgrimes
1765144026Sharti		while (((c = ParseReadc()) != '\n' || lastc == '\\')
1766144026Sharti		    && c != EOF) {
1767144026Sharti			if (skip && c == '#' && lastc != '\\') {
1768144026Sharti				/*
1769144026Sharti				 * let a comment be terminated even by an
1770144026Sharti				 * escaped \n. This is consistent to comment
1771144026Sharti				 * handling in ParseReadLine
1772144026Sharti				 */
1773144026Sharti				while ((c = ParseReadc()) != '\n' && c != EOF)
1774144026Sharti					;
1775144026Sharti				break;
1776144026Sharti			}
1777144026Sharti			if (c == '\n') {
1778144026Sharti				if (keep_newline)
1779144026Sharti					Buf_AddByte(buf, (Byte)c);
1780144026Sharti				else
1781144026Sharti					Buf_ReplaceLastByte(buf, (Byte)' ');
1782144341Sharti				CURFILE->lineno++;
17838874Srgrimes
1784144026Sharti				while ((c = ParseReadc()) == ' ' || c == '\t')
1785144026Sharti					continue;
17868874Srgrimes
1787144026Sharti				if (c == EOF)
1788144026Sharti					break;
1789144026Sharti			}
179074272Swill
1791144026Sharti			Buf_AddByte(buf, (Byte)c);
1792144026Sharti			lastc = c;
1793144026Sharti		}
179418456Ssteve
1795144026Sharti		if (c == EOF) {
1796144026Sharti			Parse_Error(PARSE_FATAL,
1797144026Sharti			    "Unclosed conditional/for loop");
1798144026Sharti			Buf_Destroy(buf, TRUE);
1799144026Sharti			return (NULL);
1800144026Sharti		}
180118456Ssteve
1802144341Sharti		CURFILE->lineno++;
1803144026Sharti		Buf_AddByte(buf, (Byte)'\0');
1804144026Sharti		line = Buf_Data(buf);
1805144026Sharti	} while (skip == 1 && line[0] != '.');
180618456Ssteve
1807144026Sharti	Buf_Destroy(buf, FALSE);
1808144026Sharti	return (line);
18091590Srgrimes}
18101590Srgrimes
18111590Srgrimes/*-
18121590Srgrimes *---------------------------------------------------------------------
18131590Srgrimes * ParseReadLine --
18141590Srgrimes *	Read an entire line from the input file. Called only by Parse_File.
18151590Srgrimes *	To facilitate escaped newlines and what have you, a character is
18161590Srgrimes *	buffered in 'lastc', which is '\0' when no characters have been
18171590Srgrimes *	read. When we break out of the loop, c holds the terminating
18181590Srgrimes *	character and lastc holds a character that should be added to
18191590Srgrimes *	the line (unless we don't read anything but a terminator).
18201590Srgrimes *
18211590Srgrimes * Results:
18221590Srgrimes *	A line w/o its newline
18231590Srgrimes *
18241590Srgrimes * Side Effects:
18251590Srgrimes *	Only those associated with reading a character
18261590Srgrimes *---------------------------------------------------------------------
18271590Srgrimes */
18281590Srgrimesstatic char *
1829138232ShartiParseReadLine(void)
18301590Srgrimes{
1831144026Sharti	Buffer	*buf;		/* Buffer for current line */
1832144026Sharti	int	c;		/* the current character */
1833144026Sharti	int	lastc;		/* The most-recent character */
1834144026Sharti	Boolean	semiNL;		/* treat semi-colons as newlines */
1835144026Sharti	Boolean	ignDepOp;	/* TRUE if should ignore dependency operators
18361590Srgrimes				 * for the purposes of setting semiNL */
1837144026Sharti	Boolean	ignComment;	/* TRUE if should ignore comments (in a
18381590Srgrimes				 * shell command */
1839144026Sharti	char	*line;		/* Result */
1840144026Sharti	char	*ep;		/* to strip trailing blanks */
18411590Srgrimes
1842144742Sharti  again:
1843144026Sharti	semiNL = FALSE;
1844144026Sharti	ignDepOp = FALSE;
1845144026Sharti	ignComment = FALSE;
18461590Srgrimes
1847144742Sharti	lastc = '\0';
1848144742Sharti
1849144026Sharti	/*
1850144742Sharti	 * Handle tab at the beginning of the line. A leading tab (shell
1851144742Sharti	 * command) forces us to ignore comments and dependency operators and
1852144742Sharti	 * treat semi-colons as semi-colons (by leaving semiNL FALSE).
1853144742Sharti	 * This also discards completely blank lines.
1854144026Sharti	 */
1855144026Sharti	for (;;) {
1856144026Sharti		c = ParseReadc();
1857144742Sharti		if (c == EOF) {
1858144742Sharti			if (ParsePopInput() == DONE) {
1859144742Sharti				/* End of all inputs - return NULL */
1860144742Sharti				return (NULL);
1861144742Sharti			}
1862144742Sharti			continue;
1863144742Sharti		}
18641590Srgrimes
1865144026Sharti		if (c == '\t') {
1866144026Sharti			ignComment = ignDepOp = TRUE;
1867144742Sharti			lastc = c;
1868144026Sharti			break;
1869144742Sharti		}
1870144742Sharti		if (c != '\n') {
1871144026Sharti			ParseUnreadc(c);
1872144026Sharti			break;
1873144026Sharti		}
1874144742Sharti		CURFILE->lineno++;
18751590Srgrimes	}
18768874Srgrimes
1877144742Sharti	buf = Buf_Init(MAKE_BSIZE);
18788874Srgrimes
1879144742Sharti	while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) {
1880144026Sharti  test_char:
1881144742Sharti		switch (c) {
1882144742Sharti		  case '\n':
1883144742Sharti			/*
1884144742Sharti			 * Escaped newline: read characters until a
1885144742Sharti			 * non-space or an unescaped newline and
1886144742Sharti			 * replace them all by a single space. This is
1887144742Sharti			 * done by storing the space over the backslash
1888144742Sharti			 * and dropping through with the next nonspace.
1889144742Sharti			 * If it is a semi-colon and semiNL is TRUE,
1890144742Sharti			 * it will be recognized as a newline in the
1891144742Sharti			 * code below this...
1892144742Sharti			 */
1893144742Sharti			CURFILE->lineno++;
1894144742Sharti			lastc = ' ';
1895144742Sharti			while ((c = ParseReadc()) == ' ' || c == '\t') {
1896144742Sharti				continue;
1897144742Sharti			}
1898144742Sharti			if (c == EOF || c == '\n') {
1899144742Sharti				goto line_read;
1900144742Sharti			} else {
1901144026Sharti				/*
1902144742Sharti				 * Check for comments, semiNL's, etc. --
1903144742Sharti				 * easier than ParseUnreadc(c);
1904144742Sharti				 * continue;
1905144026Sharti				 */
1906144742Sharti				goto test_char;
1907144742Sharti			}
1908144742Sharti			/*NOTREACHED*/
1909144742Sharti			break;
1910144026Sharti
1911144742Sharti		  case ';':
1912144742Sharti			/*
1913144742Sharti			 * Semi-colon: Need to see if it should be
1914144742Sharti			 * interpreted as a newline
1915144742Sharti			 */
1916144742Sharti			if (semiNL) {
1917144026Sharti				/*
1918144742Sharti				 * To make sure the command that may
1919144742Sharti				 * be following this semi-colon begins
1920144742Sharti				 * with a tab, we push one back into the
1921144742Sharti				 * input stream. This will overwrite the
1922144742Sharti				 * semi-colon in the buffer. If there is
1923144742Sharti				 * no command following, this does no
1924144742Sharti				 * harm, since the newline remains in
1925144742Sharti				 * the buffer and the
1926144742Sharti				 * whole line is ignored.
1927144026Sharti				 */
1928144742Sharti				ParseUnreadc('\t');
1929144742Sharti				goto line_read;
1930144742Sharti			}
1931144742Sharti			break;
1932144742Sharti		  case '=':
1933144742Sharti			if (!semiNL) {
1934144742Sharti				/*
1935144742Sharti				 * Haven't seen a dependency operator
1936144742Sharti				 * before this, so this must be a
1937144742Sharti				 * variable assignment -- don't pay
1938144742Sharti				 * attention to dependency operators
1939144742Sharti				 * after this.
1940144742Sharti				 */
1941144742Sharti				ignDepOp = TRUE;
1942144742Sharti			} else if (lastc == ':' || lastc == '!') {
1943144742Sharti				/*
1944144742Sharti				 * Well, we've seen a dependency
1945144742Sharti				 * operator already, but it was the
1946144742Sharti				 * previous character, so this is really
1947144742Sharti				 * just an expanded variable assignment.
1948144742Sharti				 * Revert semi-colons to being just
1949144742Sharti				 * semi-colons again and ignore any more
1950144742Sharti				 * dependency operators.
1951144742Sharti				 *
1952144742Sharti				 * XXX: Note that a line like
1953144742Sharti				 * "foo : a:=b" will blow up, but who'd
1954144742Sharti				 * write a line like that anyway?
1955144742Sharti				 */
1956144742Sharti				ignDepOp = TRUE;
1957144742Sharti				semiNL = FALSE;
1958144742Sharti			}
1959144742Sharti			break;
1960144742Sharti		  case '#':
1961144742Sharti			if (!ignComment) {
1962144742Sharti				if (lastc != '\\') {
1963144026Sharti					/*
1964144742Sharti					 * If the character is a hash
1965144742Sharti					 * mark and it isn't escaped
1966144742Sharti					 * (or we're being compatible),
1967144742Sharti					 * the thing is a comment.
1968144742Sharti					 * Skip to the end of the line.
1969144026Sharti					 */
1970144742Sharti					do {
1971144742Sharti						c = ParseReadc();
1972144742Sharti					} while (c != '\n' && c != EOF);
1973144026Sharti					goto line_read;
1974144742Sharti				} else {
1975144026Sharti					/*
1976144742Sharti					 * Don't add the backslash.
1977144742Sharti					 * Just let the # get copied
1978144742Sharti					 * over.
1979144026Sharti					 */
1980144742Sharti					lastc = c;
1981144742Sharti					continue;
1982144026Sharti				}
1983144742Sharti			}
1984144742Sharti			break;
1985144026Sharti
1986144742Sharti		  case ':':
1987144742Sharti		  case '!':
1988144742Sharti			if (!ignDepOp) {
1989144742Sharti				/*
1990144742Sharti				 * A semi-colon is recognized as a
1991144742Sharti				 * newline only on dependency lines.
1992144742Sharti				 * Dependency lines are lines with a
1993144742Sharti				 * colon or an exclamation point.
1994144742Sharti				 * Ergo...
1995144742Sharti				 */
1996144742Sharti				semiNL = TRUE;
1997144742Sharti			}
1998144742Sharti			break;
1999144026Sharti
2000144742Sharti		  default:
2001144742Sharti			break;
2002144742Sharti		}
2003144742Sharti		/*
2004144742Sharti		 * Copy in the previous character (there may be none if this
2005144742Sharti		 * was the first character) and save this one in
2006144742Sharti		 * lastc.
2007144742Sharti		 */
2008144742Sharti		if (lastc != '\0')
2009144026Sharti			Buf_AddByte(buf, (Byte)lastc);
2010144742Sharti		lastc = c;
2011144742Sharti	}
2012144026Sharti  line_read:
2013144742Sharti	CURFILE->lineno++;
2014144026Sharti
2015144742Sharti	if (lastc != '\0') {
2016144742Sharti		Buf_AddByte(buf, (Byte)lastc);
2017144742Sharti	}
2018144742Sharti	Buf_AddByte(buf, (Byte)'\0');
2019144742Sharti	line = Buf_Peel(buf);
20201590Srgrimes
2021144742Sharti	/*
2022144742Sharti	 * Strip trailing blanks and tabs from the line.
2023144742Sharti	 * Do not strip a blank or tab that is preceded by
2024144742Sharti	 * a '\'
2025144742Sharti	 */
2026144742Sharti	ep = line;
2027144742Sharti	while (*ep)
2028144742Sharti		++ep;
2029144742Sharti	while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
2030144742Sharti		if (ep > line + 1 && ep[-2] == '\\')
2031144742Sharti			break;
2032144742Sharti		--ep;
2033144742Sharti	}
2034144742Sharti	*ep = 0;
2035144742Sharti
2036144742Sharti	if (line[0] == '\0') {
2037144742Sharti		/* empty line - just ignore */
2038144742Sharti		free(line);
2039144742Sharti		goto again;
2040144742Sharti	}
2041144742Sharti
2042144742Sharti	return (line);
20431590Srgrimes}
20441590Srgrimes
20451590Srgrimes/*-
20461590Srgrimes *-----------------------------------------------------------------------
20471590Srgrimes * ParseFinishLine --
20481590Srgrimes *	Handle the end of a dependency group.
20491590Srgrimes *
20501590Srgrimes * Results:
20511590Srgrimes *	Nothing.
20521590Srgrimes *
20531590Srgrimes * Side Effects:
20541590Srgrimes *	inLine set FALSE. 'targets' list destroyed.
20551590Srgrimes *
20561590Srgrimes *-----------------------------------------------------------------------
20571590Srgrimes */
20581590Srgrimesstatic void
2059104696SjmallettParseFinishLine(void)
20601590Srgrimes{
2061143372Sharti	const LstNode	*ln;
2062138232Sharti
2063143372Sharti	if (inLine) {
2064143372Sharti		LST_FOREACH(ln, &targets) {
2065143372Sharti			if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM)
2066143372Sharti				Suff_EndTransform(Lst_Datum(ln));
2067143372Sharti		}
2068143372Sharti		Lst_Destroy(&targets, ParseHasCommands);
2069143372Sharti		inLine = FALSE;
2070143372Sharti	}
20711590Srgrimes}
20721590Srgrimes
2073144894Sharti/**
2074167330Sfjoe * xparse_include
2075144894Sharti *	Parse an .include directive and push the file onto the input stack.
2076144894Sharti *	The input is the line minus the .include. A file spec is a string
2077144894Sharti *	enclosed in <> or "". The former is looked for only in sysIncPath.
2078144894Sharti *	The latter in . and the directories specified by -I command line
2079144894Sharti *	options
2080144894Sharti */
2081144894Shartistatic void
2082150595Sphkxparse_include(char *file, int sinclude)
2083144894Sharti{
2084144894Sharti	char	*fullname;	/* full pathname of file */
2085144894Sharti	char	endc;		/* the character which ends the file spec */
2086144894Sharti	char	*cp;		/* current position in file spec */
2087144894Sharti	Boolean	isSystem;	/* TRUE if makefile is a system makefile */
2088144894Sharti	char	*prefEnd, *Fname;
2089144894Sharti	char	*newName;
20908874Srgrimes
2091144894Sharti	/*
2092144894Sharti	 * Skip to delimiter character so we know where to look
2093144894Sharti	 */
2094144894Sharti	while (*file == ' ' || *file == '\t') {
2095144894Sharti		file++;
2096144894Sharti	}
2097144894Sharti
2098144894Sharti	if (*file != '"' && *file != '<') {
2099144894Sharti		Parse_Error(PARSE_FATAL,
2100144894Sharti		    ".include filename must be delimited by '\"' or '<'");
2101144894Sharti		return;
2102144894Sharti	}
2103144894Sharti
2104144894Sharti	/*
2105144894Sharti	 * Set the search path on which to find the include file based on the
2106144894Sharti	 * characters which bracket its name. Angle-brackets imply it's
2107144894Sharti	 * a system Makefile while double-quotes imply it's a user makefile
2108144894Sharti	 */
2109144894Sharti	if (*file == '<') {
2110144894Sharti		isSystem = TRUE;
2111144894Sharti		endc = '>';
2112144894Sharti	} else {
2113144894Sharti		isSystem = FALSE;
2114144894Sharti		endc = '"';
2115144894Sharti	}
2116144894Sharti
2117144894Sharti	/*
2118144894Sharti	* Skip to matching delimiter
2119144894Sharti	*/
2120144894Sharti	for (cp = ++file; *cp != endc; cp++) {
2121144894Sharti		if (*cp == '\0') {
2122144894Sharti			Parse_Error(PARSE_FATAL,
2123144894Sharti			    "Unclosed .include filename. '%c' expected", endc);
2124144894Sharti			return;
2125144894Sharti		}
2126144894Sharti	}
2127144894Sharti	*cp = '\0';
2128144894Sharti
2129144894Sharti	/*
2130144894Sharti	 * Substitute for any variables in the file name before trying to
2131144894Sharti	 * find the thing.
2132144894Sharti	 */
2133146027Sharti	file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE));
2134144894Sharti
2135144894Sharti	/*
2136144894Sharti	 * Now we know the file's name and its search path, we attempt to
2137144894Sharti	 * find the durn thing. A return of NULL indicates the file don't
2138144894Sharti	 * exist.
2139144894Sharti	 */
2140144894Sharti	if (!isSystem) {
2141144894Sharti		/*
2142144894Sharti		 * Include files contained in double-quotes are first searched
2143144894Sharti		 * for relative to the including file's location. We don't want
2144144894Sharti		 * to cd there, of course, so we just tack on the old file's
2145151419Sru		 * leading path components and call Path_FindFile to see if
2146144894Sharti		 * we can locate the beast.
2147144894Sharti		 */
2148144894Sharti
2149144894Sharti		/* Make a temporary copy of this, to be safe. */
2150144894Sharti		Fname = estrdup(CURFILE->fname);
2151144894Sharti
2152144894Sharti		prefEnd = strrchr(Fname, '/');
2153144894Sharti		if (prefEnd != NULL) {
2154144894Sharti			*prefEnd = '\0';
2155144894Sharti			if (file[0] == '/')
2156144894Sharti				newName = estrdup(file);
2157144894Sharti			else
2158144894Sharti				newName = str_concat(Fname, file, STR_ADDSLASH);
2159144894Sharti			fullname = Path_FindFile(newName, &parseIncPath);
2160144894Sharti			if (fullname == NULL) {
2161144894Sharti				fullname = Path_FindFile(newName,
2162144894Sharti				    &dirSearchPath);
2163144894Sharti			}
2164144894Sharti			free(newName);
2165144894Sharti			*prefEnd = '/';
2166144894Sharti		} else {
2167144894Sharti			fullname = NULL;
2168144894Sharti		}
2169144894Sharti		free(Fname);
2170151419Sru		if (fullname == NULL) {
2171151419Sru			/*
2172151419Sru			 * Makefile wasn't found in same directory as included
2173151419Sru			 * makefile. Search for it first on the -I search path,
2174151419Sru			 * then on the .PATH search path, if not found in a -I
2175151419Sru			 * directory.
2176151419Sru			 * XXX: Suffix specific?
2177151419Sru			 */
2178151419Sru			fullname = Path_FindFile(file, &parseIncPath);
2179151419Sru			if (fullname == NULL) {
2180151419Sru				fullname = Path_FindFile(file, &dirSearchPath);
2181151419Sru			}
2182151419Sru		}
2183144894Sharti	} else {
2184144894Sharti		fullname = NULL;
2185144894Sharti	}
2186144894Sharti
2187144894Sharti	if (fullname == NULL) {
2188144894Sharti		/*
2189151419Sru		 * System makefile or still haven't found the makefile.
2190151419Sru		 * Look for it on the system path.
2191144894Sharti		 */
2192144894Sharti		fullname = Path_FindFile(file, &sysIncPath);
2193144894Sharti	}
2194144894Sharti
2195144894Sharti	if (fullname == NULL) {
2196144894Sharti		*cp = endc;
2197150595Sphk		if (!sinclude)
2198150595Sphk			Parse_Error(PARSE_FATAL, "Could not find %s", file);
2199167330Sfjoe		else
2200167330Sfjoe			Main_AddSourceMakefile(file);
2201144894Sharti		free(file);
2202144894Sharti		return;
2203144894Sharti	}
2204167330Sfjoe	Main_AddSourceMakefile(fullname);
2205144894Sharti	free(file);
2206144894Sharti
2207144894Sharti	/*
2208144894Sharti	 * We set up the name of the file to be the absolute
2209144894Sharti	 * name of the include file so error messages refer to the right
2210144894Sharti	 * place.
2211144894Sharti	 */
2212144894Sharti	ParsePushInput(fullname, NULL, NULL, 0);
2213160574Sobrien	DEBUGF(DIR, (".include %s\n", fullname));
2214144894Sharti}
2215144894Sharti
2216150595Sphkstatic void
2217150595Sphkparse_include(char *file, int code __unused, int lineno __unused)
2218150595Sphk{
2219150595Sphk	xparse_include(file, 0);
2220150595Sphk}
2221150595Sphk
2222150595Sphkstatic void
2223150595Sphkparse_sinclude(char *file, int code __unused, int lineno __unused)
2224150595Sphk{
2225150595Sphk	xparse_include(file, 1);
2226150595Sphk}
2227150595Sphk
2228144894Sharti/**
2229144894Sharti * parse_message
2230144894Sharti *	Parse a .warning or .error directive
2231144894Sharti *
2232144894Sharti *	The input is the line minus the ".error"/".warning".  We substitute
2233144894Sharti *	variables, print the message and exit(1) (for .error) or just print
2234144894Sharti *	a warning if the directive is malformed.
2235144894Sharti */
2236144894Shartistatic void
2237144894Shartiparse_message(char *line, int iserror, int lineno __unused)
2238144894Sharti{
2239144894Sharti
2240144894Sharti	if (!isspace((u_char)*line)) {
2241144894Sharti		Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s",
2242144894Sharti		    iserror ? "error" : "warning", line);
2243144894Sharti		return;
2244144894Sharti	}
2245144894Sharti
2246144894Sharti	while (isspace((u_char)*line))
2247144894Sharti		line++;
2248144894Sharti
2249168671Sru	line = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE));
2250144894Sharti	Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line);
2251144894Sharti	free(line);
2252144894Sharti
2253144894Sharti	if (iserror) {
2254144894Sharti		/* Terminate immediately. */
2255144894Sharti		exit(1);
2256144894Sharti	}
2257144894Sharti}
2258144894Sharti
2259144894Sharti/**
2260144894Sharti * parse_undef
2261144894Sharti *	Parse an .undef directive.
2262144894Sharti */
2263144894Shartistatic void
2264144894Shartiparse_undef(char *line, int code __unused, int lineno __unused)
2265144894Sharti{
2266144894Sharti	char *cp;
2267144894Sharti
2268144894Sharti	while (isspace((u_char)*line))
2269144894Sharti		line++;
2270144894Sharti
2271144894Sharti	for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) {
2272144894Sharti		;
2273144894Sharti	}
2274144894Sharti	*cp = '\0';
2275144894Sharti
2276146027Sharti	cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE));
2277144894Sharti	Var_Delete(cp, VAR_GLOBAL);
2278144894Sharti	free(cp);
2279144894Sharti}
2280144894Sharti
2281144894Sharti/**
2282144894Sharti * parse_for
2283144894Sharti *	Parse a .for directive.
2284144894Sharti */
2285144894Shartistatic void
2286144894Shartiparse_for(char *line, int code __unused, int lineno)
2287144894Sharti{
2288144894Sharti
2289144894Sharti	if (!For_For(line)) {
2290144894Sharti		/* syntax error */
2291144894Sharti		return;
2292144894Sharti	}
2293144894Sharti	line = NULL;
2294144894Sharti
2295144894Sharti	/*
2296144894Sharti	 * Skip after the matching endfor.
2297144894Sharti	 */
2298144894Sharti	do {
2299144894Sharti		free(line);
2300144894Sharti		line = ParseSkipLine(0, 1);
2301144894Sharti		if (line == NULL) {
2302144894Sharti			Parse_Error(PARSE_FATAL,
2303144894Sharti			    "Unexpected end of file in for loop.\n");
2304144894Sharti			return;
2305144894Sharti		}
2306144894Sharti	} while (For_Eval(line));
2307144894Sharti	free(line);
2308144894Sharti
2309144894Sharti	/* execute */
2310144894Sharti	For_Run(lineno);
2311144894Sharti}
2312144894Sharti
2313144894Sharti/**
2314144894Sharti * parse_endfor
2315144894Sharti *	Parse endfor. This may only happen if there was no matching .for.
2316144894Sharti */
2317144894Shartistatic void
2318144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused)
2319144894Sharti{
2320144894Sharti
2321144894Sharti	Parse_Error(PARSE_FATAL, "for-less endfor");
2322144894Sharti}
2323144894Sharti
2324144894Sharti/**
2325144894Sharti * parse_directive
2326144894Sharti *	Got a line starting with a '.'. Check if this is a directive
2327144894Sharti *	and parse it.
2328144894Sharti *
2329144894Sharti * return:
2330144894Sharti *	TRUE if line was a directive, FALSE otherwise.
2331144894Sharti */
2332144894Shartistatic Boolean
2333144894Shartiparse_directive(char *line)
2334144894Sharti{
2335144894Sharti	char	*start;
2336144894Sharti	char	*cp;
2337144894Sharti	int	dir;
2338144894Sharti
2339144894Sharti	/*
2340144894Sharti	 * Get the keyword:
2341144894Sharti	 *	.[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).*
2342144894Sharti	 * \1 is the keyword.
2343144894Sharti	 */
2344144894Sharti	for (start = line; isspace((u_char)*start); start++) {
2345144894Sharti		;
2346144894Sharti	}
2347144894Sharti
2348144894Sharti	if (!isalpha((u_char)*start)) {
2349144894Sharti		return (FALSE);
2350144894Sharti	}
2351144894Sharti
2352144894Sharti	cp = start + 1;
2353144894Sharti	while (isalnum((u_char)*cp) || *cp == '_') {
2354144894Sharti		cp++;
2355144894Sharti	}
2356144894Sharti
2357144894Sharti	dir = directive_hash(start, cp - start);
2358144894Sharti	if (dir < 0 || dir >= (int)NDIRECTS ||
2359144894Sharti	    (size_t)(cp - start) != strlen(directives[dir].name) ||
2360144894Sharti	    strncmp(start, directives[dir].name, cp - start) != 0) {
2361144894Sharti		/* not actually matched */
2362144894Sharti		return (FALSE);
2363144894Sharti	}
2364144894Sharti
2365144894Sharti	if (!skipLine || directives[dir].skip_flag)
2366144894Sharti		(*directives[dir].func)(cp, directives[dir].code,
2367144894Sharti		    CURFILE->lineno);
2368144894Sharti	return (TRUE);
2369144894Sharti}
2370144894Sharti
23711590Srgrimes/*-
23721590Srgrimes *---------------------------------------------------------------------
23731590Srgrimes * Parse_File --
23741590Srgrimes *	Parse a file into its component parts, incorporating it into the
23751590Srgrimes *	current dependency graph. This is the main function and controls
23761590Srgrimes *	almost every other function in this module
23771590Srgrimes *
23781590Srgrimes * Results:
23791590Srgrimes *	None
23801590Srgrimes *
23811590Srgrimes * Side Effects:
23821590Srgrimes *	Loads. Nodes are added to the list of all targets, nodes and links
23831590Srgrimes *	are added to the dependency graph. etc. etc. etc.
23841590Srgrimes *---------------------------------------------------------------------
23851590Srgrimes */
23861590Srgrimesvoid
2387144341ShartiParse_File(const char *name, FILE *stream)
23881590Srgrimes{
2389144026Sharti	char	*cp;	/* pointer into the line */
2390144026Sharti	char	*line;	/* the line we're working on */
23911590Srgrimes
2392144026Sharti	inLine = FALSE;
2393144026Sharti	fatals = 0;
23941590Srgrimes
2395144341Sharti	ParsePushInput(estrdup(name), stream, NULL, 0);
2396131456Seik
2397144742Sharti	while ((line = ParseReadLine()) != NULL) {
2398144894Sharti		if (*line == '.' && parse_directive(line + 1)) {
2399144894Sharti			/* directive consumed */
2400144894Sharti			goto nextLine;
2401144742Sharti		}
2402144894Sharti		if (skipLine || *line == '#') {
2403144894Sharti			/* Skipping .if block or comment. */
2404144742Sharti			goto nextLine;
2405144742Sharti		}
24068874Srgrimes
2407144742Sharti		if (*line == '\t') {
2408144742Sharti			/*
2409144742Sharti			 * If a line starts with a tab, it can only
2410144742Sharti			 * hope to be a creation command.
2411144742Sharti			 */
2412144742Sharti			for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
2413144742Sharti				continue;
2414144742Sharti			}
2415144742Sharti			if (*cp) {
2416144742Sharti				if (inLine) {
2417144742Sharti					LstNode	*ln;
2418144742Sharti					GNode	*gn;
2419143684Sharti
2420144742Sharti					/*
2421144742Sharti					 * So long as it's not a blank
2422144742Sharti					 * line and we're actually in a
2423144742Sharti					 * dependency spec, add the
2424144742Sharti					 * command to the list of
2425144742Sharti					 * commands of all targets in
2426144742Sharti					 * the dependency spec.
2427144742Sharti					 */
2428144742Sharti					LST_FOREACH(ln, &targets) {
2429144742Sharti						gn = Lst_Datum(ln);
2430144742Sharti
2431144026Sharti						/*
2432144742Sharti						 * if target already
2433144742Sharti						 * supplied, ignore
2434144742Sharti						 * commands
2435144026Sharti						 */
2436144742Sharti						if (!(gn->type & OP_HAS_COMMANDS))
2437144742Sharti							Lst_AtEnd(&gn->commands, cp);
2438144742Sharti						else
2439144742Sharti							Parse_Error(PARSE_WARNING, "duplicate script "
2440144742Sharti							    "for target \"%s\" ignored", gn->name);
2441144026Sharti					}
2442144742Sharti					continue;
2443144742Sharti				} else {
2444144742Sharti					Parse_Error(PARSE_FATAL,
2445144742Sharti					     "Unassociated shell command \"%s\"",
2446144742Sharti					     cp);
2447144026Sharti				}
2448144742Sharti			}
24491590Srgrimes#ifdef SYSVINCLUDE
2450144742Sharti		} else if (strncmp(line, "include", 7) == 0 &&
2451144742Sharti		    isspace((unsigned char)line[7]) &&
2452144742Sharti		    strchr(line, ':') == NULL) {
2453144742Sharti			/*
2454144742Sharti			 * It's an S3/S5-style "include".
2455144742Sharti			 */
2456144742Sharti			ParseTraditionalInclude(line + 7);
2457144742Sharti			goto nextLine;
24581590Srgrimes#endif
2459144742Sharti		} else if (Parse_IsVar(line)) {
2460144742Sharti			ParseFinishLine();
2461144742Sharti			Parse_DoVar(line, VAR_GLOBAL);
24628874Srgrimes
2463144742Sharti		} else {
2464144742Sharti			/*
2465144742Sharti			 * We now know it's a dependency line so it
2466144742Sharti			 * needs to have all variables expanded before
2467144742Sharti			 * being parsed. Tell the variable module to
2468144742Sharti			 * complain if some variable is undefined...
2469144742Sharti			 * To make life easier on novices, if the line
2470144742Sharti			 * is indented we first make sure the line has
2471144742Sharti			 * a dependency operator in it. If it doesn't
2472144742Sharti			 * have an operator and we're in a dependency
2473144742Sharti			 * line's script, we assume it's actually a
2474144742Sharti			 * shell command and add it to the current
2475144894Sharti			 * list of targets. XXX this comment seems wrong.
2476144742Sharti			 */
2477144742Sharti			cp = line;
2478144742Sharti			if (isspace((unsigned char)line[0])) {
2479144742Sharti				while (*cp != '\0' &&
2480144742Sharti				    isspace((unsigned char)*cp)) {
2481144742Sharti					cp++;
2482144026Sharti				}
2483144742Sharti				if (*cp == '\0') {
2484144742Sharti					goto nextLine;
2485144742Sharti				}
2486144742Sharti			}
24871590Srgrimes
2488144742Sharti			ParseFinishLine();
2489142457Sharti
2490146027Sharti			cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE));
24918874Srgrimes
2492144742Sharti			free(line);
2493144742Sharti			line = cp;
2494144026Sharti
2495144742Sharti			/*
2496144742Sharti			 * Need a non-circular list for the target nodes
2497144742Sharti			 */
2498144742Sharti			Lst_Destroy(&targets, NOFREE);
2499144742Sharti			inLine = TRUE;
2500144026Sharti
2501144742Sharti			ParseDoDependency(line);
2502144026Sharti		}
2503144026Sharti
2504144742Sharti  nextLine:
2505144742Sharti		free(line);
2506144742Sharti	}
25078874Srgrimes
2508144026Sharti	ParseFinishLine();
25091590Srgrimes
25101590Srgrimes	/*
2511144026Sharti	 * Make sure conditionals are clean
25121590Srgrimes	 */
2513144026Sharti	Cond_End();
25141590Srgrimes
2515144026Sharti	if (fatals)
2516144026Sharti		errx(1, "fatal errors encountered -- cannot continue");
25171590Srgrimes}
25181590Srgrimes
25191590Srgrimes/*-
25201590Srgrimes *-----------------------------------------------------------------------
25211590Srgrimes * Parse_MainName --
25221590Srgrimes *	Return a Lst of the main target to create for main()'s sake. If
25231590Srgrimes *	no such target exists, we Punt with an obnoxious error message.
25241590Srgrimes *
25251590Srgrimes * Results:
25261590Srgrimes *	A Lst of the single node to create.
25271590Srgrimes *
25281590Srgrimes * Side Effects:
25291590Srgrimes *	None.
25301590Srgrimes *
25311590Srgrimes *-----------------------------------------------------------------------
25321590Srgrimes */
2533138916Shartivoid
2534138916ShartiParse_MainName(Lst *listmain)
25351590Srgrimes{
25361590Srgrimes
2537144026Sharti	if (mainNode == NULL) {
2538144026Sharti		Punt("no target to make.");
2539144026Sharti		/*NOTREACHED*/
2540144026Sharti	} else if (mainNode->type & OP_DOUBLEDEP) {
2541144026Sharti		Lst_AtEnd(listmain, mainNode);
2542144026Sharti		Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW);
2543144026Sharti	} else
2544144026Sharti		Lst_AtEnd(listmain, mainNode);
25451590Srgrimes}
2546