xref: /freebsd/contrib/bmake/parse.c (revision dba7640e44c5ec148a84b0d58c6c9a3c9e5147f3)
1 /*	$NetBSD: parse.c,v 1.443 2020/11/16 21:39:22 rillig Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1989, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Adam de Boor.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /*
36  * Copyright (c) 1989 by Berkeley Softworks
37  * All rights reserved.
38  *
39  * This code is derived from software contributed to Berkeley by
40  * Adam de Boor.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *	This product includes software developed by the University of
53  *	California, Berkeley and its contributors.
54  * 4. Neither the name of the University nor the names of its contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  */
70 
71 /*
72  * Parsing of makefiles.
73  *
74  * Parse_File is the main entry point and controls most of the other
75  * functions in this module.
76  *
77  * The directories for the .include "..." directive are kept in
78  * 'parseIncPath', while those for .include <...> are kept in 'sysIncPath'.
79  * The targets currently being defined are kept in 'targets'.
80  *
81  * Interface:
82  *	Parse_Init	Initialize the module
83  *
84  *	Parse_End	Clean up the module
85  *
86  *	Parse_File	Parse a top-level makefile.  Included files are
87  *			handled by Parse_include_file though.
88  *
89  *	Parse_IsVar	Return TRUE if the given line is a variable
90  *			assignment. Used by MainParseArgs to determine if
91  *			an argument is a target or a variable assignment.
92  *			Used internally for pretty much the same thing.
93  *
94  *	Parse_Error	Report a parse error, a warning or an informational
95  *			message.
96  *
97  *	Parse_MainName	Returns a list of the main target to create.
98  */
99 
100 #include <sys/types.h>
101 #include <sys/stat.h>
102 #include <errno.h>
103 #include <stdarg.h>
104 
105 #include "make.h"
106 
107 #ifdef HAVE_STDINT_H
108 #include <stdint.h>
109 #endif
110 
111 #ifdef HAVE_MMAP
112 #include <sys/mman.h>
113 
114 #ifndef MAP_COPY
115 #define MAP_COPY MAP_PRIVATE
116 #endif
117 #ifndef MAP_FILE
118 #define MAP_FILE 0
119 #endif
120 #endif
121 
122 #include "dir.h"
123 #include "job.h"
124 #include "pathnames.h"
125 
126 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
127 MAKE_RCSID("$NetBSD: parse.c,v 1.443 2020/11/16 21:39:22 rillig Exp $");
128 
129 /* types and constants */
130 
131 /*
132  * Structure for a file being read ("included file")
133  */
134 typedef struct IFile {
135     char *fname;		/* name of file (relative? absolute?) */
136     Boolean fromForLoop;	/* simulated .include by the .for loop */
137     int lineno;			/* current line number in file */
138     int first_lineno;		/* line number of start of text */
139     unsigned int cond_depth;	/* 'if' nesting when file opened */
140     Boolean depending;		/* state of doing_depend on EOF */
141 
142     /* The buffer from which the file's content is read. */
143     char *buf_freeIt;
144     char *buf_ptr;		/* next char to be read */
145     char *buf_end;
146 
147     char *(*nextbuf)(void *, size_t *); /* Function to get more data */
148     void *nextbuf_arg;		/* Opaque arg for nextbuf() */
149     struct loadedfile *lf;	/* loadedfile object, if any */
150 } IFile;
151 
152 /*
153  * Tokens for target attributes
154  */
155 typedef enum ParseSpecial {
156     SP_ATTRIBUTE,	/* Generic attribute */
157     SP_BEGIN,		/* .BEGIN */
158     SP_DEFAULT,		/* .DEFAULT */
159     SP_DELETE_ON_ERROR,	/* .DELETE_ON_ERROR */
160     SP_END,		/* .END */
161     SP_ERROR,		/* .ERROR */
162     SP_IGNORE,		/* .IGNORE */
163     SP_INCLUDES,	/* .INCLUDES; not mentioned in the manual page */
164     SP_INTERRUPT,	/* .INTERRUPT */
165     SP_LIBS,		/* .LIBS; not mentioned in the manual page */
166     SP_MAIN,		/* .MAIN and we don't have anything user-specified to
167 			 * make */
168     SP_META,		/* .META */
169     SP_MFLAGS,		/* .MFLAGS or .MAKEFLAGS */
170     SP_NOMETA,		/* .NOMETA */
171     SP_NOMETA_CMP,	/* .NOMETA_CMP */
172     SP_NOPATH,		/* .NOPATH */
173     SP_NOT,		/* Not special */
174     SP_NOTPARALLEL,	/* .NOTPARALLEL or .NO_PARALLEL */
175     SP_NULL,		/* .NULL; not mentioned in the manual page */
176     SP_OBJDIR,		/* .OBJDIR */
177     SP_ORDER,		/* .ORDER */
178     SP_PARALLEL,	/* .PARALLEL; not mentioned in the manual page */
179     SP_PATH,		/* .PATH or .PATH.suffix */
180     SP_PHONY,		/* .PHONY */
181 #ifdef POSIX
182     SP_POSIX,		/* .POSIX; not mentioned in the manual page */
183 #endif
184     SP_PRECIOUS,	/* .PRECIOUS */
185     SP_SHELL,		/* .SHELL */
186     SP_SILENT,		/* .SILENT */
187     SP_SINGLESHELL,	/* .SINGLESHELL; not mentioned in the manual page */
188     SP_STALE,		/* .STALE */
189     SP_SUFFIXES,	/* .SUFFIXES */
190     SP_WAIT		/* .WAIT */
191 } ParseSpecial;
192 
193 typedef List SearchPathList;
194 typedef ListNode SearchPathListNode;
195 
196 /* result data */
197 
198 /*
199  * The main target to create. This is the first target on the first
200  * dependency line in the first makefile.
201  */
202 static GNode *mainNode;
203 
204 /* eval state */
205 
206 /* During parsing, the targets from the left-hand side of the currently
207  * active dependency line, or NULL if the current line does not belong to a
208  * dependency line, for example because it is a variable assignment.
209  *
210  * See unit-tests/deptgt.mk, keyword "parse.c:targets". */
211 static GNodeList *targets;
212 
213 #ifdef CLEANUP
214 /* All shell commands for all targets, in no particular order and possibly
215  * with duplicates.  Kept in a separate list since the commands from .USE or
216  * .USEBEFORE nodes are shared with other GNodes, thereby giving up the
217  * easily understandable ownership over the allocated strings. */
218 static StringList *targCmds;
219 #endif
220 
221 /*
222  * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
223  * seen, then set to each successive source on the line.
224  */
225 static GNode *order_pred;
226 
227 /* parser state */
228 
229 /* number of fatal errors */
230 static int fatals = 0;
231 
232 /*
233  * Variables for doing includes
234  */
235 
236 /* The include chain of makefiles.  At the bottom is the top-level makefile
237  * from the command line, and on top of that, there are the included files or
238  * .for loops, up to and including the current file.
239  *
240  * This data could be used to print stack traces on parse errors.  As of
241  * 2020-09-14, this is not done though.  It seems quite simple to print the
242  * tuples (fname:lineno:fromForLoop), from top to bottom.  This simple idea is
243  * made complicated by the fact that the .for loops also use this stack for
244  * storing information.
245  *
246  * The lineno fields of the IFiles with fromForLoop == TRUE look confusing,
247  * which is demonstrated by the test 'include-main.mk'.  They seem sorted
248  * backwards since they tell the number of completely parsed lines, which for
249  * a .for loop is right after the terminating .endfor.  To compensate for this
250  * confusion, there is another field first_lineno pointing at the start of the
251  * .for loop, 1-based for human consumption.
252  *
253  * To make the stack trace intuitive, the entry below the first .for loop must
254  * be ignored completely since neither its lineno nor its first_lineno is
255  * useful.  Instead, the topmost of each chain of .for loop needs to be
256  * printed twice, once with its first_lineno and once with its lineno.
257  *
258  * As of 2020-10-28, using the above rules, the stack trace for the .info line
259  * in include-subsub.mk would be:
260  *
261  *	includes[5]:	include-subsub.mk:4
262  *			(lineno, from an .include)
263  *	includes[4]:	include-sub.mk:32
264  *			(lineno, from a .for loop below an .include)
265  *	includes[4]:	include-sub.mk:31
266  *			(first_lineno, from a .for loop, lineno == 32)
267  *	includes[3]:	include-sub.mk:30
268  *			(first_lineno, from a .for loop, lineno == 33)
269  *	includes[2]:	include-sub.mk:29
270  *			(first_lineno, from a .for loop, lineno == 34)
271  *	includes[1]:	include-sub.mk:35
272  *			(not printed since it is below a .for loop)
273  *	includes[0]:	include-main.mk:27
274  */
275 static Vector /* of IFile */ includes;
276 
277 static IFile *
278 GetInclude(size_t i)
279 {
280     return Vector_Get(&includes, i);
281 }
282 
283 /* The file that is currently being read. */
284 static IFile *
285 CurFile(void)
286 {
287     return GetInclude(includes.len - 1);
288 }
289 
290 /* include paths */
291 SearchPath *parseIncPath;	/* dirs for "..." includes */
292 SearchPath *sysIncPath;		/* dirs for <...> includes */
293 SearchPath *defSysIncPath;	/* default for sysIncPath */
294 
295 /* parser tables */
296 
297 /*
298  * The parseKeywords table is searched using binary search when deciding
299  * if a target or source is special. The 'spec' field is the ParseSpecial
300  * type of the keyword (SP_NOT if the keyword isn't special as a target) while
301  * the 'op' field is the operator to apply to the list of targets if the
302  * keyword is used as a source ("0" if the keyword isn't special as a source)
303  */
304 static const struct {
305     const char   *name;		/* Name of keyword */
306     ParseSpecial  spec;		/* Type when used as a target */
307     GNodeType	  op;		/* Operator when used as a source */
308 } parseKeywords[] = {
309     { ".BEGIN",		SP_BEGIN,	0 },
310     { ".DEFAULT",	SP_DEFAULT,	0 },
311     { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, 0 },
312     { ".END",		SP_END,		0 },
313     { ".ERROR",		SP_ERROR,	0 },
314     { ".EXEC",		SP_ATTRIBUTE,	OP_EXEC },
315     { ".IGNORE",	SP_IGNORE,	OP_IGNORE },
316     { ".INCLUDES",	SP_INCLUDES,	0 },
317     { ".INTERRUPT",	SP_INTERRUPT,	0 },
318     { ".INVISIBLE",	SP_ATTRIBUTE,	OP_INVISIBLE },
319     { ".JOIN",		SP_ATTRIBUTE,	OP_JOIN },
320     { ".LIBS",		SP_LIBS,	0 },
321     { ".MADE",		SP_ATTRIBUTE,	OP_MADE },
322     { ".MAIN",		SP_MAIN,	0 },
323     { ".MAKE",		SP_ATTRIBUTE,	OP_MAKE },
324     { ".MAKEFLAGS",	SP_MFLAGS,	0 },
325     { ".META",		SP_META,	OP_META },
326     { ".MFLAGS",	SP_MFLAGS,	0 },
327     { ".NOMETA",	SP_NOMETA,	OP_NOMETA },
328     { ".NOMETA_CMP",	SP_NOMETA_CMP,	OP_NOMETA_CMP },
329     { ".NOPATH",	SP_NOPATH,	OP_NOPATH },
330     { ".NOTMAIN",	SP_ATTRIBUTE,	OP_NOTMAIN },
331     { ".NOTPARALLEL",	SP_NOTPARALLEL,	0 },
332     { ".NO_PARALLEL",	SP_NOTPARALLEL,	0 },
333     { ".NULL",		SP_NULL,	0 },
334     { ".OBJDIR",	SP_OBJDIR,	0 },
335     { ".OPTIONAL",	SP_ATTRIBUTE,	OP_OPTIONAL },
336     { ".ORDER",		SP_ORDER,	0 },
337     { ".PARALLEL",	SP_PARALLEL,	0 },
338     { ".PATH",		SP_PATH,	0 },
339     { ".PHONY",		SP_PHONY,	OP_PHONY },
340 #ifdef POSIX
341     { ".POSIX",		SP_POSIX,	0 },
342 #endif
343     { ".PRECIOUS",	SP_PRECIOUS,	OP_PRECIOUS },
344     { ".RECURSIVE",	SP_ATTRIBUTE,	OP_MAKE },
345     { ".SHELL",		SP_SHELL,	0 },
346     { ".SILENT",	SP_SILENT,	OP_SILENT },
347     { ".SINGLESHELL",	SP_SINGLESHELL,	0 },
348     { ".STALE",		SP_STALE,	0 },
349     { ".SUFFIXES",	SP_SUFFIXES,	0 },
350     { ".USE",		SP_ATTRIBUTE,	OP_USE },
351     { ".USEBEFORE",	SP_ATTRIBUTE,	OP_USEBEFORE },
352     { ".WAIT",		SP_WAIT,	0 },
353 };
354 
355 /* file loader */
356 
357 struct loadedfile {
358 	/* XXX: What is the lifetime of this path? Who manages the memory? */
359 	const char *path;		/* name, for error reports */
360 	char *buf;			/* contents buffer */
361 	size_t len;			/* length of contents */
362 	size_t maplen;			/* length of mmap area, or 0 */
363 	Boolean used;			/* XXX: have we used the data yet */
364 };
365 
366 /* XXX: What is the lifetime of the path? Who manages the memory? */
367 static struct loadedfile *
368 loadedfile_create(const char *path)
369 {
370 	struct loadedfile *lf;
371 
372 	lf = bmake_malloc(sizeof *lf);
373 	lf->path = path == NULL ? "(stdin)" : path;
374 	lf->buf = NULL;
375 	lf->len = 0;
376 	lf->maplen = 0;
377 	lf->used = FALSE;
378 	return lf;
379 }
380 
381 static void
382 loadedfile_destroy(struct loadedfile *lf)
383 {
384 	if (lf->buf != NULL) {
385 #ifdef HAVE_MMAP
386 		if (lf->maplen > 0)
387 			munmap(lf->buf, lf->maplen);
388 		else
389 #endif
390 			free(lf->buf);
391 	}
392 	free(lf);
393 }
394 
395 /*
396  * nextbuf() operation for loadedfile, as needed by the weird and twisted
397  * logic below. Once that's cleaned up, we can get rid of lf->used...
398  */
399 static char *
400 loadedfile_nextbuf(void *x, size_t *len)
401 {
402 	struct loadedfile *lf = x;
403 
404 	if (lf->used)
405 		return NULL;
406 
407 	lf->used = TRUE;
408 	*len = lf->len;
409 	return lf->buf;
410 }
411 
412 /*
413  * Try to get the size of a file.
414  */
415 static Boolean
416 load_getsize(int fd, size_t *ret)
417 {
418 	struct stat st;
419 
420 	if (fstat(fd, &st) < 0)
421 		return FALSE;
422 
423 	if (!S_ISREG(st.st_mode))
424 		return FALSE;
425 
426 	/*
427 	 * st_size is an off_t, which is 64 bits signed; *ret is
428 	 * size_t, which might be 32 bits unsigned or 64 bits
429 	 * unsigned. Rather than being elaborate, just punt on
430 	 * files that are more than 2^31 bytes. We should never
431 	 * see a makefile that size in practice...
432 	 *
433 	 * While we're at it reject negative sizes too, just in case.
434 	 */
435 	if (st.st_size < 0 || st.st_size > 0x7fffffff)
436 		return FALSE;
437 
438 	*ret = (size_t)st.st_size;
439 	return TRUE;
440 }
441 
442 #ifdef HAVE_MMAP
443 static Boolean
444 loadedfile_mmap(struct loadedfile *lf, int fd)
445 {
446 	static unsigned long pagesize = 0;
447 
448 	if (!load_getsize(fd, &lf->len))
449 		return FALSE;
450 
451 	/* found a size, try mmap */
452 #ifdef _SC_PAGESIZE
453 	if (pagesize == 0)
454 		pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
455 #endif
456 	if (pagesize == 0 || pagesize == (unsigned long)-1)
457 		pagesize = 0x1000;
458 
459 	/* round size up to a page */
460 	lf->maplen = pagesize * ((lf->len + pagesize - 1) / pagesize);
461 
462 	/*
463 	 * XXX hack for dealing with empty files; remove when
464 	 * we're no longer limited by interfacing to the old
465 	 * logic elsewhere in this file.
466 	 */
467 	if (lf->maplen == 0)
468 		lf->maplen = pagesize;
469 
470 	/*
471 	 * FUTURE: remove PROT_WRITE when the parser no longer
472 	 * needs to scribble on the input.
473 	 */
474 	lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE,
475 		       MAP_FILE|MAP_COPY, fd, 0);
476 	if (lf->buf == MAP_FAILED)
477 		return FALSE;
478 
479 	if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
480 		char *b = bmake_malloc(lf->len + 1);
481 		b[lf->len] = '\n';
482 		memcpy(b, lf->buf, lf->len++);
483 		munmap(lf->buf, lf->maplen);
484 		lf->maplen = 0;
485 		lf->buf = b;
486 	}
487 
488 	return TRUE;
489 }
490 #endif
491 
492 /*
493  * Read in a file.
494  *
495  * Until the path search logic can be moved under here instead of
496  * being in the caller in another source file, we need to have the fd
497  * passed in already open. Bleh.
498  *
499  * If the path is NULL, use stdin.
500  */
501 static struct loadedfile *
502 loadfile(const char *path, int fd)
503 {
504 	struct loadedfile *lf;
505 	ssize_t result;
506 	size_t bufpos;
507 
508 	lf = loadedfile_create(path);
509 
510 	if (path == NULL) {
511 		assert(fd == -1);
512 		fd = STDIN_FILENO;
513 	} else {
514 #if 0 /* notyet */
515 		fd = open(path, O_RDONLY);
516 		if (fd < 0) {
517 			...
518 			Error("%s: %s", path, strerror(errno));
519 			exit(1);
520 		}
521 #endif
522 	}
523 
524 #ifdef HAVE_MMAP
525 	if (loadedfile_mmap(lf, fd))
526 		goto done;
527 #endif
528 
529 	/* cannot mmap; load the traditional way */
530 
531 	lf->maplen = 0;
532 	lf->len = 1024;
533 	lf->buf = bmake_malloc(lf->len);
534 
535 	bufpos = 0;
536 	for (;;) {
537 		assert(bufpos <= lf->len);
538 		if (bufpos == lf->len) {
539 			if (lf->len > SIZE_MAX/2) {
540 				errno = EFBIG;
541 				Error("%s: file too large", path);
542 				exit(1);
543 			}
544 			lf->len *= 2;
545 			lf->buf = bmake_realloc(lf->buf, lf->len);
546 		}
547 		assert(bufpos < lf->len);
548 		result = read(fd, lf->buf + bufpos, lf->len - bufpos);
549 		if (result < 0) {
550 			Error("%s: read error: %s", path, strerror(errno));
551 			exit(1);
552 		}
553 		if (result == 0)
554 			break;
555 
556 		bufpos += (size_t)result;
557 	}
558 	assert(bufpos <= lf->len);
559 	lf->len = bufpos;
560 
561 	/* truncate malloc region to actual length (maybe not useful) */
562 	if (lf->len > 0) {
563 		/* as for mmap case, ensure trailing \n */
564 		if (lf->buf[lf->len - 1] != '\n')
565 			lf->len++;
566 		lf->buf = bmake_realloc(lf->buf, lf->len);
567 		lf->buf[lf->len - 1] = '\n';
568 	}
569 
570 #ifdef HAVE_MMAP
571 done:
572 #endif
573 	if (path != NULL)
574 		close(fd);
575 
576 	return lf;
577 }
578 
579 /* old code */
580 
581 /* Check if the current character is escaped on the current line. */
582 static Boolean
583 ParseIsEscaped(const char *line, const char *c)
584 {
585     Boolean active = FALSE;
586     for (;;) {
587 	if (line == c)
588 	    return active;
589 	if (*--c != '\\')
590 	    return active;
591 	active = !active;
592     }
593 }
594 
595 /* Add the filename and lineno to the GNode so that we remember where it
596  * was first defined. */
597 static void
598 ParseMark(GNode *gn)
599 {
600     IFile *curFile = CurFile();
601     gn->fname = curFile->fname;
602     gn->lineno = curFile->lineno;
603 }
604 
605 /* Look in the table of keywords for one matching the given string.
606  * Return the index of the keyword, or -1 if it isn't there. */
607 static int
608 ParseFindKeyword(const char *str)
609 {
610     int start = 0;
611     int end = sizeof parseKeywords / sizeof parseKeywords[0] - 1;
612 
613     do {
614 	int cur = start + (end - start) / 2;
615 	int diff = strcmp(str, parseKeywords[cur].name);
616 
617 	if (diff == 0)
618 	    return cur;
619 	if (diff < 0)
620 	    end = cur - 1;
621 	else
622 	    start = cur + 1;
623     } while (start <= end);
624 
625     return -1;
626 }
627 
628 static void
629 PrintLocation(FILE *f, const char *fname, size_t lineno)
630 {
631 	char dirbuf[MAXPATHLEN+1];
632 	const char *dir, *base;
633 	void *dir_freeIt, *base_freeIt;
634 
635 	if (*fname == '/' || strcmp(fname, "(stdin)") == 0) {
636 		(void)fprintf(f, "\"%s\" line %zu: ", fname, lineno);
637 		return;
638 	}
639 
640 	/* Find out which makefile is the culprit.
641 	 * We try ${.PARSEDIR} and apply realpath(3) if not absolute. */
642 
643 	dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &dir_freeIt);
644 	if (dir == NULL)
645 		dir = ".";
646 	if (*dir != '/')
647 		dir = realpath(dir, dirbuf);
648 
649 	base = Var_Value(".PARSEFILE", VAR_GLOBAL, &base_freeIt);
650 	if (base == NULL) {
651 		const char *slash = strrchr(fname, '/');
652 		base = slash != NULL ? slash + 1 : fname;
653 	}
654 
655 	(void)fprintf(f, "\"%s/%s\" line %zu: ", dir, base, lineno);
656 	bmake_free(base_freeIt);
657 	bmake_free(dir_freeIt);
658 }
659 
660 static void
661 ParseVErrorInternal(FILE *f, const char *fname, size_t lineno,
662 		    ParseErrorLevel type, const char *fmt, va_list ap)
663 {
664 	static Boolean fatal_warning_error_printed = FALSE;
665 
666 	(void)fprintf(f, "%s: ", progname);
667 
668 	if (fname != NULL)
669 		PrintLocation(f, fname, lineno);
670 	if (type == PARSE_WARNING)
671 		(void)fprintf(f, "warning: ");
672 	(void)vfprintf(f, fmt, ap);
673 	(void)fprintf(f, "\n");
674 	(void)fflush(f);
675 
676 	if (type == PARSE_INFO)
677 		return;
678 	if (type == PARSE_FATAL || opts.parseWarnFatal)
679 		fatals++;
680 	if (opts.parseWarnFatal && !fatal_warning_error_printed) {
681 		Error("parsing warnings being treated as errors");
682 		fatal_warning_error_printed = TRUE;
683 	}
684 }
685 
686 static void
687 ParseErrorInternal(const char *fname, size_t lineno,
688 		   ParseErrorLevel type, const char *fmt, ...)
689 {
690 	va_list ap;
691 
692 	(void)fflush(stdout);
693 	va_start(ap, fmt);
694 	ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
695 	va_end(ap);
696 
697 	if (opts.debug_file != stderr && opts.debug_file != stdout) {
698 		va_start(ap, fmt);
699 		ParseVErrorInternal(opts.debug_file, fname, lineno, type,
700 				    fmt, ap);
701 		va_end(ap);
702 	}
703 }
704 
705 /* Print a parse error message, including location information.
706  *
707  * If the level is PARSE_FATAL, continue parsing until the end of the
708  * current top-level makefile, then exit (see Parse_File).
709  *
710  * Fmt is given without a trailing newline. */
711 void
712 Parse_Error(ParseErrorLevel type, const char *fmt, ...)
713 {
714 	va_list ap;
715 	const char *fname;
716 	size_t lineno;
717 
718 	if (includes.len == 0) {
719 		fname = NULL;
720 		lineno = 0;
721 	} else {
722 		IFile *curFile = CurFile();
723 		fname = curFile->fname;
724 		lineno = (size_t)curFile->lineno;
725 	}
726 
727 	va_start(ap, fmt);
728 	(void)fflush(stdout);
729 	ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
730 	va_end(ap);
731 
732 	if (opts.debug_file != stderr && opts.debug_file != stdout) {
733 		va_start(ap, fmt);
734 		ParseVErrorInternal(opts.debug_file, fname, lineno, type,
735 				    fmt, ap);
736 		va_end(ap);
737 	}
738 }
739 
740 
741 /* Parse and handle a .info, .warning or .error directive.
742  * For an .error directive, immediately exit. */
743 static Boolean
744 ParseMessage(const char *directive)
745 {
746     const char *p = directive;
747     int mtype = *p == 'i' ? PARSE_INFO :
748 		*p == 'w' ? PARSE_WARNING : PARSE_FATAL;
749     char *arg;
750 
751     while (ch_isalpha(*p))
752 	p++;
753     if (!ch_isspace(*p))
754 	return FALSE;		/* missing argument */
755 
756     cpp_skip_whitespace(&p);
757     (void)Var_Subst(p, VAR_CMDLINE, VARE_WANTRES, &arg);
758     /* TODO: handle errors */
759 
760     Parse_Error(mtype, "%s", arg);
761     free(arg);
762 
763     if (mtype == PARSE_FATAL) {
764 	PrintOnError(NULL, NULL);
765 	exit(1);
766     }
767     return TRUE;
768 }
769 
770 /* Add the child to the parent's children.
771  *
772  * Additionally, add the parent to the child's parents, but only if the
773  * target is not special.  An example for such a special target is .END,
774  * which does not need to be informed once the child target has been made. */
775 static void
776 LinkSource(GNode *pgn, GNode *cgn, Boolean isSpecial)
777 {
778     if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(pgn->cohorts))
779 	pgn = pgn->cohorts->last->datum;
780 
781     Lst_Append(pgn->children, cgn);
782     pgn->unmade++;
783 
784     /* Special targets like .END don't need any children. */
785     if (!isSpecial)
786 	Lst_Append(cgn->parents, pgn);
787 
788     if (DEBUG(PARSE)) {
789 	debug_printf("# %s: added child %s - %s\n",
790 		     __func__, pgn->name, cgn->name);
791 	Targ_PrintNode(pgn, 0);
792 	Targ_PrintNode(cgn, 0);
793     }
794 }
795 
796 /* Add the node to each target from the current dependency group. */
797 static void
798 LinkToTargets(GNode *gn, Boolean isSpecial)
799 {
800     GNodeListNode *ln;
801     for (ln = targets->first; ln != NULL; ln = ln->next)
802 	LinkSource(ln->datum, gn, isSpecial);
803 }
804 
805 static Boolean
806 TryApplyDependencyOperator(GNode *gn, GNodeType op)
807 {
808     /*
809      * If the node occurred on the left-hand side of a dependency and the
810      * operator also defines a dependency, they must match.
811      */
812     if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) &&
813 	((op & OP_OPMASK) != (gn->type & OP_OPMASK)))
814     {
815 	Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
816 	return FALSE;
817     }
818 
819     if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
820 	/*
821 	 * If the node was of the left-hand side of a '::' operator, we need
822 	 * to create a new instance of it for the children and commands on
823 	 * this dependency line since each of these dependency groups has its
824 	 * own attributes and commands, separate from the others.
825 	 *
826 	 * The new instance is placed on the 'cohorts' list of the
827 	 * initial one (note the initial one is not on its own cohorts list)
828 	 * and the new instance is linked to all parents of the initial
829 	 * instance.
830 	 */
831 	GNode *cohort;
832 
833 	/*
834 	 * Propagate copied bits to the initial node.  They'll be propagated
835 	 * back to the rest of the cohorts later.
836 	 */
837 	gn->type |= op & ~OP_OPMASK;
838 
839 	cohort = Targ_NewInternalNode(gn->name);
840 	if (doing_depend)
841 	    ParseMark(cohort);
842 	/*
843 	 * Make the cohort invisible as well to avoid duplicating it into
844 	 * other variables. True, parents of this target won't tend to do
845 	 * anything with their local variables, but better safe than
846 	 * sorry. (I think this is pointless now, since the relevant list
847 	 * traversals will no longer see this node anyway. -mycroft)
848 	 */
849 	cohort->type = op | OP_INVISIBLE;
850 	Lst_Append(gn->cohorts, cohort);
851 	cohort->centurion = gn;
852 	gn->unmade_cohorts++;
853 	snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d",
854 		 (unsigned int)gn->unmade_cohorts % 1000000);
855     } else {
856 	/*
857 	 * We don't want to nuke any previous flags (whatever they were) so we
858 	 * just OR the new operator into the old.
859 	 */
860 	gn->type |= op;
861     }
862 
863     return TRUE;
864 }
865 
866 static void
867 ApplyDependencyOperator(GNodeType op)
868 {
869     GNodeListNode *ln;
870     for (ln = targets->first; ln != NULL; ln = ln->next)
871 	if (!TryApplyDependencyOperator(ln->datum, op))
872 	    break;
873 }
874 
875 static Boolean
876 ParseDoSrcKeyword(const char *src, ParseSpecial specType)
877 {
878     static int wait_number = 0;
879     char wait_src[16];
880     GNode *gn;
881 
882     if (*src == '.' && ch_isupper(src[1])) {
883 	int keywd = ParseFindKeyword(src);
884 	if (keywd != -1) {
885 	    GNodeType op = parseKeywords[keywd].op;
886 	    if (op != 0) {
887 		ApplyDependencyOperator(op);
888 		return TRUE;
889 	    }
890 	    if (parseKeywords[keywd].spec == SP_WAIT) {
891 		/*
892 		 * We add a .WAIT node in the dependency list.
893 		 * After any dynamic dependencies (and filename globbing)
894 		 * have happened, it is given a dependency on each
895 		 * previous child, back until the previous .WAIT node.
896 		 * The next child won't be scheduled until the .WAIT node
897 		 * is built.
898 		 * We give each .WAIT node a unique name (mainly for
899 		 * diagnostics).
900 		 */
901 		snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
902 		gn = Targ_NewInternalNode(wait_src);
903 		if (doing_depend)
904 		    ParseMark(gn);
905 		gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
906 		LinkToTargets(gn, specType != SP_NOT);
907 		return TRUE;
908 	    }
909 	}
910     }
911     return FALSE;
912 }
913 
914 static void
915 ParseDoSrcMain(const char *src)
916 {
917     /*
918      * In a line like ".MAIN: source1 source2", it means we need to add
919      * the sources of said target to the list of things to create.
920      *
921      * Note that this will only be invoked if the user didn't specify a
922      * target on the command line. This is to allow .ifmake to succeed.
923      *
924      * XXX: Double-check all of the above comment.
925      */
926     Lst_Append(opts.create, bmake_strdup(src));
927     /*
928      * Add the name to the .TARGETS variable as well, so the user can
929      * employ that, if desired.
930      */
931     Var_Append(".TARGETS", src, VAR_GLOBAL);
932 }
933 
934 static void
935 ParseDoSrcOrder(const char *src)
936 {
937     GNode *gn;
938     /*
939      * Create proper predecessor/successor links between the previous
940      * source and the current one.
941      */
942     gn = Targ_GetNode(src);
943     if (doing_depend)
944 	ParseMark(gn);
945     if (order_pred != NULL) {
946 	Lst_Append(order_pred->order_succ, gn);
947 	Lst_Append(gn->order_pred, order_pred);
948 	if (DEBUG(PARSE)) {
949 	    debug_printf("# %s: added Order dependency %s - %s\n",
950 			 __func__, order_pred->name, gn->name);
951 	    Targ_PrintNode(order_pred, 0);
952 	    Targ_PrintNode(gn, 0);
953 	}
954     }
955     /*
956      * The current source now becomes the predecessor for the next one.
957      */
958     order_pred = gn;
959 }
960 
961 static void
962 ParseDoSrcOther(const char *src, GNodeType tOp, ParseSpecial specType)
963 {
964     GNode *gn;
965 
966     /*
967      * If the source is not an attribute, we need to find/create
968      * a node for it. After that we can apply any operator to it
969      * from a special target or link it to its parents, as
970      * appropriate.
971      *
972      * In the case of a source that was the object of a :: operator,
973      * the attribute is applied to all of its instances (as kept in
974      * the 'cohorts' list of the node) or all the cohorts are linked
975      * to all the targets.
976      */
977 
978     /* Find/create the 'src' node and attach to all targets */
979     gn = Targ_GetNode(src);
980     if (doing_depend)
981 	ParseMark(gn);
982     if (tOp != OP_NONE)
983 	gn->type |= tOp;
984     else
985 	LinkToTargets(gn, specType != SP_NOT);
986 }
987 
988 /* Given the name of a source in a dependency line, figure out if it is an
989  * attribute (such as .SILENT) and apply it to the targets if it is. Else
990  * decide if there is some attribute which should be applied *to* the source
991  * because of some special target (such as .PHONY) and apply it if so.
992  * Otherwise, make the source a child of the targets in the list 'targets'.
993  *
994  * Input:
995  *	tOp		operator (if any) from special targets
996  *	src		name of the source to handle
997  */
998 static void
999 ParseDoSrc(GNodeType tOp, const char *src, ParseSpecial specType)
1000 {
1001     if (ParseDoSrcKeyword(src, specType))
1002 	return;
1003 
1004     if (specType == SP_MAIN)
1005 	ParseDoSrcMain(src);
1006     else if (specType == SP_ORDER)
1007 	ParseDoSrcOrder(src);
1008     else
1009 	ParseDoSrcOther(src, tOp, specType);
1010 }
1011 
1012 /* If we have yet to decide on a main target to make, in the absence of any
1013  * user input, we want the first target on the first dependency line that is
1014  * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made. */
1015 static void
1016 FindMainTarget(void)
1017 {
1018     GNodeListNode *ln;
1019 
1020     if (mainNode != NULL)
1021 	return;
1022 
1023     for (ln = targets->first; ln != NULL; ln = ln->next) {
1024 	GNode *gn = ln->datum;
1025 	if (!(gn->type & OP_NOTARGET)) {
1026 	    mainNode = gn;
1027 	    Targ_SetMain(gn);
1028 	    return;
1029 	}
1030     }
1031 }
1032 
1033 /*
1034  * We got to the end of the line while we were still looking at targets.
1035  *
1036  * Ending a dependency line without an operator is a Bozo no-no.  As a
1037  * heuristic, this is also often triggered by undetected conflicts from
1038  * cvs/rcs merges.
1039  */
1040 static void
1041 ParseErrorNoDependency(const char *lstart)
1042 {
1043     if ((strncmp(lstart, "<<<<<<", 6) == 0) ||
1044 	(strncmp(lstart, "======", 6) == 0) ||
1045 	(strncmp(lstart, ">>>>>>", 6) == 0))
1046 	Parse_Error(PARSE_FATAL,
1047 		    "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
1048     else if (lstart[0] == '.') {
1049 	const char *dirstart = lstart + 1;
1050 	const char *dirend;
1051 	cpp_skip_whitespace(&dirstart);
1052 	dirend = dirstart;
1053 	while (ch_isalnum(*dirend) || *dirend == '-')
1054 	    dirend++;
1055 	Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
1056 		    (int)(dirend - dirstart), dirstart);
1057     } else
1058 	Parse_Error(PARSE_FATAL, "Need an operator");
1059 }
1060 
1061 static void
1062 ParseDependencyTargetWord(/*const*/ char **pp, const char *lstart)
1063 {
1064     /*const*/ char *cp = *pp;
1065 
1066     while (*cp != '\0') {
1067 	if ((ch_isspace(*cp) || *cp == '!' || *cp == ':' || *cp == '(') &&
1068 	    !ParseIsEscaped(lstart, cp))
1069 	    break;
1070 
1071 	if (*cp == '$') {
1072 	    /*
1073 	     * Must be a dynamic source (would have been expanded
1074 	     * otherwise), so call the Var module to parse the puppy
1075 	     * so we can safely advance beyond it...There should be
1076 	     * no errors in this, as they would have been discovered
1077 	     * in the initial Var_Subst and we wouldn't be here.
1078 	     */
1079 	    const char *nested_p = cp;
1080 	    const char *nested_val;
1081 	    void *freeIt;
1082 
1083 	    (void)Var_Parse(&nested_p, VAR_CMDLINE,
1084 			    VARE_WANTRES | VARE_UNDEFERR, &nested_val, &freeIt);
1085 	    /* TODO: handle errors */
1086 	    free(freeIt);
1087 	    cp += nested_p - cp;
1088 	} else
1089 	    cp++;
1090     }
1091 
1092     *pp = cp;
1093 }
1094 
1095 /* Handle special targets like .PATH, .DEFAULT, .BEGIN, .ORDER. */
1096 static void
1097 ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType,
1098 			       const char *line,
1099 			       SearchPathList **inout_paths)
1100 {
1101     switch (*inout_specType) {
1102     case SP_PATH:
1103 	if (*inout_paths == NULL)
1104 	    *inout_paths = Lst_New();
1105 	Lst_Append(*inout_paths, dirSearchPath);
1106 	break;
1107     case SP_MAIN:
1108 	/* Allow targets from the command line to override the .MAIN node. */
1109 	if (!Lst_IsEmpty(opts.create))
1110 	    *inout_specType = SP_NOT;
1111 	break;
1112     case SP_BEGIN:
1113     case SP_END:
1114     case SP_STALE:
1115     case SP_ERROR:
1116     case SP_INTERRUPT: {
1117 	GNode *gn = Targ_GetNode(line);
1118 	if (doing_depend)
1119 	    ParseMark(gn);
1120 	gn->type |= OP_NOTMAIN|OP_SPECIAL;
1121 	Lst_Append(targets, gn);
1122 	break;
1123     }
1124     case SP_DEFAULT: {
1125 	/* Need to create a node to hang commands on, but we don't want it
1126 	 * in the graph, nor do we want it to be the Main Target. We claim
1127 	 * the node is a transformation rule to make life easier later,
1128 	 * when we'll use Make_HandleUse to actually apply the .DEFAULT
1129 	 * commands. */
1130 	GNode *gn = GNode_New(".DEFAULT");
1131 	gn->type |= OP_NOTMAIN|OP_TRANSFORM;
1132 	Lst_Append(targets, gn);
1133 	defaultNode = gn;
1134 	break;
1135     }
1136     case SP_DELETE_ON_ERROR:
1137 	deleteOnError = TRUE;
1138 	break;
1139     case SP_NOTPARALLEL:
1140 	opts.maxJobs = 1;
1141 	break;
1142     case SP_SINGLESHELL:
1143 	opts.compatMake = TRUE;
1144 	break;
1145     case SP_ORDER:
1146 	order_pred = NULL;
1147 	break;
1148     default:
1149 	break;
1150     }
1151 }
1152 
1153 /*
1154  * .PATH<suffix> has to be handled specially.
1155  * Call on the suffix module to give us a path to modify.
1156  */
1157 static Boolean
1158 ParseDoDependencyTargetPath(const char *line, SearchPathList **inout_paths)
1159 {
1160     SearchPath *path;
1161 
1162     path = Suff_GetPath(&line[5]);
1163     if (path == NULL) {
1164 	Parse_Error(PARSE_FATAL,
1165 		    "Suffix '%s' not defined (yet)",
1166 		    &line[5]);
1167 	return FALSE;
1168     }
1169 
1170     if (*inout_paths == NULL)
1171 	*inout_paths = Lst_New();
1172     Lst_Append(*inout_paths, path);
1173 
1174     return TRUE;
1175 }
1176 
1177 /*
1178  * See if it's a special target and if so set specType to match it.
1179  */
1180 static Boolean
1181 ParseDoDependencyTarget(const char *line, ParseSpecial *inout_specType,
1182 			GNodeType *out_tOp, SearchPathList **inout_paths)
1183 {
1184     int keywd;
1185 
1186     if (!(*line == '.' && ch_isupper(line[1])))
1187 	return TRUE;
1188 
1189     /*
1190      * See if the target is a special target that must have it
1191      * or its sources handled specially.
1192      */
1193     keywd = ParseFindKeyword(line);
1194     if (keywd != -1) {
1195 	if (*inout_specType == SP_PATH && parseKeywords[keywd].spec != SP_PATH) {
1196 	    Parse_Error(PARSE_FATAL, "Mismatched special targets");
1197 	    return FALSE;
1198 	}
1199 
1200 	*inout_specType = parseKeywords[keywd].spec;
1201 	*out_tOp = parseKeywords[keywd].op;
1202 
1203 	ParseDoDependencyTargetSpecial(inout_specType, line, inout_paths);
1204 
1205     } else if (strncmp(line, ".PATH", 5) == 0) {
1206 	*inout_specType = SP_PATH;
1207 	if (!ParseDoDependencyTargetPath(line, inout_paths))
1208 	    return FALSE;
1209     }
1210     return TRUE;
1211 }
1212 
1213 static void
1214 ParseDoDependencyTargetMundane(char *line, StringList *curTargs)
1215 {
1216     if (Dir_HasWildcards(line)) {
1217 	/*
1218 	 * Targets are to be sought only in the current directory,
1219 	 * so create an empty path for the thing. Note we need to
1220 	 * use Dir_Destroy in the destruction of the path as the
1221 	 * Dir module could have added a directory to the path...
1222 	 */
1223 	SearchPath *emptyPath = Lst_New();
1224 
1225 	Dir_Expand(line, emptyPath, curTargs);
1226 
1227 	Lst_Destroy(emptyPath, Dir_Destroy);
1228     } else {
1229 	/*
1230 	 * No wildcards, but we want to avoid code duplication,
1231 	 * so create a list with the word on it.
1232 	 */
1233 	Lst_Append(curTargs, line);
1234     }
1235 
1236     /* Apply the targets. */
1237 
1238     while (!Lst_IsEmpty(curTargs)) {
1239 	char *targName = Lst_Dequeue(curTargs);
1240 	GNode *gn = Suff_IsTransform(targName)
1241 		    ? Suff_AddTransform(targName)
1242 		    : Targ_GetNode(targName);
1243 	if (doing_depend)
1244 	    ParseMark(gn);
1245 
1246 	Lst_Append(targets, gn);
1247     }
1248 }
1249 
1250 static void
1251 ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart)
1252 {
1253     Boolean warning = FALSE;
1254     char *cp = *pp;
1255 
1256     while (*cp != '\0') {
1257 	if (!ParseIsEscaped(lstart, cp) && (*cp == '!' || *cp == ':'))
1258 	    break;
1259 	if (ParseIsEscaped(lstart, cp) || (*cp != ' ' && *cp != '\t'))
1260 	    warning = TRUE;
1261 	cp++;
1262     }
1263     if (warning)
1264 	Parse_Error(PARSE_WARNING, "Extra target ignored");
1265 
1266     *pp = cp;
1267 }
1268 
1269 static void
1270 ParseDoDependencyCheckSpec(ParseSpecial specType)
1271 {
1272     switch (specType) {
1273     default:
1274 	Parse_Error(PARSE_WARNING,
1275 		    "Special and mundane targets don't mix. "
1276 		    "Mundane ones ignored");
1277 	break;
1278     case SP_DEFAULT:
1279     case SP_STALE:
1280     case SP_BEGIN:
1281     case SP_END:
1282     case SP_ERROR:
1283     case SP_INTERRUPT:
1284 	/*
1285 	 * These create nodes on which to hang commands, so targets
1286 	 * shouldn't be empty...
1287 	 */
1288     case SP_NOT:
1289 	/* Nothing special here -- targets can be empty if it wants. */
1290 	break;
1291     }
1292 }
1293 
1294 static Boolean
1295 ParseDoDependencyParseOp(char **pp, const char *lstart, GNodeType *out_op)
1296 {
1297     const char *cp = *pp;
1298 
1299     if (*cp == '!') {
1300 	*out_op = OP_FORCE;
1301 	(*pp)++;
1302 	return TRUE;
1303     }
1304 
1305     if (*cp == ':') {
1306 	if (cp[1] == ':') {
1307 	    *out_op = OP_DOUBLEDEP;
1308 	    (*pp) += 2;
1309 	} else {
1310 	    *out_op = OP_DEPENDS;
1311 	    (*pp)++;
1312 	}
1313 	return TRUE;
1314     }
1315 
1316     {
1317 	const char *msg = lstart[0] == '.' ? "Unknown directive"
1318 					   : "Missing dependency operator";
1319 	Parse_Error(PARSE_FATAL, "%s", msg);
1320 	return FALSE;
1321     }
1322 }
1323 
1324 static void
1325 ClearPaths(SearchPathList *paths)
1326 {
1327     if (paths != NULL) {
1328 	SearchPathListNode *ln;
1329 	for (ln = paths->first; ln != NULL; ln = ln->next)
1330 	    Dir_ClearPath(ln->datum);
1331     }
1332 
1333     Dir_SetPATH();
1334 }
1335 
1336 static void
1337 ParseDoDependencySourcesEmpty(ParseSpecial specType, SearchPathList *paths)
1338 {
1339     switch (specType) {
1340     case SP_SUFFIXES:
1341 	Suff_ClearSuffixes();
1342 	break;
1343     case SP_PRECIOUS:
1344 	allPrecious = TRUE;
1345 	break;
1346     case SP_IGNORE:
1347 	opts.ignoreErrors = TRUE;
1348 	break;
1349     case SP_SILENT:
1350 	opts.beSilent = TRUE;
1351 	break;
1352     case SP_PATH:
1353 	ClearPaths(paths);
1354 	break;
1355 #ifdef POSIX
1356     case SP_POSIX:
1357 	Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1358 	break;
1359 #endif
1360     default:
1361 	break;
1362     }
1363 }
1364 
1365 static void
1366 AddToPaths(const char *dir, SearchPathList *paths)
1367 {
1368     if (paths != NULL) {
1369 	SearchPathListNode *ln;
1370 	for (ln = paths->first; ln != NULL; ln = ln->next)
1371 	    (void)Dir_AddDir(ln->datum, dir);
1372     }
1373 }
1374 
1375 /*
1376  * If the target was one that doesn't take files as its sources
1377  * but takes something like suffixes, we take each
1378  * space-separated word on the line as a something and deal
1379  * with it accordingly.
1380  *
1381  * If the target was .SUFFIXES, we take each source as a
1382  * suffix and add it to the list of suffixes maintained by the
1383  * Suff module.
1384  *
1385  * If the target was a .PATH, we add the source as a directory
1386  * to search on the search path.
1387  *
1388  * If it was .INCLUDES, the source is taken to be the suffix of
1389  * files which will be #included and whose search path should
1390  * be present in the .INCLUDES variable.
1391  *
1392  * If it was .LIBS, the source is taken to be the suffix of
1393  * files which are considered libraries and whose search path
1394  * should be present in the .LIBS variable.
1395  *
1396  * If it was .NULL, the source is the suffix to use when a file
1397  * has no valid suffix.
1398  *
1399  * If it was .OBJDIR, the source is a new definition for .OBJDIR,
1400  * and will cause make to do a new chdir to that path.
1401  */
1402 static void
1403 ParseDoDependencySourceSpecial(ParseSpecial specType, char *word,
1404 			       SearchPathList *paths)
1405 {
1406     switch (specType) {
1407     case SP_SUFFIXES:
1408 	Suff_AddSuffix(word, &mainNode);
1409 	break;
1410     case SP_PATH:
1411 	AddToPaths(word, paths);
1412 	break;
1413     case SP_INCLUDES:
1414 	Suff_AddInclude(word);
1415 	break;
1416     case SP_LIBS:
1417 	Suff_AddLib(word);
1418 	break;
1419     case SP_NULL:
1420 	Suff_SetNull(word);
1421 	break;
1422     case SP_OBJDIR:
1423 	Main_SetObjdir(FALSE, "%s", word);
1424 	break;
1425     default:
1426 	break;
1427     }
1428 }
1429 
1430 static Boolean
1431 ParseDoDependencyTargets(char **inout_cp,
1432 			 char **inout_line,
1433 			 const char *lstart,
1434 			 ParseSpecial *inout_specType,
1435 			 GNodeType *inout_tOp,
1436 			 SearchPathList **inout_paths,
1437 			 StringList *curTargs)
1438 {
1439     char *cp = *inout_cp;
1440     char *line = *inout_line;
1441     char savec;
1442 
1443     for (;;) {
1444 	/*
1445 	 * Here LINE points to the beginning of the next word, and
1446 	 * LSTART points to the actual beginning of the line.
1447 	 */
1448 
1449 	/* Find the end of the next word. */
1450 	cp = line;
1451 	ParseDependencyTargetWord(&cp, lstart);
1452 
1453 	/*
1454 	 * If the word is followed by a left parenthesis, it's the
1455 	 * name of an object file inside an archive (ar file).
1456 	 */
1457 	if (!ParseIsEscaped(lstart, cp) && *cp == '(') {
1458 	    /*
1459 	     * Archives must be handled specially to make sure the OP_ARCHV
1460 	     * flag is set in their 'type' field, for one thing, and because
1461 	     * things like "archive(file1.o file2.o file3.o)" are permissible.
1462 	     * Arch_ParseArchive will set 'line' to be the first non-blank
1463 	     * after the archive-spec. It creates/finds nodes for the members
1464 	     * and places them on the given list, returning TRUE if all
1465 	     * went well and FALSE if there was an error in the
1466 	     * specification. On error, line should remain untouched.
1467 	     */
1468 	    if (!Arch_ParseArchive(&line, targets, VAR_CMDLINE)) {
1469 		Parse_Error(PARSE_FATAL,
1470 			    "Error in archive specification: \"%s\"", line);
1471 		return FALSE;
1472 	    } else {
1473 		/* Done with this word; on to the next. */
1474 		cp = line;
1475 		continue;
1476 	    }
1477 	}
1478 
1479 	if (!*cp) {
1480 	    ParseErrorNoDependency(lstart);
1481 	    return FALSE;
1482 	}
1483 
1484 	/* Insert a null terminator. */
1485 	savec = *cp;
1486 	*cp = '\0';
1487 
1488 	if (!ParseDoDependencyTarget(line, inout_specType, inout_tOp,
1489 				     inout_paths))
1490 	    return FALSE;
1491 
1492 	/*
1493 	 * Have word in line. Get or create its node and stick it at
1494 	 * the end of the targets list
1495 	 */
1496 	if (*inout_specType == SP_NOT && *line != '\0')
1497 	    ParseDoDependencyTargetMundane(line, curTargs);
1498 	else if (*inout_specType == SP_PATH && *line != '.' && *line != '\0')
1499 	    Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1500 
1501 	/* Don't need the inserted null terminator any more. */
1502 	*cp = savec;
1503 
1504 	/*
1505 	 * If it is a special type and not .PATH, it's the only target we
1506 	 * allow on this line...
1507 	 */
1508 	if (*inout_specType != SP_NOT && *inout_specType != SP_PATH)
1509 	    ParseDoDependencyTargetExtraWarn(&cp, lstart);
1510 	else
1511 	    pp_skip_whitespace(&cp);
1512 
1513 	line = cp;
1514 	if (*line == '\0')
1515 	    break;
1516 	if ((*line == '!' || *line == ':') && !ParseIsEscaped(lstart, line))
1517 	    break;
1518     }
1519 
1520     *inout_cp = cp;
1521     *inout_line = line;
1522     return TRUE;
1523 }
1524 
1525 static void
1526 ParseDoDependencySourcesSpecial(char *start, char *end,
1527 				ParseSpecial specType, SearchPathList *paths)
1528 {
1529     char savec;
1530 
1531     while (*start) {
1532 	while (*end && !ch_isspace(*end))
1533 	    end++;
1534 	savec = *end;
1535 	*end = '\0';
1536 	ParseDoDependencySourceSpecial(specType, start, paths);
1537 	*end = savec;
1538 	if (savec != '\0')
1539 	    end++;
1540 	pp_skip_whitespace(&end);
1541 	start = end;
1542     }
1543 }
1544 
1545 static Boolean
1546 ParseDoDependencySourcesMundane(char *start, char *end,
1547 				ParseSpecial specType, GNodeType tOp)
1548 {
1549     while (*start != '\0') {
1550 	/*
1551 	 * The targets take real sources, so we must beware of archive
1552 	 * specifications (i.e. things with left parentheses in them)
1553 	 * and handle them accordingly.
1554 	 */
1555 	for (; *end && !ch_isspace(*end); end++) {
1556 	    if (*end == '(' && end > start && end[-1] != '$') {
1557 		/*
1558 		 * Only stop for a left parenthesis if it isn't at the
1559 		 * start of a word (that'll be for variable changes
1560 		 * later) and isn't preceded by a dollar sign (a dynamic
1561 		 * source).
1562 		 */
1563 		break;
1564 	    }
1565 	}
1566 
1567 	if (*end == '(') {
1568 	    GNodeList *sources = Lst_New();
1569 	    if (!Arch_ParseArchive(&start, sources, VAR_CMDLINE)) {
1570 		Parse_Error(PARSE_FATAL,
1571 			    "Error in source archive spec \"%s\"", start);
1572 		return FALSE;
1573 	    }
1574 
1575 	    while (!Lst_IsEmpty(sources)) {
1576 		GNode *gn = Lst_Dequeue(sources);
1577 		ParseDoSrc(tOp, gn->name, specType);
1578 	    }
1579 	    Lst_Free(sources);
1580 	    end = start;
1581 	} else {
1582 	    if (*end) {
1583 		*end = '\0';
1584 		end++;
1585 	    }
1586 
1587 	    ParseDoSrc(tOp, start, specType);
1588 	}
1589 	pp_skip_whitespace(&end);
1590 	start = end;
1591     }
1592     return TRUE;
1593 }
1594 
1595 /* Parse a dependency line consisting of targets, followed by a dependency
1596  * operator, optionally followed by sources.
1597  *
1598  * The nodes of the sources are linked as children to the nodes of the
1599  * targets. Nodes are created as necessary.
1600  *
1601  * The operator is applied to each node in the global 'targets' list,
1602  * which is where the nodes found for the targets are kept, by means of
1603  * the ParseDoOp function.
1604  *
1605  * The sources are parsed in much the same way as the targets, except
1606  * that they are expanded using the wildcarding scheme of the C-Shell,
1607  * and a target is created for each expanded word. Each of the resulting
1608  * nodes is then linked to each of the targets as one of its children.
1609  *
1610  * Certain targets and sources such as .PHONY or .PRECIOUS are handled
1611  * specially. These are the ones detailed by the specType variable.
1612  *
1613  * The storing of transformation rules such as '.c.o' is also taken care of
1614  * here. A target is recognized as a transformation rule by calling
1615  * Suff_IsTransform. If it is a transformation rule, its node is gotten
1616  * from the suffix module via Suff_AddTransform rather than the standard
1617  * Targ_FindNode in the target module.
1618  *
1619  * Upon return, the value of the line is unspecified.
1620  */
1621 static void
1622 ParseDoDependency(char *line)
1623 {
1624     char *cp;			/* our current position */
1625     GNodeType op;		/* the operator on the line */
1626     SearchPathList *paths;	/* search paths to alter when parsing
1627 				 * a list of .PATH targets */
1628     GNodeType tOp;		/* operator from special target */
1629     StringList *curTargs;	/* target names to be found and added
1630 				 * to the targets list */
1631     char *lstart = line;
1632 
1633     /*
1634      * specType contains the SPECial TYPE of the current target. It is SP_NOT
1635      * if the target is unspecial. If it *is* special, however, the children
1636      * are linked as children of the parent but not vice versa.
1637      */
1638     ParseSpecial specType = SP_NOT;
1639 
1640     DEBUG1(PARSE, "ParseDoDependency(%s)\n", line);
1641     tOp = OP_NONE;
1642 
1643     paths = NULL;
1644 
1645     curTargs = Lst_New();
1646 
1647     /*
1648      * First, grind through the targets.
1649      */
1650     if (!ParseDoDependencyTargets(&cp, &line, lstart, &specType, &tOp, &paths,
1651 				  curTargs))
1652 	goto out;
1653 
1654     /* Don't need the list of target names anymore.
1655      * The targets themselves are now in the global variable 'targets'. */
1656     Lst_Free(curTargs);
1657     curTargs = NULL;
1658 
1659     if (!Lst_IsEmpty(targets))
1660 	ParseDoDependencyCheckSpec(specType);
1661 
1662     /*
1663      * Have now parsed all the target names. Must parse the operator next.
1664      */
1665     if (!ParseDoDependencyParseOp(&cp, lstart, &op))
1666 	goto out;
1667 
1668     /*
1669      * Apply the operator to the target. This is how we remember which
1670      * operator a target was defined with. It fails if the operator
1671      * used isn't consistent across all references.
1672      */
1673     ApplyDependencyOperator(op);
1674 
1675     /*
1676      * Onward to the sources.
1677      *
1678      * LINE will now point to the first source word, if any, or the
1679      * end of the string if not.
1680      */
1681     pp_skip_whitespace(&cp);
1682     line = cp;			/* XXX: 'line' is an inappropriate name */
1683 
1684     /*
1685      * Several special targets take different actions if present with no
1686      * sources:
1687      *	a .SUFFIXES line with no sources clears out all old suffixes
1688      *	a .PRECIOUS line makes all targets precious
1689      *	a .IGNORE line ignores errors for all targets
1690      *	a .SILENT line creates silence when making all targets
1691      *	a .PATH removes all directories from the search path(s).
1692      */
1693     if (line[0] == '\0') {
1694 	ParseDoDependencySourcesEmpty(specType, paths);
1695     } else if (specType == SP_MFLAGS) {
1696 	/*
1697 	 * Call on functions in main.c to deal with these arguments and
1698 	 * set the initial character to a null-character so the loop to
1699 	 * get sources won't get anything
1700 	 */
1701 	Main_ParseArgLine(line);
1702 	*line = '\0';
1703     } else if (specType == SP_SHELL) {
1704 	if (!Job_ParseShell(line)) {
1705 	    Parse_Error(PARSE_FATAL, "improper shell specification");
1706 	    goto out;
1707 	}
1708 	*line = '\0';
1709     } else if (specType == SP_NOTPARALLEL || specType == SP_SINGLESHELL ||
1710 	       specType == SP_DELETE_ON_ERROR) {
1711 	*line = '\0';
1712     }
1713 
1714     /* Now go for the sources. */
1715     if (specType == SP_SUFFIXES || specType == SP_PATH ||
1716 	specType == SP_INCLUDES || specType == SP_LIBS ||
1717 	specType == SP_NULL || specType == SP_OBJDIR)
1718     {
1719 	ParseDoDependencySourcesSpecial(line, cp, specType, paths);
1720 	if (paths) {
1721 	    Lst_Free(paths);
1722 	    paths = NULL;
1723 	}
1724 	if (specType == SP_PATH)
1725 	    Dir_SetPATH();
1726     } else {
1727 	assert(paths == NULL);
1728 	if (!ParseDoDependencySourcesMundane(line, cp, specType, tOp))
1729 	    goto out;
1730     }
1731 
1732     FindMainTarget();
1733 
1734 out:
1735     if (paths != NULL)
1736 	Lst_Free(paths);
1737     if (curTargs != NULL)
1738 	Lst_Free(curTargs);
1739 }
1740 
1741 typedef struct VarAssignParsed {
1742     const char *nameStart;	/* unexpanded */
1743     const char *nameEnd;	/* before operator adjustment */
1744     const char *eq;		/* the '=' of the assignment operator */
1745 } VarAssignParsed;
1746 
1747 /* Determine the assignment operator and adjust the end of the variable
1748  * name accordingly. */
1749 static void
1750 AdjustVarassignOp(const VarAssignParsed *pvar, const char *value,
1751 		  VarAssign *out_var)
1752 {
1753     const char *op = pvar->eq;
1754     const char * const name = pvar->nameStart;
1755     VarAssignOp type;
1756 
1757     if (op > name && op[-1] == '+') {
1758 	type = VAR_APPEND;
1759 	op--;
1760 
1761     } else if (op > name && op[-1] == '?') {
1762 	op--;
1763 	type = VAR_DEFAULT;
1764 
1765     } else if (op > name && op[-1] == ':') {
1766 	op--;
1767 	type = VAR_SUBST;
1768 
1769     } else if (op > name && op[-1] == '!') {
1770 	op--;
1771 	type = VAR_SHELL;
1772 
1773     } else {
1774 	type = VAR_NORMAL;
1775 #ifdef SUNSHCMD
1776 	while (op > name && ch_isspace(op[-1]))
1777 	    op--;
1778 
1779 	if (op >= name + 3 && op[-3] == ':' && op[-2] == 's' && op[-1] == 'h') {
1780 	    type = VAR_SHELL;
1781 	    op -= 3;
1782 	}
1783 #endif
1784     }
1785 
1786     {
1787 	const char *nameEnd = pvar->nameEnd < op ? pvar->nameEnd : op;
1788 	out_var->varname = bmake_strsedup(pvar->nameStart, nameEnd);
1789 	out_var->op = type;
1790 	out_var->value = value;
1791     }
1792 }
1793 
1794 /* Parse a variable assignment, consisting of a single-word variable name,
1795  * optional whitespace, an assignment operator, optional whitespace and the
1796  * variable value.
1797  *
1798  * Note: There is a lexical ambiguity with assignment modifier characters
1799  * in variable names. This routine interprets the character before the =
1800  * as a modifier. Therefore, an assignment like
1801  *	C++=/usr/bin/CC
1802  * is interpreted as "C+ +=" instead of "C++ =".
1803  *
1804  * Used for both lines in a file and command line arguments. */
1805 Boolean
1806 Parse_IsVar(const char *p, VarAssign *out_var)
1807 {
1808     VarAssignParsed pvar;
1809     const char *firstSpace = NULL;
1810     int level = 0;
1811 
1812     cpp_skip_hspace(&p);	/* Skip to variable name */
1813 
1814     /* During parsing, the '+' of the '+=' operator is initially parsed
1815      * as part of the variable name.  It is later corrected, as is the ':sh'
1816      * modifier. Of these two (nameEnd and op), the earlier one determines the
1817      * actual end of the variable name. */
1818     pvar.nameStart = p;
1819 #ifdef CLEANUP
1820     pvar.nameEnd = NULL;
1821     pvar.eq = NULL;
1822 #endif
1823 
1824     /* Scan for one of the assignment operators outside a variable expansion */
1825     while (*p != '\0') {
1826 	char ch = *p++;
1827 	if (ch == '(' || ch == '{') {
1828 	    level++;
1829 	    continue;
1830 	}
1831 	if (ch == ')' || ch == '}') {
1832 	    level--;
1833 	    continue;
1834 	}
1835 
1836 	if (level != 0)
1837 	    continue;
1838 
1839 	if (ch == ' ' || ch == '\t')
1840 	    if (firstSpace == NULL)
1841 		firstSpace = p - 1;
1842 	while (ch == ' ' || ch == '\t')
1843 	    ch = *p++;
1844 
1845 #ifdef SUNSHCMD
1846 	if (ch == ':' && p[0] == 's' && p[1] == 'h') {
1847 	    p += 2;
1848 	    continue;
1849 	}
1850 #endif
1851 	if (ch == '=') {
1852 	    pvar.eq = p - 1;
1853 	    pvar.nameEnd = firstSpace != NULL ? firstSpace : p - 1;
1854 	    cpp_skip_whitespace(&p);
1855 	    AdjustVarassignOp(&pvar, p, out_var);
1856 	    return TRUE;
1857 	}
1858 	if (*p == '=' && (ch == '+' || ch == ':' || ch == '?' || ch == '!')) {
1859 	    pvar.eq = p;
1860 	    pvar.nameEnd = firstSpace != NULL ? firstSpace : p;
1861 	    p++;
1862 	    cpp_skip_whitespace(&p);
1863 	    AdjustVarassignOp(&pvar, p, out_var);
1864 	    return TRUE;
1865 	}
1866 	if (firstSpace != NULL)
1867 	    return FALSE;
1868     }
1869 
1870     return FALSE;
1871 }
1872 
1873 static void
1874 VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *ctxt)
1875 {
1876     if (opts.lint) {
1877 	if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) {
1878 	    /* Check for syntax errors such as unclosed expressions or
1879 	     * unknown modifiers. */
1880 	    char *expandedValue;
1881 
1882 	    (void)Var_Subst(uvalue, ctxt, VARE_NONE, &expandedValue);
1883 	    /* TODO: handle errors */
1884 	    free(expandedValue);
1885 	}
1886     }
1887 }
1888 
1889 static void
1890 VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *ctxt,
1891 		    const char **out_avalue, void **out_avalue_freeIt)
1892 {
1893     const char *avalue = uvalue;
1894     char *evalue;
1895     Boolean savedPreserveUndefined = preserveUndefined;
1896 
1897     /* TODO: Can this assignment to preserveUndefined be moved further down
1898      * to the actually interesting Var_Subst call, without affecting any
1899      * edge cases?
1900      *
1901      * It might affect the implicit expansion of the variable name in the
1902      * Var_Exists and Var_Set calls, even though it's unlikely that anyone
1903      * cared about this edge case when adding this code.  In addition,
1904      * variable assignments should not refer to any undefined variables in
1905      * the variable name. */
1906     preserveUndefined = TRUE;
1907 
1908     /*
1909      * make sure that we set the variable the first time to nothing
1910      * so that it gets substituted!
1911      */
1912     if (!Var_Exists(name, ctxt))
1913 	Var_Set(name, "", ctxt);
1914 
1915     (void)Var_Subst(uvalue, ctxt, VARE_WANTRES|VARE_KEEP_DOLLAR, &evalue);
1916     /* TODO: handle errors */
1917     preserveUndefined = savedPreserveUndefined;
1918     avalue = evalue;
1919     Var_Set(name, avalue, ctxt);
1920 
1921     *out_avalue = avalue;
1922     *out_avalue_freeIt = evalue;
1923 }
1924 
1925 static void
1926 VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt,
1927 		    const char **out_avalue, void **out_avalue_freeIt)
1928 {
1929     const char *cmd, *errfmt;
1930     char *cmdOut;
1931     void *cmd_freeIt = NULL;
1932 
1933     cmd = uvalue;
1934     if (strchr(cmd, '$') != NULL) {
1935 	char *ecmd;
1936 	(void)Var_Subst(cmd, VAR_CMDLINE, VARE_WANTRES | VARE_UNDEFERR, &ecmd);
1937 	/* TODO: handle errors */
1938 	cmd = cmd_freeIt = ecmd;
1939     }
1940 
1941     cmdOut = Cmd_Exec(cmd, &errfmt);
1942     Var_Set(name, cmdOut, ctxt);
1943     *out_avalue = *out_avalue_freeIt = cmdOut;
1944 
1945     if (errfmt)
1946 	Parse_Error(PARSE_WARNING, errfmt, cmd);
1947 
1948     free(cmd_freeIt);
1949 }
1950 
1951 /* Perform a variable assignment.
1952  *
1953  * The actual value of the variable is returned in *out_avalue and
1954  * *out_avalue_freeIt.  Especially for VAR_SUBST and VAR_SHELL this can differ
1955  * from the literal value.
1956  *
1957  * Return whether the assignment was actually done.  The assignment is only
1958  * skipped if the operator is '?=' and the variable already exists. */
1959 static Boolean
1960 VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
1961 	       GNode *ctxt, const char **out_avalue, void **out_avalue_freeIt)
1962 {
1963     const char *avalue = uvalue;
1964     void *avalue_freeIt = NULL;
1965 
1966     if (op == VAR_APPEND)
1967 	Var_Append(name, uvalue, ctxt);
1968     else if (op == VAR_SUBST)
1969 	VarAssign_EvalSubst(name, uvalue, ctxt, &avalue, &avalue_freeIt);
1970     else if (op == VAR_SHELL)
1971 	VarAssign_EvalShell(name, uvalue, ctxt, &avalue, &avalue_freeIt);
1972     else {
1973 	if (op == VAR_DEFAULT && Var_Exists(name, ctxt)) {
1974 	    *out_avalue_freeIt = NULL;
1975 	    return FALSE;
1976 	}
1977 
1978 	/* Normal assignment -- just do it. */
1979 	Var_Set(name, uvalue, ctxt);
1980     }
1981 
1982     *out_avalue = avalue;
1983     *out_avalue_freeIt = avalue_freeIt;
1984     return TRUE;
1985 }
1986 
1987 static void
1988 VarAssignSpecial(const char *name, const char *avalue)
1989 {
1990     if (strcmp(name, MAKEOVERRIDES) == 0)
1991 	Main_ExportMAKEFLAGS(FALSE);	/* re-export MAKEFLAGS */
1992     else if (strcmp(name, ".CURDIR") == 0) {
1993 	/*
1994 	 * Someone is being (too?) clever...
1995 	 * Let's pretend they know what they are doing and
1996 	 * re-initialize the 'cur' CachedDir.
1997 	 */
1998 	Dir_InitCur(avalue);
1999 	Dir_SetPATH();
2000     } else if (strcmp(name, MAKE_JOB_PREFIX) == 0)
2001 	Job_SetPrefix();
2002     else if (strcmp(name, MAKE_EXPORTED) == 0)
2003 	Var_Export(avalue, FALSE);
2004 }
2005 
2006 /* Perform the variable variable assignment in the given context. */
2007 void
2008 Parse_DoVar(VarAssign *var, GNode *ctxt)
2009 {
2010     const char *avalue;		/* actual value (maybe expanded) */
2011     void *avalue_freeIt;
2012 
2013     VarCheckSyntax(var->op, var->value, ctxt);
2014     if (VarAssign_Eval(var->varname, var->op, var->value, ctxt,
2015 		       &avalue, &avalue_freeIt))
2016 	VarAssignSpecial(var->varname, avalue);
2017 
2018     free(avalue_freeIt);
2019     free(var->varname);
2020 }
2021 
2022 
2023 /* See if the command possibly calls a sub-make by using the variable
2024  * expressions ${.MAKE}, ${MAKE} or the plain word "make". */
2025 static Boolean
2026 MaybeSubMake(const char *cmd)
2027 {
2028     const char *start;
2029 
2030     for (start = cmd; *start != '\0'; start++) {
2031 	const char *p = start;
2032 	char endc;
2033 
2034 	/* XXX: What if progname != "make"? */
2035 	if (p[0] == 'm' && p[1] == 'a' && p[2] == 'k' && p[3] == 'e')
2036 	    if (start == cmd || !ch_isalnum(p[-1]))
2037 		if (!ch_isalnum(p[4]))
2038 		    return TRUE;
2039 
2040 	if (*p != '$')
2041 	    continue;
2042 	p++;
2043 
2044 	if (*p == '{')
2045 	    endc = '}';
2046 	else if (*p == '(')
2047 	    endc = ')';
2048 	else
2049 	    continue;
2050 	p++;
2051 
2052 	if (*p == '.')		/* Accept either ${.MAKE} or ${MAKE}. */
2053 	    p++;
2054 
2055 	if (p[0] == 'M' && p[1] == 'A' && p[2] == 'K' && p[3] == 'E')
2056 	    if (p[4] == endc)
2057 		return TRUE;
2058     }
2059     return FALSE;
2060 }
2061 
2062 /* Append the command to the target node.
2063  *
2064  * The node may be marked as a submake node if the command is determined to
2065  * be that. */
2066 static void
2067 ParseAddCmd(GNode *gn, char *cmd)
2068 {
2069     /* Add to last (ie current) cohort for :: targets */
2070     if ((gn->type & OP_DOUBLEDEP) && gn->cohorts->last != NULL)
2071 	gn = gn->cohorts->last->datum;
2072 
2073     /* if target already supplied, ignore commands */
2074     if (!(gn->type & OP_HAS_COMMANDS)) {
2075 	Lst_Append(gn->commands, cmd);
2076 	if (MaybeSubMake(cmd))
2077 	    gn->type |= OP_SUBMAKE;
2078 	ParseMark(gn);
2079     } else {
2080 #if 0
2081 	/* XXX: We cannot do this until we fix the tree */
2082 	Lst_Append(gn->commands, cmd);
2083 	Parse_Error(PARSE_WARNING,
2084 		     "overriding commands for target \"%s\"; "
2085 		     "previous commands defined at %s: %d ignored",
2086 		     gn->name, gn->fname, gn->lineno);
2087 #else
2088 	Parse_Error(PARSE_WARNING,
2089 		    "duplicate script for target \"%s\" ignored",
2090 		    gn->name);
2091 	ParseErrorInternal(gn->fname, (size_t)gn->lineno, PARSE_WARNING,
2092 			   "using previous script for \"%s\" defined here",
2093 			   gn->name);
2094 #endif
2095     }
2096 }
2097 
2098 /* Add a directory to the path searched for included makefiles bracketed
2099  * by double-quotes. */
2100 void
2101 Parse_AddIncludeDir(const char *dir)
2102 {
2103     (void)Dir_AddDir(parseIncPath, dir);
2104 }
2105 
2106 /* Handle one of the .[-ds]include directives by remembering the current file
2107  * and pushing the included file on the stack.  After the included file has
2108  * finished, parsing continues with the including file; see Parse_SetInput
2109  * and ParseEOF.
2110  *
2111  * System includes are looked up in sysIncPath, any other includes are looked
2112  * up in the parsedir and then in the directories specified by the -I command
2113  * line options.
2114  */
2115 static void
2116 Parse_include_file(char *file, Boolean isSystem, Boolean depinc, Boolean silent)
2117 {
2118     struct loadedfile *lf;
2119     char *fullname;		/* full pathname of file */
2120     char *newName;
2121     char *slash, *incdir;
2122     int fd;
2123     int i;
2124 
2125     fullname = file[0] == '/' ? bmake_strdup(file) : NULL;
2126 
2127     if (fullname == NULL && !isSystem) {
2128 	/*
2129 	 * Include files contained in double-quotes are first searched
2130 	 * relative to the including file's location. We don't want to
2131 	 * cd there, of course, so we just tack on the old file's
2132 	 * leading path components and call Dir_FindFile to see if
2133 	 * we can locate the file.
2134 	 */
2135 
2136 	incdir = bmake_strdup(CurFile()->fname);
2137 	slash = strrchr(incdir, '/');
2138 	if (slash != NULL) {
2139 	    *slash = '\0';
2140 	    /* Now do lexical processing of leading "../" on the filename */
2141 	    for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) {
2142 		slash = strrchr(incdir + 1, '/');
2143 		if (slash == NULL || strcmp(slash, "/..") == 0)
2144 		    break;
2145 		*slash = '\0';
2146 	    }
2147 	    newName = str_concat3(incdir, "/", file + i);
2148 	    fullname = Dir_FindFile(newName, parseIncPath);
2149 	    if (fullname == NULL)
2150 		fullname = Dir_FindFile(newName, dirSearchPath);
2151 	    free(newName);
2152 	}
2153 	free(incdir);
2154 
2155 	if (fullname == NULL) {
2156 	    /*
2157 	     * Makefile wasn't found in same directory as included makefile.
2158 	     * Search for it first on the -I search path,
2159 	     * then on the .PATH search path, if not found in a -I directory.
2160 	     * If we have a suffix specific path we should use that.
2161 	     */
2162 	    const char *suff;
2163 	    SearchPath *suffPath = NULL;
2164 
2165 	    if ((suff = strrchr(file, '.'))) {
2166 		suffPath = Suff_GetPath(suff);
2167 		if (suffPath != NULL)
2168 		    fullname = Dir_FindFile(file, suffPath);
2169 	    }
2170 	    if (fullname == NULL) {
2171 		fullname = Dir_FindFile(file, parseIncPath);
2172 		if (fullname == NULL)
2173 		    fullname = Dir_FindFile(file, dirSearchPath);
2174 	    }
2175 	}
2176     }
2177 
2178     /* Looking for a system file or file still not found */
2179     if (fullname == NULL) {
2180 	/*
2181 	 * Look for it on the system path
2182 	 */
2183 	SearchPath *path = Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath;
2184 	fullname = Dir_FindFile(file, path);
2185     }
2186 
2187     if (fullname == NULL) {
2188 	if (!silent)
2189 	    Parse_Error(PARSE_FATAL, "Could not find %s", file);
2190 	return;
2191     }
2192 
2193     /* Actually open the file... */
2194     fd = open(fullname, O_RDONLY);
2195     if (fd == -1) {
2196 	if (!silent)
2197 	    Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
2198 	free(fullname);
2199 	return;
2200     }
2201 
2202     /* load it */
2203     lf = loadfile(fullname, fd);
2204 
2205     /* Start reading from this file next */
2206     Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
2207     CurFile()->lf = lf;
2208     if (depinc)
2209 	doing_depend = depinc;	/* only turn it on */
2210 }
2211 
2212 static void
2213 ParseDoInclude(char *line)
2214 {
2215     char endc;			/* the character which ends the file spec */
2216     char *cp;			/* current position in file spec */
2217     Boolean silent = *line != 'i';
2218     char *file = line + (silent ? 8 : 7);
2219 
2220     /* Skip to delimiter character so we know where to look */
2221     pp_skip_hspace(&file);
2222 
2223     if (*file != '"' && *file != '<') {
2224 	Parse_Error(PARSE_FATAL,
2225 		    ".include filename must be delimited by '\"' or '<'");
2226 	return;
2227     }
2228 
2229     /*
2230      * Set the search path on which to find the include file based on the
2231      * characters which bracket its name. Angle-brackets imply it's
2232      * a system Makefile while double-quotes imply it's a user makefile
2233      */
2234     if (*file == '<')
2235 	endc = '>';
2236     else
2237 	endc = '"';
2238 
2239     /* Skip to matching delimiter */
2240     for (cp = ++file; *cp && *cp != endc; cp++)
2241 	continue;
2242 
2243     if (*cp != endc) {
2244 	Parse_Error(PARSE_FATAL,
2245 		    "Unclosed .include filename. '%c' expected", endc);
2246 	return;
2247     }
2248 
2249     *cp = '\0';
2250 
2251     /*
2252      * Substitute for any variables in the filename before trying to
2253      * find the file.
2254      */
2255     (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &file);
2256     /* TODO: handle errors */
2257 
2258     Parse_include_file(file, endc == '>', *line == 'd', silent);
2259     free(file);
2260 }
2261 
2262 /* Split filename into dirname + basename, then assign these to the
2263  * given variables. */
2264 static void
2265 SetFilenameVars(const char *filename, const char *dirvar, const char *filevar)
2266 {
2267     const char *slash, *dirname, *basename;
2268     void *freeIt;
2269 
2270     slash = strrchr(filename, '/');
2271     if (slash == NULL) {
2272 	dirname = curdir;
2273 	basename = filename;
2274 	freeIt = NULL;
2275     } else {
2276 	dirname = freeIt = bmake_strsedup(filename, slash);
2277 	basename = slash + 1;
2278     }
2279 
2280     Var_Set(dirvar, dirname, VAR_GLOBAL);
2281     Var_Set(filevar, basename, VAR_GLOBAL);
2282 
2283     DEBUG5(PARSE, "%s: ${%s} = `%s' ${%s} = `%s'\n",
2284 	   __func__, dirvar, dirname, filevar, basename);
2285     free(freeIt);
2286 }
2287 
2288 /* Return the immediately including file.
2289  *
2290  * This is made complicated since the .for loop is implemented as a special
2291  * kind of .include; see For_Run. */
2292 static const char *
2293 GetActuallyIncludingFile(void)
2294 {
2295     size_t i;
2296     const IFile *incs = GetInclude(0);
2297 
2298     for (i = includes.len; i >= 2; i--)
2299 	if (!incs[i - 1].fromForLoop)
2300 	    return incs[i - 2].fname;
2301     return NULL;
2302 }
2303 
2304 /* Set .PARSEDIR, .PARSEFILE, .INCLUDEDFROMDIR and .INCLUDEDFROMFILE. */
2305 static void
2306 ParseSetParseFile(const char *filename)
2307 {
2308     const char *including;
2309 
2310     SetFilenameVars(filename, ".PARSEDIR", ".PARSEFILE");
2311 
2312     including = GetActuallyIncludingFile();
2313     if (including != NULL) {
2314 	SetFilenameVars(including,
2315 			".INCLUDEDFROMDIR", ".INCLUDEDFROMFILE");
2316     } else {
2317 	Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL);
2318 	Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL);
2319     }
2320 }
2321 
2322 static Boolean
2323 StrContainsWord(const char *str, const char *word)
2324 {
2325     size_t strLen = strlen(str);
2326     size_t wordLen = strlen(word);
2327     const char *p, *end;
2328 
2329     if (strLen < wordLen)
2330 	return FALSE;		/* str is too short to contain word */
2331 
2332     end = str + strLen - wordLen;
2333     for (p = str; p != NULL; p = strchr(p, ' ')) {
2334 	if (*p == ' ')
2335 	    p++;
2336 	if (p > end)
2337 	    return FALSE;	/* cannot contain word */
2338 
2339 	if (memcmp(p, word, wordLen) == 0 &&
2340 	    (p[wordLen] == '\0' || p[wordLen] == ' '))
2341 	    return TRUE;
2342     }
2343     return FALSE;
2344 }
2345 
2346 /* XXX: Searching through a set of words with this linear search is
2347  * inefficient for variables that contain thousands of words. */
2348 /* XXX: The paths in this list don't seem to be normalized in any way. */
2349 static Boolean
2350 VarContainsWord(const char *varname, const char *word)
2351 {
2352     void *val_freeIt;
2353     const char *val = Var_Value(varname, VAR_GLOBAL, &val_freeIt);
2354     Boolean found = val != NULL && StrContainsWord(val, word);
2355     bmake_free(val_freeIt);
2356     return found;
2357 }
2358 
2359 /* Track the makefiles we read - so makefiles can set dependencies on them.
2360  * Avoid adding anything more than once.
2361  *
2362  * Time complexity: O(n) per call, in total O(n^2), where n is the number
2363  * of makefiles that have been loaded. */
2364 static void
2365 ParseTrackInput(const char *name)
2366 {
2367     if (!VarContainsWord(MAKE_MAKEFILES, name))
2368 	Var_Append(MAKE_MAKEFILES, name, VAR_GLOBAL);
2369 }
2370 
2371 
2372 /* Start parsing from the given source.
2373  *
2374  * The given file is added to the includes stack. */
2375 void
2376 Parse_SetInput(const char *name, int line, int fd,
2377 	       char *(*nextbuf)(void *, size_t *), void *arg)
2378 {
2379     IFile *curFile;
2380     char *buf;
2381     size_t len;
2382     Boolean fromForLoop = name == NULL;
2383 
2384     if (fromForLoop)
2385 	name = CurFile()->fname;
2386     else
2387 	ParseTrackInput(name);
2388 
2389     if (DEBUG(PARSE))
2390 	debug_printf("%s: file %s, line %d, fd %d, nextbuf %s, arg %p\n",
2391 		     __func__, name, line, fd,
2392 		     nextbuf == loadedfile_nextbuf ? "loadedfile" : "other",
2393 		     arg);
2394 
2395     if (fd == -1 && nextbuf == NULL)
2396 	/* sanity */
2397 	return;
2398 
2399     curFile = Vector_Push(&includes);
2400     curFile->fname = bmake_strdup(name);
2401     curFile->fromForLoop = fromForLoop;
2402     curFile->lineno = line;
2403     curFile->first_lineno = line;
2404     curFile->nextbuf = nextbuf;
2405     curFile->nextbuf_arg = arg;
2406     curFile->lf = NULL;
2407     curFile->depending = doing_depend;	/* restore this on EOF */
2408 
2409     assert(nextbuf != NULL);
2410 
2411     /* Get first block of input data */
2412     buf = curFile->nextbuf(curFile->nextbuf_arg, &len);
2413     if (buf == NULL) {
2414 	/* Was all a waste of time ... */
2415 	if (curFile->fname)
2416 	    free(curFile->fname);
2417 	free(curFile);
2418 	return;
2419     }
2420     curFile->buf_freeIt = buf;
2421     curFile->buf_ptr = buf;
2422     curFile->buf_end = buf + len;
2423 
2424     curFile->cond_depth = Cond_save_depth();
2425     ParseSetParseFile(name);
2426 }
2427 
2428 /* Check if the directive is an include directive. */
2429 static Boolean
2430 IsInclude(const char *dir, Boolean sysv)
2431 {
2432 	if (dir[0] == 's' || dir[0] == '-' || (dir[0] == 'd' && !sysv))
2433 		dir++;
2434 
2435 	if (strncmp(dir, "include", 7) != 0)
2436 		return FALSE;
2437 
2438 	/* Space is not mandatory for BSD .include */
2439 	return !sysv || ch_isspace(dir[7]);
2440 }
2441 
2442 
2443 #ifdef SYSVINCLUDE
2444 /* Check if the line is a SYSV include directive. */
2445 static Boolean
2446 IsSysVInclude(const char *line)
2447 {
2448 	const char *p;
2449 
2450 	if (!IsInclude(line, TRUE))
2451 		return FALSE;
2452 
2453 	/* Avoid interpreting a dependency line as an include */
2454 	for (p = line; (p = strchr(p, ':')) != NULL;) {
2455 
2456 		/* end of line -> it's a dependency */
2457 		if (*++p == '\0')
2458 			return FALSE;
2459 
2460 		/* '::' operator or ': ' -> it's a dependency */
2461 		if (*p == ':' || ch_isspace(*p))
2462 			return FALSE;
2463 	}
2464 	return TRUE;
2465 }
2466 
2467 /* Push to another file.  The line points to the word "include". */
2468 static void
2469 ParseTraditionalInclude(char *line)
2470 {
2471     char *cp;			/* current position in file spec */
2472     Boolean done = FALSE;
2473     Boolean silent = line[0] != 'i';
2474     char *file = line + (silent ? 8 : 7);
2475     char *all_files;
2476 
2477     DEBUG2(PARSE, "%s: %s\n", __func__, file);
2478 
2479     pp_skip_whitespace(&file);
2480 
2481     /*
2482      * Substitute for any variables in the file name before trying to
2483      * find the thing.
2484      */
2485     (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &all_files);
2486     /* TODO: handle errors */
2487 
2488     if (*file == '\0') {
2489 	Parse_Error(PARSE_FATAL, "Filename missing from \"include\"");
2490 	goto out;
2491     }
2492 
2493     for (file = all_files; !done; file = cp + 1) {
2494 	/* Skip to end of line or next whitespace */
2495 	for (cp = file; *cp && !ch_isspace(*cp); cp++)
2496 	    continue;
2497 
2498 	if (*cp != '\0')
2499 	    *cp = '\0';
2500 	else
2501 	    done = TRUE;
2502 
2503 	Parse_include_file(file, FALSE, FALSE, silent);
2504     }
2505 out:
2506     free(all_files);
2507 }
2508 #endif
2509 
2510 #ifdef GMAKEEXPORT
2511 /* Parse "export <variable>=<value>", and actually export it. */
2512 static void
2513 ParseGmakeExport(char *line)
2514 {
2515     char *variable = line + 6;
2516     char *value;
2517 
2518     DEBUG2(PARSE, "%s: %s\n", __func__, variable);
2519 
2520     pp_skip_whitespace(&variable);
2521 
2522     for (value = variable; *value && *value != '='; value++)
2523 	continue;
2524 
2525     if (*value != '=') {
2526 	Parse_Error(PARSE_FATAL,
2527 		    "Variable/Value missing from \"export\"");
2528 	return;
2529     }
2530     *value++ = '\0';		/* terminate variable */
2531 
2532     /*
2533      * Expand the value before putting it in the environment.
2534      */
2535     (void)Var_Subst(value, VAR_CMDLINE, VARE_WANTRES, &value);
2536     /* TODO: handle errors */
2537 
2538     setenv(variable, value, 1);
2539     free(value);
2540 }
2541 #endif
2542 
2543 /* Called when EOF is reached in the current file. If we were reading an
2544  * include file or a .for loop, the includes stack is popped and things set
2545  * up to go back to reading the previous file at the previous location.
2546  *
2547  * Results:
2548  *	TRUE to continue parsing, i.e. it had only reached the end of an
2549  *	included file, FALSE if the main file has been parsed completely.
2550  */
2551 static Boolean
2552 ParseEOF(void)
2553 {
2554     char *ptr;
2555     size_t len;
2556     IFile *curFile = CurFile();
2557 
2558     assert(curFile->nextbuf != NULL);
2559 
2560     doing_depend = curFile->depending;	/* restore this */
2561     /* get next input buffer, if any */
2562     ptr = curFile->nextbuf(curFile->nextbuf_arg, &len);
2563     curFile->buf_ptr = ptr;
2564     curFile->buf_freeIt = ptr;
2565     curFile->buf_end = ptr + len; /* XXX: undefined behavior if ptr == NULL */
2566     curFile->lineno = curFile->first_lineno;
2567     if (ptr != NULL)
2568 	return TRUE;		/* Iterate again */
2569 
2570     /* Ensure the makefile (or loop) didn't have mismatched conditionals */
2571     Cond_restore_depth(curFile->cond_depth);
2572 
2573     if (curFile->lf != NULL) {
2574 	loadedfile_destroy(curFile->lf);
2575 	curFile->lf = NULL;
2576     }
2577 
2578     /* Dispose of curFile info */
2579     /* Leak curFile->fname because all the gnodes have pointers to it */
2580     free(curFile->buf_freeIt);
2581     Vector_Pop(&includes);
2582 
2583     if (includes.len == 0) {
2584 	/* We've run out of input */
2585 	Var_Delete(".PARSEDIR", VAR_GLOBAL);
2586 	Var_Delete(".PARSEFILE", VAR_GLOBAL);
2587 	Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL);
2588 	Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL);
2589 	return FALSE;
2590     }
2591 
2592     curFile = CurFile();
2593     DEBUG2(PARSE, "ParseEOF: returning to file %s, line %d\n",
2594 	   curFile->fname, curFile->lineno);
2595 
2596     ParseSetParseFile(curFile->fname);
2597     return TRUE;
2598 }
2599 
2600 typedef enum GetLineMode {
2601     PARSE_NORMAL,
2602     PARSE_RAW,
2603     PARSE_SKIP
2604 } GetLineMode;
2605 
2606 static char *
2607 ParseGetLine(GetLineMode mode)
2608 {
2609     IFile *cf = CurFile();
2610     char *ptr;
2611     char ch;
2612     char *line;
2613     char *line_end;
2614     char *escaped;
2615     char *comment;
2616     char *tp;
2617 
2618     /* Loop through blank lines and comment lines */
2619     for (;;) {
2620 	cf->lineno++;
2621 	line = cf->buf_ptr;
2622 	ptr = line;
2623 	line_end = line;
2624 	escaped = NULL;
2625 	comment = NULL;
2626 	for (;;) {
2627 	    /* XXX: can buf_end ever be null? */
2628 	    if (cf->buf_end != NULL && ptr == cf->buf_end) {
2629 		/* end of buffer */
2630 		ch = '\0';
2631 		break;
2632 	    }
2633 	    ch = *ptr;
2634 	    if (ch == '\0' || (ch == '\\' && ptr[1] == '\0')) {
2635 		/* XXX: can buf_end ever be null? */
2636 		if (cf->buf_end == NULL)
2637 		    /* End of string (aka for loop) data */
2638 		    break;
2639 		/* see if there is more we can parse */
2640 		while (ptr++ < cf->buf_end) {
2641 		    if ((ch = *ptr) == '\n') {
2642 			if (ptr > line && ptr[-1] == '\\')
2643 			    continue;
2644 			Parse_Error(PARSE_WARNING,
2645 				    "Zero byte read from file, "
2646 				    "skipping rest of line.");
2647 			break;
2648 		    }
2649 		}
2650 		/* XXX: Can cf->nextbuf ever be NULL? */
2651 		if (cf->nextbuf != NULL) {
2652 		    /*
2653 		     * End of this buffer; return EOF and outer logic
2654 		     * will get the next one. (eww)
2655 		     */
2656 		    break;
2657 		}
2658 		Parse_Error(PARSE_FATAL, "Zero byte read from file");
2659 		return NULL;
2660 	    }
2661 
2662 	    if (ch == '\\') {
2663 		/* Don't treat next character as special, remember first one */
2664 		if (escaped == NULL)
2665 		    escaped = ptr;
2666 		if (ptr[1] == '\n')
2667 		    cf->lineno++;
2668 		ptr += 2;
2669 		line_end = ptr;
2670 		continue;
2671 	    }
2672 	    if (ch == '#' && comment == NULL) {
2673 		/* Remember first '#' for comment stripping */
2674 		/* Unless previous char was '[', as in modifier :[#] */
2675 		if (!(ptr > line && ptr[-1] == '['))
2676 		    comment = line_end;
2677 	    }
2678 	    ptr++;
2679 	    if (ch == '\n')
2680 		break;
2681 	    if (!ch_isspace(ch))
2682 		/* We are not interested in trailing whitespace */
2683 		line_end = ptr;
2684 	}
2685 
2686 	/* Save next 'to be processed' location */
2687 	cf->buf_ptr = ptr;
2688 
2689 	/* Check we have a non-comment, non-blank line */
2690 	if (line_end == line || comment == line) {
2691 	    if (ch == '\0')
2692 		/* At end of file */
2693 		return NULL;
2694 	    /* Parse another line */
2695 	    continue;
2696 	}
2697 
2698 	/* We now have a line of data */
2699 	*line_end = '\0';
2700 
2701 	if (mode == PARSE_RAW) {
2702 	    /* Leave '\' (etc) in line buffer (eg 'for' lines) */
2703 	    return line;
2704 	}
2705 
2706 	if (mode == PARSE_SKIP) {
2707 	    /* Completely ignore non-directives */
2708 	    if (line[0] != '.')
2709 		continue;
2710 	    /* We could do more of the .else/.elif/.endif checks here */
2711 	}
2712 	break;
2713     }
2714 
2715     /* Brutally ignore anything after a non-escaped '#' in non-commands */
2716     if (comment != NULL && line[0] != '\t') {
2717 	line_end = comment;
2718 	*line_end = '\0';
2719     }
2720 
2721     /* If we didn't see a '\\' then the in-situ data is fine */
2722     if (escaped == NULL)
2723 	return line;
2724 
2725     /* Remove escapes from '\n' and '#' */
2726     tp = ptr = escaped;
2727     escaped = line;
2728     for (; ; *tp++ = ch) {
2729 	ch = *ptr++;
2730 	if (ch != '\\') {
2731 	    if (ch == '\0')
2732 		break;
2733 	    continue;
2734 	}
2735 
2736 	ch = *ptr++;
2737 	if (ch == '\0') {
2738 	    /* Delete '\\' at end of buffer */
2739 	    tp--;
2740 	    break;
2741 	}
2742 
2743 	if (ch == '#' && line[0] != '\t')
2744 	    /* Delete '\\' from before '#' on non-command lines */
2745 	    continue;
2746 
2747 	if (ch != '\n') {
2748 	    /* Leave '\\' in buffer for later */
2749 	    *tp++ = '\\';
2750 	    /* Make sure we don't delete an escaped ' ' from the line end */
2751 	    escaped = tp + 1;
2752 	    continue;
2753 	}
2754 
2755 	/* Escaped '\n' -- replace following whitespace with a single ' '. */
2756 	pp_skip_hspace(&ptr);
2757 	ch = ' ';
2758     }
2759 
2760     /* Delete any trailing spaces - eg from empty continuations */
2761     while (tp > escaped && ch_isspace(tp[-1]))
2762 	tp--;
2763 
2764     *tp = '\0';
2765     return line;
2766 }
2767 
2768 /* Read an entire line from the input file. Called only by Parse_File.
2769  *
2770  * Results:
2771  *	A line without its newline and without any trailing whitespace.
2772  */
2773 static char *
2774 ParseReadLine(void)
2775 {
2776     char *line;			/* Result */
2777     int lineno;			/* Saved line # */
2778     int rval;
2779 
2780     for (;;) {
2781 	line = ParseGetLine(PARSE_NORMAL);
2782 	if (line == NULL)
2783 	    return NULL;
2784 
2785 	if (line[0] != '.')
2786 	    return line;
2787 
2788 	/*
2789 	 * The line might be a conditional. Ask the conditional module
2790 	 * about it and act accordingly
2791 	 */
2792 	switch (Cond_EvalLine(line)) {
2793 	case COND_SKIP:
2794 	    /* Skip to next conditional that evaluates to COND_PARSE.  */
2795 	    do {
2796 		line = ParseGetLine(PARSE_SKIP);
2797 	    } while (line && Cond_EvalLine(line) != COND_PARSE);
2798 	    if (line == NULL)
2799 		break;
2800 	    continue;
2801 	case COND_PARSE:
2802 	    continue;
2803 	case COND_INVALID:    /* Not a conditional line */
2804 	    /* Check for .for loops */
2805 	    rval = For_Eval(line);
2806 	    if (rval == 0)
2807 		/* Not a .for line */
2808 		break;
2809 	    if (rval < 0)
2810 		/* Syntax error - error printed, ignore line */
2811 		continue;
2812 	    /* Start of a .for loop */
2813 	    lineno = CurFile()->lineno;
2814 	    /* Accumulate loop lines until matching .endfor */
2815 	    do {
2816 		line = ParseGetLine(PARSE_RAW);
2817 		if (line == NULL) {
2818 		    Parse_Error(PARSE_FATAL,
2819 				"Unexpected end of file in for loop.");
2820 		    break;
2821 		}
2822 	    } while (For_Accum(line));
2823 	    /* Stash each iteration as a new 'input file' */
2824 	    For_Run(lineno);
2825 	    /* Read next line from for-loop buffer */
2826 	    continue;
2827 	}
2828 	return line;
2829     }
2830 }
2831 
2832 static void
2833 FinishDependencyGroup(void)
2834 {
2835     GNodeListNode *ln;
2836 
2837     if (targets == NULL)
2838 	return;
2839 
2840     for (ln = targets->first; ln != NULL; ln = ln->next) {
2841 	GNode *gn = ln->datum;
2842 
2843 	Suff_EndTransform(gn);
2844 
2845 	/* Mark the target as already having commands if it does, to
2846 	 * keep from having shell commands on multiple dependency lines. */
2847 	if (!Lst_IsEmpty(gn->commands))
2848 	    gn->type |= OP_HAS_COMMANDS;
2849     }
2850 
2851     Lst_Free(targets);
2852     targets = NULL;
2853 }
2854 
2855 /* Add the command to each target from the current dependency spec. */
2856 static void
2857 ParseLine_ShellCommand(const char *p)
2858 {
2859     cpp_skip_whitespace(&p);
2860     if (*p == '\0')
2861 	return;			/* skip empty commands */
2862 
2863     if (targets == NULL) {
2864 	Parse_Error(PARSE_FATAL, "Unassociated shell command \"%s\"", p);
2865 	return;
2866     }
2867 
2868     {
2869 	char *cmd = bmake_strdup(p);
2870 	GNodeListNode *ln;
2871 
2872 	for (ln = targets->first; ln != NULL; ln = ln->next) {
2873 	    GNode *gn = ln->datum;
2874 	    ParseAddCmd(gn, cmd);
2875 	}
2876 #ifdef CLEANUP
2877 	Lst_Append(targCmds, cmd);
2878 #endif
2879     }
2880 }
2881 
2882 static Boolean
2883 ParseDirective(char *line)
2884 {
2885     char *cp;
2886 
2887     if (*line == '.') {
2888 	/*
2889 	 * Lines that begin with '.' can be pretty much anything:
2890 	 *	- directives like '.include' or '.if',
2891 	 *	- suffix rules like '.c.o:',
2892 	 *	- dependencies for filenames that start with '.',
2893 	 *	- variable assignments like '.tmp=value'.
2894 	 */
2895 	cp = line + 1;
2896 	pp_skip_whitespace(&cp);
2897 	if (IsInclude(cp, FALSE)) {
2898 	    ParseDoInclude(cp);
2899 	    return TRUE;
2900 	}
2901 	if (strncmp(cp, "undef", 5) == 0) {
2902 	    const char *varname;
2903 	    cp += 5;
2904 	    pp_skip_whitespace(&cp);
2905 	    varname = cp;
2906 	    for (; !ch_isspace(*cp) && *cp != '\0'; cp++)
2907 		continue;
2908 	    *cp = '\0';
2909 	    Var_Delete(varname, VAR_GLOBAL);
2910 	    /* TODO: undefine all variables, not only the first */
2911 	    /* TODO: use Str_Words, like everywhere else */
2912 	    return TRUE;
2913 	} else if (strncmp(cp, "export", 6) == 0) {
2914 	    cp += 6;
2915 	    pp_skip_whitespace(&cp);
2916 	    Var_Export(cp, TRUE);
2917 	    return TRUE;
2918 	} else if (strncmp(cp, "unexport", 8) == 0) {
2919 	    Var_UnExport(cp);
2920 	    return TRUE;
2921 	} else if (strncmp(cp, "info", 4) == 0 ||
2922 		   strncmp(cp, "error", 5) == 0 ||
2923 		   strncmp(cp, "warning", 7) == 0) {
2924 	    if (ParseMessage(cp))
2925 		return TRUE;
2926 	}
2927     }
2928     return FALSE;
2929 }
2930 
2931 static Boolean
2932 ParseVarassign(const char *line)
2933 {
2934     VarAssign var;
2935 
2936     if (!Parse_IsVar(line, &var))
2937 	return FALSE;
2938 
2939     FinishDependencyGroup();
2940     Parse_DoVar(&var, VAR_GLOBAL);
2941     return TRUE;
2942 }
2943 
2944 static char *
2945 FindSemicolon(char *p)
2946 {
2947     int level = 0;
2948 
2949     for (; *p != '\0'; p++) {
2950 	if (*p == '\\' && p[1] != '\0') {
2951 	    p++;
2952 	    continue;
2953 	}
2954 
2955 	if (*p == '$' && (p[1] == '(' || p[1] == '{'))
2956 	    level++;
2957 	else if (level > 0 && (*p == ')' || *p == '}'))
2958 	    level--;
2959 	else if (level == 0 && *p == ';')
2960 	    break;
2961     }
2962     return p;
2963 }
2964 
2965 /* dependency	-> target... op [source...]
2966  * op		-> ':' | '::' | '!' */
2967 static void
2968 ParseDependency(char *line)
2969 {
2970     VarEvalFlags eflags;
2971     char *expanded_line;
2972     const char *shellcmd = NULL;
2973 
2974     /*
2975      * For some reason - probably to make the parser impossible -
2976      * a ';' can be used to separate commands from dependencies.
2977      * Attempt to avoid ';' inside substitution patterns.
2978      */
2979     {
2980 	char *semicolon = FindSemicolon(line);
2981 	if (*semicolon != '\0') {
2982 	    /* Terminate the dependency list at the ';' */
2983 	    *semicolon = '\0';
2984 	    shellcmd = semicolon + 1;
2985 	}
2986     }
2987 
2988     /*
2989      * We now know it's a dependency line so it needs to have all
2990      * variables expanded before being parsed.
2991      *
2992      * XXX: Ideally the dependency line would first be split into
2993      * its left-hand side, dependency operator and right-hand side,
2994      * and then each side would be expanded on its own.  This would
2995      * allow for the left-hand side to allow only defined variables
2996      * and to allow variables on the right-hand side to be undefined
2997      * as well.
2998      *
2999      * Parsing the line first would also prevent that targets
3000      * generated from variable expressions are interpreted as the
3001      * dependency operator, such as in "target${:U\:} middle: source",
3002      * in which the middle is interpreted as a source, not a target.
3003      */
3004 
3005     /* In lint mode, allow undefined variables to appear in
3006      * dependency lines.
3007      *
3008      * Ideally, only the right-hand side would allow undefined
3009      * variables since it is common to have optional dependencies.
3010      * Having undefined variables on the left-hand side is more
3011      * unusual though.  Since both sides are expanded in a single
3012      * pass, there is not much choice what to do here.
3013      *
3014      * In normal mode, it does not matter whether undefined
3015      * variables are allowed or not since as of 2020-09-14,
3016      * Var_Parse does not print any parse errors in such a case.
3017      * It simply returns the special empty string var_Error,
3018      * which cannot be detected in the result of Var_Subst. */
3019     eflags = opts.lint ? VARE_WANTRES : VARE_WANTRES | VARE_UNDEFERR;
3020     (void)Var_Subst(line, VAR_CMDLINE, eflags, &expanded_line);
3021     /* TODO: handle errors */
3022 
3023     /* Need a fresh list for the target nodes */
3024     if (targets != NULL)
3025 	Lst_Free(targets);
3026     targets = Lst_New();
3027 
3028     ParseDoDependency(expanded_line);
3029     free(expanded_line);
3030 
3031     if (shellcmd != NULL)
3032 	ParseLine_ShellCommand(shellcmd);
3033 }
3034 
3035 static void
3036 ParseLine(char *line)
3037 {
3038     if (ParseDirective(line))
3039 	return;
3040 
3041     if (*line == '\t') {
3042 	ParseLine_ShellCommand(line + 1);
3043 	return;
3044     }
3045 
3046 #ifdef SYSVINCLUDE
3047     if (IsSysVInclude(line)) {
3048 	/*
3049 	 * It's an S3/S5-style "include".
3050 	 */
3051 	ParseTraditionalInclude(line);
3052 	return;
3053     }
3054 #endif
3055 
3056 #ifdef GMAKEEXPORT
3057     if (strncmp(line, "export", 6) == 0 && ch_isspace(line[6]) &&
3058 	strchr(line, ':') == NULL) {
3059 	/*
3060 	 * It's a Gmake "export".
3061 	 */
3062 	ParseGmakeExport(line);
3063 	return;
3064     }
3065 #endif
3066 
3067     if (ParseVarassign(line))
3068 	return;
3069 
3070     FinishDependencyGroup();
3071 
3072     ParseDependency(line);
3073 }
3074 
3075 /* Parse a top-level makefile, incorporating its content into the global
3076  * dependency graph.
3077  *
3078  * Input:
3079  *	name		The name of the file being read
3080  *	fd		The open file to parse; will be closed at the end
3081  */
3082 void
3083 Parse_File(const char *name, int fd)
3084 {
3085     char *line;			/* the line we're working on */
3086     struct loadedfile *lf;
3087 
3088     lf = loadfile(name, fd);
3089 
3090     assert(targets == NULL);
3091 
3092     if (name == NULL)
3093 	name = "(stdin)";
3094 
3095     Parse_SetInput(name, 0, -1, loadedfile_nextbuf, lf);
3096     CurFile()->lf = lf;
3097 
3098     do {
3099 	while ((line = ParseReadLine()) != NULL) {
3100 	    DEBUG2(PARSE, "ParseReadLine (%d): '%s'\n",
3101 		   CurFile()->lineno, line);
3102 	    ParseLine(line);
3103 	}
3104 	/*
3105 	 * Reached EOF, but it may be just EOF of an include file...
3106 	 */
3107     } while (ParseEOF());
3108 
3109     FinishDependencyGroup();
3110 
3111     if (fatals != 0) {
3112 	(void)fflush(stdout);
3113 	(void)fprintf(stderr,
3114 		      "%s: Fatal errors encountered -- cannot continue",
3115 		      progname);
3116 	PrintOnError(NULL, NULL);
3117 	exit(1);
3118     }
3119 }
3120 
3121 /* Initialize the parsing module. */
3122 void
3123 Parse_Init(void)
3124 {
3125     mainNode = NULL;
3126     parseIncPath = Lst_New();
3127     sysIncPath = Lst_New();
3128     defSysIncPath = Lst_New();
3129     Vector_Init(&includes, sizeof(IFile));
3130 #ifdef CLEANUP
3131     targCmds = Lst_New();
3132 #endif
3133 }
3134 
3135 /* Clean up the parsing module. */
3136 void
3137 Parse_End(void)
3138 {
3139 #ifdef CLEANUP
3140     Lst_Destroy(targCmds, free);
3141     assert(targets == NULL);
3142     Lst_Destroy(defSysIncPath, Dir_Destroy);
3143     Lst_Destroy(sysIncPath, Dir_Destroy);
3144     Lst_Destroy(parseIncPath, Dir_Destroy);
3145     assert(includes.len == 0);
3146     Vector_Done(&includes);
3147 #endif
3148 }
3149 
3150 
3151 /*
3152  * Return a list containing the single main target to create.
3153  * If no such target exists, we Punt with an obnoxious error message.
3154  */
3155 GNodeList *
3156 Parse_MainName(void)
3157 {
3158     GNodeList *mainList;
3159 
3160     mainList = Lst_New();
3161 
3162     if (mainNode == NULL)
3163 	Punt("no target to make.");
3164 
3165     if (mainNode->type & OP_DOUBLEDEP) {
3166 	Lst_Append(mainList, mainNode);
3167 	Lst_AppendAll(mainList, mainNode->cohorts);
3168     } else
3169 	Lst_Append(mainList, mainNode);
3170 
3171     Var_Append(".TARGETS", mainNode->name, VAR_GLOBAL);
3172 
3173     return mainList;
3174 }
3175 
3176 int
3177 Parse_GetFatals(void)
3178 {
3179     return fatals;
3180 }
3181