parse.c revision 144894
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 144894 2005-04-11 07:20:10Z harti $");
431590Srgrimes
441590Srgrimes/*-
451590Srgrimes * parse.c --
461590Srgrimes *	Functions to parse a makefile.
471590Srgrimes *
481590Srgrimes *	One function, Parse_Init, must be called before any functions
491590Srgrimes *	in this module are used. After that, the function Parse_File is the
501590Srgrimes *	main entry point and controls most of the other functions in this
511590Srgrimes *	module.
521590Srgrimes *
531590Srgrimes *	Most important structures are kept in Lsts. Directories for
541590Srgrimes *	the #include "..." function are kept in the 'parseIncPath' Lst, while
551590Srgrimes *	those for the #include <...> are kept in the 'sysIncPath' Lst. The
561590Srgrimes *	targets currently being defined are kept in the 'targets' Lst.
571590Srgrimes *
58126824Sru *	The variables 'curFile.fname' and 'curFile.lineno' are used to track
59126824Sru *	the name of the current file and the line number in that file so that
60126824Sru *	error messages can be more meaningful.
611590Srgrimes *
621590Srgrimes * Interface:
63144026Sharti *	Parse_Init	Initialization function which must be
64144026Sharti *			called before anything else in this module is used.
651590Srgrimes *
66144026Sharti *	Parse_File	Function used to parse a makefile. It must
67144026Sharti *			be given the name of the file, which should
68144026Sharti *			already have been opened, and a function
69144026Sharti *			to call to read a character from the file.
701590Srgrimes *
71144026Sharti *	Parse_IsVar	Returns TRUE if the given line is a
72144026Sharti *			variable assignment. Used by MainParseArgs
73144026Sharti *			to determine if an argument is a target
74144026Sharti *			or a variable assignment. Used internally
75144026Sharti *			for pretty much the same thing...
761590Srgrimes *
77144026Sharti *	Parse_Error	Function called when an error occurs in
78144026Sharti *			parsing. Used by the variable and
79144026Sharti *			conditional modules.
80144026Sharti *
81144026Sharti *	Parse_MainName	Returns a Lst of the main target to create.
821590Srgrimes */
831590Srgrimes
84144341Sharti#include <assert.h>
85141104Sharti#include <ctype.h>
861590Srgrimes#include <stdarg.h>
87141104Sharti#include <string.h>
88141104Sharti#include <stdlib.h>
8927644Scharnier#include <err.h>
90141104Sharti
91141104Sharti#include "arch.h"
92141104Sharti#include "buf.h"
93141104Sharti#include "cond.h"
94141104Sharti#include "config.h"
951590Srgrimes#include "dir.h"
96141104Sharti#include "for.h"
97141104Sharti#include "globals.h"
98141104Sharti#include "GNode.h"
991590Srgrimes#include "job.h"
100141104Sharti#include "make.h"
101141104Sharti#include "nonints.h"
102141104Sharti#include "parse.h"
1031590Srgrimes#include "pathnames.h"
104141104Sharti#include "str.h"
105141104Sharti#include "suff.h"
106141104Sharti#include "targ.h"
107141104Sharti#include "util.h"
108141104Sharti#include "var.h"
1091590Srgrimes
1101590Srgrimes/*
111144341Sharti * These values are returned by ParsePopInput to tell Parse_File whether to
1121590Srgrimes * CONTINUE parsing, i.e. it had only reached the end of an include file,
1131590Srgrimes * or if it's DONE.
1141590Srgrimes */
1151590Srgrimes#define	CONTINUE	1
1161590Srgrimes#define	DONE		0
117138916Sharti
118138916Sharti/* targets we're working on */
119138916Shartistatic Lst targets = Lst_Initializer(targets);
120138916Sharti
121144026Sharti/* true if currently in a dependency line or its commands */
122144026Shartistatic Boolean inLine;
1231590Srgrimes
124144026Shartistatic int fatals = 0;
1251590Srgrimes
126144026Sharti/*
127144026Sharti * The main target to create. This is the first target on the
128144026Sharti * first dependency line in the first makefile.
129144026Sharti */
130144026Shartistatic GNode *mainNode;
131126824Sru
132144341Sharti/*
133144341Sharti * Definitions for handling #include specifications
134144341Sharti */
135144341Shartistruct IFile {
136144341Sharti	char	*fname;		/* name of previous file */
137144341Sharti	int	lineno;		/* saved line number */
138144341Sharti	FILE	*F;		/* the open stream */
139144341Sharti	char	*str;		/* the string when parsing a string */
140144341Sharti	char	*ptr;		/* the current pointer when parsing a string */
141144341Sharti	TAILQ_ENTRY(IFile) link;/* stack the files */
142144341Sharti};
143144026Sharti
144138916Sharti/* stack of IFiles generated by * #includes */
145144341Shartistatic TAILQ_HEAD(, IFile) includes = TAILQ_HEAD_INITIALIZER(includes);
1461590Srgrimes
147144341Sharti/* access current file */
148144341Sharti#define	CURFILE	(TAILQ_FIRST(&includes))
149144341Sharti
150138916Sharti/* list of directories for "..." includes */
151144020Shartistruct Path parseIncPath = TAILQ_HEAD_INITIALIZER(parseIncPath);
152138916Sharti
153138916Sharti/* list of directories for <...> includes */
154144020Shartistruct Path sysIncPath = TAILQ_HEAD_INITIALIZER(sysIncPath);
155138916Sharti
156144026Sharti/*
1571590Srgrimes * specType contains the SPECial TYPE of the current target. It is
1581590Srgrimes * Not if the target is unspecial. If it *is* special, however, the children
1591590Srgrimes * are linked as children of the parent but not vice versa. This variable is
1601590Srgrimes * set in ParseDoDependency
1611590Srgrimes */
1621590Srgrimestypedef enum {
163144026Sharti	Begin,		/* .BEGIN */
164144026Sharti	Default,	/* .DEFAULT */
165144026Sharti	End,		/* .END */
166144026Sharti	Ignore,		/* .IGNORE */
167144026Sharti	Includes,	/* .INCLUDES */
168144026Sharti	Interrupt,	/* .INTERRUPT */
169144026Sharti	Libs,		/* .LIBS */
170144026Sharti	MFlags,		/* .MFLAGS or .MAKEFLAGS */
171144026Sharti	Main,		/* .MAIN and we don't have anyth. user-spec. to make */
172144026Sharti	NoExport,	/* .NOEXPORT */
173144026Sharti	Not,		/* Not special */
174144026Sharti	NotParallel,	/* .NOTPARALELL */
175144026Sharti	Null,		/* .NULL */
176144026Sharti	Order,		/* .ORDER */
177144026Sharti	Parallel,	/* .PARALLEL */
178144026Sharti	ExPath,		/* .PATH */
179144026Sharti	Phony,		/* .PHONY */
180144026Sharti	Posix,		/* .POSIX */
181144026Sharti	Precious,	/* .PRECIOUS */
182144026Sharti	ExShell,	/* .SHELL */
183144026Sharti	Silent,		/* .SILENT */
184144026Sharti	SingleShell,	/* .SINGLESHELL */
185144026Sharti	Suffixes,	/* .SUFFIXES */
186144026Sharti	Wait,		/* .WAIT */
187144026Sharti	Attribute	/* Generic attribute */
1881590Srgrimes} ParseSpecial;
1891590Srgrimes
1901590Srgrimesstatic ParseSpecial specType;
19118730Sstevestatic int waiting;
1921590Srgrimes
1931590Srgrimes/*
19469527Swill * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
1951590Srgrimes * seen, then set to each successive source on the line.
1961590Srgrimes */
197144026Shartistatic GNode *predecessor;
1981590Srgrimes
1991590Srgrimes/*
2001590Srgrimes * The parseKeywords table is searched using binary search when deciding
2011590Srgrimes * if a target or source is special. The 'spec' field is the ParseSpecial
2021590Srgrimes * type of the keyword ("Not" if the keyword isn't special as a target) while
2031590Srgrimes * the 'op' field is the operator to apply to the list of targets if the
2041590Srgrimes * keyword is used as a source ("0" if the keyword isn't special as a source)
2051590Srgrimes */
2061590Srgrimesstatic struct {
207144026Sharti	const char	*name;	/* Name of keyword */
208144026Sharti	ParseSpecial	spec;	/* Type when used as a target */
209144026Sharti	int		op;	/* Operator when used as a source */
2101590Srgrimes} parseKeywords[] = {
211144026Sharti	{ ".BEGIN",		Begin,		0 },
212144026Sharti	{ ".DEFAULT",		Default,	0 },
213144026Sharti	{ ".END",		End,		0 },
214144026Sharti	{ ".EXEC",		Attribute,	OP_EXEC },
215144026Sharti	{ ".IGNORE",		Ignore,		OP_IGNORE },
216144026Sharti	{ ".INCLUDES",		Includes,	0 },
217144026Sharti	{ ".INTERRUPT",		Interrupt,	0 },
218144026Sharti	{ ".INVISIBLE",		Attribute,	OP_INVISIBLE },
219144026Sharti	{ ".JOIN",		Attribute,	OP_JOIN },
220144026Sharti	{ ".LIBS",		Libs,		0 },
221144026Sharti	{ ".MAIN",		Main,		0 },
222144026Sharti	{ ".MAKE",		Attribute,	OP_MAKE },
223144026Sharti	{ ".MAKEFLAGS",		MFlags,		0 },
224144026Sharti	{ ".MFLAGS",		MFlags,		0 },
225144026Sharti	{ ".NOTMAIN",		Attribute,	OP_NOTMAIN },
226144026Sharti	{ ".NOTPARALLEL",	NotParallel,	0 },
227144026Sharti	{ ".NO_PARALLEL",	NotParallel,	0 },
228144026Sharti	{ ".NULL",		Null,		0 },
229144026Sharti	{ ".OPTIONAL",		Attribute,	OP_OPTIONAL },
230144026Sharti	{ ".ORDER",		Order,		0 },
231144026Sharti	{ ".PARALLEL",		Parallel,	0 },
232144026Sharti	{ ".PATH",		ExPath,		0 },
233144026Sharti	{ ".PHONY",		Phony,		OP_PHONY },
234144026Sharti	{ ".POSIX",		Posix,		0 },
235144026Sharti	{ ".PRECIOUS",		Precious,	OP_PRECIOUS },
236144026Sharti	{ ".RECURSIVE",		Attribute,	OP_MAKE },
237144026Sharti	{ ".SHELL",		ExShell,	0 },
238144026Sharti	{ ".SILENT",		Silent,		OP_SILENT },
239144026Sharti	{ ".SINGLESHELL",	SingleShell,	0 },
240144026Sharti	{ ".SUFFIXES",		Suffixes,	0 },
241144026Sharti	{ ".USE",		Attribute,	OP_USE },
242144026Sharti	{ ".WAIT",		Wait,		0 },
2431590Srgrimes};
2441590Srgrimes
245144894Sharti/*
246144894Sharti * Directive table. We use a hash table. This hash table has been generated
247144894Sharti * with mph which can be found on the usual GNU mirrors. If you change the
248144894Sharti * directives (adding, deleting, reordering) you need to create a new table
249144894Sharti * and hash function (directive_hash). The command line to generate the
250144894Sharti * table is:
251144894Sharti *
252144894Sharti * mph -d2 -m1 <tab | emitc -l -s
253144894Sharti *
254144894Sharti * Where tab is a file containing just the directive strings, one per line.
255144894Sharti *
256144894Sharti * While inporting the result of this the following changes have been made
257144894Sharti * to the generated code:
258144894Sharti *
259144894Sharti *	prefix the names of the g, T0 and T1 arrays with 'directive_'.
260144894Sharti *
261144894Sharti *	make the type of the tables 'const [un]signed char'.
262144894Sharti *
263144894Sharti *	make the hash function use the length for termination,
264144894Sharti *	not the trailing '\0'.
265144894Sharti */
266144894Shartistatic void parse_include(char *, int, int);
267144894Shartistatic void parse_message(char *, int, int);
268144894Shartistatic void parse_undef(char *, int, int);
269144894Shartistatic void parse_for(char *, int, int);
270144894Shartistatic void parse_endfor(char *, int, int);
271144894Sharti
272144894Shartistatic const signed char directive_g[] = {
273144894Sharti	16, 0, -1, 14, 5, 2, 2, -1, 0, 0,
274144894Sharti	-1, -1, 16, 11, -1, 15, -1, 14, 7, -1,
275144894Sharti	8, 6, 1, -1, -1, 0, 4, 6, -1, 0,
276144894Sharti	0, 2, 0, 13, -1, 14, -1, 0,
277144894Sharti};
278144894Sharti
279144894Shartistatic const unsigned char directive_T0[] = {
280144894Sharti	11, 25, 14, 30, 14, 26, 23, 15, 9, 37,
281144894Sharti	27, 32, 27, 1, 17, 27, 35, 13, 8, 22,
282144894Sharti	8, 28, 7,
283144894Sharti};
284144894Sharti
285144894Shartistatic const unsigned char directive_T1[] = {
286144894Sharti	19, 20, 31, 17, 29, 2, 7, 12, 1, 31,
287144894Sharti	11, 18, 11, 20, 10, 2, 15, 19, 4, 10,
288144894Sharti	13, 36, 3,
289144894Sharti};
290144894Sharti
291144894Shartistatic const struct directive {
292144894Sharti	const char	*name;
293144894Sharti	int		code;
294144894Sharti	Boolean		skip_flag;	/* execute even when skipped */
295144894Sharti	void		(*func)(char *, int, int);
296144894Sharti} directives[] = {
297144894Sharti	{ "elif",	COND_ELIF,	TRUE,	Cond_If },
298144894Sharti	{ "elifdef",	COND_ELIFDEF,	TRUE,	Cond_If },
299144894Sharti	{ "elifmake",	COND_ELIFMAKE,	TRUE,	Cond_If },
300144894Sharti	{ "elifndef",	COND_ELIFNDEF,	TRUE,	Cond_If },
301144894Sharti	{ "elifnmake",	COND_ELIFNMAKE,	TRUE,	Cond_If },
302144894Sharti	{ "else",	COND_ELSE,	TRUE,	Cond_Else },
303144894Sharti	{ "endfor",	0,		FALSE,	parse_endfor },
304144894Sharti	{ "endif",	COND_ENDIF,	TRUE,	Cond_Endif },
305144894Sharti	{ "error",	1,		FALSE,	parse_message },
306144894Sharti	{ "for",	0,		FALSE,	parse_for },
307144894Sharti	{ "if",		COND_IF,	TRUE,	Cond_If },
308144894Sharti	{ "ifdef",	COND_IFDEF,	TRUE,	Cond_If },
309144894Sharti	{ "ifmake",	COND_IFMAKE,	TRUE,	Cond_If },
310144894Sharti	{ "ifndef",	COND_IFNDEF,	TRUE,	Cond_If },
311144894Sharti	{ "ifnmake",	COND_IFNMAKE,	TRUE,	Cond_If },
312144894Sharti	{ "include",	0,		FALSE,	parse_include },
313144894Sharti	{ "undef",	0,		FALSE,	parse_undef },
314144894Sharti	{ "warning",	0,		FALSE,	parse_message },
315144894Sharti};
316144894Sharti#define	NDIRECTS	(sizeof(directives) / sizeof(directives[0]))
317144894Sharti
3181590Srgrimes/*-
3191590Srgrimes *----------------------------------------------------------------------
3201590Srgrimes * ParseFindKeyword --
3211590Srgrimes *	Look in the table of keywords for one matching the given string.
3221590Srgrimes *
3231590Srgrimes * Results:
3241590Srgrimes *	The index of the keyword, or -1 if it isn't there.
3251590Srgrimes *
3261590Srgrimes * Side Effects:
3271590Srgrimes *	None
3281590Srgrimes *----------------------------------------------------------------------
3291590Srgrimes */
3301590Srgrimesstatic int
331138232ShartiParseFindKeyword(char *str)
3321590Srgrimes{
333144026Sharti	int	start;
334144026Sharti	int	end;
335144026Sharti	int	cur;
336144026Sharti	int	diff;
3378874Srgrimes
338144026Sharti	start = 0;
339144026Sharti	end = (sizeof(parseKeywords) / sizeof(parseKeywords[0])) - 1;
3401590Srgrimes
341144026Sharti	do {
342144026Sharti		cur = start + (end - start) / 2;
343144026Sharti		diff = strcmp(str, parseKeywords[cur].name);
344144026Sharti		if (diff == 0) {
345144026Sharti			return (cur);
346144026Sharti		} else if (diff < 0) {
347144026Sharti			end = cur - 1;
348144026Sharti		} else {
349144026Sharti			start = cur + 1;
350144026Sharti		}
351144026Sharti	} while (start <= end);
3521590Srgrimes
353144026Sharti	return (-1);
3541590Srgrimes}
3551590Srgrimes
3561590Srgrimes/*-
3571590Srgrimes * Parse_Error  --
3581590Srgrimes *	Error message abort function for parsing. Prints out the context
3591590Srgrimes *	of the error (line number and file) as well as the message with
3601590Srgrimes *	two optional arguments.
3611590Srgrimes *
3621590Srgrimes * Results:
3631590Srgrimes *	None
3641590Srgrimes *
3651590Srgrimes * Side Effects:
3661590Srgrimes *	"fatals" is incremented if the level is PARSE_FATAL.
3671590Srgrimes */
3681590Srgrimes/* VARARGS */
3691590Srgrimesvoid
37098136SjmallettParse_Error(int type, const char *fmt, ...)
3711590Srgrimes{
3721590Srgrimes	va_list ap;
37393056Simp
3741590Srgrimes	va_start(ap, fmt);
375144745Sharti	if (CURFILE != NULL)
376144745Sharti		fprintf(stderr, "\"%s\", line %d: ",
377144745Sharti		    CURFILE->fname, CURFILE->lineno);
3781590Srgrimes	if (type == PARSE_WARNING)
379138232Sharti		fprintf(stderr, "warning: ");
380138232Sharti	vfprintf(stderr, fmt, ap);
3811590Srgrimes	va_end(ap);
382138232Sharti	fprintf(stderr, "\n");
383138232Sharti	fflush(stderr);
3841590Srgrimes	if (type == PARSE_FATAL)
3851590Srgrimes		fatals += 1;
3861590Srgrimes}
3871590Srgrimes
388144341Sharti/**
389144341Sharti * ParsePushInput
390144341Sharti *
391144341Sharti * Push a new input source onto the input stack. If ptr is NULL
392144341Sharti * the fullname is used to fopen the file. If it is not NULL,
393144341Sharti * ptr is assumed to point to the string to be parsed. If opening the
394144341Sharti * file fails, the fullname is freed.
395144341Sharti */
396144341Shartistatic void
397144341ShartiParsePushInput(char *fullname, FILE *fp, char *ptr, int lineno)
398144341Sharti{
399144341Sharti	struct IFile *nf;
400144341Sharti
401144341Sharti	nf = emalloc(sizeof(*nf));
402144341Sharti	nf->fname = fullname;
403144341Sharti	nf->lineno = lineno;
404144341Sharti
405144341Sharti	if (ptr == NULL) {
406144341Sharti		/* the input source is a file */
407144341Sharti		if ((nf->F = fp) == NULL) {
408144341Sharti			nf->F = fopen(fullname, "r");
409144341Sharti			if (nf->F == NULL) {
410144341Sharti				Parse_Error(PARSE_FATAL, "Cannot open %s",
411144341Sharti				    fullname);
412144341Sharti				free(fullname);
413144341Sharti				free(nf);
414144341Sharti				return;
415144341Sharti			}
416144341Sharti		}
417144341Sharti		nf->str = nf->ptr = NULL;
418144341Sharti		Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL);
419144341Sharti	} else {
420144341Sharti		nf->str = nf->ptr = ptr;
421144341Sharti		nf->F = NULL;
422144341Sharti	}
423144341Sharti	TAILQ_INSERT_HEAD(&includes, nf, link);
424144341Sharti}
425144341Sharti
426144341Sharti/**
427144341Sharti * ParsePopInput
428144341Sharti *	Called when EOF is reached in the current file. If we were reading
429144341Sharti *	an include file, the includes stack is popped and things set up
430144341Sharti *	to go back to reading the previous file at the previous location.
431144341Sharti *
432144341Sharti * Results:
433144341Sharti *	CONTINUE if there's more to do. DONE if not.
434144341Sharti *
435144341Sharti * Side Effects:
436144341Sharti *	The old curFile.F is closed. The includes list is shortened.
437144341Sharti *	curFile.lineno, curFile.F, and curFile.fname are changed if
438144341Sharti *	CONTINUE is returned.
439144341Sharti */
440144341Shartistatic int
441144341ShartiParsePopInput(void)
442144341Sharti{
443144341Sharti	struct IFile *ifile;	/* the state on the top of the includes stack */
444144341Sharti
445144341Sharti	assert(!TAILQ_EMPTY(&includes));
446144341Sharti
447144341Sharti	ifile = TAILQ_FIRST(&includes);
448144341Sharti	TAILQ_REMOVE(&includes, ifile, link);
449144341Sharti
450144341Sharti	free(ifile->fname);
451144341Sharti	if (ifile->F != NULL) {
452144341Sharti		fclose(ifile->F);
453144341Sharti		Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL);
454144341Sharti	}
455144341Sharti	if (ifile->str != NULL) {
456144341Sharti		free(ifile->str);
457144341Sharti	}
458144341Sharti	free(ifile);
459144341Sharti
460144341Sharti	return (TAILQ_EMPTY(&includes) ? DONE : CONTINUE);
461144341Sharti}
462144341Sharti
4631590Srgrimes/*-
4641590Srgrimes *---------------------------------------------------------------------
4651590Srgrimes * ParseLinkSrc  --
466143100Sharti *	Link the parent nodes to their new child. Used by
4671590Srgrimes *	ParseDoDependency. If the specType isn't 'Not', the parent
4681590Srgrimes *	isn't linked as a parent of the child.
4691590Srgrimes *
4701590Srgrimes * Side Effects:
471143100Sharti *	New elements are added to the parents lists of cgn and the
4721590Srgrimes *	children list of cgn. the unmade field of pgn is updated
4731590Srgrimes *	to reflect the additional child.
4741590Srgrimes *---------------------------------------------------------------------
4751590Srgrimes */
476143027Shartistatic void
477143027ShartiParseLinkSrc(Lst *parents, GNode *cgn)
4781590Srgrimes{
479143027Sharti	LstNode	*ln;
480143027Sharti	GNode *pgn;
481138232Sharti
482143027Sharti	LST_FOREACH(ln, parents) {
483143027Sharti		pgn = Lst_Datum(ln);
484143027Sharti		if (Lst_Member(&pgn->children, cgn) == NULL) {
485143027Sharti			Lst_AtEnd(&pgn->children, cgn);
486143027Sharti			if (specType == Not) {
487143027Sharti				Lst_AtEnd(&cgn->parents, pgn);
488143027Sharti			}
489143027Sharti			pgn->unmade += 1;
490143027Sharti		}
4911590Srgrimes	}
4921590Srgrimes}
4931590Srgrimes
4941590Srgrimes/*-
4951590Srgrimes *---------------------------------------------------------------------
4961590Srgrimes * ParseDoOp  --
497143684Sharti *	Apply the parsed operator to all target nodes. Used in
498143684Sharti *	ParseDoDependency once all targets have been found and their
499143684Sharti *	operator parsed. If the previous and new operators are incompatible,
500143684Sharti *	a major error is taken.
5011590Srgrimes *
5021590Srgrimes * Side Effects:
5031590Srgrimes *	The type field of the node is altered to reflect any new bits in
5041590Srgrimes *	the op.
5051590Srgrimes *---------------------------------------------------------------------
5061590Srgrimes */
507143684Shartistatic void
508143684ShartiParseDoOp(int op)
5091590Srgrimes{
510143684Sharti	GNode	*cohort;
511143684Sharti	LstNode	*ln;
512143684Sharti	GNode	*gn;
513138232Sharti
514143684Sharti	LST_FOREACH(ln, &targets) {
515143684Sharti		gn = Lst_Datum(ln);
5161590Srgrimes
517143684Sharti		/*
518143684Sharti		 * If the dependency mask of the operator and the node don't
519143684Sharti		 * match and the node has actually had an operator applied to
520143684Sharti		 * it before, and the operator actually has some dependency
521143684Sharti		 * information in it, complain.
522143684Sharti		 */
523143684Sharti		if ((op & OP_OPMASK) != (gn->type & OP_OPMASK) &&
524143684Sharti		    !OP_NOP(gn->type) && !OP_NOP(op)) {
525143684Sharti			Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
526143684Sharti			    gn->name);
527143684Sharti			return;
528143684Sharti		}
5298874Srgrimes
530143684Sharti		if (op == OP_DOUBLEDEP &&
531143684Sharti		    (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
532143684Sharti			/*
533143684Sharti			 * If the node was the object of a :: operator, we need
534143684Sharti			 * to create a new instance of it for the children and
535143684Sharti			 * commands on this dependency line. The new instance
536143684Sharti			 * is placed on the 'cohorts' list of the initial one
537143684Sharti			 * (note the initial one is not on its own cohorts list)
538143684Sharti			 * and the new instance is linked to all parents of the
539143684Sharti			 * initial instance.
540143684Sharti			 */
541143684Sharti			cohort = Targ_NewGN(gn->name);
5421590Srgrimes
543143684Sharti			/*
544143684Sharti			 * Duplicate links to parents so graph traversal is
545143684Sharti			 * simple. Perhaps some type bits should be duplicated?
546143684Sharti			 *
547143684Sharti			 * Make the cohort invisible as well to avoid
548143684Sharti			 * duplicating it into other variables. True, parents
549143684Sharti			 * of this target won't tend to do anything with their
550143684Sharti			 * local variables, but better safe than sorry.
551143684Sharti			 */
552143684Sharti			ParseLinkSrc(&gn->parents, cohort);
553143684Sharti			cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
554143684Sharti			Lst_AtEnd(&gn->cohorts, cohort);
5551590Srgrimes
556143684Sharti			/*
557143684Sharti			 * Replace the node in the targets list with the
558143684Sharti			 * new copy
559143684Sharti			 */
560143684Sharti			Lst_Replace(ln, cohort);
561143684Sharti			gn = cohort;
562143684Sharti		}
563143684Sharti		/*
564143684Sharti		 * We don't want to nuke any previous flags (whatever they were)
565143684Sharti		 * so we just OR the new operator into the old
566143684Sharti		 */
567143684Sharti		gn->type |= op;
568143684Sharti	}
5691590Srgrimes}
5701590Srgrimes
5711590Srgrimes/*-
5721590Srgrimes *---------------------------------------------------------------------
5731590Srgrimes * ParseDoSrc  --
5741590Srgrimes *	Given the name of a source, figure out if it is an attribute
5751590Srgrimes *	and apply it to the targets if it is. Else decide if there is
5761590Srgrimes *	some attribute which should be applied *to* the source because
5771590Srgrimes *	of some special target and apply it if so. Otherwise, make the
5781590Srgrimes *	source be a child of the targets in the list 'targets'
5791590Srgrimes *
5801590Srgrimes * Results:
5811590Srgrimes *	None
5821590Srgrimes *
5831590Srgrimes * Side Effects:
5841590Srgrimes *	Operator bits may be added to the list of targets or to the source.
5851590Srgrimes *	The targets may have a new source added to their lists of children.
5861590Srgrimes *---------------------------------------------------------------------
5871590Srgrimes */
5881590Srgrimesstatic void
589138512ShartiParseDoSrc(int tOp, char *src, Lst *allsrc)
5901590Srgrimes{
591144026Sharti	GNode	*gn = NULL;
5921590Srgrimes
593144026Sharti	if (*src == '.' && isupper ((unsigned char) src[1])) {
594144026Sharti		int keywd = ParseFindKeyword(src);
595144026Sharti		if (keywd != -1) {
596144026Sharti			if(parseKeywords[keywd].op != 0) {
597144026Sharti				ParseDoOp(parseKeywords[keywd].op);
598144026Sharti				return;
599144026Sharti			}
600144026Sharti			if (parseKeywords[keywd].spec == Wait) {
601144026Sharti				waiting++;
602144026Sharti				return;
603144026Sharti			}
604144026Sharti		}
6051590Srgrimes	}
60618730Ssteve
607144026Sharti	switch (specType) {
608144026Sharti	  case Main:
609144026Sharti		/*
610144026Sharti		 * If we have noted the existence of a .MAIN, it means we need
611144026Sharti		 * to add the sources of said target to the list of things
612144026Sharti		 * to create. The string 'src' is likely to be free, so we
613144026Sharti		 * must make a new copy of it. Note that this will only be
614144026Sharti		 * invoked if the user didn't specify a target on the command
615144026Sharti		 * line. This is to allow #ifmake's to succeed, or something...
616144026Sharti		 */
617144026Sharti		Lst_AtEnd(&create, estrdup(src));
618144026Sharti		/*
619144026Sharti		 * Add the name to the .TARGETS variable as well, so the user
620144026Sharti		 * can employ that, if desired.
621144026Sharti		 */
622144026Sharti		Var_Append(".TARGETS", src, VAR_GLOBAL);
623144026Sharti		return;
62418730Ssteve
625144026Sharti	  case Order:
626144026Sharti		/*
627144026Sharti		 * Create proper predecessor/successor links between the
628144026Sharti		 * previous source and the current one.
629144026Sharti		 */
630144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
631144026Sharti		if (predecessor != NULL) {
632144026Sharti			Lst_AtEnd(&predecessor->successors, gn);
633144026Sharti			Lst_AtEnd(&gn->preds, predecessor);
634144026Sharti		}
635144026Sharti		/*
636144026Sharti		 * The current source now becomes the predecessor for the next
637144026Sharti		 * one.
638144026Sharti		 */
639144026Sharti		predecessor = gn;
640144026Sharti		break;
64118730Ssteve
642144026Sharti	  default:
643144026Sharti		/*
644144026Sharti		 * If the source is not an attribute, we need to find/create
645144026Sharti		 * a node for it. After that we can apply any operator to it
646144026Sharti		 * from a special target or link it to its parents, as
647144026Sharti		 * appropriate.
648144026Sharti		 *
649144026Sharti		 * In the case of a source that was the object of a :: operator,
650144026Sharti		 * the attribute is applied to all of its instances (as kept in
651144026Sharti		 * the 'cohorts' list of the node) or all the cohorts are linked
652144026Sharti		 * to all the targets.
653144026Sharti		 */
654144026Sharti		gn = Targ_FindNode(src, TARG_CREATE);
6551590Srgrimes		if (tOp) {
656144026Sharti			gn->type |= tOp;
6571590Srgrimes		} else {
658144026Sharti			ParseLinkSrc(&targets, gn);
6591590Srgrimes		}
660144026Sharti		if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
661144026Sharti			GNode	*cohort;
662144026Sharti			LstNode	*ln;
663144026Sharti
664144026Sharti			for (ln = Lst_First(&gn->cohorts); ln != NULL;
665144026Sharti			    ln = Lst_Succ(ln)) {
666144026Sharti				cohort = Lst_Datum(ln);
667144026Sharti				if (tOp) {
668144026Sharti					cohort->type |= tOp;
669144026Sharti				} else {
670144026Sharti					ParseLinkSrc(&targets, cohort);
671144026Sharti				}
672144026Sharti			}
673144026Sharti		}
674144026Sharti		break;
6751590Srgrimes	}
67618730Ssteve
677144026Sharti	gn->order = waiting;
678144026Sharti	Lst_AtEnd(allsrc, gn);
679144026Sharti	if (waiting) {
680144026Sharti		LstNode	*ln;
681144026Sharti		GNode	*p;
6821590Srgrimes
683143684Sharti		/*
684144026Sharti		 * Check if GNodes needs to be synchronized.
685144026Sharti		 * This has to be when two nodes are on different sides of a
686144026Sharti		 * .WAIT directive.
687143684Sharti		 */
688144026Sharti		LST_FOREACH(ln, allsrc) {
689144026Sharti			p = Lst_Datum(ln);
690144026Sharti
691144026Sharti			if (p->order >= gn->order)
692144026Sharti				break;
693144026Sharti			/*
694144026Sharti			 * XXX: This can cause loops, and loops can cause
695144026Sharti			 * unmade targets, but checking is tedious, and the
696144026Sharti			 * debugging output can show the problem
697144026Sharti			 */
698144026Sharti			Lst_AtEnd(&p->successors, gn);
699144026Sharti			Lst_AtEnd(&gn->preds, p);
700144026Sharti		}
701143684Sharti	}
7021590Srgrimes}
7031590Srgrimes
704138232Sharti
7051590Srgrimes/*-
7061590Srgrimes *---------------------------------------------------------------------
7071590Srgrimes * ParseDoDependency  --
7081590Srgrimes *	Parse the dependency line in line.
7091590Srgrimes *
7101590Srgrimes * Results:
7111590Srgrimes *	None
7121590Srgrimes *
7131590Srgrimes * Side Effects:
7141590Srgrimes *	The nodes of the sources are linked as children to the nodes of the
7151590Srgrimes *	targets. Some nodes may be created.
7161590Srgrimes *
7171590Srgrimes *	We parse a dependency line by first extracting words from the line and
7181590Srgrimes * finding nodes in the list of all targets with that name. This is done
7191590Srgrimes * until a character is encountered which is an operator character. Currently
7201590Srgrimes * these are only ! and :. At this point the operator is parsed and the
7211590Srgrimes * pointer into the line advanced until the first source is encountered.
722144026Sharti *	The parsed operator is applied to each node in the 'targets' list,
7231590Srgrimes * which is where the nodes found for the targets are kept, by means of
7241590Srgrimes * the ParseDoOp function.
7251590Srgrimes *	The sources are read in much the same way as the targets were except
7261590Srgrimes * that now they are expanded using the wildcarding scheme of the C-Shell
7271590Srgrimes * and all instances of the resulting words in the list of all targets
7281590Srgrimes * are found. Each of the resulting nodes is then linked to each of the
7291590Srgrimes * targets as one of its children.
7301590Srgrimes *	Certain targets are handled specially. These are the ones detailed
7311590Srgrimes * by the specType variable.
7321590Srgrimes *	The storing of transformation rules is also taken care of here.
7331590Srgrimes * A target is recognized as a transformation rule by calling
7341590Srgrimes * Suff_IsTransform. If it is a transformation rule, its node is gotten
7351590Srgrimes * from the suffix module via Suff_AddTransform rather than the standard
7361590Srgrimes * Targ_FindNode in the target module.
7371590Srgrimes *---------------------------------------------------------------------
7381590Srgrimes */
7391590Srgrimesstatic void
740141270ShartiParseDoDependency(char *line)
7411590Srgrimes{
742144026Sharti	char	*cp;	/* our current position */
743144026Sharti	GNode	*gn;	/* a general purpose temporary node */
744144026Sharti	int	op;	/* the operator on the line */
745144026Sharti	char	savec;	/* a place to save a character */
746144026Sharti	Lst	paths;	/* Search paths to alter when parsing .PATH targets */
747144026Sharti	int	tOp;	/* operator from special target */
748144026Sharti	LstNode	*ln;
7491590Srgrimes
750144026Sharti	tOp = 0;
7511590Srgrimes
752144026Sharti	specType = Not;
753144026Sharti	waiting = 0;
754144026Sharti	Lst_Init(&paths);
7551590Srgrimes
756144026Sharti	do {
757144026Sharti		for (cp = line;
758144026Sharti		    *cp && !isspace((unsigned char)*cp) && *cp != '(';
759144026Sharti		    cp++) {
760144026Sharti			if (*cp == '$') {
761144026Sharti				/*
762144026Sharti				 * Must be a dynamic source (would have been
763144026Sharti				 * expanded otherwise), so call the Var module
764144026Sharti				 * to parse the puppy so we can safely advance
765144026Sharti				 * beyond it...There should be no errors in this
766144026Sharti				 * as they would have been discovered in the
767144026Sharti				 * initial Var_Subst and we wouldn't be here.
768144026Sharti				 */
769144026Sharti				size_t	length = 0;
770144026Sharti				Boolean	freeIt;
771144026Sharti				char	*result;
7721590Srgrimes
773144026Sharti				result = Var_Parse(cp, VAR_CMD, TRUE,
774144026Sharti				    &length, &freeIt);
7751590Srgrimes
776144026Sharti				if (freeIt) {
777144026Sharti					free(result);
778144026Sharti				}
779144026Sharti				cp += length - 1;
780102178Sru
781144026Sharti			} else if (*cp == '!' || *cp == ':') {
782144026Sharti				/*
783144026Sharti				 * We don't want to end a word on ':' or '!' if
784144026Sharti				 * there is a better match later on in the
785144026Sharti				 * string (greedy matching).
786144026Sharti				 * This allows the user to have targets like:
787144026Sharti				 *    fie::fi:fo: fum
788144026Sharti				 *    foo::bar:
789144026Sharti				 * where "fie::fi:fo" and "foo::bar" are the
790144026Sharti				 * targets. In real life this is used for perl5
791144026Sharti				 * library man pages where "::" separates an
792144026Sharti				 * object from its class. Ie:
793144026Sharti				 * "File::Spec::Unix". This behaviour is also
794144026Sharti				 * consistent with other versions of make.
795144026Sharti				 */
796144026Sharti				char *p = cp + 1;
797102178Sru
798144026Sharti				if (*cp == ':' && *p == ':')
799144026Sharti					p++;
800102178Sru
801144026Sharti				/* Found the best match already. */
802144026Sharti				if (*p == '\0' || isspace(*p))
803144026Sharti					break;
804102178Sru
805144026Sharti				p += strcspn(p, "!:");
8068874Srgrimes
807144026Sharti				/* No better match later on... */
808144026Sharti				if (*p == '\0')
809144026Sharti					break;
810144026Sharti			}
811144026Sharti			continue;
8121590Srgrimes		}
813144026Sharti		if (*cp == '(') {
814144026Sharti			/*
815144026Sharti			 * Archives must be handled specially to make sure the
816144026Sharti			 * OP_ARCHV flag is set in their 'type' field, for one
817144026Sharti			 * thing, and because things like "archive(file1.o
818144026Sharti			 * file2.o file3.o)" are permissible. Arch_ParseArchive
819144026Sharti			 * will set 'line' to be the first non-blank after the
820144026Sharti			 * archive-spec. It creates/finds nodes for the members
821144026Sharti			 * and places them on the given list, returning SUCCESS
822144026Sharti			 * if all went well and FAILURE if there was an error in
823144026Sharti			 * the specification. On error, line should remain
824144026Sharti			 * untouched.
825144026Sharti			 */
826144026Sharti			if (Arch_ParseArchive(&line, &targets, VAR_CMD) !=
827144026Sharti			    SUCCESS) {
828144026Sharti				Parse_Error(PARSE_FATAL,
829144026Sharti				    "Error in archive specification: \"%s\"",
830144026Sharti				    line);
831144026Sharti				return;
832144026Sharti			} else {
833144026Sharti				cp = line;
834144026Sharti				continue;
835144026Sharti			}
836144026Sharti		}
837144026Sharti		savec = *cp;
8388874Srgrimes
839144026Sharti		if (!*cp) {
840144026Sharti			/*
841144026Sharti			 * Ending a dependency line without an operator is a				 * Bozo no-no. As a heuristic, this is also often
842144026Sharti			 * triggered by undetected conflicts from cvs/rcs
843144026Sharti			 * merges.
844144026Sharti			 */
845144026Sharti			if (strncmp(line, "<<<<<<", 6) == 0 ||
846144026Sharti			    strncmp(line, "======", 6) == 0 ||
847144026Sharti			    strncmp(line, ">>>>>>", 6) == 0) {
848144026Sharti				Parse_Error(PARSE_FATAL, "Makefile appears to "
849144026Sharti				    "contain unresolved cvs/rcs/??? merge "
850144026Sharti				    "conflicts");
851144026Sharti			} else
852144026Sharti				Parse_Error(PARSE_FATAL, "Need an operator");
853144026Sharti			return;
854144026Sharti		}
855144026Sharti		*cp = '\0';
8561590Srgrimes		/*
857144026Sharti		 * Have a word in line. See if it's a special target and set
858144026Sharti		 * specType to match it.
8591590Srgrimes		 */
860144026Sharti		if (*line == '.' && isupper((unsigned char)line[1])) {
861144026Sharti			/*
862144026Sharti			 * See if the target is a special target that must have
863144026Sharti			 * it or its sources handled specially.
864144026Sharti			 */
865144026Sharti			int keywd = ParseFindKeyword(line);
866144026Sharti
867144026Sharti			if (keywd != -1) {
868144026Sharti				if (specType == ExPath &&
869144026Sharti				    parseKeywords[keywd].spec != ExPath) {
870144026Sharti					Parse_Error(PARSE_FATAL,
871144026Sharti					    "Mismatched special targets");
872144026Sharti					return;
873144026Sharti				}
874144026Sharti
875144026Sharti				specType = parseKeywords[keywd].spec;
876144026Sharti				tOp = parseKeywords[keywd].op;
877144026Sharti
878144026Sharti				/*
879144026Sharti				 * Certain special targets have special
880144026Sharti				 * semantics:
881144026Sharti				 *  .PATH	Have to set the dirSearchPath
882144026Sharti				 *		variable too
883144026Sharti				 *  .MAIN	Its sources are only used if
884144026Sharti				 *		nothing has been specified to
885144026Sharti				 *		create.
886144026Sharti				 *  .DEFAULT    Need to create a node to hang
887144026Sharti				 *		commands on, but we don't want
888144026Sharti				 *		it in the graph, nor do we want
889144026Sharti				 *		it to be the Main Target, so we
890144026Sharti				 *		create it, set OP_NOTMAIN and
891144026Sharti				 *		add it to the list, setting
892144026Sharti				 *		DEFAULT to the new node for
893144026Sharti				 *		later use. We claim the node is
894144026Sharti				 *		A transformation rule to make
895144026Sharti				 *		life easier later, when we'll
896144026Sharti				 *		use Make_HandleUse to actually
897144026Sharti				 *		apply the .DEFAULT commands.
898144026Sharti				 *  .PHONY	The list of targets
899144026Sharti				 *  .BEGIN
900144026Sharti				 *  .END
901144026Sharti				 *  .INTERRUPT	Are not to be considered the
902144026Sharti				 *		main target.
903144026Sharti				 *  .NOTPARALLEL Make only one target at a time.
904144026Sharti				 *  .SINGLESHELL Create a shell for each
905144026Sharti				 *		command.
906144026Sharti				 *  .ORDER	Must set initial predecessor
907144026Sharti				 *		to NULL
908144026Sharti				 */
909144026Sharti				switch (specType) {
910144026Sharti				  case ExPath:
911144026Sharti					Lst_AtEnd(&paths, &dirSearchPath);
912144026Sharti					break;
913144026Sharti				  case Main:
914144026Sharti					if (!Lst_IsEmpty(&create)) {
915144026Sharti						specType = Not;
916144026Sharti					}
917144026Sharti					break;
918144026Sharti				  case Begin:
919144026Sharti				  case End:
920144026Sharti				  case Interrupt:
921144026Sharti					gn = Targ_FindNode(line, TARG_CREATE);
922144026Sharti					gn->type |= OP_NOTMAIN;
923144026Sharti					Lst_AtEnd(&targets, gn);
924144026Sharti					break;
925144026Sharti				  case Default:
926144026Sharti					gn = Targ_NewGN(".DEFAULT");
927144026Sharti					gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
928144026Sharti					Lst_AtEnd(&targets, gn);
929144026Sharti					DEFAULT = gn;
930144026Sharti					break;
931144026Sharti				  case NotParallel:
932144026Sharti					maxJobs = 1;
933144026Sharti					break;
934144026Sharti				  case SingleShell:
935144026Sharti					compatMake = 1;
936144026Sharti					break;
937144026Sharti				  case Order:
938144026Sharti					predecessor = NULL;
939144026Sharti					break;
940144026Sharti				  default:
941144026Sharti					break;
942144026Sharti				}
943144026Sharti
944144026Sharti			} else if (strncmp(line, ".PATH", 5) == 0) {
945144026Sharti				/*
946144026Sharti				 * .PATH<suffix> has to be handled specially.
947144026Sharti				 * Call on the suffix module to give us a path
948144026Sharti				 * to modify.
949144026Sharti				 */
950144026Sharti				struct Path *path;
951144026Sharti
952144026Sharti				specType = ExPath;
953144026Sharti				path = Suff_GetPath(&line[5]);
954144026Sharti				if (path == NULL) {
955144026Sharti					Parse_Error(PARSE_FATAL, "Suffix '%s' "
956144026Sharti					    "not defined (yet)", &line[5]);
957144026Sharti					return;
958144026Sharti				} else
959144026Sharti					Lst_AtEnd(&paths, path);
9601590Srgrimes			}
9611590Srgrimes		}
962144026Sharti
9631590Srgrimes		/*
964144026Sharti		 * Have word in line. Get or create its node and stick it at
965144026Sharti		 * the end of the targets list
9661590Srgrimes		 */
967144029Sharti		if (specType == Not && *line != '\0') {
9688874Srgrimes
969144026Sharti			/* target names to be found and added to targets list */
970144026Sharti			Lst curTargs = Lst_Initializer(curTargs);
9718874Srgrimes
972144026Sharti			if (Dir_HasWildcards(line)) {
973144026Sharti				/*
974144026Sharti				 * Targets are to be sought only in the current
975144026Sharti				 * directory, so create an empty path for the
976144026Sharti				 * thing. Note we need to use Path_Clear in the
977144026Sharti				 * destruction of the path as the Dir module
978144026Sharti				 * could have added a directory to the path...
979144026Sharti				 */
980144026Sharti				struct Path emptyPath =
981144026Sharti				    TAILQ_HEAD_INITIALIZER(emptyPath);
982138916Sharti
983144026Sharti				Path_Expand(line, &emptyPath, &curTargs);
984144026Sharti				Path_Clear(&emptyPath);
9858874Srgrimes
986144026Sharti			} else {
987144026Sharti				/*
988144026Sharti				 * No wildcards, but we want to avoid code
989144026Sharti				 * duplication, so create a list with the word
990144026Sharti				 * on it.
991144026Sharti				 */
992144026Sharti				Lst_AtEnd(&curTargs, line);
993144026Sharti			}
9948874Srgrimes
995144026Sharti			while (!Lst_IsEmpty(&curTargs)) {
996144026Sharti				char	*targName = Lst_DeQueue(&curTargs);
997144026Sharti
998144026Sharti				if (!Suff_IsTransform (targName)) {
999144026Sharti					gn = Targ_FindNode(targName,
1000144026Sharti					    TARG_CREATE);
1001144026Sharti				} else {
1002144026Sharti					gn = Suff_AddTransform(targName);
1003144026Sharti				}
1004144026Sharti
1005144026Sharti				Lst_AtEnd(&targets, gn);
1006144026Sharti			}
1007144026Sharti		} else if (specType == ExPath && *line != '.' && *line != '\0'){
1008144026Sharti			Parse_Error(PARSE_WARNING, "Extra target (%s) ignored",
1009144026Sharti			    line);
1010144026Sharti		}
1011144026Sharti
1012144026Sharti		*cp = savec;
10131590Srgrimes		/*
1014144026Sharti		 * If it is a special type and not .PATH, it's the only
1015144026Sharti		 * target we allow on this line...
10161590Srgrimes		 */
1017144026Sharti		if (specType != Not && specType != ExPath) {
1018144026Sharti			Boolean warnFlag = FALSE;
10198874Srgrimes
1020144029Sharti			while (*cp != '!' && *cp != ':' && *cp) {
1021144026Sharti				if (*cp != ' ' && *cp != '\t') {
1022144026Sharti					warnFlag = TRUE;
1023144026Sharti				}
1024144026Sharti				cp++;
1025144026Sharti			}
1026144026Sharti			if (warnFlag) {
1027144026Sharti				Parse_Error(PARSE_WARNING,
1028144026Sharti				    "Extra target ignored");
1029144026Sharti			}
10301590Srgrimes		} else {
1031144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1032144026Sharti				cp++;
1033144026Sharti			}
10341590Srgrimes		}
1035144026Sharti		line = cp;
1036144029Sharti	} while (*line != '!' && *line != ':' && *line);
10378874Srgrimes
1038144026Sharti	if (!Lst_IsEmpty(&targets)) {
1039144026Sharti		switch (specType) {
1040144026Sharti		  default:
1041144026Sharti			Parse_Error(PARSE_WARNING, "Special and mundane "
1042144026Sharti			    "targets don't mix. Mundane ones ignored");
1043144026Sharti			break;
1044144026Sharti		  case Default:
1045144026Sharti		  case Begin:
1046144026Sharti		  case End:
1047144026Sharti		  case Interrupt:
1048144026Sharti			/*
1049144026Sharti			 * These four create nodes on which to hang commands, so
1050144026Sharti			 * targets shouldn't be empty...
1051144026Sharti			 */
1052144026Sharti		  case Not:
1053144026Sharti			/*
1054144026Sharti			 * Nothing special here -- targets can be empty if it
1055144026Sharti			 * wants.
1056144026Sharti			 */
1057144026Sharti			break;
1058144026Sharti		}
10591590Srgrimes	}
10608874Srgrimes
10611590Srgrimes	/*
1062144026Sharti	 * Have now parsed all the target names. Must parse the operator next.
1063144026Sharti	 * The result is left in op.
10641590Srgrimes	 */
1065144026Sharti	if (*cp == '!') {
1066144026Sharti		op = OP_FORCE;
1067144026Sharti	} else if (*cp == ':') {
1068144026Sharti		if (cp[1] == ':') {
1069144026Sharti			op = OP_DOUBLEDEP;
1070144026Sharti			cp++;
1071144026Sharti		} else {
1072144026Sharti			op = OP_DEPENDS;
10731590Srgrimes		}
10741590Srgrimes	} else {
1075144026Sharti		Parse_Error(PARSE_FATAL, "Missing dependency operator");
1076144026Sharti		return;
1077144026Sharti	}
1078144026Sharti
1079144026Sharti	cp++;			/* Advance beyond operator */
1080144026Sharti
1081144026Sharti	ParseDoOp(op);
1082144026Sharti
1083144026Sharti	/*
1084144026Sharti	 * Get to the first source
1085144026Sharti	 */
1086144026Sharti	while (*cp && isspace((unsigned char)*cp)) {
10871590Srgrimes		cp++;
10881590Srgrimes	}
10891590Srgrimes	line = cp;
10901590Srgrimes
1091144026Sharti	/*
1092144026Sharti	 * Several special targets take different actions if present with no
1093144026Sharti	 * sources:
1094144026Sharti	 *	a .SUFFIXES line with no sources clears out all old suffixes
1095144026Sharti	 *	a .PRECIOUS line makes all targets precious
1096144026Sharti	 *	a .IGNORE line ignores errors for all targets
1097144026Sharti	 *	a .SILENT line creates silence when making all targets
1098144026Sharti	 *	a .PATH removes all directories from the search path(s).
1099144026Sharti	 */
1100144026Sharti	if (!*line) {
1101144026Sharti		switch (specType) {
1102144026Sharti		  case Suffixes:
1103144026Sharti			Suff_ClearSuffixes();
1104144026Sharti			break;
1105144026Sharti		  case Precious:
1106144026Sharti			allPrecious = TRUE;
1107144026Sharti			break;
1108144026Sharti		  case Ignore:
1109144026Sharti			ignoreErrors = TRUE;
1110144026Sharti			break;
1111144026Sharti		  case Silent:
1112144026Sharti			beSilent = TRUE;
1113144026Sharti			break;
1114144026Sharti		  case ExPath:
1115144026Sharti			LST_FOREACH(ln, &paths)
1116144026Sharti			Path_Clear(Lst_Datum(ln));
1117144026Sharti			break;
1118144026Sharti		  case Posix:
1119144026Sharti			Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1120144026Sharti			break;
1121144026Sharti		  default:
1122144026Sharti			break;
1123144026Sharti		}
1124144026Sharti
1125144026Sharti	} else if (specType == MFlags) {
11261590Srgrimes		/*
1127144026Sharti		 * Call on functions in main.c to deal with these arguments and
1128144026Sharti		 * set the initial character to a null-character so the loop to
1129144026Sharti		 * get sources won't get anything
11301590Srgrimes		 */
1131144026Sharti		Main_ParseArgLine(line, 0);
1132144026Sharti		*line = '\0';
11331590Srgrimes
1134144026Sharti	} else if (specType == ExShell) {
1135144026Sharti		if (Job_ParseShell(line) != SUCCESS) {
1136144026Sharti			Parse_Error(PARSE_FATAL,
1137144026Sharti			    "improper shell specification");
1138144026Sharti			return;
1139144026Sharti		}
1140144026Sharti		*line = '\0';
1141144026Sharti
1142144029Sharti	} else if (specType == NotParallel || specType == SingleShell) {
1143144026Sharti		*line = '\0';
11441590Srgrimes	}
11451590Srgrimes
1146144026Sharti	/*
1147144026Sharti	* NOW GO FOR THE SOURCES
1148144026Sharti	*/
1149144029Sharti	if (specType == Suffixes || specType == ExPath ||
1150144029Sharti	    specType == Includes || specType == Libs ||
1151144029Sharti	    specType == Null) {
1152144026Sharti		while (*line) {
1153144026Sharti			/*
1154144026Sharti			 * If the target was one that doesn't take files as its
1155144026Sharti			 * sources but takes something like suffixes, we take
1156144026Sharti			 * each space-separated word on the line as a something
1157144026Sharti			 * and deal with it accordingly.
1158144026Sharti			 *
1159144026Sharti			 * If the target was .SUFFIXES, we take each source as
1160144026Sharti			 * a suffix and add it to the list of suffixes
1161144026Sharti			 * maintained by the Suff module.
1162144026Sharti			 *
1163144026Sharti			 * If the target was a .PATH, we add the source as a
1164144026Sharti			 * directory to search on the search path.
1165144026Sharti			 *
1166144026Sharti			 * If it was .INCLUDES, the source is taken to be the
1167144026Sharti			 * suffix of files which will be #included and whose
1168144026Sharti			 * search path should be present in the .INCLUDES
1169144026Sharti			 * variable.
1170144026Sharti			 *
1171144026Sharti			 * If it was .LIBS, the source is taken to be the
1172144026Sharti			 * suffix of files which are considered libraries and
1173144026Sharti			 * whose search path should be present in the .LIBS
1174144026Sharti			 * variable.
1175144026Sharti			 *
1176144026Sharti			 * If it was .NULL, the source is the suffix to use
1177144026Sharti			 * when a file has no valid suffix.
1178144026Sharti			 */
1179144026Sharti			char  savech;
1180144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1181144026Sharti				cp++;
1182144026Sharti			}
1183144026Sharti			savech = *cp;
1184144026Sharti			*cp = '\0';
1185144026Sharti			switch (specType) {
1186144026Sharti			  case Suffixes:
1187144026Sharti				Suff_AddSuffix(line);
1188144026Sharti				break;
1189144026Sharti			  case ExPath:
1190144026Sharti				LST_FOREACH(ln, &paths)
1191144026Sharti					Path_AddDir(Lst_Datum(ln), line);
1192144026Sharti				break;
1193144026Sharti			  case Includes:
1194144026Sharti				Suff_AddInclude(line);
1195144026Sharti				break;
1196144026Sharti			  case Libs:
1197144026Sharti				Suff_AddLib(line);
1198144026Sharti				break;
1199144026Sharti			  case Null:
1200144026Sharti				Suff_SetNull(line);
1201144026Sharti				break;
1202144026Sharti			  default:
1203144026Sharti				break;
1204144026Sharti			}
1205144026Sharti			*cp = savech;
1206144026Sharti			if (savech != '\0') {
1207144026Sharti				cp++;
1208144026Sharti			}
1209144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1210144026Sharti				cp++;
1211144026Sharti			}
1212144026Sharti			line = cp;
1213144026Sharti		}
1214144026Sharti		Lst_Destroy(&paths, NOFREE);
12151590Srgrimes
1216144026Sharti	} else {
1217144026Sharti		/* list of sources in order */
1218144026Sharti		Lst curSrcs = Lst_Initializer(curSrc);
12191590Srgrimes
1220144026Sharti		while (*line) {
1221144026Sharti			/*
1222144026Sharti			 * The targets take real sources, so we must beware of
1223144026Sharti			 * archive specifications (i.e. things with left
1224144026Sharti			 * parentheses in them) and handle them accordingly.
1225144026Sharti			 */
1226144026Sharti			while (*cp && !isspace((unsigned char)*cp)) {
1227144026Sharti				if (*cp == '(' && cp > line && cp[-1] != '$') {
1228144026Sharti					/*
1229144026Sharti					 * Only stop for a left parenthesis if
1230144026Sharti					 * it isn't at the start of a word
1231144026Sharti					 * (that'll be for variable changes
1232144026Sharti					 * later) and isn't preceded by a dollar
1233144026Sharti					 * sign (a dynamic source).
1234144026Sharti					 */
1235144026Sharti					break;
1236144026Sharti				} else {
1237144026Sharti					cp++;
1238144026Sharti				}
1239144026Sharti			}
12401590Srgrimes
1241144026Sharti			if (*cp == '(') {
1242144026Sharti				GNode	  *gnp;
12438874Srgrimes
1244144026Sharti				/* list of archive source names after exp. */
1245144026Sharti				Lst sources = Lst_Initializer(sources);
1246138916Sharti
1247144026Sharti				if (Arch_ParseArchive(&line, &sources,
1248144026Sharti				    VAR_CMD) != SUCCESS) {
1249144026Sharti					Parse_Error(PARSE_FATAL, "Error in "
1250144026Sharti					    "source archive spec \"%s\"", line);
1251144026Sharti					return;
1252144026Sharti				}
1253141270Sharti
1254144026Sharti				while (!Lst_IsEmpty(&sources)) {
1255144026Sharti					gnp = Lst_DeQueue(&sources);
1256144026Sharti					ParseDoSrc(tOp, gnp->name, &curSrcs);
1257144026Sharti				}
1258144026Sharti				cp = line;
1259144026Sharti			} else {
1260144026Sharti				if (*cp) {
1261144026Sharti					*cp = '\0';
1262144026Sharti					cp += 1;
1263144026Sharti				}
12641590Srgrimes
1265144026Sharti				ParseDoSrc(tOp, line, &curSrcs);
1266144026Sharti			}
1267144026Sharti			while (*cp && isspace((unsigned char)*cp)) {
1268144026Sharti				cp++;
1269144026Sharti			}
1270144026Sharti			line = cp;
12711590Srgrimes		}
1272144026Sharti		Lst_Destroy(&curSrcs, NOFREE);
1273144026Sharti	}
12741590Srgrimes
1275144026Sharti	if (mainNode == NULL) {
1276144026Sharti		/*
1277144026Sharti		 * If we have yet to decide on a main target to make, in the
1278144026Sharti		 * absence of any user input, we want the first target on
1279144026Sharti		 * the first dependency line that is actually a real target
1280144026Sharti		 * (i.e. isn't a .USE or .EXEC rule) to be made.
1281144026Sharti		 */
1282144026Sharti		LST_FOREACH(ln, &targets) {
1283144026Sharti			gn = Lst_Datum(ln);
1284144026Sharti			if ((gn->type & (OP_NOTMAIN | OP_USE |
1285144026Sharti			    OP_EXEC | OP_TRANSFORM)) == 0) {
1286144026Sharti				mainNode = gn;
1287144026Sharti				Targ_SetMain(gn);
1288144026Sharti				break;
1289144026Sharti			}
12901590Srgrimes		}
12911590Srgrimes	}
12921590Srgrimes}
12931590Srgrimes
12941590Srgrimes/*-
12951590Srgrimes *---------------------------------------------------------------------
12961590Srgrimes * Parse_IsVar  --
12971590Srgrimes *	Return TRUE if the passed line is a variable assignment. A variable
12981590Srgrimes *	assignment consists of a single word followed by optional whitespace
12991590Srgrimes *	followed by either a += or an = operator.
13001590Srgrimes *	This function is used both by the Parse_File function and main when
13011590Srgrimes *	parsing the command-line arguments.
13021590Srgrimes *
13031590Srgrimes * Results:
13041590Srgrimes *	TRUE if it is. FALSE if it ain't
13051590Srgrimes *
13061590Srgrimes * Side Effects:
13071590Srgrimes *	none
13081590Srgrimes *---------------------------------------------------------------------
13091590Srgrimes */
13101590SrgrimesBoolean
1311138232ShartiParse_IsVar(char *line)
13121590Srgrimes{
1313144026Sharti	Boolean wasSpace = FALSE;	/* set TRUE if found a space */
1314144026Sharti	Boolean haveName = FALSE;	/* Set TRUE if have a variable name */
1315138232Sharti
1316144026Sharti	int level = 0;
1317103503Sjmallett#define	ISEQOPERATOR(c) \
1318144029Sharti	((c) == '+' || (c) == ':' || (c) == '?' || (c) == '!')
13191590Srgrimes
1320144026Sharti	/*
1321144026Sharti	 * Skip to variable name
1322144026Sharti	 */
1323144029Sharti	for (; *line == ' ' || *line == '\t'; line++)
1324144026Sharti		continue;
13251590Srgrimes
1326144026Sharti	for (; *line != '=' || level != 0; line++) {
1327144026Sharti		switch (*line) {
1328144026Sharti		  case '\0':
1329144026Sharti			/*
1330144026Sharti			 * end-of-line -- can't be a variable assignment.
1331144026Sharti			 */
1332144026Sharti			return (FALSE);
133318730Ssteve
1334144026Sharti		  case ' ':
1335144026Sharti		  case '\t':
1336144026Sharti			/*
1337144026Sharti			 * there can be as much white space as desired so long
1338144026Sharti			 * as there is only one word before the operator
1339144026Sharti			*/
1340144026Sharti			wasSpace = TRUE;
1341144026Sharti			break;
134218730Ssteve
1343144026Sharti		  case '(':
1344144026Sharti		  case '{':
1345144026Sharti			level++;
1346144026Sharti			break;
134718730Ssteve
1348144026Sharti		  case '}':
1349144026Sharti		  case ')':
1350144026Sharti			level--;
1351144026Sharti			break;
135218730Ssteve
1353144026Sharti		  default:
1354144026Sharti			if (wasSpace && haveName) {
1355144026Sharti				if (ISEQOPERATOR(*line)) {
1356144026Sharti					/*
1357144026Sharti					 * We must have a finished word
1358144026Sharti					 */
1359144026Sharti					if (level != 0)
1360144026Sharti						return (FALSE);
136118730Ssteve
1362144026Sharti					/*
1363144026Sharti					 * When an = operator [+?!:] is found,
1364144026Sharti					 * the next character must be an = or
1365144026Sharti					 * it ain't a valid assignment.
1366144026Sharti					 */
1367144026Sharti					if (line[1] == '=')
1368144026Sharti						return (haveName);
136918730Ssteve#ifdef SUNSHCMD
1370144026Sharti					/*
1371144026Sharti					 * This is a shell command
1372144026Sharti					 */
1373144026Sharti					if (strncmp(line, ":sh", 3) == 0)
1374144026Sharti						return (haveName);
137518730Ssteve#endif
1376144026Sharti				}
1377144026Sharti				/*
1378144026Sharti				 * This is the start of another word, so not
1379144026Sharti				 * assignment.
1380144026Sharti				 */
1381144026Sharti				return (FALSE);
1382144026Sharti
1383144026Sharti			} else {
1384144026Sharti				haveName = TRUE;
1385144026Sharti				wasSpace = FALSE;
1386144026Sharti			}
1387144026Sharti			break;
1388144026Sharti		}
13891590Srgrimes	}
13901590Srgrimes
1391144026Sharti	return (haveName);
13921590Srgrimes}
13931590Srgrimes
13941590Srgrimes/*-
13951590Srgrimes *---------------------------------------------------------------------
13961590Srgrimes * Parse_DoVar  --
13971590Srgrimes *	Take the variable assignment in the passed line and do it in the
13981590Srgrimes *	global context.
13991590Srgrimes *
14001590Srgrimes *	Note: There is a lexical ambiguity with assignment modifier characters
14011590Srgrimes *	in variable names. This routine interprets the character before the =
14021590Srgrimes *	as a modifier. Therefore, an assignment like
14031590Srgrimes *	    C++=/usr/bin/CC
14041590Srgrimes *	is interpreted as "C+ +=" instead of "C++ =".
14051590Srgrimes *
14061590Srgrimes * Results:
14071590Srgrimes *	none
14081590Srgrimes *
14091590Srgrimes * Side Effects:
14101590Srgrimes *	the variable structure of the given variable name is altered in the
14111590Srgrimes *	global context.
14121590Srgrimes *---------------------------------------------------------------------
14131590Srgrimes */
14141590Srgrimesvoid
1415138232ShartiParse_DoVar(char *line, GNode *ctxt)
14161590Srgrimes{
1417144026Sharti	char	*cp;	/* pointer into line */
1418144026Sharti	enum {
1419144026Sharti		VAR_SUBST,
1420144026Sharti		VAR_APPEND,
1421144026Sharti		VAR_SHELL,
1422144026Sharti		VAR_NORMAL
1423144026Sharti	}	type;	/* Type of assignment */
1424144026Sharti	char	*opc;	/* ptr to operator character to
1425144026Sharti			 * null-terminate the variable name */
1426144026Sharti
1427144026Sharti	/*
1428144026Sharti	 * Avoid clobbered variable warnings by forcing the compiler
1429144026Sharti	 * to ``unregister'' variables
1430144026Sharti	 */
14311590Srgrimes#if __GNUC__
1432144026Sharti	(void)&cp;
1433144026Sharti	(void)&line;
14345814Sjkh#endif
14351590Srgrimes
1436144026Sharti	/*
1437144026Sharti	 * Skip to variable name
1438144026Sharti	 */
1439144029Sharti	while (*line == ' ' || *line == '\t') {
1440144026Sharti		line++;
1441144026Sharti	}
14421590Srgrimes
1443144026Sharti	/*
1444144026Sharti	 * Skip to operator character, nulling out whitespace as we go
1445144026Sharti	 */
1446144026Sharti	for (cp = line + 1; *cp != '='; cp++) {
1447144026Sharti		if (isspace((unsigned char)*cp)) {
1448144026Sharti			*cp = '\0';
1449144026Sharti		}
14501590Srgrimes	}
1451144026Sharti	opc = cp - 1;		/* operator is the previous character */
1452144026Sharti	*cp++ = '\0';		/* nuke the = */
14531590Srgrimes
1454144026Sharti	/*
1455144026Sharti	 * Check operator type
1456144026Sharti	 */
1457144026Sharti	switch (*opc) {
1458144026Sharti	  case '+':
1459144026Sharti		type = VAR_APPEND;
1460144026Sharti		*opc = '\0';
1461144026Sharti		break;
14621590Srgrimes
1463144026Sharti	  case '?':
1464144026Sharti		/*
1465144026Sharti		 * If the variable already has a value, we don't do anything.
1466144026Sharti		 */
1467144026Sharti		*opc = '\0';
1468144026Sharti		if (Var_Exists(line, ctxt)) {
1469144026Sharti			return;
1470144026Sharti		} else {
1471144026Sharti			type = VAR_NORMAL;
1472144026Sharti		}
1473144026Sharti		break;
14741590Srgrimes
1475144026Sharti	  case ':':
1476144026Sharti		type = VAR_SUBST;
1477144026Sharti		*opc = '\0';
1478144026Sharti		break;
14791590Srgrimes
1480144026Sharti	  case '!':
1481144026Sharti		type = VAR_SHELL;
1482144026Sharti		*opc = '\0';
1483144026Sharti		break;
14841590Srgrimes
1485144026Sharti	  default:
148618730Ssteve#ifdef SUNSHCMD
1487144026Sharti		while (*opc != ':') {
1488144026Sharti			if (opc == line)
1489144026Sharti				break;
1490144026Sharti			else
1491144026Sharti				--opc;
1492144026Sharti		}
149318730Ssteve
1494144026Sharti		if (strncmp(opc, ":sh", 3) == 0) {
1495144026Sharti			type = VAR_SHELL;
1496144026Sharti			*opc = '\0';
1497144026Sharti			break;
1498144026Sharti		}
1499144026Sharti#endif
1500144026Sharti		type = VAR_NORMAL;
150118730Ssteve		break;
1502144026Sharti	}
15031590Srgrimes
1504144026Sharti	while (isspace((unsigned char)*cp)) {
1505144026Sharti		cp++;
1506144026Sharti	}
15071590Srgrimes
1508144026Sharti	if (type == VAR_APPEND) {
1509144026Sharti		Var_Append(line, cp, ctxt);
15101590Srgrimes
1511144026Sharti	} else if (type == VAR_SUBST) {
1512144026Sharti		/*
1513144026Sharti		 * Allow variables in the old value to be undefined, but leave
1514144026Sharti		 * their invocation alone -- this is done by forcing oldVars
1515144026Sharti		 * to be false.
1516144026Sharti		 * XXX: This can cause recursive variables, but that's not
1517144026Sharti		 * hard to do, and this allows someone to do something like
1518144026Sharti		 *
1519144026Sharti		 *  CFLAGS = $(.INCLUDES)
1520144026Sharti		 *  CFLAGS := -I.. $(CFLAGS)
1521144026Sharti		 *
1522144026Sharti		 * And not get an error.
1523144026Sharti		 */
1524144026Sharti		Boolean oldOldVars = oldVars;
152598509Sjmallett
1526144026Sharti		oldVars = FALSE;
152798509Sjmallett
1528144026Sharti		/*
1529144026Sharti		 * make sure that we set the variable the first time to nothing
1530144026Sharti		 * so that it gets substituted!
1531144026Sharti		 */
1532144026Sharti		if (!Var_Exists(line, ctxt))
1533144026Sharti			Var_Set(line, "", ctxt);
1534142457Sharti
1535144026Sharti		cp = Buf_Peel(Var_Subst(NULL, cp, ctxt, FALSE));
15361590Srgrimes
1537144026Sharti		oldVars = oldOldVars;
15381590Srgrimes
1539144026Sharti		Var_Set(line, cp, ctxt);
1540144026Sharti		free(cp);
15411590Srgrimes
1542144026Sharti	} else if (type == VAR_SHELL) {
1543144026Sharti		/*
1544144026Sharti		 * TRUE if the command needs to be freed, i.e.
1545144026Sharti		 * if any variable expansion was performed
1546144026Sharti		 */
1547144026Sharti		Boolean	freeCmd = FALSE;
1548144026Sharti		Buffer *buf;
1549144026Sharti		const char *error;
15501590Srgrimes
1551144026Sharti		if (strchr(cp, '$') != NULL) {
1552144026Sharti			/*
1553144026Sharti			 * There's a dollar sign in the command, so perform
1554144026Sharti			 * variable expansion on the whole thing. The
1555144026Sharti			 * resulting string will need freeing when we're done,
1556144026Sharti			 * so set freeCmd to TRUE.
1557144026Sharti			 */
1558144026Sharti			cp = Buf_Peel(Var_Subst(NULL, cp, VAR_CMD, TRUE));
1559144026Sharti			freeCmd = TRUE;
1560144026Sharti		}
15611590Srgrimes
1562144026Sharti		buf = Cmd_Exec(cp, &error);
1563144026Sharti		Var_Set(line, Buf_Data(buf), ctxt);
1564144026Sharti		Buf_Destroy(buf, TRUE);
1565144026Sharti
1566144026Sharti		if (error)
1567144026Sharti			Parse_Error(PARSE_WARNING, error, cp);
1568144026Sharti
1569144026Sharti		if (freeCmd)
1570144026Sharti			free(cp);
1571144026Sharti
1572144026Sharti	} else {
1573144026Sharti		/*
1574144026Sharti		 * Normal assignment -- just do it.
1575144026Sharti		 */
1576144026Sharti		Var_Set(line, cp, ctxt);
1577144026Sharti	}
15781590Srgrimes}
15791590Srgrimes
15801590Srgrimes/*-
15811590Srgrimes *-----------------------------------------------------------------------
15821590Srgrimes * ParseHasCommands --
15831590Srgrimes *	Callback procedure for Parse_File when destroying the list of
15841590Srgrimes *	targets on the last dependency line. Marks a target as already
15851590Srgrimes *	having commands if it does, to keep from having shell commands
15861590Srgrimes *	on multiple dependency lines.
15871590Srgrimes *
15881590Srgrimes * Results:
15895814Sjkh *	None
15901590Srgrimes *
15911590Srgrimes * Side Effects:
15921590Srgrimes *	OP_HAS_COMMANDS may be set for the target.
15931590Srgrimes *
15941590Srgrimes *-----------------------------------------------------------------------
15951590Srgrimes */
15965814Sjkhstatic void
1597104696SjmallettParseHasCommands(void *gnp)
15981590Srgrimes{
1599144026Sharti	GNode *gn = gnp;
1600138232Sharti
1601144026Sharti	if (!Lst_IsEmpty(&gn->commands)) {
1602144026Sharti		gn->type |= OP_HAS_COMMANDS;
1603144026Sharti	}
16041590Srgrimes}
16051590Srgrimes
16061590Srgrimes/*-
16071590Srgrimes *-----------------------------------------------------------------------
16081590Srgrimes * Parse_AddIncludeDir --
16091590Srgrimes *	Add a directory to the path searched for included makefiles
16101590Srgrimes *	bracketed by double-quotes. Used by functions in main.c
16111590Srgrimes *
16121590Srgrimes * Results:
16131590Srgrimes *	None.
16141590Srgrimes *
16151590Srgrimes * Side Effects:
16161590Srgrimes *	The directory is appended to the list.
16171590Srgrimes *
16181590Srgrimes *-----------------------------------------------------------------------
16191590Srgrimes */
16201590Srgrimesvoid
1621138232ShartiParse_AddIncludeDir(char *dir)
16221590Srgrimes{
1623138232Sharti
1624144026Sharti	Path_AddDir(&parseIncPath, dir);
16251590Srgrimes}
16261590Srgrimes
16271590Srgrimes/*-
16281590Srgrimes *---------------------------------------------------------------------
16291590Srgrimes * Parse_FromString  --
16301590Srgrimes *	Start Parsing from the given string
16318874Srgrimes *
16321590Srgrimes * Results:
16331590Srgrimes *	None
16341590Srgrimes *
16351590Srgrimes * Side Effects:
1636126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1637126824Sru *	curFile.fname and curFile.F are altered for the new file
16381590Srgrimes *---------------------------------------------------------------------
16391590Srgrimes */
16401590Srgrimesvoid
1641126824SruParse_FromString(char *str, int lineno)
16421590Srgrimes{
16431590Srgrimes
1644144026Sharti	DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno));
16451590Srgrimes
1646144341Sharti	ParsePushInput(estrdup(CURFILE->fname), NULL, str, lineno);
16471590Srgrimes}
16481590Srgrimes
16491590Srgrimes#ifdef SYSVINCLUDE
16501590Srgrimes/*-
16511590Srgrimes *---------------------------------------------------------------------
16521590Srgrimes * ParseTraditionalInclude  --
16531590Srgrimes *	Push to another file.
16548874Srgrimes *
16551590Srgrimes *	The input is the line minus the "include".  The file name is
16561590Srgrimes *	the string following the "include".
16571590Srgrimes *
16581590Srgrimes * Results:
16591590Srgrimes *	None
16601590Srgrimes *
16611590Srgrimes * Side Effects:
1662126824Sru *	A structure is added to the includes Lst and readProc, curFile.lineno,
1663126824Sru *	curFile.fname and curFile.F are altered for the new file
16641590Srgrimes *---------------------------------------------------------------------
16651590Srgrimes */
16661590Srgrimesstatic void
1667141270ShartiParseTraditionalInclude(char *file)
16681590Srgrimes{
1669144026Sharti	char	*fullname;	/* full pathname of file */
1670144026Sharti	char	*cp;		/* current position in file spec */
16711590Srgrimes
1672144026Sharti	/*
1673144026Sharti	 * Skip over whitespace
1674144026Sharti	 */
1675144029Sharti	while (*file == ' ' || *file == '\t') {
1676144026Sharti		file++;
1677144026Sharti	}
16781590Srgrimes
1679144026Sharti	if (*file == '\0') {
1680144026Sharti		Parse_Error(PARSE_FATAL, "Filename missing from \"include\"");
1681144026Sharti		return;
1682144026Sharti	}
16831590Srgrimes
1684144026Sharti	/*
1685144026Sharti	* Skip to end of line or next whitespace
1686144026Sharti	*/
1687144026Sharti	for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
1688144026Sharti		continue;
1689144026Sharti	}
16901590Srgrimes
1691144026Sharti	*cp = '\0';
16921590Srgrimes
1693144026Sharti	/*
1694144026Sharti	 * Substitute for any variables in the file name before trying to
1695144026Sharti	 * find the thing.
1696144026Sharti	 */
1697144894Sharti	file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE));
16981590Srgrimes
16991590Srgrimes	/*
1700144026Sharti	 * Now we know the file's name, we attempt to find the durn thing.
1701144026Sharti	 * Search for it first on the -I search path, then on the .PATH
1702144026Sharti	 * search path, if not found in a -I directory.
17031590Srgrimes	 */
1704144026Sharti	fullname = Path_FindFile(file, &parseIncPath);
1705144026Sharti	if (fullname == NULL) {
1706144026Sharti		fullname = Path_FindFile(file, &dirSearchPath);
1707144026Sharti	}
17081590Srgrimes
1709144026Sharti	if (fullname == NULL) {
1710144026Sharti		/*
1711144026Sharti		 * Still haven't found the makefile. Look for it on the system
1712144026Sharti		 * path as a last resort.
1713144026Sharti		 */
1714144026Sharti		fullname = Path_FindFile(file, &sysIncPath);
1715144026Sharti	}
17161590Srgrimes
1717144026Sharti	if (fullname == NULL) {
1718144026Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
1719144026Sharti		/* XXXHB free(file) */
1720144026Sharti		return;
1721144026Sharti	}
1722142457Sharti
1723144026Sharti	/* XXXHB free(file) */
17241590Srgrimes
1725144026Sharti	/*
1726144341Sharti	 * We set up the name of the file to be the absolute
1727144026Sharti	 * name of the include file so error messages refer to the right
1728144341Sharti	 * place.
17291590Srgrimes	 */
1730144341Sharti	ParsePushInput(fullname, NULL, NULL, 0);
17311590Srgrimes}
17321590Srgrimes#endif
17331590Srgrimes
17341590Srgrimes/*-
17351590Srgrimes *---------------------------------------------------------------------
17361590Srgrimes * ParseReadc  --
17378874Srgrimes *	Read a character from the current file
17381590Srgrimes *
17391590Srgrimes * Results:
17401590Srgrimes *	The character that was read
17411590Srgrimes *
17421590Srgrimes * Side Effects:
17431590Srgrimes *---------------------------------------------------------------------
17441590Srgrimes */
17451590Srgrimesstatic int
1746104696SjmallettParseReadc(void)
17471590Srgrimes{
1748138232Sharti
1749144341Sharti	if (CURFILE->F != NULL)
1750144341Sharti		return (fgetc(CURFILE->F));
17518874Srgrimes
1752144341Sharti	if (CURFILE->str != NULL && *CURFILE->ptr != '\0')
1753144341Sharti		return (*CURFILE->ptr++);
1754144341Sharti
1755144026Sharti	return (EOF);
17561590Srgrimes}
17571590Srgrimes
17581590Srgrimes
17591590Srgrimes/*-
17601590Srgrimes *---------------------------------------------------------------------
17611590Srgrimes * ParseUnreadc  --
17628874Srgrimes *	Put back a character to the current file
17631590Srgrimes *
17641590Srgrimes * Results:
17651590Srgrimes *	None.
17661590Srgrimes *
17671590Srgrimes * Side Effects:
17681590Srgrimes *---------------------------------------------------------------------
17691590Srgrimes */
17701590Srgrimesstatic void
1771104696SjmallettParseUnreadc(int c)
17721590Srgrimes{
1773138232Sharti
1774144341Sharti	if (CURFILE->F != NULL) {
1775144341Sharti		ungetc(c, CURFILE->F);
1776144026Sharti		return;
1777144026Sharti	}
1778144341Sharti	if (CURFILE->str != NULL) {
1779144341Sharti		*--(CURFILE->ptr) = c;
1780144026Sharti		return;
1781144026Sharti	}
17821590Srgrimes}
17831590Srgrimes
17841590Srgrimes/* ParseSkipLine():
1785104696Sjmallett *	Grab the next line unless it begins with a dot (`.') and we're told to
1786104696Sjmallett *	ignore such lines.
17871590Srgrimes */
17881590Srgrimesstatic char *
1789126824SruParseSkipLine(int skip, int keep_newline)
17901590Srgrimes{
1791144026Sharti	char *line;
1792144026Sharti	int c, lastc;
1793144026Sharti	Buffer *buf;
17941590Srgrimes
1795144026Sharti	buf = Buf_Init(MAKE_BSIZE);
17961590Srgrimes
1797144026Sharti	do {
1798144026Sharti		Buf_Clear(buf);
1799144026Sharti		lastc = '\0';
18008874Srgrimes
1801144026Sharti		while (((c = ParseReadc()) != '\n' || lastc == '\\')
1802144026Sharti		    && c != EOF) {
1803144026Sharti			if (skip && c == '#' && lastc != '\\') {
1804144026Sharti				/*
1805144026Sharti				 * let a comment be terminated even by an
1806144026Sharti				 * escaped \n. This is consistent to comment
1807144026Sharti				 * handling in ParseReadLine
1808144026Sharti				 */
1809144026Sharti				while ((c = ParseReadc()) != '\n' && c != EOF)
1810144026Sharti					;
1811144026Sharti				break;
1812144026Sharti			}
1813144026Sharti			if (c == '\n') {
1814144026Sharti				if (keep_newline)
1815144026Sharti					Buf_AddByte(buf, (Byte)c);
1816144026Sharti				else
1817144026Sharti					Buf_ReplaceLastByte(buf, (Byte)' ');
1818144341Sharti				CURFILE->lineno++;
18198874Srgrimes
1820144026Sharti				while ((c = ParseReadc()) == ' ' || c == '\t')
1821144026Sharti					continue;
18228874Srgrimes
1823144026Sharti				if (c == EOF)
1824144026Sharti					break;
1825144026Sharti			}
182674272Swill
1827144026Sharti			Buf_AddByte(buf, (Byte)c);
1828144026Sharti			lastc = c;
1829144026Sharti		}
183018456Ssteve
1831144026Sharti		if (c == EOF) {
1832144026Sharti			Parse_Error(PARSE_FATAL,
1833144026Sharti			    "Unclosed conditional/for loop");
1834144026Sharti			Buf_Destroy(buf, TRUE);
1835144026Sharti			return (NULL);
1836144026Sharti		}
183718456Ssteve
1838144341Sharti		CURFILE->lineno++;
1839144026Sharti		Buf_AddByte(buf, (Byte)'\0');
1840144026Sharti		line = Buf_Data(buf);
1841144026Sharti	} while (skip == 1 && line[0] != '.');
184218456Ssteve
1843144026Sharti	Buf_Destroy(buf, FALSE);
1844144026Sharti	return (line);
18451590Srgrimes}
18461590Srgrimes
18471590Srgrimes/*-
18481590Srgrimes *---------------------------------------------------------------------
18491590Srgrimes * ParseReadLine --
18501590Srgrimes *	Read an entire line from the input file. Called only by Parse_File.
18511590Srgrimes *	To facilitate escaped newlines and what have you, a character is
18521590Srgrimes *	buffered in 'lastc', which is '\0' when no characters have been
18531590Srgrimes *	read. When we break out of the loop, c holds the terminating
18541590Srgrimes *	character and lastc holds a character that should be added to
18551590Srgrimes *	the line (unless we don't read anything but a terminator).
18561590Srgrimes *
18571590Srgrimes * Results:
18581590Srgrimes *	A line w/o its newline
18591590Srgrimes *
18601590Srgrimes * Side Effects:
18611590Srgrimes *	Only those associated with reading a character
18621590Srgrimes *---------------------------------------------------------------------
18631590Srgrimes */
18641590Srgrimesstatic char *
1865138232ShartiParseReadLine(void)
18661590Srgrimes{
1867144026Sharti	Buffer	*buf;		/* Buffer for current line */
1868144026Sharti	int	c;		/* the current character */
1869144026Sharti	int	lastc;		/* The most-recent character */
1870144026Sharti	Boolean	semiNL;		/* treat semi-colons as newlines */
1871144026Sharti	Boolean	ignDepOp;	/* TRUE if should ignore dependency operators
18721590Srgrimes				 * for the purposes of setting semiNL */
1873144026Sharti	Boolean	ignComment;	/* TRUE if should ignore comments (in a
18741590Srgrimes				 * shell command */
1875144026Sharti	char	*line;		/* Result */
1876144026Sharti	char	*ep;		/* to strip trailing blanks */
18771590Srgrimes
1878144742Sharti  again:
1879144026Sharti	semiNL = FALSE;
1880144026Sharti	ignDepOp = FALSE;
1881144026Sharti	ignComment = FALSE;
18821590Srgrimes
1883144742Sharti	lastc = '\0';
1884144742Sharti
1885144026Sharti	/*
1886144742Sharti	 * Handle tab at the beginning of the line. A leading tab (shell
1887144742Sharti	 * command) forces us to ignore comments and dependency operators and
1888144742Sharti	 * treat semi-colons as semi-colons (by leaving semiNL FALSE).
1889144742Sharti	 * This also discards completely blank lines.
1890144026Sharti	 */
1891144026Sharti	for (;;) {
1892144026Sharti		c = ParseReadc();
1893144742Sharti		if (c == EOF) {
1894144742Sharti			if (ParsePopInput() == DONE) {
1895144742Sharti				/* End of all inputs - return NULL */
1896144742Sharti				return (NULL);
1897144742Sharti			}
1898144742Sharti			continue;
1899144742Sharti		}
19001590Srgrimes
1901144026Sharti		if (c == '\t') {
1902144026Sharti			ignComment = ignDepOp = TRUE;
1903144742Sharti			lastc = c;
1904144026Sharti			break;
1905144742Sharti		}
1906144742Sharti		if (c != '\n') {
1907144026Sharti			ParseUnreadc(c);
1908144026Sharti			break;
1909144026Sharti		}
1910144742Sharti		CURFILE->lineno++;
19111590Srgrimes	}
19128874Srgrimes
1913144742Sharti	buf = Buf_Init(MAKE_BSIZE);
19148874Srgrimes
1915144742Sharti	while (((c = ParseReadc()) != '\n' || lastc == '\\') && c != EOF) {
1916144026Sharti  test_char:
1917144742Sharti		switch (c) {
1918144742Sharti		  case '\n':
1919144742Sharti			/*
1920144742Sharti			 * Escaped newline: read characters until a
1921144742Sharti			 * non-space or an unescaped newline and
1922144742Sharti			 * replace them all by a single space. This is
1923144742Sharti			 * done by storing the space over the backslash
1924144742Sharti			 * and dropping through with the next nonspace.
1925144742Sharti			 * If it is a semi-colon and semiNL is TRUE,
1926144742Sharti			 * it will be recognized as a newline in the
1927144742Sharti			 * code below this...
1928144742Sharti			 */
1929144742Sharti			CURFILE->lineno++;
1930144742Sharti			lastc = ' ';
1931144742Sharti			while ((c = ParseReadc()) == ' ' || c == '\t') {
1932144742Sharti				continue;
1933144742Sharti			}
1934144742Sharti			if (c == EOF || c == '\n') {
1935144742Sharti				goto line_read;
1936144742Sharti			} else {
1937144026Sharti				/*
1938144742Sharti				 * Check for comments, semiNL's, etc. --
1939144742Sharti				 * easier than ParseUnreadc(c);
1940144742Sharti				 * continue;
1941144026Sharti				 */
1942144742Sharti				goto test_char;
1943144742Sharti			}
1944144742Sharti			/*NOTREACHED*/
1945144742Sharti			break;
1946144026Sharti
1947144742Sharti		  case ';':
1948144742Sharti			/*
1949144742Sharti			 * Semi-colon: Need to see if it should be
1950144742Sharti			 * interpreted as a newline
1951144742Sharti			 */
1952144742Sharti			if (semiNL) {
1953144026Sharti				/*
1954144742Sharti				 * To make sure the command that may
1955144742Sharti				 * be following this semi-colon begins
1956144742Sharti				 * with a tab, we push one back into the
1957144742Sharti				 * input stream. This will overwrite the
1958144742Sharti				 * semi-colon in the buffer. If there is
1959144742Sharti				 * no command following, this does no
1960144742Sharti				 * harm, since the newline remains in
1961144742Sharti				 * the buffer and the
1962144742Sharti				 * whole line is ignored.
1963144026Sharti				 */
1964144742Sharti				ParseUnreadc('\t');
1965144742Sharti				goto line_read;
1966144742Sharti			}
1967144742Sharti			break;
1968144742Sharti		  case '=':
1969144742Sharti			if (!semiNL) {
1970144742Sharti				/*
1971144742Sharti				 * Haven't seen a dependency operator
1972144742Sharti				 * before this, so this must be a
1973144742Sharti				 * variable assignment -- don't pay
1974144742Sharti				 * attention to dependency operators
1975144742Sharti				 * after this.
1976144742Sharti				 */
1977144742Sharti				ignDepOp = TRUE;
1978144742Sharti			} else if (lastc == ':' || lastc == '!') {
1979144742Sharti				/*
1980144742Sharti				 * Well, we've seen a dependency
1981144742Sharti				 * operator already, but it was the
1982144742Sharti				 * previous character, so this is really
1983144742Sharti				 * just an expanded variable assignment.
1984144742Sharti				 * Revert semi-colons to being just
1985144742Sharti				 * semi-colons again and ignore any more
1986144742Sharti				 * dependency operators.
1987144742Sharti				 *
1988144742Sharti				 * XXX: Note that a line like
1989144742Sharti				 * "foo : a:=b" will blow up, but who'd
1990144742Sharti				 * write a line like that anyway?
1991144742Sharti				 */
1992144742Sharti				ignDepOp = TRUE;
1993144742Sharti				semiNL = FALSE;
1994144742Sharti			}
1995144742Sharti			break;
1996144742Sharti		  case '#':
1997144742Sharti			if (!ignComment) {
1998144742Sharti				if (lastc != '\\') {
1999144026Sharti					/*
2000144742Sharti					 * If the character is a hash
2001144742Sharti					 * mark and it isn't escaped
2002144742Sharti					 * (or we're being compatible),
2003144742Sharti					 * the thing is a comment.
2004144742Sharti					 * Skip to the end of the line.
2005144026Sharti					 */
2006144742Sharti					do {
2007144742Sharti						c = ParseReadc();
2008144742Sharti					} while (c != '\n' && c != EOF);
2009144026Sharti					goto line_read;
2010144742Sharti				} else {
2011144026Sharti					/*
2012144742Sharti					 * Don't add the backslash.
2013144742Sharti					 * Just let the # get copied
2014144742Sharti					 * over.
2015144026Sharti					 */
2016144742Sharti					lastc = c;
2017144742Sharti					continue;
2018144026Sharti				}
2019144742Sharti			}
2020144742Sharti			break;
2021144026Sharti
2022144742Sharti		  case ':':
2023144742Sharti		  case '!':
2024144742Sharti			if (!ignDepOp) {
2025144742Sharti				/*
2026144742Sharti				 * A semi-colon is recognized as a
2027144742Sharti				 * newline only on dependency lines.
2028144742Sharti				 * Dependency lines are lines with a
2029144742Sharti				 * colon or an exclamation point.
2030144742Sharti				 * Ergo...
2031144742Sharti				 */
2032144742Sharti				semiNL = TRUE;
2033144742Sharti			}
2034144742Sharti			break;
2035144026Sharti
2036144742Sharti		  default:
2037144742Sharti			break;
2038144742Sharti		}
2039144742Sharti		/*
2040144742Sharti		 * Copy in the previous character (there may be none if this
2041144742Sharti		 * was the first character) and save this one in
2042144742Sharti		 * lastc.
2043144742Sharti		 */
2044144742Sharti		if (lastc != '\0')
2045144026Sharti			Buf_AddByte(buf, (Byte)lastc);
2046144742Sharti		lastc = c;
2047144742Sharti	}
2048144026Sharti  line_read:
2049144742Sharti	CURFILE->lineno++;
2050144026Sharti
2051144742Sharti	if (lastc != '\0') {
2052144742Sharti		Buf_AddByte(buf, (Byte)lastc);
2053144742Sharti	}
2054144742Sharti	Buf_AddByte(buf, (Byte)'\0');
2055144742Sharti	line = Buf_Peel(buf);
20561590Srgrimes
2057144742Sharti	/*
2058144742Sharti	 * Strip trailing blanks and tabs from the line.
2059144742Sharti	 * Do not strip a blank or tab that is preceded by
2060144742Sharti	 * a '\'
2061144742Sharti	 */
2062144742Sharti	ep = line;
2063144742Sharti	while (*ep)
2064144742Sharti		++ep;
2065144742Sharti	while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
2066144742Sharti		if (ep > line + 1 && ep[-2] == '\\')
2067144742Sharti			break;
2068144742Sharti		--ep;
2069144742Sharti	}
2070144742Sharti	*ep = 0;
2071144742Sharti
2072144742Sharti	if (line[0] == '\0') {
2073144742Sharti		/* empty line - just ignore */
2074144742Sharti		free(line);
2075144742Sharti		goto again;
2076144742Sharti	}
2077144742Sharti
2078144742Sharti	return (line);
20791590Srgrimes}
20801590Srgrimes
20811590Srgrimes/*-
20821590Srgrimes *-----------------------------------------------------------------------
20831590Srgrimes * ParseFinishLine --
20841590Srgrimes *	Handle the end of a dependency group.
20851590Srgrimes *
20861590Srgrimes * Results:
20871590Srgrimes *	Nothing.
20881590Srgrimes *
20891590Srgrimes * Side Effects:
20901590Srgrimes *	inLine set FALSE. 'targets' list destroyed.
20911590Srgrimes *
20921590Srgrimes *-----------------------------------------------------------------------
20931590Srgrimes */
20941590Srgrimesstatic void
2095104696SjmallettParseFinishLine(void)
20961590Srgrimes{
2097143372Sharti	const LstNode	*ln;
2098138232Sharti
2099143372Sharti	if (inLine) {
2100143372Sharti		LST_FOREACH(ln, &targets) {
2101143372Sharti			if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM)
2102143372Sharti				Suff_EndTransform(Lst_Datum(ln));
2103143372Sharti		}
2104143372Sharti		Lst_Destroy(&targets, ParseHasCommands);
2105143372Sharti		inLine = FALSE;
2106143372Sharti	}
21071590Srgrimes}
21081590Srgrimes
2109144894Sharti/**
2110144894Sharti * parse_include
2111144894Sharti *	Parse an .include directive and push the file onto the input stack.
2112144894Sharti *	The input is the line minus the .include. A file spec is a string
2113144894Sharti *	enclosed in <> or "". The former is looked for only in sysIncPath.
2114144894Sharti *	The latter in . and the directories specified by -I command line
2115144894Sharti *	options
2116144894Sharti */
2117144894Shartistatic void
2118144894Shartiparse_include(char *file, int code __unused, int lineno __unused)
2119144894Sharti{
2120144894Sharti	char	*fullname;	/* full pathname of file */
2121144894Sharti	char	endc;		/* the character which ends the file spec */
2122144894Sharti	char	*cp;		/* current position in file spec */
2123144894Sharti	Boolean	isSystem;	/* TRUE if makefile is a system makefile */
2124144894Sharti	char	*prefEnd, *Fname;
2125144894Sharti	char	*newName;
21268874Srgrimes
2127144894Sharti	/*
2128144894Sharti	 * Skip to delimiter character so we know where to look
2129144894Sharti	 */
2130144894Sharti	while (*file == ' ' || *file == '\t') {
2131144894Sharti		file++;
2132144894Sharti	}
2133144894Sharti
2134144894Sharti	if (*file != '"' && *file != '<') {
2135144894Sharti		Parse_Error(PARSE_FATAL,
2136144894Sharti		    ".include filename must be delimited by '\"' or '<'");
2137144894Sharti		return;
2138144894Sharti	}
2139144894Sharti
2140144894Sharti	/*
2141144894Sharti	 * Set the search path on which to find the include file based on the
2142144894Sharti	 * characters which bracket its name. Angle-brackets imply it's
2143144894Sharti	 * a system Makefile while double-quotes imply it's a user makefile
2144144894Sharti	 */
2145144894Sharti	if (*file == '<') {
2146144894Sharti		isSystem = TRUE;
2147144894Sharti		endc = '>';
2148144894Sharti	} else {
2149144894Sharti		isSystem = FALSE;
2150144894Sharti		endc = '"';
2151144894Sharti	}
2152144894Sharti
2153144894Sharti	/*
2154144894Sharti	* Skip to matching delimiter
2155144894Sharti	*/
2156144894Sharti	for (cp = ++file; *cp != endc; cp++) {
2157144894Sharti		if (*cp == '\0') {
2158144894Sharti			Parse_Error(PARSE_FATAL,
2159144894Sharti			    "Unclosed .include filename. '%c' expected", endc);
2160144894Sharti			return;
2161144894Sharti		}
2162144894Sharti	}
2163144894Sharti	*cp = '\0';
2164144894Sharti
2165144894Sharti	/*
2166144894Sharti	 * Substitute for any variables in the file name before trying to
2167144894Sharti	 * find the thing.
2168144894Sharti	 */
2169144894Sharti	file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE));
2170144894Sharti
2171144894Sharti	/*
2172144894Sharti	 * Now we know the file's name and its search path, we attempt to
2173144894Sharti	 * find the durn thing. A return of NULL indicates the file don't
2174144894Sharti	 * exist.
2175144894Sharti	 */
2176144894Sharti	if (!isSystem) {
2177144894Sharti		/*
2178144894Sharti		 * Include files contained in double-quotes are first searched
2179144894Sharti		 * for relative to the including file's location. We don't want
2180144894Sharti		 * to cd there, of course, so we just tack on the old file's
2181144894Sharti		 * leading path components and call Dir_FindFile to see if
2182144894Sharti		 * we can locate the beast.
2183144894Sharti		 */
2184144894Sharti
2185144894Sharti		/* Make a temporary copy of this, to be safe. */
2186144894Sharti		Fname = estrdup(CURFILE->fname);
2187144894Sharti
2188144894Sharti		prefEnd = strrchr(Fname, '/');
2189144894Sharti		if (prefEnd != NULL) {
2190144894Sharti			*prefEnd = '\0';
2191144894Sharti			if (file[0] == '/')
2192144894Sharti				newName = estrdup(file);
2193144894Sharti			else
2194144894Sharti				newName = str_concat(Fname, file, STR_ADDSLASH);
2195144894Sharti			fullname = Path_FindFile(newName, &parseIncPath);
2196144894Sharti			if (fullname == NULL) {
2197144894Sharti				fullname = Path_FindFile(newName,
2198144894Sharti				    &dirSearchPath);
2199144894Sharti			}
2200144894Sharti			free(newName);
2201144894Sharti			*prefEnd = '/';
2202144894Sharti		} else {
2203144894Sharti			fullname = NULL;
2204144894Sharti		}
2205144894Sharti		free(Fname);
2206144894Sharti	} else {
2207144894Sharti		fullname = NULL;
2208144894Sharti	}
2209144894Sharti
2210144894Sharti	if (fullname == NULL) {
2211144894Sharti		/*
2212144894Sharti		 * System makefile or makefile wasn't found in same directory as
2213144894Sharti		 * included makefile. Search for it first on the -I search path,
2214144894Sharti		 * then on the .PATH search path, if not found in a -I
2215144894Sharti		 * directory.
2216144894Sharti		 * XXX: Suffix specific?
2217144894Sharti		 */
2218144894Sharti		fullname = Path_FindFile(file, &parseIncPath);
2219144894Sharti		if (fullname == NULL) {
2220144894Sharti			fullname = Path_FindFile(file, &dirSearchPath);
2221144894Sharti		}
2222144894Sharti	}
2223144894Sharti
2224144894Sharti	if (fullname == NULL) {
2225144894Sharti		/*
2226144894Sharti		 * Still haven't found the makefile. Look for it on the system
2227144894Sharti		 * path as a last resort.
2228144894Sharti		 */
2229144894Sharti		fullname = Path_FindFile(file, &sysIncPath);
2230144894Sharti	}
2231144894Sharti
2232144894Sharti	if (fullname == NULL) {
2233144894Sharti		*cp = endc;
2234144894Sharti		Parse_Error(PARSE_FATAL, "Could not find %s", file);
2235144894Sharti		free(file);
2236144894Sharti		return;
2237144894Sharti	}
2238144894Sharti	free(file);
2239144894Sharti
2240144894Sharti	/*
2241144894Sharti	 * We set up the name of the file to be the absolute
2242144894Sharti	 * name of the include file so error messages refer to the right
2243144894Sharti	 * place.
2244144894Sharti	 */
2245144894Sharti	ParsePushInput(fullname, NULL, NULL, 0);
2246144894Sharti}
2247144894Sharti
2248144894Sharti/**
2249144894Sharti * parse_message
2250144894Sharti *	Parse a .warning or .error directive
2251144894Sharti *
2252144894Sharti *	The input is the line minus the ".error"/".warning".  We substitute
2253144894Sharti *	variables, print the message and exit(1) (for .error) or just print
2254144894Sharti *	a warning if the directive is malformed.
2255144894Sharti */
2256144894Shartistatic void
2257144894Shartiparse_message(char *line, int iserror, int lineno __unused)
2258144894Sharti{
2259144894Sharti
2260144894Sharti	if (!isspace((u_char)*line)) {
2261144894Sharti		Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s",
2262144894Sharti		    iserror ? "error" : "warning", line);
2263144894Sharti		return;
2264144894Sharti	}
2265144894Sharti
2266144894Sharti	while (isspace((u_char)*line))
2267144894Sharti		line++;
2268144894Sharti
2269144894Sharti	line = Buf_Peel(Var_Subst(NULL, line, VAR_GLOBAL, FALSE));
2270144894Sharti	Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line);
2271144894Sharti	free(line);
2272144894Sharti
2273144894Sharti	if (iserror) {
2274144894Sharti		/* Terminate immediately. */
2275144894Sharti		exit(1);
2276144894Sharti	}
2277144894Sharti}
2278144894Sharti
2279144894Sharti/**
2280144894Sharti * parse_undef
2281144894Sharti *	Parse an .undef directive.
2282144894Sharti */
2283144894Shartistatic void
2284144894Shartiparse_undef(char *line, int code __unused, int lineno __unused)
2285144894Sharti{
2286144894Sharti	char *cp;
2287144894Sharti
2288144894Sharti	while (isspace((u_char)*line))
2289144894Sharti		line++;
2290144894Sharti
2291144894Sharti	for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) {
2292144894Sharti		;
2293144894Sharti	}
2294144894Sharti	*cp = '\0';
2295144894Sharti
2296144894Sharti	cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, FALSE));
2297144894Sharti	Var_Delete(cp, VAR_GLOBAL);
2298144894Sharti	free(cp);
2299144894Sharti}
2300144894Sharti
2301144894Sharti/**
2302144894Sharti * parse_for
2303144894Sharti *	Parse a .for directive.
2304144894Sharti */
2305144894Shartistatic void
2306144894Shartiparse_for(char *line, int code __unused, int lineno)
2307144894Sharti{
2308144894Sharti
2309144894Sharti	if (!For_For(line)) {
2310144894Sharti		/* syntax error */
2311144894Sharti		return;
2312144894Sharti	}
2313144894Sharti	line = NULL;
2314144894Sharti
2315144894Sharti	/*
2316144894Sharti	 * Skip after the matching endfor.
2317144894Sharti	 */
2318144894Sharti	do {
2319144894Sharti		free(line);
2320144894Sharti		line = ParseSkipLine(0, 1);
2321144894Sharti		if (line == NULL) {
2322144894Sharti			Parse_Error(PARSE_FATAL,
2323144894Sharti			    "Unexpected end of file in for loop.\n");
2324144894Sharti			return;
2325144894Sharti		}
2326144894Sharti	} while (For_Eval(line));
2327144894Sharti	free(line);
2328144894Sharti
2329144894Sharti	/* execute */
2330144894Sharti	For_Run(lineno);
2331144894Sharti}
2332144894Sharti
2333144894Sharti/**
2334144894Sharti * parse_endfor
2335144894Sharti *	Parse endfor. This may only happen if there was no matching .for.
2336144894Sharti */
2337144894Shartistatic void
2338144894Shartiparse_endfor(char *line __unused, int code __unused, int lineno __unused)
2339144894Sharti{
2340144894Sharti
2341144894Sharti	Parse_Error(PARSE_FATAL, "for-less endfor");
2342144894Sharti}
2343144894Sharti
2344144894Sharti/**
2345144894Sharti * directive_hash
2346144894Sharti */
2347144894Shartistatic int
2348144894Shartidirective_hash(const u_char *key, size_t len)
2349144894Sharti{
2350144894Sharti	unsigned f0, f1;
2351144894Sharti	const u_char *kp = key;
2352144894Sharti
2353144894Sharti	if (len < 2 || len > 9)
2354144894Sharti		return (-1);
2355144894Sharti
2356144894Sharti	for (f0 = f1 = 0; kp < key + len; ++kp) {
2357144894Sharti		if (*kp < 97 || *kp > 119)
2358144894Sharti			return (-1);
2359144894Sharti		f0 += directive_T0[-97 + *kp];
2360144894Sharti		f1 += directive_T1[-97 + *kp];
2361144894Sharti	}
2362144894Sharti
2363144894Sharti	f0 %= 38;
2364144894Sharti	f1 %= 38;
2365144894Sharti
2366144894Sharti	return (directive_g[f0] + directive_g[f1]) % 18;
2367144894Sharti}
2368144894Sharti
2369144894Sharti/**
2370144894Sharti * parse_directive
2371144894Sharti *	Got a line starting with a '.'. Check if this is a directive
2372144894Sharti *	and parse it.
2373144894Sharti *
2374144894Sharti * return:
2375144894Sharti *	TRUE if line was a directive, FALSE otherwise.
2376144894Sharti */
2377144894Shartistatic Boolean
2378144894Shartiparse_directive(char *line)
2379144894Sharti{
2380144894Sharti	char	*start;
2381144894Sharti	char	*cp;
2382144894Sharti	int	dir;
2383144894Sharti
2384144894Sharti	/*
2385144894Sharti	 * Get the keyword:
2386144894Sharti	 *	.[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).*
2387144894Sharti	 * \1 is the keyword.
2388144894Sharti	 */
2389144894Sharti	for (start = line; isspace((u_char)*start); start++) {
2390144894Sharti		;
2391144894Sharti	}
2392144894Sharti
2393144894Sharti	if (!isalpha((u_char)*start)) {
2394144894Sharti		return (FALSE);
2395144894Sharti	}
2396144894Sharti
2397144894Sharti	cp = start + 1;
2398144894Sharti	while (isalnum((u_char)*cp) || *cp == '_') {
2399144894Sharti		cp++;
2400144894Sharti	}
2401144894Sharti
2402144894Sharti	dir = directive_hash(start, cp - start);
2403144894Sharti	if (dir < 0 || dir >= (int)NDIRECTS ||
2404144894Sharti	    (size_t)(cp - start) != strlen(directives[dir].name) ||
2405144894Sharti	    strncmp(start, directives[dir].name, cp - start) != 0) {
2406144894Sharti		/* not actually matched */
2407144894Sharti		return (FALSE);
2408144894Sharti	}
2409144894Sharti
2410144894Sharti	if (!skipLine || directives[dir].skip_flag)
2411144894Sharti		(*directives[dir].func)(cp, directives[dir].code,
2412144894Sharti		    CURFILE->lineno);
2413144894Sharti	return (TRUE);
2414144894Sharti}
2415144894Sharti
24161590Srgrimes/*-
24171590Srgrimes *---------------------------------------------------------------------
24181590Srgrimes * Parse_File --
24191590Srgrimes *	Parse a file into its component parts, incorporating it into the
24201590Srgrimes *	current dependency graph. This is the main function and controls
24211590Srgrimes *	almost every other function in this module
24221590Srgrimes *
24231590Srgrimes * Results:
24241590Srgrimes *	None
24251590Srgrimes *
24261590Srgrimes * Side Effects:
24271590Srgrimes *	Loads. Nodes are added to the list of all targets, nodes and links
24281590Srgrimes *	are added to the dependency graph. etc. etc. etc.
24291590Srgrimes *---------------------------------------------------------------------
24301590Srgrimes */
24311590Srgrimesvoid
2432144341ShartiParse_File(const char *name, FILE *stream)
24331590Srgrimes{
2434144026Sharti	char	*cp;	/* pointer into the line */
2435144026Sharti	char	*line;	/* the line we're working on */
24361590Srgrimes
2437144026Sharti	inLine = FALSE;
2438144026Sharti	fatals = 0;
24391590Srgrimes
2440144341Sharti	ParsePushInput(estrdup(name), stream, NULL, 0);
2441131456Seik
2442144742Sharti	while ((line = ParseReadLine()) != NULL) {
2443144894Sharti		if (*line == '.' && parse_directive(line + 1)) {
2444144894Sharti			/* directive consumed */
2445144894Sharti			goto nextLine;
2446144742Sharti		}
2447144894Sharti		if (skipLine || *line == '#') {
2448144894Sharti			/* Skipping .if block or comment. */
2449144742Sharti			goto nextLine;
2450144742Sharti		}
24518874Srgrimes
2452144742Sharti		if (*line == '\t') {
2453144742Sharti			/*
2454144742Sharti			 * If a line starts with a tab, it can only
2455144742Sharti			 * hope to be a creation command.
2456144742Sharti			 */
2457144742Sharti			for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
2458144742Sharti				continue;
2459144742Sharti			}
2460144742Sharti			if (*cp) {
2461144742Sharti				if (inLine) {
2462144742Sharti					LstNode	*ln;
2463144742Sharti					GNode	*gn;
2464143684Sharti
2465144742Sharti					/*
2466144742Sharti					 * So long as it's not a blank
2467144742Sharti					 * line and we're actually in a
2468144742Sharti					 * dependency spec, add the
2469144742Sharti					 * command to the list of
2470144742Sharti					 * commands of all targets in
2471144742Sharti					 * the dependency spec.
2472144742Sharti					 */
2473144742Sharti					LST_FOREACH(ln, &targets) {
2474144742Sharti						gn = Lst_Datum(ln);
2475144742Sharti
2476144026Sharti						/*
2477144742Sharti						 * if target already
2478144742Sharti						 * supplied, ignore
2479144742Sharti						 * commands
2480144026Sharti						 */
2481144742Sharti						if (!(gn->type & OP_HAS_COMMANDS))
2482144742Sharti							Lst_AtEnd(&gn->commands, cp);
2483144742Sharti						else
2484144742Sharti							Parse_Error(PARSE_WARNING, "duplicate script "
2485144742Sharti							    "for target \"%s\" ignored", gn->name);
2486144026Sharti					}
2487144742Sharti					continue;
2488144742Sharti				} else {
2489144742Sharti					Parse_Error(PARSE_FATAL,
2490144742Sharti					     "Unassociated shell command \"%s\"",
2491144742Sharti					     cp);
2492144026Sharti				}
2493144742Sharti			}
24941590Srgrimes#ifdef SYSVINCLUDE
2495144742Sharti		} else if (strncmp(line, "include", 7) == 0 &&
2496144742Sharti		    isspace((unsigned char)line[7]) &&
2497144742Sharti		    strchr(line, ':') == NULL) {
2498144742Sharti			/*
2499144742Sharti			 * It's an S3/S5-style "include".
2500144742Sharti			 */
2501144742Sharti			ParseTraditionalInclude(line + 7);
2502144742Sharti			goto nextLine;
25031590Srgrimes#endif
2504144742Sharti		} else if (Parse_IsVar(line)) {
2505144742Sharti			ParseFinishLine();
2506144742Sharti			Parse_DoVar(line, VAR_GLOBAL);
25078874Srgrimes
2508144742Sharti		} else {
2509144742Sharti			/*
2510144742Sharti			 * We now know it's a dependency line so it
2511144742Sharti			 * needs to have all variables expanded before
2512144742Sharti			 * being parsed. Tell the variable module to
2513144742Sharti			 * complain if some variable is undefined...
2514144742Sharti			 * To make life easier on novices, if the line
2515144742Sharti			 * is indented we first make sure the line has
2516144742Sharti			 * a dependency operator in it. If it doesn't
2517144742Sharti			 * have an operator and we're in a dependency
2518144742Sharti			 * line's script, we assume it's actually a
2519144742Sharti			 * shell command and add it to the current
2520144894Sharti			 * list of targets. XXX this comment seems wrong.
2521144742Sharti			 */
2522144742Sharti			cp = line;
2523144742Sharti			if (isspace((unsigned char)line[0])) {
2524144742Sharti				while (*cp != '\0' &&
2525144742Sharti				    isspace((unsigned char)*cp)) {
2526144742Sharti					cp++;
2527144026Sharti				}
2528144742Sharti				if (*cp == '\0') {
2529144742Sharti					goto nextLine;
2530144742Sharti				}
2531144742Sharti			}
25321590Srgrimes
2533144742Sharti			ParseFinishLine();
2534142457Sharti
2535144894Sharti			cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, TRUE));
25368874Srgrimes
2537144742Sharti			free(line);
2538144742Sharti			line = cp;
2539144026Sharti
2540144742Sharti			/*
2541144742Sharti			 * Need a non-circular list for the target nodes
2542144742Sharti			 */
2543144742Sharti			Lst_Destroy(&targets, NOFREE);
2544144742Sharti			inLine = TRUE;
2545144026Sharti
2546144742Sharti			ParseDoDependency(line);
2547144026Sharti		}
2548144026Sharti
2549144742Sharti  nextLine:
2550144742Sharti		free(line);
2551144742Sharti	}
25528874Srgrimes
2553144026Sharti	ParseFinishLine();
25541590Srgrimes
25551590Srgrimes	/*
2556144026Sharti	 * Make sure conditionals are clean
25571590Srgrimes	 */
2558144026Sharti	Cond_End();
25591590Srgrimes
2560144026Sharti	if (fatals)
2561144026Sharti		errx(1, "fatal errors encountered -- cannot continue");
25621590Srgrimes}
25631590Srgrimes
25641590Srgrimes/*-
25651590Srgrimes *-----------------------------------------------------------------------
25661590Srgrimes * Parse_MainName --
25671590Srgrimes *	Return a Lst of the main target to create for main()'s sake. If
25681590Srgrimes *	no such target exists, we Punt with an obnoxious error message.
25691590Srgrimes *
25701590Srgrimes * Results:
25711590Srgrimes *	A Lst of the single node to create.
25721590Srgrimes *
25731590Srgrimes * Side Effects:
25741590Srgrimes *	None.
25751590Srgrimes *
25761590Srgrimes *-----------------------------------------------------------------------
25771590Srgrimes */
2578138916Shartivoid
2579138916ShartiParse_MainName(Lst *listmain)
25801590Srgrimes{
25811590Srgrimes
2582144026Sharti	if (mainNode == NULL) {
2583144026Sharti		Punt("no target to make.");
2584144026Sharti		/*NOTREACHED*/
2585144026Sharti	} else if (mainNode->type & OP_DOUBLEDEP) {
2586144026Sharti		Lst_AtEnd(listmain, mainNode);
2587144026Sharti		Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW);
2588144026Sharti	} else
2589144026Sharti		Lst_AtEnd(listmain, mainNode);
25901590Srgrimes}
2591