parse.c revision 146140
1141104Sharti/*-
21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * This code is derived from software contributed to Berkeley by
81590Srgrimes * Adam de Boor.
91590Srgrimes *
101590Srgrimes * Redistribution and use in source and binary forms, with or without
111590Srgrimes * modification, are permitted provided that the following conditions
121590Srgrimes * are met:
131590Srgrimes * 1. Redistributions of source code must retain the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer.
151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161590Srgrimes *    notice, this list of conditions and the following disclaimer in the
171590Srgrimes *    documentation and/or other materials provided with the distribution.
181590Srgrimes * 3. All advertising materials mentioning features or use of this software
191590Srgrimes *    must display the following acknowledgement:
201590Srgrimes *	This product includes software developed by the University of
211590Srgrimes *	California, Berkeley and its contributors.
221590Srgrimes * 4. Neither the name of the University nor the names of its contributors
231590Srgrimes *    may be used to endorse or promote products derived from this software
241590Srgrimes *    without specific prior written permission.
251590Srgrimes *
261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361590Srgrimes * SUCH DAMAGE.
3762833Swsanchez *
3862833Swsanchez * @(#)parse.c	8.3 (Berkeley) 3/19/94
391590Srgrimes */
401590Srgrimes
4162833Swsanchez#include <sys/cdefs.h>
4294587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/parse.c 146140 2005-05-12 14:16:44Z harti $");
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"
93141104Sharti#include "str.h"
94141104Sharti#include "suff.h"
95141104Sharti#include "targ.h"
96141104Sharti#include "util.h"
97141104Sharti#include "var.h"
981590Srgrimes
991590Srgrimes/*
100144341Sharti * These values are returned by ParsePopInput to tell Parse_File whether to
1011590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file,
1021590Srgrimes * or if it's DONE.
1031590Srgrimes */
1041590Srgrimes#define	CONTINUE	1
1051590Srgrimes#define	DONE		0
106138916Sharti
107138916Sharti/* targets we're working on */
108138916Shartistatic Lst targets = Lst_Initializer(targets);
109138916Sharti
110144026Sharti/* true if currently in a dependency line or its commands */
111144026Shartistatic Boolean inLine;
1121590Srgrimes
113144026Shartistatic int fatals = 0;
1141590Srgrimes
115144026Sharti/*
116144026Sharti * The main target to create. This is the first target on the
117144026Sharti * first dependency line in the first makefile.
118144026Sharti */
119144026Shartistatic GNode *mainNode;
120126824Sru
121144341Sharti/*
122144341Sharti * Definitions for handling #include specifications
123144341Sharti */
124144341Shartistruct IFile {
125144341Sharti	char	*fname;		/* name of previous file */
126144341Sharti	int	lineno;		/* saved line number */
127144341Sharti	FILE	*F;		/* the open stream */
128144341Sharti	char	*str;		/* the string when parsing a string */
129144341Sharti	char	*ptr;		/* the current pointer when parsing a string */
130144341Sharti	TAILQ_ENTRY(IFile) link;/* stack the files */
131144341Sharti};
132144026Sharti
133138916Sharti/* stack of IFiles generated by * #includes */
134144341Shartistatic TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes);
1351590Srgrimes
136144341Sharti/* access current file */
137144341Sharti#define	CURFILE	(TAILQ_FIRST(&includes))
138144341Sharti
139138916Sharti/* list of directories for "..." includes */
140144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath);
141138916Sharti
142138916Sharti/* list of directories for <...> includes */
143144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath);
144138916Sharti
145144026Sharti/*
1461590Srgrimes * specType contains the SPECial TYPE of the current target. It is
1471590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children
1481590Srgrimes * are linked as children of the parent but not vice versa. This variable is
1491590Srgrimes * set in ParseDoDependency
1501590Srgrimes */
1511590Srgrimestypedef enum {
152144026Sharti	Begin,		/* .BEGIN */
153144026Sharti	Default,	/* .DEFAULT */
154144026Sharti	End,		/* .END */
155145971Sharti	ExportVar,	/* .EXPORTVAR */
156144026Sharti	Ignore,		/* .IGNORE */
157144026Sharti	Includes,	/* .INCLUDES */
158144026Sharti	Interrupt,	/* .INTERRUPT */
159144026Sharti	Libs,		/* .LIBS */
160144026Sharti	MFlags,		/* .MFLAGS or .MAKEFLAGS */
161144026Sharti	Main,		/* .MAIN and we don't have anyth. user-spec. to make */
162144026Sharti	Not,		/* Not special */
163144026Sharti	NotParallel,	/* .NOTPARALELL */
164144026Sharti	Null,		/* .NULL */
165144026Sharti	Order,		/* .ORDER */
166144026Sharti	Parallel,	/* .PARALLEL */
167144026Sharti	ExPath,		/* .PATH */
168144026Sharti	Phony,		/* .PHONY */
169144026Sharti	Posix,		/* .POSIX */
170144026Sharti	Precious,	/* .PRECIOUS */
171144026Sharti	ExShell,	/* .SHELL */
172144026Sharti	Silent,		/* .SILENT */
173144026Sharti	SingleShell,	/* .SINGLESHELL */
174144026Sharti	Suffixes,	/* .SUFFIXES */
175144026Sharti	Wait,		/* .WAIT */
176145679Sharti	Warn,		/* .WARN */
177144026Sharti	Attribute	/* Generic attribute */
1781590Srgrimes} ParseSpecial;
1791590Srgrimes
1801590Srgrimesstatic ParseSpecial specType;
18118730Sstevestatic int waiting;
1821590Srgrimes
1831590Srgrimes/*
18469527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1851590Srgrimes * seen, then set to each successive source on the line.
1861590Srgrimes */
187144026Shartistatic GNode *predecessor;
1881590Srgrimes
1891590Srgrimes/*
1901590Srgrimes * The parseKeywords table is searched using binary search when deciding
1911590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial
1921590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while
1931590Srgrimes * the 'op' field is the operator to apply to the list of targets if the
1941590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source)
1951590Srgrimes */
196145616Shartistatic const struct keyword {
197144026Sharti	const char	*name;	/* Name of keyword */
198144026Sharti	ParseSpecial	spec;	/* Type when used as a target */
199144026Sharti	int		op;	/* Operator when used as a source */
2001590Srgrimes} parseKeywords[] = {
201145616Sharti	/* KEYWORD-START-TAG */
202144026Sharti	{ ".BEGIN",		Begin,		0 },
203144026Sharti	{ ".DEFAULT",		Default,	0 },
204144026Sharti	{ ".END",		End,		0 },
205144026Sharti	{ ".EXEC",		Attribute,	OP_EXEC },
206145971Sharti	{ ".EXPORTVAR",		ExportVar,	0 },
207144026Sharti	{ ".IGNORE",		Ignore,		OP_IGNORE },
208144026Sharti	{ ".INCLUDES",		Includes,	0 },
209144026Sharti	{ ".INTERRUPT",		Interrupt,	0 },
210144026Sharti	{ ".INVISIBLE",		Attribute,	OP_INVISIBLE },
211144026Sharti	{ ".JOIN",		Attribute,	OP_JOIN },
212144026Sharti	{ ".LIBS",		Libs,		0 },
213144026Sharti	{ ".MAIN",		Main,		0 },
214144026Sharti	{ ".MAKE",		Attribute,	OP_MAKE },
215144026Sharti	{ ".MAKEFLAGS",		MFlags,		0 },
216144026Sharti	{ ".MFLAGS",		MFlags,		0 },
217144026Sharti	{ ".NOTMAIN",		Attribute,	OP_NOTMAIN },
218144026Sharti	{ ".NOTPARALLEL",	NotParallel,	0 },
219144026Sharti	{ ".NO_PARALLEL",	NotParallel,	0 },
220144026Sharti	{ ".NULL",		Null,		0 },
221144026Sharti	{ ".OPTIONAL",		Attribute,	OP_OPTIONAL },
222144026Sharti	{ ".ORDER",		Order,		0 },
223144026Sharti	{ ".PARALLEL",		Parallel,	0 },
224144026Sharti	{ ".PATH",		ExPath,		0 },
225144026Sharti	{ ".PHONY",		Phony,		OP_PHONY },
226144026Sharti	{ ".POSIX",		Posix,		0 },
227144026Sharti	{ ".PRECIOUS",		Precious,	OP_PRECIOUS },
228144026Sharti	{ ".RECURSIVE",		Attribute,	OP_MAKE },
229144026Sharti	{ ".SHELL",		ExShell,	0 },
230144026Sharti	{ ".SILENT",		Silent,		OP_SILENT },
231144026Sharti	{ ".SINGLESHELL",	SingleShell,	0 },
232144026Sharti	{ ".SUFFIXES",		Suffixes,	0 },
233144026Sharti	{ ".USE",		Attribute,	OP_USE },
234144026Sharti	{ ".WAIT",		Wait,		0 },
235145679Sharti	{ ".WARN",		Warn,		0 },
236145616Sharti	/* KEYWORD-END-TAG */
2371590Srgrimes};
238145616Sharti#define	NKEYWORDS	(sizeof(parseKeywords) / sizeof(parseKeywords[0]))
2391590Srgrimes
240144894Shartistatic void parse_include(char *, int, int);
241144894Shartistatic void parse_message(char *, int, int);
242144894Shartistatic void parse_undef(char *, int, int);
243144894Shartistatic void parse_for(char *, int, int);
244144894Shartistatic void parse_endfor(char *, int, int);
245144894Sharti
246144894Shartistatic const struct directive {
247144894Sharti	const char	*name;
248144894Sharti	int		code;
249144894Sharti	Boolean		skip_flag;	/* execute even when skipped */
250144894Sharti	void		(*func)(char *, int, int);
251144894Sharti} directives[] = {
252145612Sharti	/* DIRECTIVES-START-TAG */
253144894Sharti	{ "elif",	COND_ELIF,	TRUE,	Cond_If },
254144894Sharti	{ "elifdef",	COND_ELIFDEF,	TRUE,	Cond_If },
255144894Sharti	{ "elifmake",	COND_ELIFMAKE,	TRUE,	Cond_If },
256144894Sharti	{ "elifndef",	COND_ELIFNDEF,	TRUE,	Cond_If },
257144894Sharti	{ "elifnmake",	COND_ELIFNMAKE,	TRUE,	Cond_If },
258144894Sharti	{ "else",	COND_ELSE,	TRUE,	Cond_Else },
259144894Sharti	{ "endfor",	0,		FALSE,	parse_endfor },
260144894Sharti	{ "endif",	COND_ENDIF,	TRUE,	Cond_Endif },
261144894Sharti	{ "error",	1,		FALSE,	parse_message },
262144894Sharti	{ "for",	0,		FALSE,	parse_for },
263144894Sharti	{ "if",		COND_IF,	TRUE,	Cond_If },
264144894Sharti	{ "ifdef",	COND_IFDEF,	TRUE,	Cond_If },
265144894Sharti	{ "ifmake",	COND_IFMAKE,	TRUE,	Cond_If },
266144894Sharti	{ "ifndef",	COND_IFNDEF,	TRUE,	Cond_If },
267144894Sharti	{ "ifnmake",	COND_IFNMAKE,	TRUE,	Cond_If },
268144894Sharti	{ "include",	0,		FALSE,	parse_include },
269144894Sharti	{ "undef",	0,		FALSE,	parse_undef },
270144894Sharti	{ "warning",	0,		FALSE,	parse_message },
271145612Sharti	/* DIRECTIVES-END-TAG */
272144894Sharti};
273144894Sharti#define	NDIRECTS	(sizeof(directives) / sizeof(directives[0]))
274144894Sharti
2751590Srgrimes/*-
276145616Sharti * ParseFindKeyword
2771590Srgrimes *	Look in the table of keywords for one matching the given string.
2781590Srgrimes *
2791590Srgrimes * Results:
280145616Sharti *	The pointer to keyword table entry or NULL.
2811590Srgrimes */
282145616Shartistatic const struct keyword *
283145616ShartiParseFindKeyword(const char *str)
2841590Srgrimes{
285145616Sharti	int kw;
2868874Srgrimes
287145616Sharti	kw = keyword_hash(str, strlen(str));
288145616Sharti	if (kw < 0 || kw >= (int)NKEYWORDS ||
289145616Sharti	    strcmp(str, parseKeywords[kw].name) != 0)
290145616Sharti		return (NULL);
291145616Sharti	return (&parseKeywords[kw]);
2921590Srgrimes}
2931590Srgrimes
2941590Srgrimes/*-
2951590Srgrimes * Parse_Error  --
2961590Srgrimes *	Error message abort function for parsing. Prints out the context
2971590Srgrimes *	of the error (line number and file) as well as the message with
2981590Srgrimes *	two optional arguments.
2991590Srgrimes *
3001590Srgrimes * Results:
3011590Srgrimes *	None
3021590Srgrimes *
3031590Srgrimes * Side Effects:
3041590Srgrimes *	"fatals" is incremented if the level is PARSE_FATAL.
3051590Srgrimes */
3061590Srgrimes/* VARARGS */
3071590Srgrimesvoid
30898136SjmallettParse_Error(int type, const char *fmt, ...)
3091590Srgrimes{
3101590Srgrimes	va_list ap;
31193056Simp
3121590Srgrimes	va_start(ap, fmt);
313144745Sharti	if (CURFILE != NULL)
314144745Sharti		fprintf(stderr, "\"%s\", line %d: ",
315144745Sharti		    CURFILE->fname, CURFILE->lineno);
3161590Srgrimes	if (type == PARSE_WARNING)
317138232Sharti		fprintf(stderr, "warning: ");
318138232Sharti	vfprintf(stderr, fmt, ap);
3191590Srgrimes	va_end(ap);
320138232Sharti	fprintf(stderr, "\n");
321138232Sharti	fflush(stderr);
3221590Srgrimes	if (type == PARSE_FATAL)
3231590Srgrimes		fatals += 1;
3241590Srgrimes}
3251590Srgrimes
326144341Sharti/**
327144341Sharti * ParsePushInput
328144341Sharti *
329144341Sharti * Push a new input source onto the input stack. If ptr is NULL
330144341Sharti * the fullname is used to fopen the file. If it is not NULL,
331144341Sharti * ptr is assumed to point to the string to be parsed. If opening the
332144341Sharti * file fails, the fullname is freed.
333144341Sharti */
334144341Shartistatic void
335144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno)
336144341Sharti{
337144341Sharti	struct IFile *nf;
338144341Sharti
339144341Sharti	nf = emalloc(sizeof(*nf));
340144341Sharti	nf->fname = fullname;
341144341Sharti	nf->lineno = lineno;
342144341Sharti
343144341Sharti	if (ptr == NULL) {
344144341Sharti		/* the input source is a file */
345144341Sharti		if ((nf->F = fp) == NULL) {
346144341Sharti			nf->F = fopen(fullname, "r");
347144341Sharti			if (nf->F == NULL) {
348144341Sharti				Parse_Error(PARSE_FATAL, "Cannot open %s",
349144341Sharti				    fullname);
350144341Sharti				free(fullname);
351144341Sharti				free(nf);
352144341Sharti				return;
353144341Sharti			}
354144341Sharti		}
355144341Sharti		nf->str = nf->ptr = NULL;
356144341Sharti		Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
357144341Sharti	} else {
358144341Sharti		nf->str = nf->ptr = ptr;
359144341Sharti		nf->F = NULL;
360144341Sharti	}
361144341Sharti	TAILQ_INSERT_HEAD(&includes, nf, link);
362144341Sharti}
363144341Sharti
364144341Sharti/**
365144341Sharti * ParsePopInput
366144341Sharti *	Called when EOF is reached in the current file. If we were reading
367144341Sharti *	an include file, the includes stack is popped and things set up
368144341Sharti *	to go back to reading the previous file at the previous location.
369144341Sharti *
370144341Sharti * Results:
371144341Sharti *	CONTINUE if there's more to do. DONE if not.
372144341Sharti *
373144341Sharti * Side Effects:
374144341Sharti *	The old curFile.F is closed. The includes list is shortened.
375144341Sharti *	curFile.lineno, curFile.F, and curFile.fname are changed if
376144341Sharti *	CONTINUE is returned.
377144341Sharti */
378144341Shartistatic int
379144341ShartiParsePopInput(void)
380144341Sharti{
381144341Sharti	struct IFile *ifile;	/* the state on the top of the includes stack */
382144341Sharti
383144341Sharti	assert(!TAILQ_EMPTY(&includes));
384144341Sharti
385144341Sharti	ifile = TAILQ_FIRST(&includes);
386144341Sharti	TAILQ_REMOVE(&includes, ifile, link);
387144341Sharti
388144341Sharti	free(ifile->fname);
389144341Sharti	if (ifile->F != NULL) {
390144341Sharti		fclose(ifile->F);
391144341Sharti		Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
392144341Sharti	}
393144341Sharti	if (ifile->str != NULL) {
394144341Sharti		free(ifile->str);
395144341Sharti	}
396144341Sharti	free(ifile);
397144341Sharti
398144341Sharti	return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE);
399144341Sharti}
400144341Sharti
401145679Sharti/**
402145679Sharti * parse_warn
403145679Sharti *	Parse the .WARN pseudo-target.
404145679Sharti */
405145679Shartistatic void
406145679Shartiparse_warn(char *line)
407145679Sharti{
408145679Sharti	char **argv;
409145679Sharti	int argc;
410145679Sharti	int i;
411145679Sharti
412145679Sharti	argv = brk_string(line, &argc, TRUE);
413145679Sharti
414145679Sharti	for (i = 1; i < argc; i++)
415145679Sharti		Main_ParseWarn(argv[i], 0);
416145679Sharti}
417145679Sharti
4181590Srgrimes/*-
4191590Srgrimes *---------------------------------------------------------------------
4201590Srgrimes * ParseLinkSrc  --
421143100Sharti *	Link the parent nodes to their new child. Used by
4221590Srgrimes *	ParseDoDependency. If the specType isn't 'Not', the parent
4231590Srgrimes *	isn't linked as a parent of the child.
4241590Srgrimes *
4251590Srgrimes * Side Effects:
426143100Sharti *	New elements are added to the parents lists of cgn and the
4271590Srgrimes *	children list of cgn. the unmade field of pgn is updated
4281590Srgrimes *	to reflect the additional child.
4291590Srgrimes *---------------------------------------------------------------------
4301590Srgrimes */
431143027Shartistatic void
432143027ShartiParseLinkSrc(Lst *parents, GNode *cgn)
4331590Srgrimes{
434143027Sharti	LstNode	*ln;
435143027Sharti	GNode *pgn;
436138232Sharti
437143027Sharti	LST_FOREACH(ln, parents) {
438143027Sharti		pgn = Lst_Datum(ln);
439143027Sharti		if (Lst_Member(&pgn->children, cgn) == NULL) {
440143027Sharti			Lst_AtEnd(&pgn->children, cgn);
441143027Sharti			if (specType == Not) {
442143027Sharti				Lst_AtEnd(&cgn->parents, pgn);
443143027Sharti			}
444143027Sharti			pgn->unmade += 1;
445143027Sharti		}
4461590Srgrimes	}
4471590Srgrimes}
4481590Srgrimes
4491590Srgrimes/*-
4501590Srgrimes *---------------------------------------------------------------------
4511590Srgrimes * ParseDoOp  --
452143684Sharti *	Apply the parsed operator to all target nodes. Used in
453143684Sharti *	ParseDoDependency once all targets have been found and their
454143684Sharti *	operator parsed. If the previous and new operators are incompatible,
455143684Sharti *	a major error is taken.
4561590Srgrimes *
4571590Srgrimes * Side Effects:
4581590Srgrimes *	The type field of the node is altered to reflect any new bits in
4591590Srgrimes *	the op.
4601590Srgrimes *---------------------------------------------------------------------
4611590Srgrimes */
462143684Shartistatic void
463143684ShartiParseDoOp(int op)
4641590Srgrimes{
465143684Sharti	GNode	*cohort;
466143684Sharti	LstNode	*ln;
467143684Sharti	GNode	*gn;
468138232Sharti
469143684Sharti	LST_FOREACH(ln, &targets) {
470143684Sharti		gn = Lst_Datum(ln);
4711590Srgrimes
472143684Sharti		/*
473143684Sharti		 * If the dependency mask of the operator and the node don't
474143684Sharti		 * match and the node has actually had an operator applied to
475143684Sharti		 * it before, and the operator actually has some dependency
476143684Sharti		 * information in it, complain.
477143684Sharti		 */
478143684Sharti		if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) &&
479143684Sharti		    !OP_NOP(gn->type) && !OP_NOP(op)) {
480143684Sharti			Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
481143684Sharti			    gn->name);
482143684Sharti			return;
483143684Sharti		}
4848874Srgrimes
485143684Sharti		if (op == OP_DOUBLEDEP &&
486143684Sharti		    (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
487143684Sharti			/*
488143684Sharti			 * If the node was the object of a :: operator, we need
489143684Sharti			 * to create a new instance of it for the children and
490143684Sharti			 * commands on this dependency line. The new instance
491143684Sharti			 * is placed on the 'cohorts' list of the initial one
492143684Sharti			 * (note the initial one is not on its own cohorts list)
493143684Sharti			 * and the new instance is linked to all parents of the
494143684Sharti			 * initial instance.
495143684Sharti			 */
496143684Sharti			cohort = Targ_NewGN(gn->name);
4971590Srgrimes
498143684Sharti			/*
499143684Sharti			 * Duplicate links to parents so graph traversal is
500143684Sharti			 * simple. Perhaps some type bits should be duplicated?
501143684Sharti			 *
502143684Sharti			 * Make the cohort invisible as well to avoid
503143684Sharti			 * duplicating it into other variables. True, parents
504143684Sharti			 * of this target won't tend to do anything with their
505143684Sharti			 * local variables, but better safe than sorry.
506143684Sharti			 */
507143684Sharti			ParseLinkSrc(&gn->parents, cohort);
508143684Sharti			cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
509143684Sharti			Lst_AtEnd(&gn->cohorts, cohort);
5101590Srgrimes
511143684Sharti			/*
512143684Sharti			 * Replace the node in the targets list with the
513143684Sharti			 * new copy
514143684Sharti			 */
515143684Sharti			Lst_Replace(ln, cohort);
516143684Sharti			gn = cohort;
517143684Sharti		}
518143684Sharti		/*
519143684Sharti		 * We don't want to nuke any previous flags (whatever they were)
520143684Sharti		 * so we just OR the new operator into the old
521143684Sharti		 */
522143684Sharti		gn->type |= op;
523143684Sharti	}
5241590Srgrimes}
5251590Srgrimes
5261590Srgrimes/*-
5271590Srgrimes *---------------------------------------------------------------------
5281590Srgrimes * ParseDoSrc  --
5291590Srgrimes *	Given the name of a source, figure out if it is an attribute
5301590Srgrimes *	and apply it to the targets if it is. Else decide if there is
5311590Srgrimes *	some attribute which should be applied *to* the source because
5321590Srgrimes *	of some special target and apply it if so. Otherwise, make the
5331590Srgrimes *	source be a child of the targets in the list 'targets'
5341590Srgrimes *
5351590Srgrimes * Results:
5361590Srgrimes *	None
5371590Srgrimes *
5381590Srgrimes * Side Effects:
5391590Srgrimes *	Operator bits may be added to the list of targets or to the source.
5401590Srgrimes *	The targets may have a new source added to their lists of children.
5411590Srgrimes *---------------------------------------------------------------------
5421590Srgrimes */
5431590Srgrimesstatic void
544138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc)
5451590Srgrimes{
546144026Sharti	GNode	*gn = NULL;
547145616Sharti	const struct keyword *kw;
5481590Srgrimes
549145616Sharti	if (src[0] == '.' && isupper ((unsigned char)src[1])) {
550145616Sharti		if ((kw = ParseFindKeyword(src)) != NULL) {
551145616Sharti			if (kw->op != 0) {
552145616Sharti				ParseDoOp(kw->op);
553144026Sharti				return;
554144026Sharti			}
555145616Sharti			if (kw->spec == Wait) {
556144026Sharti				waiting++;
557144026Sharti				return;
558144026Sharti			}
559144026Sharti		}
5601590Srgrimes	}
56118730Ssteve
562144026Sharti	switch (specType) {
563144026Sharti	  case Main:
564144026Sharti		/*
565144026Sharti		 * If we have noted the existence of a .MAIN, it means we need
566144026Sharti		 * to add the sources of said target to the list of things
567144026Sharti		 * to create. The string 'src' is likely to be free, so we
568144026Sharti		 * must make a new copy of it. Note that this will only be
569144026Sharti		 * invoked if the user didn't specify a target on the command
570144026Sharti		 * line. This is to allow #ifmake's to succeed, or something...
571144026Sharti		 */
572144026Sharti		Lst_AtEnd(&create, estrdup(src));
573144026Sharti		/*
574144026Sharti		 * Add the name to the .TARGETS variable as well, so the user
575144026Sharti		 * can employ that, if desired.
576144026Sharti		 */
577144026Sharti		Var_Append(".TARGETS", src, VAR_GLOBAL);
578144026Sharti		return;
57918730Ssteve
580144026Sharti	  case Order:
581144026Sharti		/*
582144026Sharti		 * Create proper predecessor/successor links between the
583144026Sharti		 * previous source and the current one.
584144026Sharti		 */
585144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
586144026Sharti		if (predecessor != NULL) {
587144026Sharti			Lst_AtEnd(&predecessor->successors, gn);
588144026Sharti			Lst_AtEnd(&gn->preds, predecessor);
589144026Sharti		}
590144026Sharti		/*
591144026Sharti		 * The current source now becomes the predecessor for the next
592144026Sharti		 * one.
593144026Sharti		 */
594144026Sharti		predecessor = gn;
595144026Sharti		break;
59618730Ssteve
597144026Sharti	  default:
598144026Sharti		/*
599144026Sharti		 * If the source is not an attribute, we need to find/create
600144026Sharti		 * a node for it. After that we can apply any operator to it
601144026Sharti		 * from a special target or link it to its parents, as
602144026Sharti		 * appropriate.
603144026Sharti		 *
604144026Sharti		 * In the case of a source that was the object of a :: operator,
605144026Sharti		 * the attribute is applied to all of its instances (as kept in
606144026Sharti		 * the 'cohorts' list of the node) or all the cohorts are linked
607144026Sharti		 * to all the targets.
608144026Sharti		 */
609144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
6101590Srgrimes		if (tOp) {
611144026Sharti			gn->type |= tOp;
6121590Srgrimes		} else {
613144026Sharti			ParseLinkSrc(&targets, gn);
6141590Srgrimes		}
615144026Sharti		if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
616144026Sharti			GNode	*cohort;
617144026Sharti			LstNode	*ln;
618144026Sharti
619144026Sharti			for (ln = Lst_First(&gn->cohorts); ln != NULL;
620144026Sharti			    ln = Lst_Succ(ln)) {
621144026Sharti				cohort = Lst_Datum(ln);
622144026Sharti				if (tOp) {
623144026Sharti					cohort->type |= tOp;
624144026Sharti				} else {
625144026Sharti					ParseLinkSrc(&targets, cohort);
626144026Sharti				}
627144026Sharti			}
628144026Sharti		}
629144026Sharti		break;
6301590Srgrimes	}
63118730Ssteve
632144026Sharti	gn->order = waiting;
633144026Sharti	Lst_AtEnd(allsrc, gn);
634144026Sharti	if (waiting) {
635144026Sharti		LstNode	*ln;
636144026Sharti		GNode	*p;
6371590Srgrimes
638143684Sharti		/*
639144026Sharti		 * Check if GNodes needs to be synchronized.
640144026Sharti		 * This has to be when two nodes are on different sides of a
641144026Sharti		 * .WAIT directive.
642143684Sharti		 */
643144026Sharti		LST_FOREACH(ln, allsrc) {
644144026Sharti			p = Lst_Datum(ln);
645144026Sharti
646144026Sharti			if (p->order >= gn->order)
647144026Sharti				break;
648144026Sharti			/*
649144026Sharti			 * XXX: This can cause loops, and loops can cause
650144026Sharti			 * unmade targets, but checking is tedious, and the
651144026Sharti			 * debugging output can show the problem
652144026Sharti			 */
653144026Sharti			Lst_AtEnd(&p->successors, gn);
654144026Sharti			Lst_AtEnd(&gn->preds, p);
655144026Sharti		}
656143684Sharti	}
6571590Srgrimes}
6581590Srgrimes
659138232Sharti
6601590Srgrimes/*-
6611590Srgrimes *---------------------------------------------------------------------
6621590Srgrimes * ParseDoDependency  --
6631590Srgrimes *	Parse the dependency line in line.
6641590Srgrimes *
6651590Srgrimes * Results:
6661590Srgrimes *	None
6671590Srgrimes *
6681590Srgrimes * Side Effects:
6691590Srgrimes *	The nodes of the sources are linked as children to the nodes of the
6701590Srgrimes *	targets. Some nodes may be created.
6711590Srgrimes *
6721590Srgrimes *	We parse a dependency line by first extracting words from the line and
6731590Srgrimes * finding nodes in the list of all targets with that name. This is done
6741590Srgrimes * until a character is encountered which is an operator character. Currently
6751590Srgrimes * these are only ! and :. At this point the operator is parsed and the
6761590Srgrimes * pointer into the line advanced until the first source is encountered.
677144026Sharti *	The parsed operator is applied to each node in the 'targets' list,
6781590Srgrimes * which is where the nodes found for the targets are kept, by means of
6791590Srgrimes * the ParseDoOp function.
6801590Srgrimes *	The sources are read in much the same way as the targets were except
6811590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell
6821590Srgrimes * and all instances of the resulting words in the list of all targets
6831590Srgrimes * are found. Each of the resulting nodes is then linked to each of the
6841590Srgrimes * targets as one of its children.
6851590Srgrimes *	Certain targets are handled specially. These are the ones detailed
6861590Srgrimes * by the specType variable.
6871590Srgrimes *	The storing of transformation rules is also taken care of here.
6881590Srgrimes * A target is recognized as a transformation rule by calling
6891590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten
6901590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard
6911590Srgrimes * Targ_FindNode in the target module.
6921590Srgrimes *---------------------------------------------------------------------
6931590Srgrimes */
6941590Srgrimesstatic void
695141270ShartiParseDoDependency(char *line)
6961590Srgrimes{
697144026Sharti	char	*cp;	/* our current position */
698144026Sharti	GNode	*gn;	/* a general purpose temporary node */
699144026Sharti	int	op;	/* the operator on the line */
700144026Sharti	char	savec;	/* a place to save a character */
701144026Sharti	Lst	paths;	/* Search paths to alter when parsing .PATH targets */
702144026Sharti	int	tOp;	/* operator from special target */
703144026Sharti	LstNode	*ln;
704145616Sharti	const struct keyword *kw;
7051590Srgrimes
706144026Sharti	tOp = 0;
7071590Srgrimes
708144026Sharti	specType = Not;
709144026Sharti	waiting = 0;
710144026Sharti	Lst_Init(&paths);
7111590Srgrimes
712144026Sharti	do {
713144026Sharti		for (cp = line;
714144026Sharti		    *cp && !isspace((unsigned char)*cp) && *cp != '(';
715144026Sharti		    cp++) {
716144026Sharti			if (*cp == '$') {
717144026Sharti				/*
718144026Sharti				 * Must be a dynamic source (would have been
719144026Sharti				 * expanded otherwise), so call the Var module
720144026Sharti				 * to parse the puppy so we can safely advance
721144026Sharti				 * beyond it...There should be no errors in this
722144026Sharti				 * as they would have been discovered in the
723144026Sharti				 * initial Var_Subst and we wouldn't be here.
724144026Sharti				 */
725144026Sharti				size_t	length = 0;
726144026Sharti				Boolean	freeIt;
727144026Sharti				char	*result;
7281590Srgrimes
729144026Sharti				result = Var_Parse(cp, VAR_CMD, TRUE,
730144026Sharti				    &length, &freeIt);
7311590Srgrimes
732144026Sharti				if (freeIt) {
733144026Sharti					free(result);
734144026Sharti				}
735144026Sharti				cp += length - 1;
736102178Sru
737144026Sharti			} else if (*cp == '!' || *cp == ':') {
738144026Sharti				/*
739144026Sharti				 * We don't want to end a word on ':' or '!' if
740144026Sharti				 * there is a better match later on in the
741144026Sharti				 * string (greedy matching).
742144026Sharti				 * This allows the user to have targets like:
743144026Sharti				 *    fie::fi:fo: fum
744144026Sharti				 *    foo::bar:
745144026Sharti				 * where "fie::fi:fo" and "foo::bar" are the
746144026Sharti				 * targets. In real life this is used for perl5
747144026Sharti				 * library man pages where "::" separates an
748144026Sharti				 * object from its class. Ie:
749144026Sharti				 * "File::Spec::Unix". This behaviour is also
750144026Sharti				 * consistent with other versions of make.
751144026Sharti				 */
752144026Sharti				char *p = cp + 1;
753102178Sru
754144026Sharti				if (*cp == ':' && *p == ':')
755144026Sharti					p++;
756102178Sru
757144026Sharti				/* Found the best match already. */
758144026Sharti				if (*p == '\0' || isspace(*p))
759144026Sharti					break;
760102178Sru
761144026Sharti				p += strcspn(p, "!:");
7628874Srgrimes
763144026Sharti				/* No better match later on... */
764144026Sharti				if (*p == '\0')
765144026Sharti					break;
766144026Sharti			}
767144026Sharti			continue;
7681590Srgrimes		}
769144026Sharti		if (*cp == '(') {
770144026Sharti			/*
771144026Sharti			 * Archives must be handled specially to make sure the
772144026Sharti			 * OP_ARCHV flag is set in their 'type' field, for one
773144026Sharti			 * thing, and because things like "archive(file1.o
774144026Sharti			 * file2.o file3.o)" are permissible. Arch_ParseArchive
775144026Sharti			 * will set 'line' to be the first non-blank after the
776144026Sharti			 * archive-spec. It creates/finds nodes for the members
777144026Sharti			 * and places them on the given list, returning SUCCESS
778144026Sharti			 * if all went well and FAILURE if there was an error in
779144026Sharti			 * the specification. On error, line should remain
780144026Sharti			 * untouched.
781144026Sharti			 */
782144026Sharti			if (Arch_ParseArchive(&line, &targets, VAR_CMD) !=
783144026Sharti			    SUCCESS) {
784144026Sharti				Parse_Error(PARSE_FATAL,
785144026Sharti				    "Error in archive specification: \"%s\"",
786144026Sharti				    line);
787144026Sharti				return;
788144026Sharti			} else {
789144026Sharti				cp = line;
790144026Sharti				continue;
791144026Sharti			}
792144026Sharti		}
793144026Sharti		savec = *cp;
7948874Srgrimes
795144026Sharti		if (!*cp) {
796144026Sharti			/*
797144026Sharti			 * Ending a dependency line without an operator is a				 * Bozo no-no. As a heuristic, this is also often
798144026Sharti			 * triggered by undetected conflicts from cvs/rcs
799144026Sharti			 * merges.
800144026Sharti			 */
801144026Sharti			if (strncmp(line, "<<<<<<", 6) == 0 ||
802144026Sharti			    strncmp(line, "======", 6) == 0 ||
803144026Sharti			    strncmp(line, ">>>>>>", 6) == 0) {
804144026Sharti				Parse_Error(PARSE_FATAL, "Makefile appears to "
805144026Sharti				    "contain unresolved cvs/rcs/??? merge "
806144026Sharti				    "conflicts");
807144026Sharti			} else
808144026Sharti				Parse_Error(PARSE_FATAL, "Need an operator");
809144026Sharti			return;
810144026Sharti		}
811144026Sharti		*cp = '\0';
8121590Srgrimes		/*
813144026Sharti		 * Have a word in line. See if it's a special target and set
814144026Sharti		 * specType to match it.
8151590Srgrimes		 */
816144026Sharti		if (*line == '.' && isupper((unsigned char)line[1])) {
817144026Sharti			/*
818144026Sharti			 * See if the target is a special target that must have
819144026Sharti			 * it or its sources handled specially.
820144026Sharti			 */
821145616Sharti			if ((kw = ParseFindKeyword(line)) != NULL) {
822145616Sharti				if (specType == ExPath && kw->spec != ExPath) {
823144026Sharti					Parse_Error(PARSE_FATAL,
824144026Sharti					    "Mismatched special targets");
825144026Sharti					return;
826144026Sharti				}
827144026Sharti
828145616Sharti				specType = kw->spec;
829145616Sharti				tOp = kw->op;
830144026Sharti
831144026Sharti				/*
832144026Sharti				 * Certain special targets have special
833144026Sharti				 * semantics:
834144026Sharti				 *  .PATH	Have to set the dirSearchPath
835144026Sharti				 *		variable too
836144026Sharti				 *  .MAIN	Its sources are only used if
837144026Sharti				 *		nothing has been specified to
838144026Sharti				 *		create.
839144026Sharti				 *  .DEFAULT    Need to create a node to hang
840144026Sharti				 *		commands on, but we don't want
841144026Sharti				 *		it in the graph, nor do we want
842144026Sharti				 *		it to be the Main Target, so we
843144026Sharti				 *		create it, set OP_NOTMAIN and
844144026Sharti				 *		add it to the list, setting
845144026Sharti				 *		DEFAULT to the new node for
846144026Sharti				 *		later use. We claim the node is
847144026Sharti				 *		A transformation rule to make
848144026Sharti				 *		life easier later, when we'll
849144026Sharti				 *		use Make_HandleUse to actually
850144026Sharti				 *		apply the .DEFAULT commands.
851144026Sharti				 *  .PHONY	The list of targets
852144026Sharti				 *  .BEGIN
853144026Sharti				 *  .END
854144026Sharti				 *  .INTERRUPT	Are not to be considered the
855144026Sharti				 *		main target.
856144026Sharti				 *  .NOTPARALLEL Make only one target at a time.
857144026Sharti				 *  .SINGLESHELL Create a shell for each
858144026Sharti				 *		command.
859144026Sharti				 *  .ORDER	Must set initial predecessor
860144026Sharti				 *		to NULL
861144026Sharti				 */
862144026Sharti				switch (specType) {
863144026Sharti				  case ExPath:
864144026Sharti					Lst_AtEnd(&paths, &dirSearchPath);
865144026Sharti					break;
866144026Sharti				  case Main:
867144026Sharti					if (!Lst_IsEmpty(&create)) {
868144026Sharti						specType = Not;
869144026Sharti					}
870144026Sharti					break;
871144026Sharti				  case Begin:
872144026Sharti				  case End:
873144026Sharti				  case Interrupt:
874144026Sharti					gn = Targ_FindNode(line, TARG_CREATE);
875144026Sharti					gn->type |= OP_NOTMAIN;
876144026Sharti					Lst_AtEnd(&targets, gn);
877144026Sharti					break;
878144026Sharti				  case Default:
879144026Sharti					gn = Targ_NewGN(".DEFAULT");
880144026Sharti					gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
881144026Sharti					Lst_AtEnd(&targets, gn);
882144026Sharti					DEFAULT = gn;
883144026Sharti					break;
884144026Sharti				  case NotParallel:
885146140Sharti					jobLimit = 1;
886144026Sharti					break;
887144026Sharti				  case SingleShell:
888144026Sharti					compatMake = 1;
889144026Sharti					break;
890144026Sharti				  case Order:
891144026Sharti					predecessor = NULL;
892144026Sharti					break;
893144026Sharti				  default:
894144026Sharti					break;
895144026Sharti				}
896144026Sharti
897144026Sharti			} else if (strncmp(line, ".PATH", 5) == 0) {
898144026Sharti				/*
899144026Sharti				 * .PATH<suffix> has to be handled specially.
900144026Sharti				 * Call on the suffix module to give us a path
901144026Sharti				 * to modify.
902144026Sharti				 */
903144026Sharti				struct Path *path;
904144026Sharti
905144026Sharti				specType = ExPath;
906144026Sharti				path = Suff_GetPath(&line[5]);
907144026Sharti				if (path == NULL) {
908144026Sharti					Parse_Error(PARSE_FATAL, "Suffix '%s' "
909144026Sharti					    "not defined (yet)", &line[5]);
910144026Sharti					return;
911144026Sharti				} else
912144026Sharti					Lst_AtEnd(&paths, path);
9131590Srgrimes			}
9141590Srgrimes		}
915144026Sharti
9161590Srgrimes		/*
917144026Sharti		 * Have word in line. Get or create its node and stick it at
918144026Sharti		 * the end of the targets list
9191590Srgrimes		 */
920144029Sharti		if (specType == Not && *line != '\0') {
9218874Srgrimes
922144026Sharti			/* target names to be found and added to targets list */
923144026Sharti			Lst curTargs = Lst_Initializer(curTargs);
9248874Srgrimes
925144026Sharti			if (Dir_HasWildcards(line)) {
926144026Sharti				/*
927144026Sharti				 * Targets are to be sought only in the current
928144026Sharti				 * directory, so create an empty path for the
929144026Sharti				 * thing. Note we need to use Path_Clear in the
930144026Sharti				 * destruction of the path as the Dir module
931144026Sharti				 * could have added a directory to the path...
932144026Sharti				 */
933144026Sharti				struct Path emptyPath =
934144026Sharti				    TAILQ_HEAD_INITIALIZER(emptyPath);
935138916Sharti
936144026Sharti				Path_Expand(line, &emptyPath, &curTargs);
937144026Sharti				Path_Clear(&emptyPath);
9388874Srgrimes
939144026Sharti			} else {
940144026Sharti				/*
941144026Sharti				 * No wildcards, but we want to avoid code
942144026Sharti				 * duplication, so create a list with the word
943144026Sharti				 * on it.
944144026Sharti				 */
945144026Sharti				Lst_AtEnd(&curTargs, line);
946144026Sharti			}
9478874Srgrimes
948144026Sharti			while (!Lst_IsEmpty(&curTargs)) {
949144026Sharti				char	*targName = Lst_DeQueue(&curTargs);
950144026Sharti
951144026Sharti				if (!Suff_IsTransform (targName)) {
952144026Sharti					gn = Targ_FindNode(targName,
953144026Sharti					    TARG_CREATE);
954144026Sharti				} else {
955144026Sharti					gn = Suff_AddTransform(targName);
956144026Sharti				}
957144026Sharti
958144026Sharti				Lst_AtEnd(&targets, gn);
959144026Sharti			}
960144026Sharti		} else if (specType == ExPath && *line != '.' && *line != '\0'){
961144026Sharti			Parse_Error(PARSE_WARNING, "Extra target (%s) ignored",
962144026Sharti			    line);
963144026Sharti		}
964144026Sharti
965144026Sharti		*cp = savec;
9661590Srgrimes		/*
967144026Sharti		 * If it is a special type and not .PATH, it's the only
968144026Sharti		 * target we allow on this line...
9691590Srgrimes		 */
970144026Sharti		if (specType != Not && specType != ExPath) {
971144026Sharti			Boolean warnFlag = FALSE;
9728874Srgrimes
973144029Sharti			while (*cp != '!' && *cp != ':' && *cp) {
974144026Sharti				if (*cp != ' ' && *cp != '\t') {
975144026Sharti					warnFlag = TRUE;
976144026Sharti				}
977144026Sharti				cp++;
978144026Sharti			}
979144026Sharti			if (warnFlag) {
980144026Sharti				Parse_Error(PARSE_WARNING,
981144026Sharti				    "Extra target ignored");
982144026Sharti			}
9831590Srgrimes		} else {
984144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
985144026Sharti				cp++;
986144026Sharti			}
9871590Srgrimes		}
988144026Sharti		line = cp;
989144029Sharti	} while (*line != '!' && *line != ':' && *line);
9908874Srgrimes
991144026Sharti	if (!Lst_IsEmpty(&targets)) {
992144026Sharti		switch (specType) {
993144026Sharti		  default:
994144026Sharti			Parse_Error(PARSE_WARNING, "Special and mundane "
995144026Sharti			    "targets don't mix. Mundane ones ignored");
996144026Sharti			break;
997144026Sharti		  case Default:
998144026Sharti		  case Begin:
999144026Sharti		  case End:
1000144026Sharti		  case Interrupt:
1001144026Sharti			/*
1002144026Sharti			 * These four create nodes on which to hang commands, so
1003144026Sharti			 * targets shouldn't be empty...
1004144026Sharti			 */
1005144026Sharti		  case Not:
1006144026Sharti			/*
1007144026Sharti			 * Nothing special here -- targets can be empty if it
1008144026Sharti			 * wants.
1009144026Sharti			 */
1010144026Sharti			break;
1011144026Sharti		}
10121590Srgrimes	}
10138874Srgrimes
10141590Srgrimes	/*
1015144026Sharti	 * Have now parsed all the target names. Must parse the operator next.
1016144026Sharti	 * The result is left in op.
10171590Srgrimes	 */
1018144026Sharti	if (*cp == '!') {
1019144026Sharti		op = OP_FORCE;
1020144026Sharti	} else if (*cp == ':') {
1021144026Sharti		if (cp[1] == ':') {
1022144026Sharti			op = OP_DOUBLEDEP;
1023144026Sharti			cp++;
1024144026Sharti		} else {
1025144026Sharti			op = OP_DEPENDS;
10261590Srgrimes		}
10271590Srgrimes	} else {
1028144026Sharti		Parse_Error(PARSE_FATAL, "Missing dependency operator");
1029144026Sharti		return;
1030144026Sharti	}
1031144026Sharti
1032144026Sharti	cp++;			/* Advance beyond operator */
1033144026Sharti
1034144026Sharti	ParseDoOp(op);
1035144026Sharti
1036144026Sharti	/*
1037144026Sharti	 * Get to the first source
1038144026Sharti	 */
1039144026Sharti	while (*cp && isspace((unsigned char)*cp)) {
10401590Srgrimes		cp++;
10411590Srgrimes	}
10421590Srgrimes	line = cp;
10431590Srgrimes
1044144026Sharti	/*
1045144026Sharti	 * Several special targets take different actions if present with no
1046144026Sharti	 * sources:
1047144026Sharti	 *	a .SUFFIXES line with no sources clears out all old suffixes
1048144026Sharti	 *	a .PRECIOUS line makes all targets precious
1049144026Sharti	 *	a .IGNORE line ignores errors for all targets
1050144026Sharti	 *	a .SILENT line creates silence when making all targets
1051144026Sharti	 *	a .PATH removes all directories from the search path(s).
1052144026Sharti	 */
1053144026Sharti	if (!*line) {
1054144026Sharti		switch (specType) {
1055144026Sharti		  case Suffixes:
1056144026Sharti			Suff_ClearSuffixes();
1057144026Sharti			break;
1058144026Sharti		  case Precious:
1059144026Sharti			allPrecious = TRUE;
1060144026Sharti			break;
1061144026Sharti		  case Ignore:
1062144026Sharti			ignoreErrors = TRUE;
1063144026Sharti			break;
1064144026Sharti		  case Silent:
1065144026Sharti			beSilent = TRUE;
1066144026Sharti			break;
1067144026Sharti		  case ExPath:
1068144026Sharti			LST_FOREACH(ln, &paths)
1069144026Sharti			Path_Clear(Lst_Datum(ln));
1070144026Sharti			break;
1071144026Sharti		  case Posix:
1072144026Sharti			Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1073144026Sharti			break;
1074144026Sharti		  default:
1075144026Sharti			break;
1076144026Sharti		}
1077144026Sharti
1078144026Sharti	} else if (specType == MFlags) {
10791590Srgrimes		/*
1080144026Sharti		 * Call on functions in main.c to deal with these arguments and
1081144026Sharti		 * set the initial character to a null-character so the loop to
1082144026Sharti		 * get sources won't get anything
10831590Srgrimes		 */
1084144026Sharti		Main_ParseArgLine(line, 0);
1085144026Sharti		*line = '\0';
10861590Srgrimes
1087145679Sharti	} else if (specType == Warn) {
1088145679Sharti		parse_warn(line);
1089145679Sharti		*line = '\0';
1090145679Sharti
1091144026Sharti	} else if (specType == ExShell) {
1092144026Sharti		if (Job_ParseShell(line) != SUCCESS) {
1093144026Sharti			Parse_Error(PARSE_FATAL,
1094144026Sharti			    "improper shell specification");
1095144026Sharti			return;
1096144026Sharti		}
1097144026Sharti		*line = '\0';
1098144026Sharti
1099144029Sharti	} else if (specType == NotParallel || specType == SingleShell) {
1100144026Sharti		*line = '\0';
11011590Srgrimes	}
11021590Srgrimes
1103144026Sharti	/*
1104144026Sharti	* NOW GO FOR THE SOURCES
1105144026Sharti	*/
1106144029Sharti	if (specType == Suffixes || specType == ExPath ||
1107144029Sharti	    specType == Includes || specType == Libs ||
1108144029Sharti	    specType == Null) {
1109144026Sharti		while (*line) {
1110144026Sharti			/*
1111144026Sharti			 * If the target was one that doesn't take files as its
1112144026Sharti			 * sources but takes something like suffixes, we take
1113144026Sharti			 * each space-separated word on the line as a something
1114144026Sharti			 * and deal with it accordingly.
1115144026Sharti			 *
1116144026Sharti			 * If the target was .SUFFIXES, we take each source as
1117144026Sharti			 * a suffix and add it to the list of suffixes
1118144026Sharti			 * maintained by the Suff module.
1119144026Sharti			 *
1120144026Sharti			 * If the target was a .PATH, we add the source as a
1121144026Sharti			 * directory to search on the search path.
1122144026Sharti			 *
1123144026Sharti			 * If it was .INCLUDES, the source is taken to be the
1124144026Sharti			 * suffix of files which will be #included and whose
1125144026Sharti			 * search path should be present in the .INCLUDES
1126144026Sharti			 * variable.
1127144026Sharti			 *
1128144026Sharti			 * If it was .LIBS, the source is taken to be the
1129144026Sharti			 * suffix of files which are considered libraries and
1130144026Sharti			 * whose search path should be present in the .LIBS
1131144026Sharti			 * variable.
1132144026Sharti			 *
1133144026Sharti			 * If it was .NULL, the source is the suffix to use
1134144026Sharti			 * when a file has no valid suffix.
1135144026Sharti			 */
1136144026Sharti			char  savech;
1137144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1138144026Sharti				cp++;
1139144026Sharti			}
1140144026Sharti			savech = *cp;
1141144026Sharti			*cp = '\0';
1142144026Sharti			switch (specType) {
1143144026Sharti			  case Suffixes:
1144144026Sharti				Suff_AddSuffix(line);
1145144026Sharti				break;
1146144026Sharti			  case ExPath:
1147144026Sharti				LST_FOREACH(ln, &paths)
1148144026Sharti					Path_AddDir(Lst_Datum(ln), line);
1149144026Sharti				break;
1150144026Sharti			  case Includes:
1151144026Sharti				Suff_AddInclude(line);
1152144026Sharti				break;
1153144026Sharti			  case Libs:
1154144026Sharti				Suff_AddLib(line);
1155144026Sharti				break;
1156144026Sharti			  case Null:
1157144026Sharti				Suff_SetNull(line);
1158144026Sharti				break;
1159144026Sharti			  default:
1160144026Sharti				break;
1161144026Sharti			}
1162144026Sharti			*cp = savech;
1163144026Sharti			if (savech != '\0') {
1164144026Sharti				cp++;
1165144026Sharti			}
1166144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1167144026Sharti				cp++;
1168144026Sharti			}
1169144026Sharti			line = cp;
1170144026Sharti		}
1171144026Sharti		Lst_Destroy(&paths, NOFREE);
11721590Srgrimes
1173145971Sharti	} else if (specType == ExportVar) {
1174145971Sharti		Var_SetEnv(line, VAR_GLOBAL);
1175145971Sharti
1176144026Sharti	} else {
1177144026Sharti		/* list of sources in order */
1178144026Sharti		Lst curSrcs = Lst_Initializer(curSrc);
11791590Srgrimes
1180144026Sharti		while (*line) {
1181144026Sharti			/*
1182144026Sharti			 * The targets take real sources, so we must beware of
1183144026Sharti			 * archive specifications (i.e. things with left
1184144026Sharti			 * parentheses in them) and handle them accordingly.
1185144026Sharti			 */
1186144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1187144026Sharti				if (*cp == '(' && cp > line && cp[-1] != '$') {
1188144026Sharti					/*
1189144026Sharti					 * Only stop for a left parenthesis if
1190144026Sharti					 * it isn't at the start of a word
1191144026Sharti					 * (that'll be for variable changes
1192144026Sharti					 * later) and isn't preceded by a dollar
1193144026Sharti					 * sign (a dynamic source).
1194144026Sharti					 */
1195144026Sharti					break;
1196144026Sharti				} else {
1197144026Sharti					cp++;
1198144026Sharti				}
1199144026Sharti			}
12001590Srgrimes
1201144026Sharti			if (*cp == '(') {
1202144026Sharti				GNode	  *gnp;
12038874Srgrimes
1204144026Sharti				/* list of archive source names after exp. */
1205144026Sharti				Lst sources = Lst_Initializer(sources);
1206138916Sharti
1207144026Sharti				if (Arch_ParseArchive(&line, &sources,
1208144026Sharti				    VAR_CMD) != SUCCESS) {
1209144026Sharti					Parse_Error(PARSE_FATAL, "Error in "
1210144026Sharti					    "source archive spec \"%s\"", line);
1211144026Sharti					return;
1212144026Sharti				}
1213141270Sharti
1214144026Sharti				while (!Lst_IsEmpty(&sources)) {
1215144026Sharti					gnp = Lst_DeQueue(&sources);
1216144026Sharti					ParseDoSrc(tOp, gnp->name, &curSrcs);
1217144026Sharti				}
1218144026Sharti				cp = line;
1219144026Sharti			} else {
1220144026Sharti				if (*cp) {
1221144026Sharti					*cp = '\0';
1222144026Sharti					cp += 1;
1223144026Sharti				}
12241590Srgrimes
1225144026Sharti				ParseDoSrc(tOp, line, &curSrcs);
1226144026Sharti			}
1227144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1228144026Sharti				cp++;
1229144026Sharti			}
1230144026Sharti			line = cp;
12311590Srgrimes		}
1232144026Sharti		Lst_Destroy(&curSrcs, NOFREE);
1233144026Sharti	}
12341590Srgrimes
1235144026Sharti	if (mainNode == NULL) {
1236144026Sharti		/*
1237144026Sharti		 * If we have yet to decide on a main target to make, in the
1238144026Sharti		 * absence of any user input, we want the first target on
1239144026Sharti		 * the first dependency line that is actually a real target
1240144026Sharti		 * (i.e. isn't a .USE or .EXEC rule) to be made.
1241144026Sharti		 */
1242144026Sharti		LST_FOREACH(ln, &targets) {
1243144026Sharti			gn = Lst_Datum(ln);
1244144026Sharti			if ((gn->type & (OP_NOTMAIN | OP_USE |
1245144026Sharti			    OP_EXEC | OP_TRANSFORM)) == 0) {
1246144026Sharti				mainNode = gn;
1247144026Sharti				Targ_SetMain(gn);
1248144026Sharti				break;
1249144026Sharti			}
12501590Srgrimes		}
12511590Srgrimes	}
12521590Srgrimes}
12531590Srgrimes
12541590Srgrimes/*-
12551590Srgrimes *---------------------------------------------------------------------
12561590Srgrimes * Parse_IsVar  --
12571590Srgrimes *	Return TRUE if the passed line is a variable assignment. A variable
12581590Srgrimes *	assignment consists of a single word followed by optional whitespace
12591590Srgrimes *	followed by either a += or an = operator.
12601590Srgrimes *	This function is used both by the Parse_File function and main when
12611590Srgrimes *	parsing the command-line arguments.
12621590Srgrimes *
12631590Srgrimes * Results:
12641590Srgrimes *	TRUE if it is. FALSE if it ain't
12651590Srgrimes *
12661590Srgrimes * Side Effects:
12671590Srgrimes *	none
12681590Srgrimes *---------------------------------------------------------------------
12691590Srgrimes */
12701590SrgrimesBoolean
1271138232ShartiParse_IsVar(char *line)
12721590Srgrimes{
1273144026Sharti	Boolean wasSpace = FALSE;	/* set TRUE if found a space */
1274144026Sharti	Boolean haveName = FALSE;	/* Set TRUE if have a variable name */
1275138232Sharti
1276144026Sharti	int level = 0;
1277103503Sjmallett#define	ISEQOPERATOR(c) \
1278144029Sharti	((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!')
12791590Srgrimes
1280144026Sharti	/*
1281144026Sharti	 * Skip to variable name
1282144026Sharti	 */
1283144029Sharti	for (; *line == ' ' || *line == '\t'; line++)
1284144026Sharti		continue;
12851590Srgrimes
1286144026Sharti	for (; *line != '=' || level != 0; line++) {
1287144026Sharti		switch (*line) {
1288144026Sharti		  case '\0':
1289144026Sharti			/*
1290144026Sharti			 * end-of-line -- can't be a variable assignment.
1291144026Sharti			 */
1292144026Sharti			return (FALSE);
129318730Ssteve
1294144026Sharti		  case ' ':
1295144026Sharti		  case '\t':
1296144026Sharti			/*
1297144026Sharti			 * there can be as much white space as desired so long
1298144026Sharti			 * as there is only one word before the operator
1299144026Sharti			*/
1300144026Sharti			wasSpace = TRUE;
1301144026Sharti			break;
130218730Ssteve
1303144026Sharti		  case '(':
1304144026Sharti		  case '{':
1305144026Sharti			level++;
1306144026Sharti			break;
130718730Ssteve
1308144026Sharti		  case '}':
1309144026Sharti		  case ')':
1310144026Sharti			level--;
1311144026Sharti			break;
131218730Ssteve
1313144026Sharti		  default:
1314144026Sharti			if (wasSpace && haveName) {
1315144026Sharti				if (ISEQOPERATOR(*line)) {
1316144026Sharti					/*
1317144026Sharti					 * We must have a finished word
1318144026Sharti					 */
1319144026Sharti					if (level != 0)
1320144026Sharti						return (FALSE);
132118730Ssteve
1322144026Sharti					/*
1323144026Sharti					 * When an = operator [+?!:] is found,
1324144026Sharti					 * the next character must be an = or
1325144026Sharti					 * it ain't a valid assignment.
1326144026Sharti					 */
1327144026Sharti					if (line[1] == '=')
1328144026Sharti						return (haveName);
132918730Ssteve#ifdef SUNSHCMD
1330144026Sharti					/*
1331144026Sharti					 * This is a shell command
1332144026Sharti					 */
1333144026Sharti					if (strncmp(line, ":sh", 3) == 0)
1334144026Sharti						return (haveName);
133518730Ssteve#endif
1336144026Sharti				}
1337144026Sharti				/*
1338144026Sharti				 * This is the start of another word, so not
1339144026Sharti				 * assignment.
1340144026Sharti				 */
1341144026Sharti				return (FALSE);
1342144026Sharti
1343144026Sharti			} else {
1344144026Sharti				haveName = TRUE;
1345144026Sharti				wasSpace = FALSE;
1346144026Sharti			}
1347144026Sharti			break;
1348144026Sharti		}
13491590Srgrimes	}
13501590Srgrimes
1351144026Sharti	return (haveName);
13521590Srgrimes}
13531590Srgrimes
13541590Srgrimes/*-
13551590Srgrimes *---------------------------------------------------------------------
13561590Srgrimes * Parse_DoVar  --
13571590Srgrimes *	Take the variable assignment in the passed line and do it in the
13581590Srgrimes *	global context.
13591590Srgrimes *
13601590Srgrimes *	Note: There is a lexical ambiguity with assignment modifier characters
13611590Srgrimes *	in variable names. This routine interprets the character before the =
13621590Srgrimes *	as a modifier. Therefore, an assignment like
13631590Srgrimes *	    C++=/usr/bin/CC
13641590Srgrimes *	is interpreted as "C+ +=" instead of "C++ =".
13651590Srgrimes *
13661590Srgrimes * Results:
13671590Srgrimes *	none
13681590Srgrimes *
13691590Srgrimes * Side Effects:
13701590Srgrimes *	the variable structure of the given variable name is altered in the
13711590Srgrimes *	global context.
13721590Srgrimes *---------------------------------------------------------------------
13731590Srgrimes */
13741590Srgrimesvoid
1375138232ShartiParse_DoVar(char *line, GNode *ctxt)
13761590Srgrimes{
1377144026Sharti	char	*cp;	/* pointer into line */
1378144026Sharti	enum {
1379144026Sharti		VAR_SUBST,
1380144026Sharti		VAR_APPEND,
1381144026Sharti		VAR_SHELL,
1382144026Sharti		VAR_NORMAL
1383144026Sharti	}	type;	/* Type of assignment */
1384144026Sharti	char	*opc;	/* ptr to operator character to
1385144026Sharti			 * null-terminate the variable name */
1386144026Sharti
1387144026Sharti	/*
1388144026Sharti	 * Skip to variable name
1389144026Sharti	 */
1390144029Sharti	while (*line == ' ' || *line == '\t') {
1391144026Sharti		line++;
1392144026Sharti	}
13931590Srgrimes
1394144026Sharti	/*
1395144026Sharti	 * Skip to operator character, nulling out whitespace as we go
1396144026Sharti	 */
1397144026Sharti	for (cp = line + 1; *cp != '='; cp++) {
1398144026Sharti		if (isspace((unsigned char)*cp)) {
1399144026Sharti			*cp = '\0';
1400144026Sharti		}
14011590Srgrimes	}
1402144026Sharti	opc = cp - 1;		/* operator is the previous character */
1403144026Sharti	*cp++ = '\0';		/* nuke the = */
14041590Srgrimes
1405144026Sharti	/*
1406144026Sharti	 * Check operator type
1407144026Sharti	 */
1408144026Sharti	switch (*opc) {
1409144026Sharti	  case '+':
1410144026Sharti		type = VAR_APPEND;
1411144026Sharti		*opc = '\0';
1412144026Sharti		break;
14131590Srgrimes
1414144026Sharti	  case '?':
1415144026Sharti		/*
1416144026Sharti		 * If the variable already has a value, we don't do anything.
1417144026Sharti		 */
1418144026Sharti		*opc = '\0';
1419144026Sharti		if (Var_Exists(line, ctxt)) {
1420144026Sharti			return;
1421144026Sharti		} else {
1422144026Sharti			type = VAR_NORMAL;
1423144026Sharti		}
1424144026Sharti		break;
14251590Srgrimes
1426144026Sharti	  case ':':
1427144026Sharti		type = VAR_SUBST;
1428144026Sharti		*opc = '\0';
1429144026Sharti		break;
14301590Srgrimes
1431144026Sharti	  case '!':
1432144026Sharti		type = VAR_SHELL;
1433144026Sharti		*opc = '\0';
1434144026Sharti		break;
14351590Srgrimes
1436144026Sharti	  default:
143718730Ssteve#ifdef SUNSHCMD
1438144026Sharti		while (*opc != ':') {
1439144026Sharti			if (opc == line)
1440144026Sharti				break;
1441144026Sharti			else
1442144026Sharti				--opc;
1443144026Sharti		}
144418730Ssteve
1445144026Sharti		if (strncmp(opc, ":sh", 3) == 0) {
1446144026Sharti			type = VAR_SHELL;
1447144026Sharti			*opc = '\0';
1448144026Sharti			break;
1449144026Sharti		}
1450144026Sharti#endif
1451144026Sharti		type = VAR_NORMAL;
145218730Ssteve		break;
1453144026Sharti	}
14541590Srgrimes
1455144026Sharti	while (isspace((unsigned char)*cp)) {
1456144026Sharti		cp++;
1457144026Sharti	}
14581590Srgrimes
1459144026Sharti	if (type == VAR_APPEND) {
1460144026Sharti		Var_Append(line, cp, ctxt);
14611590Srgrimes
1462144026Sharti	} else if (type == VAR_SUBST) {
1463144026Sharti		/*
1464144026Sharti		 * Allow variables in the old value to be undefined, but leave
1465144026Sharti		 * their invocation alone -- this is done by forcing oldVars
1466144026Sharti		 * to be false.
1467144026Sharti		 * XXX: This can cause recursive variables, but that's not
1468144026Sharti		 * hard to do, and this allows someone to do something like
1469144026Sharti		 *
1470144026Sharti		 *  CFLAGS = $(.INCLUDES)
1471144026Sharti		 *  CFLAGS := -I.. $(CFLAGS)
1472144026Sharti		 *
1473144026Sharti		 * And not get an error.
1474144026Sharti		 */
1475144026Sharti		Boolean oldOldVars = oldVars;
147698509Sjmallett
1477144026Sharti		oldVars = FALSE;
147898509Sjmallett
1479144026Sharti		/*
1480144026Sharti		 * make sure that we set the variable the first time to nothing
1481144026Sharti		 * so that it gets substituted!
1482144026Sharti		 */
1483144026Sharti		if (!Var_Exists(line, ctxt))
1484144026Sharti			Var_Set(line, "", ctxt);
1485142457Sharti
1486146027Sharti		cp = Buf_Peel(Var_Subst(cp, ctxt, FALSE));
14871590Srgrimes
1488144026Sharti		oldVars = oldOldVars;
14891590Srgrimes
1490144026Sharti		Var_Set(line, cp, ctxt);
1491144026Sharti		free(cp);
14921590Srgrimes
1493144026Sharti	} else if (type == VAR_SHELL) {
1494144026Sharti		/*
1495144026Sharti		 * TRUE if the command needs to be freed, i.e.
1496144026Sharti		 * if any variable expansion was performed
1497144026Sharti		 */
1498144026Sharti		Boolean	freeCmd = FALSE;
1499144026Sharti		Buffer *buf;
1500144026Sharti		const char *error;
15011590Srgrimes
1502144026Sharti		if (strchr(cp, '$') != NULL) {
1503144026Sharti			/*
1504144026Sharti			 * There's a dollar sign in the command, so perform
1505144026Sharti			 * variable expansion on the whole thing. The
1506144026Sharti			 * resulting string will need freeing when we're done,
1507144026Sharti			 * so set freeCmd to TRUE.
1508144026Sharti			 */
1509146027Sharti			cp = Buf_Peel(Var_Subst(cp, VAR_CMD, TRUE));
1510144026Sharti			freeCmd = TRUE;
1511144026Sharti		}
15121590Srgrimes
1513144026Sharti		buf = Cmd_Exec(cp, &error);
1514144026Sharti		Var_Set(line, Buf_Data(buf), ctxt);
1515144026Sharti		Buf_Destroy(buf, TRUE);
1516144026Sharti
1517144026Sharti		if (error)
1518144026Sharti			Parse_Error(PARSE_WARNING, error, cp);
1519144026Sharti
1520144026Sharti		if (freeCmd)
1521144026Sharti			free(cp);
1522144026Sharti
1523144026Sharti	} else {
1524144026Sharti		/*
1525144026Sharti		 * Normal assignment -- just do it.
1526144026Sharti		 */
1527144026Sharti		Var_Set(line, cp, ctxt);
1528144026Sharti	}
15291590Srgrimes}
15301590Srgrimes
15311590Srgrimes/*-
15321590Srgrimes *-----------------------------------------------------------------------
15331590Srgrimes * ParseHasCommands --
15341590Srgrimes *	Callback procedure for Parse_File when destroying the list of
15351590Srgrimes *	targets on the last dependency line. Marks a target as already
15361590Srgrimes *	having commands if it does, to keep from having shell commands
15371590Srgrimes *	on multiple dependency lines.
15381590Srgrimes *
15391590Srgrimes * Results:
15405814Sjkh *	None
15411590Srgrimes *
15421590Srgrimes * Side Effects:
15431590Srgrimes *	OP_HAS_COMMANDS may be set for the target.
15441590Srgrimes *
15451590Srgrimes *-----------------------------------------------------------------------
15461590Srgrimes */
15475814Sjkhstatic void
1548104696SjmallettParseHasCommands(void *gnp)
15491590Srgrimes{
1550144026Sharti	GNode *gn = gnp;
1551138232Sharti
1552144026Sharti	if (!Lst_IsEmpty(&gn->commands)) {
1553144026Sharti		gn->type |= OP_HAS_COMMANDS;
1554144026Sharti	}
15551590Srgrimes}
15561590Srgrimes
15571590Srgrimes/*-
15581590Srgrimes *-----------------------------------------------------------------------
15591590Srgrimes * Parse_AddIncludeDir --
15601590Srgrimes *	Add a directory to the path searched for included makefiles
15611590Srgrimes *	bracketed by double-quotes. Used by functions in main.c
15621590Srgrimes *
15631590Srgrimes * Results:
15641590Srgrimes *	None.
15651590Srgrimes *
15661590Srgrimes * Side Effects:
15671590Srgrimes *	The directory is appended to the list.
15681590Srgrimes *
15691590Srgrimes *-----------------------------------------------------------------------
15701590Srgrimes */
15711590Srgrimesvoid
1572138232ShartiParse_AddIncludeDir(char *dir)
15731590Srgrimes{
1574138232Sharti
1575144026Sharti	Path_AddDir(&parseIncPath, dir);
15761590Srgrimes}
15771590Srgrimes
15781590Srgrimes/*-
15791590Srgrimes *---------------------------------------------------------------------
15801590Srgrimes * Parse_FromString  --
15811590Srgrimes *	Start Parsing from the given string
15828874Srgrimes *
15831590Srgrimes * Results:
15841590Srgrimes *	None
15851590Srgrimes *
15861590Srgrimes * Side Effects:
1587126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1588126824Sru *	curFile.fname and curFile.F are altered for the new file
15891590Srgrimes *---------------------------------------------------------------------
15901590Srgrimes */
15911590Srgrimesvoid
1592126824SruParse_FromString(char *str, int lineno)
15931590Srgrimes{
15941590Srgrimes
1595144026Sharti	DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno));
15961590Srgrimes
1597144341Sharti	ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno);
15981590Srgrimes}
15991590Srgrimes
16001590Srgrimes#ifdef SYSVINCLUDE
16011590Srgrimes/*-
16021590Srgrimes *---------------------------------------------------------------------
16031590Srgrimes * ParseTraditionalInclude  --
16041590Srgrimes *	Push to another file.
16058874Srgrimes *
16061590Srgrimes *	The input is the line minus the "include".  The file name is
16071590Srgrimes *	the string following the "include".
16081590Srgrimes *
16091590Srgrimes * Results:
16101590Srgrimes *	None
16111590Srgrimes *
16121590Srgrimes * Side Effects:
1613126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1614126824Sru *	curFile.fname and curFile.F are altered for the new file
16151590Srgrimes *---------------------------------------------------------------------
16161590Srgrimes */
16171590Srgrimesstatic void
1618141270ShartiParseTraditionalInclude(char *file)
16191590Srgrimes{
1620144026Sharti	char	*fullname;	/* full pathname of file */
1621144026Sharti	char	*cp;		/* current position in file spec */
16221590Srgrimes
1623144026Sharti	/*
1624144026Sharti	 * Skip over whitespace
1625144026Sharti	 */
1626144029Sharti	while (*file == ' ' || *file == '\t') {
1627144026Sharti		file++;
1628144026Sharti	}
16291590Srgrimes
1630144026Sharti	if (*file == '\0') {
1631144026Sharti		Parse_Error(PARSE_FATAL, "Filename missing from \"include\"");
1632144026Sharti		return;
1633144026Sharti	}
16341590Srgrimes
1635144026Sharti	/*
1636144026Sharti	* Skip to end of line or next whitespace
1637144026Sharti	*/
1638144026Sharti	for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1639144026Sharti		continue;
1640144026Sharti	}
16411590Srgrimes
1642144026Sharti	*cp = '\0';
16431590Srgrimes
1644144026Sharti	/*
1645144026Sharti	 * Substitute for any variables in the file name before trying to
1646144026Sharti	 * find the thing.
1647144026Sharti	 */
1648146027Sharti	file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE));
16491590Srgrimes
16501590Srgrimes	/*
1651144026Sharti	 * Now we know the file's name, we attempt to find the durn thing.
1652144026Sharti	 * Search for it first on the -I search path, then on the .PATH
1653144026Sharti	 * search path, if not found in a -I directory.
16541590Srgrimes	 */
1655144026Sharti	fullname = Path_FindFile(file, &parseIncPath);
1656144026Sharti	if (fullname == NULL) {
1657144026Sharti		fullname = Path_FindFile(file, &dirSearchPath);
1658144026Sharti	}
16591590Srgrimes
1660144026Sharti	if (fullname == NULL) {
1661144026Sharti		/*
1662144026Sharti		 * Still haven't found the makefile. Look for it on the system
1663144026Sharti		 * path as a last resort.
1664144026Sharti		 */
1665144026Sharti		fullname = Path_FindFile(file, &sysIncPath);
1666144026Sharti	}
16671590Srgrimes
1668144026Sharti	if (fullname == NULL) {
1669144026Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
1670144026Sharti		/* XXXHB free(file) */
1671144026Sharti		return;
1672144026Sharti	}
1673142457Sharti
1674144026Sharti	/* XXXHB free(file) */
16751590Srgrimes
1676144026Sharti	/*
1677144341Sharti	 * We set up the name of the file to be the absolute
1678144026Sharti	 * name of the include file so error messages refer to the right
1679144341Sharti	 * place.
16801590Srgrimes	 */
1681144341Sharti	ParsePushInput(fullname, NULL, NULL, 0);
16821590Srgrimes}
16831590Srgrimes#endif
16841590Srgrimes
16851590Srgrimes/*-
16861590Srgrimes *---------------------------------------------------------------------
16871590Srgrimes * ParseReadc  --
16888874Srgrimes *	Read a character from the current file
16891590Srgrimes *
16901590Srgrimes * Results:
16911590Srgrimes *	The character that was read
16921590Srgrimes *
16931590Srgrimes * Side Effects:
16941590Srgrimes *---------------------------------------------------------------------
16951590Srgrimes */
16961590Srgrimesstatic int
1697104696SjmallettParseReadc(void)
16981590Srgrimes{
1699138232Sharti
1700144341Sharti	if (CURFILE->F != NULL)
1701144341Sharti		return (fgetc(CURFILE->F));
17028874Srgrimes
1703144341Sharti	if (CURFILE->str != NULL && *CURFILE->ptr != '\0')
1704144341Sharti		return (*CURFILE->ptr++);
1705144341Sharti
1706144026Sharti	return (EOF);
17071590Srgrimes}
17081590Srgrimes
17091590Srgrimes
17101590Srgrimes/*-
17111590Srgrimes *---------------------------------------------------------------------
17121590Srgrimes * ParseUnreadc  --
17138874Srgrimes *	Put back a character to the current file
17141590Srgrimes *
17151590Srgrimes * Results:
17161590Srgrimes *	None.
17171590Srgrimes *
17181590Srgrimes * Side Effects:
17191590Srgrimes *---------------------------------------------------------------------
17201590Srgrimes */
17211590Srgrimesstatic void
1722104696SjmallettParseUnreadc(int c)
17231590Srgrimes{
1724138232Sharti
1725144341Sharti	if (CURFILE->F != NULL) {
1726144341Sharti		ungetc(c, CURFILE->F);
1727144026Sharti		return;
1728144026Sharti	}
1729144341Sharti	if (CURFILE->str != NULL) {
1730144341Sharti		*--(CURFILE->ptr) = c;
1731144026Sharti		return;
1732144026Sharti	}
17331590Srgrimes}
17341590Srgrimes
17351590Srgrimes/* ParseSkipLine():
1736104696Sjmallett *	Grab the next line unless it begins with a dot (`.') and we're told to
1737104696Sjmallett *	ignore such lines.
17381590Srgrimes */
17391590Srgrimesstatic char *
1740126824SruParseSkipLine(int skip, int keep_newline)
17411590Srgrimes{
1742144026Sharti	char *line;
1743144026Sharti	int c, lastc;
1744144026Sharti	Buffer *buf;
17451590Srgrimes
1746144026Sharti	buf = Buf_Init(MAKE_BSIZE);
17471590Srgrimes
1748144026Sharti	do {
1749144026Sharti		Buf_Clear(buf);
1750144026Sharti		lastc = '\0';
17518874Srgrimes
1752144026Sharti		while (((c = ParseReadc()) != '\n' || lastc == '\\')
1753144026Sharti		    && c != EOF) {
1754144026Sharti			if (skip && c == '#' && lastc != '\\') {
1755144026Sharti				/*
1756144026Sharti				 * let a comment be terminated even by an
1757144026Sharti				 * escaped \n. This is consistent to comment
1758144026Sharti				 * handling in ParseReadLine
1759144026Sharti				 */
1760144026Sharti				while ((c = ParseReadc()) != '\n' && c != EOF)
1761144026Sharti					;
1762144026Sharti				break;
1763144026Sharti			}
1764144026Sharti			if (c == '\n') {
1765144026Sharti				if (keep_newline)
1766144026Sharti					Buf_AddByte(buf, (Byte)c);
1767144026Sharti				else
1768144026Sharti					Buf_ReplaceLastByte(buf, (Byte)' ');
1769144341Sharti				CURFILE->lineno++;
17708874Srgrimes
1771144026Sharti				while ((c = ParseReadc()) == ' ' || c == '\t')
1772144026Sharti					continue;
17738874Srgrimes
1774144026Sharti				if (c == EOF)
1775144026Sharti					break;
1776144026Sharti			}
177774272Swill
1778144026Sharti			Buf_AddByte(buf, (Byte)c);
1779144026Sharti			lastc = c;
1780144026Sharti		}
178118456Ssteve
1782144026Sharti		if (c == EOF) {
1783144026Sharti			Parse_Error(PARSE_FATAL,
1784144026Sharti			    "Unclosed conditional/for loop");
1785144026Sharti			Buf_Destroy(buf, TRUE);
1786144026Sharti			return (NULL);
1787144026Sharti		}
178818456Ssteve
1789144341Sharti		CURFILE->lineno++;
1790144026Sharti		Buf_AddByte(buf, (Byte)'\0');
1791144026Sharti		line = Buf_Data(buf);
1792144026Sharti	} while (skip == 1 && line[0] != '.');
179318456Ssteve
1794144026Sharti	Buf_Destroy(buf, FALSE);
1795144026Sharti	return (line);
17961590Srgrimes}
17971590Srgrimes
17981590Srgrimes/*-
17991590Srgrimes *---------------------------------------------------------------------
18001590Srgrimes * ParseReadLine --
18011590Srgrimes *	Read an entire line from the input file. Called only by Parse_File.
18021590Srgrimes *	To facilitate escaped newlines and what have you, a character is
18031590Srgrimes *	buffered in 'lastc', which is '\0' when no characters have been
18041590Srgrimes *	read. When we break out of the loop, c holds the terminating
18051590Srgrimes *	character and lastc holds a character that should be added to
18061590Srgrimes *	the line (unless we don't read anything but a terminator).
18071590Srgrimes *
18081590Srgrimes * Results:
18091590Srgrimes *	A line w/o its newline
18101590Srgrimes *
18111590Srgrimes * Side Effects:
18121590Srgrimes *	Only those associated with reading a character
18131590Srgrimes *---------------------------------------------------------------------
18141590Srgrimes */
18151590Srgrimesstatic char *
1816138232ShartiParseReadLine(void)
18171590Srgrimes{
1818144026Sharti	Buffer	*buf;		/* Buffer for current line */
1819144026Sharti	int	c;		/* the current character */
1820144026Sharti	int	lastc;		/* The most-recent character */
1821144026Sharti	Boolean	semiNL;		/* treat semi-colons as newlines */
1822144026Sharti	Boolean	ignDepOp;	/* TRUE if should ignore dependency operators
18231590Srgrimes				 * for the purposes of setting semiNL */
1824144026Sharti	Boolean	ignComment;	/* TRUE if should ignore comments (in a
18251590Srgrimes				 * shell command */
1826144026Sharti	char	*line;		/* Result */
1827144026Sharti	char	*ep;		/* to strip trailing blanks */
18281590Srgrimes
1829144742Sharti  again:
1830144026Sharti	semiNL = FALSE;
1831144026Sharti	ignDepOp = FALSE;
1832144026Sharti	ignComment = FALSE;
18331590Srgrimes
1834144742Sharti	lastc = '\0';
1835144742Sharti
1836144026Sharti	/*
1837144742Sharti	 * Handle tab at the beginning of the line. A leading tab (shell
1838144742Sharti	 * command) forces us to ignore comments and dependency operators and
1839144742Sharti	 * treat semi-colons as semi-colons (by leaving semiNL FALSE).
1840144742Sharti	 * This also discards completely blank lines.
1841144026Sharti	 */
1842144026Sharti	for (;;) {
1843144026Sharti		c = ParseReadc();
1844144742Sharti		if (c == EOF) {
1845144742Sharti			if (ParsePopInput() == DONE) {
1846144742Sharti				/* End of all inputs - return NULL */
1847144742Sharti				return (NULL);
1848144742Sharti			}
1849144742Sharti			continue;
1850144742Sharti		}
18511590Srgrimes
1852144026Sharti		if (c == '\t') {
1853144026Sharti			ignComment = ignDepOp = TRUE;
1854144742Sharti			lastc = c;
1855144026Sharti			break;
1856144742Sharti		}
1857144742Sharti		if (c != '\n') {
1858144026Sharti			ParseUnreadc(c);
1859144026Sharti			break;
1860144026Sharti		}
1861144742Sharti		CURFILE->lineno++;
18621590Srgrimes	}
18638874Srgrimes
1864144742Sharti	buf = Buf_Init(MAKE_BSIZE);
18658874Srgrimes
1866144742Sharti	while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) {
1867144026Sharti  test_char:
1868144742Sharti		switch (c) {
1869144742Sharti		  case '\n':
1870144742Sharti			/*
1871144742Sharti			 * Escaped newline: read characters until a
1872144742Sharti			 * non-space or an unescaped newline and
1873144742Sharti			 * replace them all by a single space. This is
1874144742Sharti			 * done by storing the space over the backslash
1875144742Sharti			 * and dropping through with the next nonspace.
1876144742Sharti			 * If it is a semi-colon and semiNL is TRUE,
1877144742Sharti			 * it will be recognized as a newline in the
1878144742Sharti			 * code below this...
1879144742Sharti			 */
1880144742Sharti			CURFILE->lineno++;
1881144742Sharti			lastc = ' ';
1882144742Sharti			while ((c = ParseReadc()) == ' ' || c == '\t') {
1883144742Sharti				continue;
1884144742Sharti			}
1885144742Sharti			if (c == EOF || c == '\n') {
1886144742Sharti				goto line_read;
1887144742Sharti			} else {
1888144026Sharti				/*
1889144742Sharti				 * Check for comments, semiNL's, etc. --
1890144742Sharti				 * easier than ParseUnreadc(c);
1891144742Sharti				 * continue;
1892144026Sharti				 */
1893144742Sharti				goto test_char;
1894144742Sharti			}
1895144742Sharti			/*NOTREACHED*/
1896144742Sharti			break;
1897144026Sharti
1898144742Sharti		  case ';':
1899144742Sharti			/*
1900144742Sharti			 * Semi-colon: Need to see if it should be
1901144742Sharti			 * interpreted as a newline
1902144742Sharti			 */
1903144742Sharti			if (semiNL) {
1904144026Sharti				/*
1905144742Sharti				 * To make sure the command that may
1906144742Sharti				 * be following this semi-colon begins
1907144742Sharti				 * with a tab, we push one back into the
1908144742Sharti				 * input stream. This will overwrite the
1909144742Sharti				 * semi-colon in the buffer. If there is
1910144742Sharti				 * no command following, this does no
1911144742Sharti				 * harm, since the newline remains in
1912144742Sharti				 * the buffer and the
1913144742Sharti				 * whole line is ignored.
1914144026Sharti				 */
1915144742Sharti				ParseUnreadc('\t');
1916144742Sharti				goto line_read;
1917144742Sharti			}
1918144742Sharti			break;
1919144742Sharti		  case '=':
1920144742Sharti			if (!semiNL) {
1921144742Sharti				/*
1922144742Sharti				 * Haven't seen a dependency operator
1923144742Sharti				 * before this, so this must be a
1924144742Sharti				 * variable assignment -- don't pay
1925144742Sharti				 * attention to dependency operators
1926144742Sharti				 * after this.
1927144742Sharti				 */
1928144742Sharti				ignDepOp = TRUE;
1929144742Sharti			} else if (lastc == ':' || lastc == '!') {
1930144742Sharti				/*
1931144742Sharti				 * Well, we've seen a dependency
1932144742Sharti				 * operator already, but it was the
1933144742Sharti				 * previous character, so this is really
1934144742Sharti				 * just an expanded variable assignment.
1935144742Sharti				 * Revert semi-colons to being just
1936144742Sharti				 * semi-colons again and ignore any more
1937144742Sharti				 * dependency operators.
1938144742Sharti				 *
1939144742Sharti				 * XXX: Note that a line like
1940144742Sharti				 * "foo : a:=b" will blow up, but who'd
1941144742Sharti				 * write a line like that anyway?
1942144742Sharti				 */
1943144742Sharti				ignDepOp = TRUE;
1944144742Sharti				semiNL = FALSE;
1945144742Sharti			}
1946144742Sharti			break;
1947144742Sharti		  case '#':
1948144742Sharti			if (!ignComment) {
1949144742Sharti				if (lastc != '\\') {
1950144026Sharti					/*
1951144742Sharti					 * If the character is a hash
1952144742Sharti					 * mark and it isn't escaped
1953144742Sharti					 * (or we're being compatible),
1954144742Sharti					 * the thing is a comment.
1955144742Sharti					 * Skip to the end of the line.
1956144026Sharti					 */
1957144742Sharti					do {
1958144742Sharti						c = ParseReadc();
1959144742Sharti					} while (c != '\n' && c != EOF);
1960144026Sharti					goto line_read;
1961144742Sharti				} else {
1962144026Sharti					/*
1963144742Sharti					 * Don't add the backslash.
1964144742Sharti					 * Just let the # get copied
1965144742Sharti					 * over.
1966144026Sharti					 */
1967144742Sharti					lastc = c;
1968144742Sharti					continue;
1969144026Sharti				}
1970144742Sharti			}
1971144742Sharti			break;
1972144026Sharti
1973144742Sharti		  case ':':
1974144742Sharti		  case '!':
1975144742Sharti			if (!ignDepOp) {
1976144742Sharti				/*
1977144742Sharti				 * A semi-colon is recognized as a
1978144742Sharti				 * newline only on dependency lines.
1979144742Sharti				 * Dependency lines are lines with a
1980144742Sharti				 * colon or an exclamation point.
1981144742Sharti				 * Ergo...
1982144742Sharti				 */
1983144742Sharti				semiNL = TRUE;
1984144742Sharti			}
1985144742Sharti			break;
1986144026Sharti
1987144742Sharti		  default:
1988144742Sharti			break;
1989144742Sharti		}
1990144742Sharti		/*
1991144742Sharti		 * Copy in the previous character (there may be none if this
1992144742Sharti		 * was the first character) and save this one in
1993144742Sharti		 * lastc.
1994144742Sharti		 */
1995144742Sharti		if (lastc != '\0')
1996144026Sharti			Buf_AddByte(buf, (Byte)lastc);
1997144742Sharti		lastc = c;
1998144742Sharti	}
1999144026Sharti  line_read:
2000144742Sharti	CURFILE->lineno++;
2001144026Sharti
2002144742Sharti	if (lastc != '\0') {
2003144742Sharti		Buf_AddByte(buf, (Byte)lastc);
2004144742Sharti	}
2005144742Sharti	Buf_AddByte(buf, (Byte)'\0');
2006144742Sharti	line = Buf_Peel(buf);
20071590Srgrimes
2008144742Sharti	/*
2009144742Sharti	 * Strip trailing blanks and tabs from the line.
2010144742Sharti	 * Do not strip a blank or tab that is preceded by
2011144742Sharti	 * a '\'
2012144742Sharti	 */
2013144742Sharti	ep = line;
2014144742Sharti	while (*ep)
2015144742Sharti		++ep;
2016144742Sharti	while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
2017144742Sharti		if (ep > line + 1 && ep[-2] == '\\')
2018144742Sharti			break;
2019144742Sharti		--ep;
2020144742Sharti	}
2021144742Sharti	*ep = 0;
2022144742Sharti
2023144742Sharti	if (line[0] == '\0') {
2024144742Sharti		/* empty line - just ignore */
2025144742Sharti		free(line);
2026144742Sharti		goto again;
2027144742Sharti	}
2028144742Sharti
2029144742Sharti	return (line);
20301590Srgrimes}
20311590Srgrimes
20321590Srgrimes/*-
20331590Srgrimes *-----------------------------------------------------------------------
20341590Srgrimes * ParseFinishLine --
20351590Srgrimes *	Handle the end of a dependency group.
20361590Srgrimes *
20371590Srgrimes * Results:
20381590Srgrimes *	Nothing.
20391590Srgrimes *
20401590Srgrimes * Side Effects:
20411590Srgrimes *	inLine set FALSE. 'targets' list destroyed.
20421590Srgrimes *
20431590Srgrimes *-----------------------------------------------------------------------
20441590Srgrimes */
20451590Srgrimesstatic void
2046104696SjmallettParseFinishLine(void)
20471590Srgrimes{
2048143372Sharti	const LstNode	*ln;
2049138232Sharti
2050143372Sharti	if (inLine) {
2051143372Sharti		LST_FOREACH(ln, &targets) {
2052143372Sharti			if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM)
2053143372Sharti				Suff_EndTransform(Lst_Datum(ln));
2054143372Sharti		}
2055143372Sharti		Lst_Destroy(&targets, ParseHasCommands);
2056143372Sharti		inLine = FALSE;
2057143372Sharti	}
20581590Srgrimes}
20591590Srgrimes
2060144894Sharti/**
2061144894Sharti * parse_include
2062144894Sharti *	Parse an .include directive and push the file onto the input stack.
2063144894Sharti *	The input is the line minus the .include. A file spec is a string
2064144894Sharti *	enclosed in <> or "". The former is looked for only in sysIncPath.
2065144894Sharti *	The latter in . and the directories specified by -I command line
2066144894Sharti *	options
2067144894Sharti */
2068144894Shartistatic void
2069144894Shartiparse_include(char *file, int code __unused, int lineno __unused)
2070144894Sharti{
2071144894Sharti	char	*fullname;	/* full pathname of file */
2072144894Sharti	char	endc;		/* the character which ends the file spec */
2073144894Sharti	char	*cp;		/* current position in file spec */
2074144894Sharti	Boolean	isSystem;	/* TRUE if makefile is a system makefile */
2075144894Sharti	char	*prefEnd, *Fname;
2076144894Sharti	char	*newName;
20778874Srgrimes
2078144894Sharti	/*
2079144894Sharti	 * Skip to delimiter character so we know where to look
2080144894Sharti	 */
2081144894Sharti	while (*file == ' ' || *file == '\t') {
2082144894Sharti		file++;
2083144894Sharti	}
2084144894Sharti
2085144894Sharti	if (*file != '"' && *file != '<') {
2086144894Sharti		Parse_Error(PARSE_FATAL,
2087144894Sharti		    ".include filename must be delimited by '\"' or '<'");
2088144894Sharti		return;
2089144894Sharti	}
2090144894Sharti
2091144894Sharti	/*
2092144894Sharti	 * Set the search path on which to find the include file based on the
2093144894Sharti	 * characters which bracket its name. Angle-brackets imply it's
2094144894Sharti	 * a system Makefile while double-quotes imply it's a user makefile
2095144894Sharti	 */
2096144894Sharti	if (*file == '<') {
2097144894Sharti		isSystem = TRUE;
2098144894Sharti		endc = '>';
2099144894Sharti	} else {
2100144894Sharti		isSystem = FALSE;
2101144894Sharti		endc = '"';
2102144894Sharti	}
2103144894Sharti
2104144894Sharti	/*
2105144894Sharti	* Skip to matching delimiter
2106144894Sharti	*/
2107144894Sharti	for (cp = ++file; *cp != endc; cp++) {
2108144894Sharti		if (*cp == '\0') {
2109144894Sharti			Parse_Error(PARSE_FATAL,
2110144894Sharti			    "Unclosed .include filename. '%c' expected", endc);
2111144894Sharti			return;
2112144894Sharti		}
2113144894Sharti	}
2114144894Sharti	*cp = '\0';
2115144894Sharti
2116144894Sharti	/*
2117144894Sharti	 * Substitute for any variables in the file name before trying to
2118144894Sharti	 * find the thing.
2119144894Sharti	 */
2120146027Sharti	file = Buf_Peel(Var_Subst(file, VAR_CMD, FALSE));
2121144894Sharti
2122144894Sharti	/*
2123144894Sharti	 * Now we know the file's name and its search path, we attempt to
2124144894Sharti	 * find the durn thing. A return of NULL indicates the file don't
2125144894Sharti	 * exist.
2126144894Sharti	 */
2127144894Sharti	if (!isSystem) {
2128144894Sharti		/*
2129144894Sharti		 * Include files contained in double-quotes are first searched
2130144894Sharti		 * for relative to the including file's location. We don't want
2131144894Sharti		 * to cd there, of course, so we just tack on the old file's
2132144894Sharti		 * leading path components and call Dir_FindFile to see if
2133144894Sharti		 * we can locate the beast.
2134144894Sharti		 */
2135144894Sharti
2136144894Sharti		/* Make a temporary copy of this, to be safe. */
2137144894Sharti		Fname = estrdup(CURFILE->fname);
2138144894Sharti
2139144894Sharti		prefEnd = strrchr(Fname, '/');
2140144894Sharti		if (prefEnd != NULL) {
2141144894Sharti			*prefEnd = '\0';
2142144894Sharti			if (file[0] == '/')
2143144894Sharti				newName = estrdup(file);
2144144894Sharti			else
2145144894Sharti				newName = str_concat(Fname, file, STR_ADDSLASH);
2146144894Sharti			fullname = Path_FindFile(newName, &parseIncPath);
2147144894Sharti			if (fullname == NULL) {
2148144894Sharti				fullname = Path_FindFile(newName,
2149144894Sharti				    &dirSearchPath);
2150144894Sharti			}
2151144894Sharti			free(newName);
2152144894Sharti			*prefEnd = '/';
2153144894Sharti		} else {
2154144894Sharti			fullname = NULL;
2155144894Sharti		}
2156144894Sharti		free(Fname);
2157144894Sharti	} else {
2158144894Sharti		fullname = NULL;
2159144894Sharti	}
2160144894Sharti
2161144894Sharti	if (fullname == NULL) {
2162144894Sharti		/*
2163144894Sharti		 * System makefile or makefile wasn't found in same directory as
2164144894Sharti		 * included makefile. Search for it first on the -I search path,
2165144894Sharti		 * then on the .PATH search path, if not found in a -I
2166144894Sharti		 * directory.
2167144894Sharti		 * XXX: Suffix specific?
2168144894Sharti		 */
2169144894Sharti		fullname = Path_FindFile(file, &parseIncPath);
2170144894Sharti		if (fullname == NULL) {
2171144894Sharti			fullname = Path_FindFile(file, &dirSearchPath);
2172144894Sharti		}
2173144894Sharti	}
2174144894Sharti
2175144894Sharti	if (fullname == NULL) {
2176144894Sharti		/*
2177144894Sharti		 * Still haven't found the makefile. Look for it on the system
2178144894Sharti		 * path as a last resort.
2179144894Sharti		 */
2180144894Sharti		fullname = Path_FindFile(file, &sysIncPath);
2181144894Sharti	}
2182144894Sharti
2183144894Sharti	if (fullname == NULL) {
2184144894Sharti		*cp = endc;
2185144894Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
2186144894Sharti		free(file);
2187144894Sharti		return;
2188144894Sharti	}
2189144894Sharti	free(file);
2190144894Sharti
2191144894Sharti	/*
2192144894Sharti	 * We set up the name of the file to be the absolute
2193144894Sharti	 * name of the include file so error messages refer to the right
2194144894Sharti	 * place.
2195144894Sharti	 */
2196144894Sharti	ParsePushInput(fullname, NULL, NULL, 0);
2197144894Sharti}
2198144894Sharti
2199144894Sharti/**
2200144894Sharti * parse_message
2201144894Sharti *	Parse a .warning or .error directive
2202144894Sharti *
2203144894Sharti *	The input is the line minus the ".error"/".warning".  We substitute
2204144894Sharti *	variables, print the message and exit(1) (for .error) or just print
2205144894Sharti *	a warning if the directive is malformed.
2206144894Sharti */
2207144894Shartistatic void
2208144894Shartiparse_message(char *line, int iserror, int lineno __unused)
2209144894Sharti{
2210144894Sharti
2211144894Sharti	if (!isspace((u_char)*line)) {
2212144894Sharti		Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s",
2213144894Sharti		    iserror ? "error" : "warning", line);
2214144894Sharti		return;
2215144894Sharti	}
2216144894Sharti
2217144894Sharti	while (isspace((u_char)*line))
2218144894Sharti		line++;
2219144894Sharti
2220146027Sharti	line = Buf_Peel(Var_Subst(line, VAR_GLOBAL, FALSE));
2221144894Sharti	Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line);
2222144894Sharti	free(line);
2223144894Sharti
2224144894Sharti	if (iserror) {
2225144894Sharti		/* Terminate immediately. */
2226144894Sharti		exit(1);
2227144894Sharti	}
2228144894Sharti}
2229144894Sharti
2230144894Sharti/**
2231144894Sharti * parse_undef
2232144894Sharti *	Parse an .undef directive.
2233144894Sharti */
2234144894Shartistatic void
2235144894Shartiparse_undef(char *line, int code __unused, int lineno __unused)
2236144894Sharti{
2237144894Sharti	char *cp;
2238144894Sharti
2239144894Sharti	while (isspace((u_char)*line))
2240144894Sharti		line++;
2241144894Sharti
2242144894Sharti	for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) {
2243144894Sharti		;
2244144894Sharti	}
2245144894Sharti	*cp = '\0';
2246144894Sharti
2247146027Sharti	cp = Buf_Peel(Var_Subst(line, VAR_CMD, FALSE));
2248144894Sharti	Var_Delete(cp, VAR_GLOBAL);
2249144894Sharti	free(cp);
2250144894Sharti}
2251144894Sharti
2252144894Sharti/**
2253144894Sharti * parse_for
2254144894Sharti *	Parse a .for directive.
2255144894Sharti */
2256144894Shartistatic void
2257144894Shartiparse_for(char *line, int code __unused, int lineno)
2258144894Sharti{
2259144894Sharti
2260144894Sharti	if (!For_For(line)) {
2261144894Sharti		/* syntax error */
2262144894Sharti		return;
2263144894Sharti	}
2264144894Sharti	line = NULL;
2265144894Sharti
2266144894Sharti	/*
2267144894Sharti	 * Skip after the matching endfor.
2268144894Sharti	 */
2269144894Sharti	do {
2270144894Sharti		free(line);
2271144894Sharti		line = ParseSkipLine(0, 1);
2272144894Sharti		if (line == NULL) {
2273144894Sharti			Parse_Error(PARSE_FATAL,
2274144894Sharti			    "Unexpected end of file in for loop.\n");
2275144894Sharti			return;
2276144894Sharti		}
2277144894Sharti	} while (For_Eval(line));
2278144894Sharti	free(line);
2279144894Sharti
2280144894Sharti	/* execute */
2281144894Sharti	For_Run(lineno);
2282144894Sharti}
2283144894Sharti
2284144894Sharti/**
2285144894Sharti * parse_endfor
2286144894Sharti *	Parse endfor. This may only happen if there was no matching .for.
2287144894Sharti */
2288144894Shartistatic void
2289144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused)
2290144894Sharti{
2291144894Sharti
2292144894Sharti	Parse_Error(PARSE_FATAL, "for-less endfor");
2293144894Sharti}
2294144894Sharti
2295144894Sharti/**
2296144894Sharti * parse_directive
2297144894Sharti *	Got a line starting with a '.'. Check if this is a directive
2298144894Sharti *	and parse it.
2299144894Sharti *
2300144894Sharti * return:
2301144894Sharti *	TRUE if line was a directive, FALSE otherwise.
2302144894Sharti */
2303144894Shartistatic Boolean
2304144894Shartiparse_directive(char *line)
2305144894Sharti{
2306144894Sharti	char	*start;
2307144894Sharti	char	*cp;
2308144894Sharti	int	dir;
2309144894Sharti
2310144894Sharti	/*
2311144894Sharti	 * Get the keyword:
2312144894Sharti	 *	.[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).*
2313144894Sharti	 * \1 is the keyword.
2314144894Sharti	 */
2315144894Sharti	for (start = line; isspace((u_char)*start); start++) {
2316144894Sharti		;
2317144894Sharti	}
2318144894Sharti
2319144894Sharti	if (!isalpha((u_char)*start)) {
2320144894Sharti		return (FALSE);
2321144894Sharti	}
2322144894Sharti
2323144894Sharti	cp = start + 1;
2324144894Sharti	while (isalnum((u_char)*cp) || *cp == '_') {
2325144894Sharti		cp++;
2326144894Sharti	}
2327144894Sharti
2328144894Sharti	dir = directive_hash(start, cp - start);
2329144894Sharti	if (dir < 0 || dir >= (int)NDIRECTS ||
2330144894Sharti	    (size_t)(cp - start) != strlen(directives[dir].name) ||
2331144894Sharti	    strncmp(start, directives[dir].name, cp - start) != 0) {
2332144894Sharti		/* not actually matched */
2333144894Sharti		return (FALSE);
2334144894Sharti	}
2335144894Sharti
2336144894Sharti	if (!skipLine || directives[dir].skip_flag)
2337144894Sharti		(*directives[dir].func)(cp, directives[dir].code,
2338144894Sharti		    CURFILE->lineno);
2339144894Sharti	return (TRUE);
2340144894Sharti}
2341144894Sharti
23421590Srgrimes/*-
23431590Srgrimes *---------------------------------------------------------------------
23441590Srgrimes * Parse_File --
23451590Srgrimes *	Parse a file into its component parts, incorporating it into the
23461590Srgrimes *	current dependency graph. This is the main function and controls
23471590Srgrimes *	almost every other function in this module
23481590Srgrimes *
23491590Srgrimes * Results:
23501590Srgrimes *	None
23511590Srgrimes *
23521590Srgrimes * Side Effects:
23531590Srgrimes *	Loads. Nodes are added to the list of all targets, nodes and links
23541590Srgrimes *	are added to the dependency graph. etc. etc. etc.
23551590Srgrimes *---------------------------------------------------------------------
23561590Srgrimes */
23571590Srgrimesvoid
2358144341ShartiParse_File(const char *name, FILE *stream)
23591590Srgrimes{
2360144026Sharti	char	*cp;	/* pointer into the line */
2361144026Sharti	char	*line;	/* the line we're working on */
23621590Srgrimes
2363144026Sharti	inLine = FALSE;
2364144026Sharti	fatals = 0;
23651590Srgrimes
2366144341Sharti	ParsePushInput(estrdup(name), stream, NULL, 0);
2367131456Seik
2368144742Sharti	while ((line = ParseReadLine()) != NULL) {
2369144894Sharti		if (*line == '.' && parse_directive(line + 1)) {
2370144894Sharti			/* directive consumed */
2371144894Sharti			goto nextLine;
2372144742Sharti		}
2373144894Sharti		if (skipLine || *line == '#') {
2374144894Sharti			/* Skipping .if block or comment. */
2375144742Sharti			goto nextLine;
2376144742Sharti		}
23778874Srgrimes
2378144742Sharti		if (*line == '\t') {
2379144742Sharti			/*
2380144742Sharti			 * If a line starts with a tab, it can only
2381144742Sharti			 * hope to be a creation command.
2382144742Sharti			 */
2383144742Sharti			for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
2384144742Sharti				continue;
2385144742Sharti			}
2386144742Sharti			if (*cp) {
2387144742Sharti				if (inLine) {
2388144742Sharti					LstNode	*ln;
2389144742Sharti					GNode	*gn;
2390143684Sharti
2391144742Sharti					/*
2392144742Sharti					 * So long as it's not a blank
2393144742Sharti					 * line and we're actually in a
2394144742Sharti					 * dependency spec, add the
2395144742Sharti					 * command to the list of
2396144742Sharti					 * commands of all targets in
2397144742Sharti					 * the dependency spec.
2398144742Sharti					 */
2399144742Sharti					LST_FOREACH(ln, &targets) {
2400144742Sharti						gn = Lst_Datum(ln);
2401144742Sharti
2402144026Sharti						/*
2403144742Sharti						 * if target already
2404144742Sharti						 * supplied, ignore
2405144742Sharti						 * commands
2406144026Sharti						 */
2407144742Sharti						if (!(gn->type & OP_HAS_COMMANDS))
2408144742Sharti							Lst_AtEnd(&gn->commands, cp);
2409144742Sharti						else
2410144742Sharti							Parse_Error(PARSE_WARNING, "duplicate script "
2411144742Sharti							    "for target \"%s\" ignored", gn->name);
2412144026Sharti					}
2413144742Sharti					continue;
2414144742Sharti				} else {
2415144742Sharti					Parse_Error(PARSE_FATAL,
2416144742Sharti					     "Unassociated shell command \"%s\"",
2417144742Sharti					     cp);
2418144026Sharti				}
2419144742Sharti			}
24201590Srgrimes#ifdef SYSVINCLUDE
2421144742Sharti		} else if (strncmp(line, "include", 7) == 0 &&
2422144742Sharti		    isspace((unsigned char)line[7]) &&
2423144742Sharti		    strchr(line, ':') == NULL) {
2424144742Sharti			/*
2425144742Sharti			 * It's an S3/S5-style "include".
2426144742Sharti			 */
2427144742Sharti			ParseTraditionalInclude(line + 7);
2428144742Sharti			goto nextLine;
24291590Srgrimes#endif
2430144742Sharti		} else if (Parse_IsVar(line)) {
2431144742Sharti			ParseFinishLine();
2432144742Sharti			Parse_DoVar(line, VAR_GLOBAL);
24338874Srgrimes
2434144742Sharti		} else {
2435144742Sharti			/*
2436144742Sharti			 * We now know it's a dependency line so it
2437144742Sharti			 * needs to have all variables expanded before
2438144742Sharti			 * being parsed. Tell the variable module to
2439144742Sharti			 * complain if some variable is undefined...
2440144742Sharti			 * To make life easier on novices, if the line
2441144742Sharti			 * is indented we first make sure the line has
2442144742Sharti			 * a dependency operator in it. If it doesn't
2443144742Sharti			 * have an operator and we're in a dependency
2444144742Sharti			 * line's script, we assume it's actually a
2445144742Sharti			 * shell command and add it to the current
2446144894Sharti			 * list of targets. XXX this comment seems wrong.
2447144742Sharti			 */
2448144742Sharti			cp = line;
2449144742Sharti			if (isspace((unsigned char)line[0])) {
2450144742Sharti				while (*cp != '\0' &&
2451144742Sharti				    isspace((unsigned char)*cp)) {
2452144742Sharti					cp++;
2453144026Sharti				}
2454144742Sharti				if (*cp == '\0') {
2455144742Sharti					goto nextLine;
2456144742Sharti				}
2457144742Sharti			}
24581590Srgrimes
2459144742Sharti			ParseFinishLine();
2460142457Sharti
2461146027Sharti			cp = Buf_Peel(Var_Subst(line, VAR_CMD, TRUE));
24628874Srgrimes
2463144742Sharti			free(line);
2464144742Sharti			line = cp;
2465144026Sharti
2466144742Sharti			/*
2467144742Sharti			 * Need a non-circular list for the target nodes
2468144742Sharti			 */
2469144742Sharti			Lst_Destroy(&targets, NOFREE);
2470144742Sharti			inLine = TRUE;
2471144026Sharti
2472144742Sharti			ParseDoDependency(line);
2473144026Sharti		}
2474144026Sharti
2475144742Sharti  nextLine:
2476144742Sharti		free(line);
2477144742Sharti	}
24788874Srgrimes
2479144026Sharti	ParseFinishLine();
24801590Srgrimes
24811590Srgrimes	/*
2482144026Sharti	 * Make sure conditionals are clean
24831590Srgrimes	 */
2484144026Sharti	Cond_End();
24851590Srgrimes
2486144026Sharti	if (fatals)
2487144026Sharti		errx(1, "fatal errors encountered -- cannot continue");
24881590Srgrimes}
24891590Srgrimes
24901590Srgrimes/*-
24911590Srgrimes *-----------------------------------------------------------------------
24921590Srgrimes * Parse_MainName --
24931590Srgrimes *	Return a Lst of the main target to create for main()'s sake. If
24941590Srgrimes *	no such target exists, we Punt with an obnoxious error message.
24951590Srgrimes *
24961590Srgrimes * Results:
24971590Srgrimes *	A Lst of the single node to create.
24981590Srgrimes *
24991590Srgrimes * Side Effects:
25001590Srgrimes *	None.
25011590Srgrimes *
25021590Srgrimes *-----------------------------------------------------------------------
25031590Srgrimes */
2504138916Shartivoid
2505138916ShartiParse_MainName(Lst *listmain)
25061590Srgrimes{
25071590Srgrimes
2508144026Sharti	if (mainNode == NULL) {
2509144026Sharti		Punt("no target to make.");
2510144026Sharti		/*NOTREACHED*/
2511144026Sharti	} else if (mainNode->type & OP_DOUBLEDEP) {
2512144026Sharti		Lst_AtEnd(listmain, mainNode);
2513144026Sharti		Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW);
2514144026Sharti	} else
2515144026Sharti		Lst_AtEnd(listmain, mainNode);
25161590Srgrimes}
2517