parse.c revision 1.751 1 /* $NetBSD: parse.c,v 1.751 2025/06/13 18:31:08 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 * Interface:
78 * Parse_Init Initialize the module
79 *
80 * Parse_End Clean up the module
81 *
82 * Parse_File Parse a top-level makefile. Included files are
83 * handled by IncludeFile instead.
84 *
85 * Parse_VarAssign
86 * Try to parse the given line as a variable assignment.
87 * Used by MainParseArgs to determine if an argument is
88 * a target or a variable assignment. Used internally
89 * for pretty much the same thing.
90 *
91 * Parse_Error Report a parse error, a warning or an informational
92 * message.
93 *
94 * Parse_MainName Populate the list of targets to create.
95 */
96
97 #include <sys/types.h>
98 #include <sys/stat.h>
99 #include <errno.h>
100 #include <stdarg.h>
101
102 #include "make.h"
103 #include "dir.h"
104 #include "job.h"
105 #include "pathnames.h"
106
107 /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
108 MAKE_RCSID("$NetBSD: parse.c,v 1.751 2025/06/13 18:31:08 rillig Exp $");
109
110 /* Detects a multiple-inclusion guard in a makefile. */
111 typedef enum {
112 GS_START, /* at the beginning of the file */
113 GS_COND, /* after the guard condition */
114 GS_DONE, /* after the closing .endif */
115 GS_NO /* the file is not guarded */
116 } GuardState;
117
118 /* A file being parsed. */
119 typedef struct IncludedFile {
120 FStr name; /* absolute or relative to the cwd */
121 unsigned lineno; /* 1-based */
122 unsigned readLines; /* the number of physical lines that have
123 * been read from the file */
124 unsigned forHeadLineno; /* 1-based */
125 unsigned forBodyReadLines; /* the number of physical lines that have
126 * been read from the file above the body of
127 * the .for loop */
128 unsigned condMinDepth; /* depth of nested 'if' directives, at the
129 * beginning of the file */
130 bool depending; /* state of doing_depend on EOF */
131
132 Buffer buf; /* the file's content or the body of the .for
133 * loop; either empty or ends with '\n' */
134 char *buf_ptr; /* next char to be read from buf */
135 char *buf_end; /* buf_end[-1] == '\n' */
136
137 GuardState guardState;
138 Guard *guard;
139
140 struct ForLoop *forLoop;
141 } IncludedFile;
142
143 /* Special attributes for target nodes. */
144 typedef enum ParseSpecial {
145 SP_ATTRIBUTE, /* Generic attribute */
146 SP_BEGIN, /* .BEGIN */
147 SP_DEFAULT, /* .DEFAULT */
148 SP_DELETE_ON_ERROR, /* .DELETE_ON_ERROR */
149 SP_END, /* .END */
150 SP_ERROR, /* .ERROR */
151 SP_IGNORE, /* .IGNORE */
152 SP_INCLUDES, /* .INCLUDES; not mentioned in the manual page */
153 SP_INTERRUPT, /* .INTERRUPT */
154 SP_LIBS, /* .LIBS; not mentioned in the manual page */
155 SP_MAIN, /* .MAIN and no user-specified targets to make */
156 SP_META, /* .META */
157 SP_MFLAGS, /* .MFLAGS or .MAKEFLAGS */
158 SP_NOMETA, /* .NOMETA */
159 SP_NOMETA_CMP, /* .NOMETA_CMP */
160 SP_NOPATH, /* .NOPATH */
161 SP_NOREADONLY, /* .NOREADONLY */
162 SP_NOT, /* Not special */
163 SP_NOTPARALLEL, /* .NOTPARALLEL or .NO_PARALLEL */
164 SP_NULL, /* .NULL; not mentioned in the manual page */
165 SP_OBJDIR, /* .OBJDIR */
166 SP_ORDER, /* .ORDER */
167 SP_PARALLEL, /* .PARALLEL; not mentioned in the manual page */
168 SP_PATH, /* .PATH or .PATH.suffix */
169 SP_PHONY, /* .PHONY */
170 SP_POSIX, /* .POSIX; not mentioned in the manual page */
171 SP_PRECIOUS, /* .PRECIOUS */
172 SP_READONLY, /* .READONLY */
173 SP_SHELL, /* .SHELL */
174 SP_SILENT, /* .SILENT */
175 SP_SINGLESHELL, /* .SINGLESHELL; not mentioned in the manual page */
176 SP_STALE, /* .STALE */
177 SP_SUFFIXES, /* .SUFFIXES */
178 SP_SYSPATH, /* .SYSPATH */
179 SP_WAIT /* .WAIT */
180 } ParseSpecial;
181
182 typedef List SearchPathList;
183 typedef ListNode SearchPathListNode;
184
185
186 typedef enum VarAssignOp {
187 VAR_NORMAL, /* = */
188 VAR_APPEND, /* += */
189 VAR_DEFAULT, /* ?= */
190 VAR_SUBST, /* := */
191 VAR_SHELL /* != or :sh= */
192 } VarAssignOp;
193
194 typedef struct VarAssign {
195 char *varname; /* unexpanded */
196 VarAssignOp op;
197 const char *value; /* unexpanded */
198 } VarAssign;
199
200 static bool Parse_IsVar(const char *, VarAssign *);
201 static void Parse_Var(VarAssign *, GNode *);
202
203 /*
204 * The target to be made if no targets are specified in the command line.
205 * This is the first target defined in any of the makefiles.
206 */
207 GNode *mainNode;
208
209 /*
210 * During parsing, the targets from the left-hand side of the currently
211 * active dependency line, or NULL if the current line does not belong to a
212 * dependency line, for example because it is a variable assignment.
213 *
214 * See unit-tests/deptgt.mk, keyword "parse.c:targets".
215 */
216 static GNodeList *targets;
217
218 #ifdef CLEANUP
219 /*
220 * All shell commands for all targets, in no particular order and possibly
221 * with duplicate values. Kept in a separate list since the commands from
222 * .USE or .USEBEFORE nodes are shared with other GNodes, thereby giving up
223 * the easily understandable ownership over the allocated strings.
224 */
225 static StringList targCmds = LST_INIT;
226 #endif
227
228 /*
229 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
230 * is seen, then set to each successive source on the line.
231 */
232 static GNode *order_pred;
233
234 int parseErrors;
235
236 /*
237 * The include chain of makefiles. At index 0 is the top-level makefile from
238 * the command line, followed by the included files or .for loops, up to and
239 * including the current file.
240 *
241 * See PrintStackTrace for how to interpret the data.
242 */
243 static Vector /* of IncludedFile */ includes;
244
245 SearchPath *parseIncPath; /* directories for "..." includes */
246 SearchPath *sysIncPath; /* directories for <...> includes */
247 SearchPath *defSysIncPath; /* default for sysIncPath */
248
249 /*
250 * The parseKeywords table is searched using binary search when deciding
251 * if a target or source is special.
252 */
253 static const struct {
254 const char name[17];
255 ParseSpecial special; /* when used as a target */
256 GNodeType targetAttr; /* when used as a source */
257 } parseKeywords[] = {
258 { ".BEGIN", SP_BEGIN, OP_NONE },
259 { ".DEFAULT", SP_DEFAULT, OP_NONE },
260 { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, OP_NONE },
261 { ".END", SP_END, OP_NONE },
262 { ".ERROR", SP_ERROR, OP_NONE },
263 { ".EXEC", SP_ATTRIBUTE, OP_EXEC },
264 { ".IGNORE", SP_IGNORE, OP_IGNORE },
265 { ".INCLUDES", SP_INCLUDES, OP_NONE },
266 { ".INTERRUPT", SP_INTERRUPT, OP_NONE },
267 { ".INVISIBLE", SP_ATTRIBUTE, OP_INVISIBLE },
268 { ".JOIN", SP_ATTRIBUTE, OP_JOIN },
269 { ".LIBS", SP_LIBS, OP_NONE },
270 { ".MADE", SP_ATTRIBUTE, OP_MADE },
271 { ".MAIN", SP_MAIN, OP_NONE },
272 { ".MAKE", SP_ATTRIBUTE, OP_MAKE },
273 { ".MAKEFLAGS", SP_MFLAGS, OP_NONE },
274 { ".META", SP_META, OP_META },
275 { ".MFLAGS", SP_MFLAGS, OP_NONE },
276 { ".NOMETA", SP_NOMETA, OP_NOMETA },
277 { ".NOMETA_CMP", SP_NOMETA_CMP, OP_NOMETA_CMP },
278 { ".NOPATH", SP_NOPATH, OP_NOPATH },
279 { ".NOREADONLY", SP_NOREADONLY, OP_NONE },
280 { ".NOTMAIN", SP_ATTRIBUTE, OP_NOTMAIN },
281 { ".NOTPARALLEL", SP_NOTPARALLEL, OP_NONE },
282 { ".NO_PARALLEL", SP_NOTPARALLEL, OP_NONE },
283 { ".NULL", SP_NULL, OP_NONE },
284 { ".OBJDIR", SP_OBJDIR, OP_NONE },
285 { ".OPTIONAL", SP_ATTRIBUTE, OP_OPTIONAL },
286 { ".ORDER", SP_ORDER, OP_NONE },
287 { ".PARALLEL", SP_PARALLEL, OP_NONE },
288 { ".PATH", SP_PATH, OP_NONE },
289 { ".PHONY", SP_PHONY, OP_PHONY },
290 { ".POSIX", SP_POSIX, OP_NONE },
291 { ".PRECIOUS", SP_PRECIOUS, OP_PRECIOUS },
292 { ".READONLY", SP_READONLY, OP_NONE },
293 { ".RECURSIVE", SP_ATTRIBUTE, OP_MAKE },
294 { ".SHELL", SP_SHELL, OP_NONE },
295 { ".SILENT", SP_SILENT, OP_SILENT },
296 { ".SINGLESHELL", SP_SINGLESHELL, OP_NONE },
297 { ".STALE", SP_STALE, OP_NONE },
298 { ".SUFFIXES", SP_SUFFIXES, OP_NONE },
299 { ".SYSPATH", SP_SYSPATH, OP_NONE },
300 { ".USE", SP_ATTRIBUTE, OP_USE },
301 { ".USEBEFORE", SP_ATTRIBUTE, OP_USEBEFORE },
302 { ".WAIT", SP_WAIT, OP_NONE },
303 };
304
305 enum PosixState posix_state = PS_NOT_YET;
306
307 static HashTable /* full file name -> Guard */ guards;
308
309
310 static List *
311 Lst_New(void)
312 {
313 List *list = bmake_malloc(sizeof *list);
314 Lst_Init(list);
315 return list;
316 }
317
318 static void
319 Lst_Free(List *list)
320 {
321
322 Lst_Done(list);
323 free(list);
324 }
325
326 static IncludedFile *
327 GetInclude(size_t i)
328 {
329 assert(i < includes.len);
330 return Vector_Get(&includes, i);
331 }
332
333 /* The makefile or the body of a .for loop that is currently being read. */
334 static IncludedFile *
335 CurFile(void)
336 {
337 return GetInclude(includes.len - 1);
338 }
339
340 unsigned
341 CurFile_CondMinDepth(void)
342 {
343 return CurFile()->condMinDepth;
344 }
345
346 static Buffer
347 LoadFile(const char *path, int fd)
348 {
349 ssize_t n;
350 Buffer buf;
351 size_t bufSize;
352 struct stat st;
353
354 bufSize = fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
355 st.st_size > 0 && st.st_size < 1024 * 1024 * 1024
356 ? (size_t)st.st_size : 1024;
357 Buf_InitSize(&buf, bufSize);
358
359 for (;;) {
360 if (buf.len == buf.cap) {
361 if (buf.cap >= 512 * 1024 * 1024) {
362 Error("%s: file too large", path);
363 exit(2); /* Not 1 so -q can distinguish error */
364 }
365 Buf_Expand(&buf);
366 }
367 assert(buf.len < buf.cap);
368 n = read(fd, buf.data + buf.len, buf.cap - buf.len);
369 if (n < 0) {
370 Error("%s: %s", path, strerror(errno));
371 exit(2); /* Not 1 so -q can distinguish error */
372 }
373 if (n == 0)
374 break;
375
376 buf.len += (size_t)n;
377 }
378 assert(buf.len <= buf.cap);
379
380 if (buf.len > 0 && !Buf_EndsWith(&buf, '\n'))
381 Buf_AddByte(&buf, '\n');
382
383 return buf; /* may not be null-terminated */
384 }
385
386 const char *
387 GetParentStackTrace(void)
388 {
389 static bool initialized;
390 static const char *parentStackTrace;
391
392 if (!initialized) {
393 const char *env = getenv("MAKE_STACK_TRACE");
394 parentStackTrace = env == NULL ? NULL
395 : env[0] == '\t' ? bmake_strdup(env)
396 : strcmp(env, "yes") == 0 ? bmake_strdup("")
397 : NULL;
398 initialized = true;
399 }
400 return parentStackTrace;
401 }
402
403 /*
404 * Print the current chain of .include and .for directives. In Parse_Fatal
405 * or other functions that already print the location, includingInnermost
406 * would be redundant, but in other cases like Error or Fatal it needs to be
407 * included.
408 */
409 char *
410 GetStackTrace(bool includingInnermost)
411 {
412 const char *parentStackTrace;
413 Buffer buffer, *buf = &buffer;
414 const IncludedFile *entries;
415 size_t i, n;
416 bool hasDetails;
417
418 Buf_Init(buf);
419 hasDetails = EvalStack_Details(buf);
420 n = includes.len;
421 if (n == 0)
422 goto add_parent_stack_trace;
423
424 entries = GetInclude(0);
425 if (!includingInnermost && !(hasDetails && n > 1)
426 && entries[n - 1].forLoop == NULL)
427 n--; /* already in the diagnostic */
428
429 for (i = n; i-- > 0;) {
430 const IncludedFile *entry = entries + i;
431 const char *fname = entry->name.str;
432 char dirbuf[MAXPATHLEN + 1];
433
434 if (fname[0] != '/' && strcmp(fname, "(stdin)") != 0) {
435 const char *realPath = realpath(fname, dirbuf);
436 if (realPath != NULL)
437 fname = realPath;
438 }
439
440 if (entry->forLoop != NULL) {
441 char *details = ForLoop_Details(entry->forLoop);
442 Buf_AddStr(buf, "\tin .for loop from ");
443 Buf_AddStr(buf, fname);
444 Buf_AddStr(buf, ":");
445 Buf_AddInt(buf, (int)entry->forHeadLineno);
446 Buf_AddStr(buf, " with ");
447 Buf_AddStr(buf, details);
448 Buf_AddStr(buf, "\n");
449 free(details);
450 } else if (i + 1 < n && entries[i + 1].forLoop != NULL) {
451 /* entry->lineno is not a useful line number */
452 } else {
453 Buf_AddStr(buf, "\tin ");
454 Buf_AddStr(buf, fname);
455 Buf_AddStr(buf, ":");
456 Buf_AddInt(buf, (int)entry->lineno);
457 Buf_AddStr(buf, "\n");
458 }
459 }
460
461 add_parent_stack_trace:
462 parentStackTrace = GetParentStackTrace();
463 if ((makelevel > 0 && (n > 0 || !includingInnermost))
464 || parentStackTrace != NULL) {
465 Buf_AddStr(buf, "\tin ");
466 Buf_AddStr(buf, progname);
467 Buf_AddStr(buf, " in directory \"");
468 Buf_AddStr(buf, curdir);
469 Buf_AddStr(buf, "\"\n");
470 }
471
472 if (parentStackTrace != NULL)
473 Buf_AddStr(buf, parentStackTrace);
474
475 return Buf_DoneData(buf);
476 }
477
478 void
479 PrintStackTrace(bool includingInnermost)
480 {
481 char *stackTrace = GetStackTrace(includingInnermost);
482 fprintf(stderr, "%s", stackTrace);
483 fflush(stderr);
484 free(stackTrace);
485 }
486
487 /* Check if the current character is escaped on the current line. */
488 static bool
489 IsEscaped(const char *line, const char *p)
490 {
491 bool escaped = false;
492 while (p > line && *--p == '\\')
493 escaped = !escaped;
494 return escaped;
495 }
496
497 /*
498 * Remember the location (filename and lineno) where the last command was
499 * added or where the node was mentioned in a .depend file.
500 */
501 static void
502 RememberLocation(GNode *gn)
503 {
504 IncludedFile *curFile = CurFile();
505 gn->fname = Str_Intern(curFile->name.str);
506 gn->lineno = curFile->lineno;
507 }
508
509 /*
510 * Look in the table of keywords for one matching the given string.
511 * Return the index of the keyword, or -1 if it isn't there.
512 */
513 static int
514 FindKeyword(const char *str)
515 {
516 int start = 0;
517 int end = sizeof parseKeywords / sizeof parseKeywords[0] - 1;
518
519 while (start <= end) {
520 int curr = start + (end - start) / 2;
521 int diff = strcmp(str, parseKeywords[curr].name);
522
523 if (diff == 0)
524 return curr;
525 if (diff < 0)
526 end = curr - 1;
527 else
528 start = curr + 1;
529 }
530
531 return -1;
532 }
533
534 void
535 PrintLocation(FILE *f, bool useVars, const GNode *gn)
536 {
537 char dirbuf[MAXPATHLEN + 1];
538 FStr dir, base;
539 const char *fname;
540 unsigned lineno;
541
542 if (gn != NULL) {
543 fname = gn->fname;
544 lineno = gn->lineno;
545 } else if (includes.len > 0) {
546 IncludedFile *curFile = CurFile();
547 fname = curFile->name.str;
548 lineno = curFile->lineno;
549 } else
550 return;
551
552 if (!useVars || fname[0] == '/' || strcmp(fname, "(stdin)") == 0) {
553 (void)fprintf(f, "%s:%u: ", fname, lineno);
554 return;
555 }
556
557 dir = Var_Value(SCOPE_GLOBAL, ".PARSEDIR");
558 if (dir.str == NULL)
559 dir.str = ".";
560 if (dir.str[0] != '/')
561 dir.str = realpath(dir.str, dirbuf);
562
563 base = Var_Value(SCOPE_GLOBAL, ".PARSEFILE");
564 if (base.str == NULL)
565 base.str = str_basename(fname);
566
567 (void)fprintf(f, "%s/%s:%u: ", dir.str, base.str, lineno);
568
569 FStr_Done(&base);
570 FStr_Done(&dir);
571 }
572
573 static void MAKE_ATTR_PRINTFLIKE(5, 0)
574 ParseVErrorInternal(FILE *f, bool useVars, const GNode *gn,
575 ParseErrorLevel level, const char *fmt, va_list ap)
576 {
577 static bool fatal_warning_error_printed = false;
578
579 (void)fprintf(f, "%s: ", progname);
580
581 PrintLocation(f, useVars, gn);
582 if (level == PARSE_WARNING)
583 (void)fprintf(f, "warning: ");
584 (void)vfprintf(f, fmt, ap);
585 (void)fprintf(f, "\n");
586 (void)fflush(f);
587
588 if (level == PARSE_FATAL)
589 parseErrors++;
590 if (level == PARSE_WARNING && opts.parseWarnFatal) {
591 if (!fatal_warning_error_printed) {
592 Error("parsing warnings being treated as errors");
593 fatal_warning_error_printed = true;
594 }
595 parseErrors++;
596 }
597
598 if (level == PARSE_FATAL || DEBUG(PARSE))
599 PrintStackTrace(false);
600 }
601
602 static void MAKE_ATTR_PRINTFLIKE(3, 4)
603 ParseErrorInternal(const GNode *gn,
604 ParseErrorLevel level, const char *fmt, ...)
605 {
606 va_list ap;
607
608 (void)fflush(stdout);
609 va_start(ap, fmt);
610 ParseVErrorInternal(stderr, false, gn, level, fmt, ap);
611 va_end(ap);
612
613 if (opts.debug_file != stdout && opts.debug_file != stderr) {
614 va_start(ap, fmt);
615 ParseVErrorInternal(opts.debug_file, false, gn,
616 level, fmt, ap);
617 va_end(ap);
618 }
619 }
620
621 /*
622 * Print a message, including location information.
623 *
624 * If the level is PARSE_FATAL, continue parsing until the end of the
625 * current top-level makefile, then exit (see Parse_File).
626 *
627 * Fmt is given without a trailing newline.
628 */
629 void
630 Parse_Error(ParseErrorLevel level, const char *fmt, ...)
631 {
632 va_list ap;
633
634 (void)fflush(stdout);
635 va_start(ap, fmt);
636 ParseVErrorInternal(stderr, true, NULL, level, fmt, ap);
637 va_end(ap);
638
639 if (opts.debug_file != stdout && opts.debug_file != stderr) {
640 va_start(ap, fmt);
641 ParseVErrorInternal(opts.debug_file, true, NULL,
642 level, fmt, ap);
643 va_end(ap);
644 }
645 }
646
647
648 /*
649 * Handle an .info, .warning or .error directive. For an .error directive,
650 * exit immediately.
651 */
652 static void
653 HandleMessage(ParseErrorLevel level, const char *levelName, const char *umsg)
654 {
655 char *xmsg;
656
657 if (umsg[0] == '\0') {
658 Parse_Error(PARSE_FATAL, "Missing argument for \".%s\"",
659 levelName);
660 return;
661 }
662
663 xmsg = Var_Subst(umsg, SCOPE_CMDLINE, VARE_EVAL);
664 /* TODO: handle errors */
665
666 Parse_Error(level, "%s", xmsg);
667 free(xmsg);
668
669 if (level == PARSE_FATAL) {
670 PrintOnError(NULL, "\n");
671 exit(1);
672 }
673 }
674
675 /*
676 * Add the child to the parent's children, and for non-special targets, vice
677 * versa.
678 */
679 static void
680 LinkSource(GNode *pgn, GNode *cgn, bool isSpecial)
681 {
682 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(&pgn->cohorts))
683 pgn = pgn->cohorts.last->datum;
684
685 Lst_Append(&pgn->children, cgn);
686 pgn->unmade++;
687
688 /*
689 * Special targets like .END do not need to be informed once the child
690 * target has been made.
691 */
692 if (!isSpecial)
693 Lst_Append(&cgn->parents, pgn);
694
695 if (DEBUG(PARSE)) {
696 debug_printf("Target \"%s\" depends on \"%s\"\n",
697 pgn->name, cgn->name);
698 Targ_PrintNode(pgn, 0);
699 Targ_PrintNode(cgn, 0);
700 }
701 }
702
703 /* Add the node to each target from the current dependency group. */
704 static void
705 LinkToTargets(GNode *gn, bool isSpecial)
706 {
707 GNodeListNode *ln;
708
709 for (ln = targets->first; ln != NULL; ln = ln->next)
710 LinkSource(ln->datum, gn, isSpecial);
711 }
712
713 static bool
714 TryApplyDependencyOperator(GNode *gn, GNodeType op)
715 {
716 /*
717 * If the node occurred on the left-hand side of a dependency and the
718 * operator also defines a dependency, they must match.
719 */
720 if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) &&
721 ((op & OP_OPMASK) != (gn->type & OP_OPMASK))) {
722 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
723 gn->name);
724 return false;
725 }
726
727 if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
728 /*
729 * If the node was on the left-hand side of a '::' operator,
730 * create a new node for the children and commands on this
731 * dependency line, since each of these dependency groups has
732 * its own attributes and commands, separate from the others.
733 *
734 * The new instance is placed on the 'cohorts' list of the
735 * initial one (note the initial one is not on its own
736 * cohorts list) and the new instance is linked to all
737 * parents of the initial instance.
738 */
739 GNode *cohort;
740
741 /*
742 * Propagate copied bits to the initial node. They'll be
743 * propagated back to the rest of the cohorts later.
744 */
745 gn->type |= op & (unsigned)~OP_OPMASK;
746
747 cohort = Targ_NewInternalNode(gn->name);
748 if (doing_depend)
749 RememberLocation(cohort);
750 /*
751 * Make the cohort invisible to avoid duplicating it
752 * into other variables. True, parents of this target won't
753 * tend to do anything with their local variables, but better
754 * safe than sorry.
755 *
756 * (I think this is pointless now, since the relevant list
757 * traversals will no longer see this node anyway. -mycroft)
758 */
759 cohort->type = op | OP_INVISIBLE;
760 Lst_Append(&gn->cohorts, cohort);
761 cohort->centurion = gn;
762 gn->unmade_cohorts++;
763 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d",
764 (unsigned)gn->unmade_cohorts % 1000000);
765 } else {
766 gn->type |= op; /* preserve any previous flags */
767 }
768
769 return true;
770 }
771
772 static void
773 ApplyDependencyOperator(GNodeType op)
774 {
775 GNodeListNode *ln;
776
777 for (ln = targets->first; ln != NULL; ln = ln->next)
778 if (!TryApplyDependencyOperator(ln->datum, op))
779 break;
780 }
781
782 /*
783 * Add a .WAIT node in the dependency list. After any dynamic dependencies
784 * (and filename globbing) have happened, it is given a dependency on each
785 * previous child, back until the previous .WAIT node. The next child won't
786 * be scheduled until the .WAIT node is built.
787 *
788 * Give each .WAIT node a unique name (mainly for diagnostics).
789 */
790 static void
791 ApplyDependencySourceWait(bool isSpecial)
792 {
793 static unsigned wait_number = 0;
794 char name[6 + 10 + 1];
795 GNode *gn;
796
797 snprintf(name, sizeof name, ".WAIT_%u", ++wait_number);
798 gn = Targ_NewInternalNode(name);
799 if (doing_depend)
800 RememberLocation(gn);
801 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
802 LinkToTargets(gn, isSpecial);
803 }
804
805 static bool
806 ApplyDependencySourceKeyword(const char *src, ParseSpecial special)
807 {
808 int keywd;
809 GNodeType targetAttr;
810
811 if (*src != '.' || !ch_isupper(src[1]))
812 return false;
813
814 keywd = FindKeyword(src);
815 if (keywd == -1)
816 return false;
817
818 targetAttr = parseKeywords[keywd].targetAttr;
819 if (targetAttr != OP_NONE) {
820 ApplyDependencyOperator(targetAttr);
821 return true;
822 }
823 if (parseKeywords[keywd].special == SP_WAIT) {
824 ApplyDependencySourceWait(special != SP_NOT);
825 return true;
826 }
827 return false;
828 }
829
830 /*
831 * In a line like ".MAIN: source1 source2", add all sources to the list of
832 * things to create, but only if the user didn't specify a target on the
833 * command line and .MAIN occurs for the first time.
834 *
835 * See HandleDependencyTargetSpecial, branch SP_MAIN.
836 * See unit-tests/cond-func-make-main.mk.
837 */
838 static void
839 ApplyDependencySourceMain(const char *src)
840 {
841 Lst_Append(&opts.create, bmake_strdup(src));
842 /*
843 * Add the name to the .TARGETS variable as well, so the user can
844 * employ that, if desired.
845 */
846 Global_Append(".TARGETS", src);
847 }
848
849 /*
850 * For the sources of a .ORDER target, create predecessor/successor links
851 * between the previous source and the current one.
852 */
853 static void
854 ApplyDependencySourceOrder(const char *src)
855 {
856 GNode *gn;
857
858 gn = Targ_GetNode(src);
859 if (doing_depend)
860 RememberLocation(gn);
861 if (order_pred != NULL) {
862 Lst_Append(&order_pred->order_succ, gn);
863 Lst_Append(&gn->order_pred, order_pred);
864 if (DEBUG(PARSE)) {
865 debug_printf(
866 "# .ORDER forces '%s' to be made before '%s'\n",
867 order_pred->name, gn->name);
868 Targ_PrintNode(order_pred, 0);
869 Targ_PrintNode(gn, 0);
870 }
871 }
872 /* The current source now becomes the predecessor for the next one. */
873 order_pred = gn;
874 }
875
876 /* The source is not an attribute, so find/create a node for it. */
877 static void
878 ApplyDependencySourceOther(const char *src, GNodeType targetAttr,
879 ParseSpecial special)
880 {
881 GNode *gn;
882
883 gn = Targ_GetNode(src);
884 if (doing_depend)
885 RememberLocation(gn);
886 if (targetAttr != OP_NONE)
887 gn->type |= targetAttr;
888 else
889 LinkToTargets(gn, special != SP_NOT);
890 }
891
892 /*
893 * Given the name of a source in a dependency line, figure out if it is an
894 * attribute (such as .SILENT) and if so, apply it to all targets. Otherwise
895 * decide if there is some attribute which should be applied *to* the source
896 * because of some special target (such as .PHONY) and apply it if so.
897 * Otherwise, make the source a child of the targets.
898 */
899 static void
900 ApplyDependencySource(GNodeType targetAttr, const char *src,
901 ParseSpecial special)
902 {
903 if (ApplyDependencySourceKeyword(src, special))
904 return;
905
906 if (special == SP_MAIN)
907 ApplyDependencySourceMain(src);
908 else if (special == SP_ORDER)
909 ApplyDependencySourceOrder(src);
910 else
911 ApplyDependencySourceOther(src, targetAttr, special);
912 }
913
914 /*
915 * If we have yet to decide on a main target to make, in the absence of any
916 * user input, we want the first target on the first dependency line that is
917 * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made.
918 */
919 static void
920 MaybeUpdateMainTarget(void)
921 {
922 GNodeListNode *ln;
923
924 if (mainNode != NULL)
925 return;
926
927 for (ln = targets->first; ln != NULL; ln = ln->next) {
928 GNode *gn = ln->datum;
929 if (GNode_IsMainCandidate(gn)) {
930 DEBUG1(MAKE, "Setting main node to \"%s\"\n",
931 gn->name);
932 mainNode = gn;
933 return;
934 }
935 }
936 }
937
938 static void
939 InvalidLineType(const char *line, const char *unexpanded_line)
940 {
941 if (unexpanded_line[0] == '.') {
942 const char *dirstart = unexpanded_line + 1;
943 const char *dirend;
944 cpp_skip_whitespace(&dirstart);
945 dirend = dirstart;
946 while (ch_isalnum(*dirend) || *dirend == '-')
947 dirend++;
948 Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
949 (int)(dirend - dirstart), dirstart);
950 } else if (strcmp(line, unexpanded_line) == 0)
951 Parse_Error(PARSE_FATAL, "Invalid line '%s'", line);
952 else
953 Parse_Error(PARSE_FATAL,
954 "Invalid line '%s', expanded to '%s'",
955 unexpanded_line, line);
956 }
957
958 static void
959 ParseDependencyTargetWord(char **pp, const char *lstart)
960 {
961 const char *p = *pp;
962
963 while (*p != '\0') {
964 if ((ch_isspace(*p) || *p == '!' || *p == ':' || *p == '(')
965 && !IsEscaped(lstart, p))
966 break;
967
968 if (*p == '$') {
969 FStr val = Var_Parse(&p, SCOPE_CMDLINE, VARE_PARSE);
970 /* TODO: handle errors */
971 FStr_Done(&val);
972 } else
973 p++;
974 }
975
976 *pp += p - *pp;
977 }
978
979 /*
980 * Handle special targets like .PATH, .DEFAULT, .BEGIN, .ORDER.
981 *
982 * See the tests deptgt-*.mk.
983 */
984 static void
985 HandleDependencyTargetSpecial(const char *targetName,
986 ParseSpecial *inout_special,
987 SearchPathList **inout_paths)
988 {
989 switch (*inout_special) {
990 case SP_PATH:
991 if (*inout_paths == NULL)
992 *inout_paths = Lst_New();
993 Lst_Append(*inout_paths, &dirSearchPath);
994 break;
995 case SP_SYSPATH:
996 if (*inout_paths == NULL)
997 *inout_paths = Lst_New();
998 Lst_Append(*inout_paths, sysIncPath);
999 break;
1000 case SP_MAIN:
1001 /*
1002 * Allow targets from the command line to override the
1003 * .MAIN node.
1004 */
1005 if (!Lst_IsEmpty(&opts.create))
1006 *inout_special = SP_NOT;
1007 break;
1008 case SP_BEGIN:
1009 case SP_END:
1010 case SP_STALE:
1011 case SP_ERROR:
1012 case SP_INTERRUPT: {
1013 GNode *gn = Targ_GetNode(targetName);
1014 if (doing_depend)
1015 RememberLocation(gn);
1016 gn->type |= OP_NOTMAIN | OP_SPECIAL;
1017 Lst_Append(targets, gn);
1018 break;
1019 }
1020 case SP_DEFAULT: {
1021 /*
1022 * Need to create a node to hang commands on, but we don't
1023 * want it in the graph, nor do we want it to be the Main
1024 * Target. We claim the node is a transformation rule to make
1025 * life easier later, when we'll use Make_HandleUse to
1026 * actually apply the .DEFAULT commands.
1027 */
1028 GNode *gn = GNode_New(".DEFAULT");
1029 gn->type |= OP_NOTMAIN | OP_TRANSFORM;
1030 Lst_Append(targets, gn);
1031 defaultNode = gn;
1032 break;
1033 }
1034 case SP_DELETE_ON_ERROR:
1035 deleteOnError = true;
1036 break;
1037 case SP_NOTPARALLEL:
1038 opts.maxJobs = 1;
1039 break;
1040 case SP_SINGLESHELL:
1041 opts.compatMake = true;
1042 break;
1043 case SP_ORDER:
1044 order_pred = NULL;
1045 break;
1046 default:
1047 break;
1048 }
1049 }
1050
1051 static bool
1052 HandleDependencyTargetPath(const char *suffixName,
1053 SearchPathList **inout_paths)
1054 {
1055 SearchPath *path;
1056
1057 path = Suff_GetPath(suffixName);
1058 if (path == NULL) {
1059 Parse_Error(PARSE_FATAL,
1060 "Suffix '%s' not defined (yet)", suffixName);
1061 return false;
1062 }
1063
1064 if (*inout_paths == NULL)
1065 *inout_paths = Lst_New();
1066 Lst_Append(*inout_paths, path);
1067
1068 return true;
1069 }
1070
1071 /* See if it's a special target and if so set inout_special to match it. */
1072 static bool
1073 HandleDependencyTarget(const char *targetName,
1074 ParseSpecial *inout_special,
1075 GNodeType *inout_targetAttr,
1076 SearchPathList **inout_paths)
1077 {
1078 int keywd;
1079
1080 if (!(targetName[0] == '.' && ch_isupper(targetName[1])))
1081 return true;
1082
1083 /*
1084 * See if the target is a special target that must have it
1085 * or its sources handled specially.
1086 */
1087 keywd = FindKeyword(targetName);
1088 if (keywd != -1) {
1089 if (*inout_special == SP_PATH &&
1090 parseKeywords[keywd].special != SP_PATH) {
1091 Parse_Error(PARSE_FATAL, "Mismatched special targets");
1092 return false;
1093 }
1094
1095 *inout_special = parseKeywords[keywd].special;
1096 *inout_targetAttr = parseKeywords[keywd].targetAttr;
1097
1098 HandleDependencyTargetSpecial(targetName, inout_special,
1099 inout_paths);
1100
1101 } else if (strncmp(targetName, ".PATH", 5) == 0) {
1102 *inout_special = SP_PATH;
1103 if (!HandleDependencyTargetPath(targetName + 5, inout_paths))
1104 return false;
1105 }
1106 return true;
1107 }
1108
1109 static void
1110 HandleSingleDependencyTargetMundane(const char *name)
1111 {
1112 GNode *gn = Suff_IsTransform(name)
1113 ? Suff_AddTransform(name)
1114 : Targ_GetNode(name);
1115 if (doing_depend)
1116 RememberLocation(gn);
1117
1118 Lst_Append(targets, gn);
1119 }
1120
1121 static void
1122 HandleDependencyTargetMundane(const char *targetName)
1123 {
1124 if (Dir_HasWildcards(targetName)) {
1125 StringList targetNames = LST_INIT;
1126
1127 SearchPath *emptyPath = SearchPath_New();
1128 SearchPath_Expand(emptyPath, targetName, &targetNames);
1129 SearchPath_Free(emptyPath);
1130
1131 while (!Lst_IsEmpty(&targetNames)) {
1132 char *targName = Lst_Dequeue(&targetNames);
1133 HandleSingleDependencyTargetMundane(targName);
1134 free(targName);
1135 }
1136 } else
1137 HandleSingleDependencyTargetMundane(targetName);
1138 }
1139
1140 static void
1141 SkipExtraTargets(char **pp, const char *lstart)
1142 {
1143 bool warning = false;
1144 const char *p = *pp;
1145
1146 while (*p != '\0') {
1147 if (!IsEscaped(lstart, p) && (*p == '!' || *p == ':'))
1148 break;
1149 if (IsEscaped(lstart, p) || (*p != ' ' && *p != '\t'))
1150 warning = true;
1151 p++;
1152 }
1153 if (warning) {
1154 const char *start = *pp;
1155 cpp_skip_whitespace(&start);
1156 Parse_Error(PARSE_WARNING, "Extra target '%.*s' ignored",
1157 (int)(p - start), start);
1158 }
1159
1160 *pp += p - *pp;
1161 }
1162
1163 static void
1164 CheckSpecialMundaneMixture(ParseSpecial special)
1165 {
1166 switch (special) {
1167 case SP_DEFAULT:
1168 case SP_STALE:
1169 case SP_BEGIN:
1170 case SP_END:
1171 case SP_ERROR:
1172 case SP_INTERRUPT:
1173 /*
1174 * These create nodes on which to hang commands, so targets
1175 * shouldn't be empty.
1176 */
1177 case SP_NOT:
1178 /* Nothing special here -- targets may be empty. */
1179 break;
1180 default:
1181 Parse_Error(PARSE_WARNING,
1182 "Special and mundane targets don't mix. "
1183 "Mundane ones ignored");
1184 break;
1185 }
1186 }
1187
1188 /*
1189 * In a dependency line like 'targets: sources' or 'targets! sources', parse
1190 * the operator ':', '::' or '!' from between the targets and the sources.
1191 */
1192 static GNodeType
1193 ParseDependencyOp(char **pp)
1194 {
1195 if (**pp == '!')
1196 return (*pp)++, OP_FORCE;
1197 if (**pp == ':' && (*pp)[1] == ':')
1198 return *pp += 2, OP_DOUBLEDEP;
1199 else if (**pp == ':')
1200 return (*pp)++, OP_DEPENDS;
1201 else
1202 return OP_NONE;
1203 }
1204
1205 static void
1206 ClearPaths(ParseSpecial special, SearchPathList *paths)
1207 {
1208 if (paths != NULL) {
1209 SearchPathListNode *ln;
1210 for (ln = paths->first; ln != NULL; ln = ln->next)
1211 SearchPath_Clear(ln->datum);
1212 }
1213 if (special == SP_SYSPATH)
1214 Dir_SetSYSPATH();
1215 else
1216 Dir_SetPATH();
1217 }
1218
1219 static char *
1220 FindInDirOfIncludingFile(const char *file)
1221 {
1222 char *fullname, *incdir, *slash, *newName;
1223 int i;
1224
1225 fullname = NULL;
1226 incdir = bmake_strdup(CurFile()->name.str);
1227 slash = strrchr(incdir, '/');
1228 if (slash != NULL) {
1229 *slash = '\0';
1230 /*
1231 * Now do lexical processing of leading "../" on the
1232 * filename.
1233 */
1234 for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) {
1235 slash = strrchr(incdir + 1, '/');
1236 if (slash == NULL || strcmp(slash, "/..") == 0)
1237 break;
1238 *slash = '\0';
1239 }
1240 newName = str_concat3(incdir, "/", file + i);
1241 fullname = Dir_FindFile(newName, parseIncPath);
1242 if (fullname == NULL)
1243 fullname = Dir_FindFile(newName, &dirSearchPath);
1244 free(newName);
1245 }
1246 free(incdir);
1247 return fullname;
1248 }
1249
1250 static char *
1251 FindInQuotPath(const char *file)
1252 {
1253 const char *suff;
1254 SearchPath *suffPath;
1255 char *fullname;
1256
1257 fullname = FindInDirOfIncludingFile(file);
1258 if (fullname == NULL &&
1259 (suff = strrchr(file, '.')) != NULL &&
1260 (suffPath = Suff_GetPath(suff)) != NULL)
1261 fullname = Dir_FindFile(file, suffPath);
1262 if (fullname == NULL)
1263 fullname = Dir_FindFile(file, parseIncPath);
1264 if (fullname == NULL)
1265 fullname = Dir_FindFile(file, &dirSearchPath);
1266 return fullname;
1267 }
1268
1269 static bool
1270 SkipGuarded(const char *fullname)
1271 {
1272 Guard *guard = HashTable_FindValue(&guards, fullname);
1273 if (guard != NULL && guard->kind == GK_VARIABLE
1274 && GNode_ValueDirect(SCOPE_GLOBAL, guard->name) != NULL)
1275 goto skip;
1276 if (guard != NULL && guard->kind == GK_TARGET
1277 && Targ_FindNode(guard->name) != NULL)
1278 goto skip;
1279 return false;
1280
1281 skip:
1282 DEBUG2(PARSE, "Skipping '%s' because '%s' is defined\n",
1283 fullname, guard->name);
1284 return true;
1285 }
1286
1287 /*
1288 * Handle one of the .[-ds]include directives by remembering the current file
1289 * and pushing the included file on the stack. After the included file has
1290 * finished, parsing continues with the including file; see Parse_PushInput
1291 * and ParseEOF.
1292 *
1293 * System includes are looked up in sysIncPath, any other includes are looked
1294 * up in the parsedir and then in the directories specified by the -I command
1295 * line options.
1296 */
1297 static void
1298 IncludeFile(const char *file, bool isSystem, bool depinc, bool silent)
1299 {
1300 Buffer buf;
1301 char *fullname; /* full pathname of file */
1302 int fd;
1303
1304 fullname = file[0] == '/' ? bmake_strdup(file) : NULL;
1305
1306 if (fullname == NULL && !isSystem)
1307 fullname = FindInQuotPath(file);
1308
1309 if (fullname == NULL) {
1310 SearchPath *path = Lst_IsEmpty(&sysIncPath->dirs)
1311 ? defSysIncPath : sysIncPath;
1312 fullname = Dir_FindInclude(file, path);
1313 }
1314
1315 if (fullname == NULL) {
1316 if (!silent)
1317 Parse_Error(PARSE_FATAL, "Could not find %s", file);
1318 return;
1319 }
1320
1321 if (SkipGuarded(fullname))
1322 goto done;
1323
1324 if ((fd = open(fullname, O_RDONLY)) == -1) {
1325 if (!silent)
1326 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
1327 goto done;
1328 }
1329
1330 buf = LoadFile(fullname, fd);
1331 (void)close(fd);
1332
1333 Parse_PushInput(fullname, 1, 0, buf, NULL);
1334 if (depinc)
1335 doing_depend = depinc; /* only turn it on */
1336 done:
1337 free(fullname);
1338 }
1339
1340 /* Handle a "dependency" line like '.SPECIAL:' without any sources. */
1341 static void
1342 HandleDependencySourcesEmpty(ParseSpecial special, SearchPathList *paths)
1343 {
1344 switch (special) {
1345 case SP_SUFFIXES:
1346 Suff_ClearSuffixes();
1347 break;
1348 case SP_PRECIOUS:
1349 allPrecious = true;
1350 break;
1351 case SP_IGNORE:
1352 opts.ignoreErrors = true;
1353 break;
1354 case SP_SILENT:
1355 opts.silent = true;
1356 break;
1357 case SP_PATH:
1358 case SP_SYSPATH:
1359 ClearPaths(special, paths);
1360 break;
1361 case SP_POSIX:
1362 if (posix_state == PS_NOW_OR_NEVER) {
1363 /*
1364 * With '-r', 'posix.mk' (if it exists)
1365 * can effectively substitute for 'sys.mk',
1366 * otherwise it is an extension.
1367 */
1368 Global_Set("%POSIX", "1003.2");
1369 posix_state = PS_SET;
1370 IncludeFile("posix.mk", true, false, true);
1371 }
1372 break;
1373 default:
1374 break;
1375 }
1376 }
1377
1378 static void
1379 AddToPaths(const char *dir, SearchPathList *paths)
1380 {
1381 if (paths != NULL) {
1382 SearchPathListNode *ln;
1383 for (ln = paths->first; ln != NULL; ln = ln->next)
1384 (void)SearchPath_Add(ln->datum, dir);
1385 }
1386 }
1387
1388 /*
1389 * If the target was one that doesn't take files as its sources but takes
1390 * something like suffixes, we take each space-separated word on the line as
1391 * a something and deal with it accordingly.
1392 */
1393 static void
1394 ParseDependencySourceSpecial(ParseSpecial special, const char *word,
1395 SearchPathList *paths)
1396 {
1397 switch (special) {
1398 case SP_SUFFIXES:
1399 Suff_AddSuffix(word);
1400 break;
1401 case SP_PATH:
1402 case SP_SYSPATH:
1403 AddToPaths(word, paths);
1404 break;
1405 case SP_INCLUDES:
1406 Suff_AddInclude(word);
1407 break;
1408 case SP_LIBS:
1409 Suff_AddLib(word);
1410 break;
1411 case SP_NOREADONLY:
1412 Var_ReadOnly(word, false);
1413 break;
1414 case SP_NULL:
1415 Suff_SetNull(word);
1416 break;
1417 case SP_OBJDIR:
1418 Main_SetObjdir(false, "%s", word);
1419 break;
1420 case SP_READONLY:
1421 Var_ReadOnly(word, true);
1422 break;
1423 default:
1424 break;
1425 }
1426 }
1427
1428 static bool
1429 ApplyDependencyTarget(char *name, char *nameEnd, ParseSpecial *inout_special,
1430 GNodeType *inout_targetAttr,
1431 SearchPathList **inout_paths)
1432 {
1433 char savedNameEnd = *nameEnd;
1434 *nameEnd = '\0';
1435
1436 if (!HandleDependencyTarget(name, inout_special,
1437 inout_targetAttr, inout_paths))
1438 return false;
1439
1440 if (*inout_special == SP_NOT && *name != '\0')
1441 HandleDependencyTargetMundane(name);
1442 else if (*inout_special == SP_PATH && *name != '.' && *name != '\0')
1443 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", name);
1444
1445 *nameEnd = savedNameEnd;
1446 return true;
1447 }
1448
1449 static bool
1450 ParseDependencyTargets(char **pp,
1451 const char *lstart,
1452 ParseSpecial *inout_special,
1453 GNodeType *inout_targetAttr,
1454 SearchPathList **inout_paths,
1455 const char *unexpanded_line)
1456 {
1457 char *p = *pp;
1458
1459 for (;;) {
1460 char *tgt = p;
1461
1462 ParseDependencyTargetWord(&p, lstart);
1463
1464 /*
1465 * If the word is followed by a left parenthesis, it's the
1466 * name of one or more files inside an archive.
1467 */
1468 if (!IsEscaped(lstart, p) && *p == '(') {
1469 p = tgt;
1470 if (!Arch_ParseArchive(&p, targets, SCOPE_CMDLINE)) {
1471 Parse_Error(PARSE_FATAL,
1472 "Error in archive specification: \"%s\"",
1473 tgt);
1474 return false;
1475 }
1476 continue;
1477 }
1478
1479 if (*p == '\0') {
1480 InvalidLineType(lstart, unexpanded_line);
1481 return false;
1482 }
1483
1484 if (!ApplyDependencyTarget(tgt, p, inout_special,
1485 inout_targetAttr, inout_paths))
1486 return false;
1487
1488 if (*inout_special != SP_NOT && *inout_special != SP_PATH)
1489 SkipExtraTargets(&p, lstart);
1490 else
1491 pp_skip_whitespace(&p);
1492
1493 if (*p == '\0')
1494 break;
1495 if ((*p == '!' || *p == ':') && !IsEscaped(lstart, p))
1496 break;
1497 }
1498
1499 *pp = p;
1500 return true;
1501 }
1502
1503 static void
1504 ParseDependencySourcesSpecial(char *start,
1505 ParseSpecial special, SearchPathList *paths)
1506 {
1507
1508 while (*start != '\0') {
1509 char savedEnd;
1510 char *end = start;
1511 while (*end != '\0' && !ch_isspace(*end))
1512 end++;
1513 savedEnd = *end;
1514 *end = '\0';
1515 ParseDependencySourceSpecial(special, start, paths);
1516 *end = savedEnd;
1517 if (savedEnd != '\0')
1518 end++;
1519 pp_skip_whitespace(&end);
1520 start = end;
1521 }
1522 }
1523
1524 static void
1525 LinkVarToTargets(VarAssign *var)
1526 {
1527 GNodeListNode *ln;
1528
1529 for (ln = targets->first; ln != NULL; ln = ln->next)
1530 Parse_Var(var, ln->datum);
1531 }
1532
1533 static bool
1534 ParseDependencySourcesMundane(char *start,
1535 ParseSpecial special, GNodeType targetAttr)
1536 {
1537 while (*start != '\0') {
1538 char *end = start;
1539 VarAssign var;
1540
1541 /*
1542 * Check for local variable assignment,
1543 * rest of the line is the value.
1544 */
1545 if (Parse_IsVar(start, &var)) {
1546 bool targetVarsEnabled = GetBooleanExpr(
1547 "${.MAKE.TARGET_LOCAL_VARIABLES}", true);
1548
1549 if (targetVarsEnabled)
1550 LinkVarToTargets(&var);
1551 free(var.varname);
1552 if (targetVarsEnabled)
1553 return true;
1554 }
1555
1556 /*
1557 * The targets take real sources, so we must beware of archive
1558 * specifications (i.e. things with left parentheses in them)
1559 * and handle them accordingly.
1560 */
1561 for (; *end != '\0' && !ch_isspace(*end); end++) {
1562 if (*end == '(' && end > start && end[-1] != '$') {
1563 /*
1564 * Only stop for a left parenthesis if it
1565 * isn't at the start of a word (that'll be
1566 * for variable changes later) and isn't
1567 * preceded by a dollar sign (a dynamic
1568 * source).
1569 */
1570 break;
1571 }
1572 }
1573
1574 if (*end == '(') {
1575 GNodeList sources = LST_INIT;
1576 if (!Arch_ParseArchive(&start, &sources,
1577 SCOPE_CMDLINE)) {
1578 Parse_Error(PARSE_FATAL,
1579 "Error in source archive spec \"%s\"",
1580 start);
1581 return false;
1582 }
1583
1584 while (!Lst_IsEmpty(&sources)) {
1585 GNode *gn = Lst_Dequeue(&sources);
1586 ApplyDependencySource(targetAttr, gn->name,
1587 special);
1588 }
1589 Lst_Done(&sources);
1590 end = start;
1591 } else {
1592 if (*end != '\0') {
1593 *end = '\0';
1594 end++;
1595 }
1596
1597 ApplyDependencySource(targetAttr, start, special);
1598 }
1599 pp_skip_whitespace(&end);
1600 start = end;
1601 }
1602 return true;
1603 }
1604
1605 /*
1606 * From a dependency line like 'targets: sources', parse the sources.
1607 *
1608 * See the tests depsrc-*.mk.
1609 */
1610 static void
1611 ParseDependencySources(char *p, GNodeType targetAttr,
1612 ParseSpecial special, SearchPathList **inout_paths)
1613 {
1614 if (*p == '\0') {
1615 HandleDependencySourcesEmpty(special, *inout_paths);
1616 } else if (special == SP_MFLAGS) {
1617 Main_ParseArgLine(p);
1618 return;
1619 } else if (special == SP_SHELL) {
1620 if (!Job_ParseShell(p)) {
1621 Parse_Error(PARSE_FATAL,
1622 "improper shell specification");
1623 return;
1624 }
1625 return;
1626 } else if (special == SP_NOTPARALLEL || special == SP_SINGLESHELL ||
1627 special == SP_DELETE_ON_ERROR) {
1628 return;
1629 }
1630
1631 switch (special) {
1632 case SP_INCLUDES:
1633 case SP_LIBS:
1634 case SP_NOREADONLY:
1635 case SP_NULL:
1636 case SP_OBJDIR:
1637 case SP_PATH:
1638 case SP_READONLY:
1639 case SP_SUFFIXES:
1640 case SP_SYSPATH:
1641 ParseDependencySourcesSpecial(p, special, *inout_paths);
1642 if (*inout_paths != NULL) {
1643 Lst_Free(*inout_paths);
1644 *inout_paths = NULL;
1645 }
1646 if (special == SP_PATH)
1647 Dir_SetPATH();
1648 if (special == SP_SYSPATH)
1649 Dir_SetSYSPATH();
1650 break;
1651 default:
1652 assert(*inout_paths == NULL);
1653 if (!ParseDependencySourcesMundane(p, special, targetAttr))
1654 return;
1655 break;
1656 }
1657
1658 MaybeUpdateMainTarget();
1659 }
1660
1661 /*
1662 * Parse a dependency line consisting of targets, followed by a dependency
1663 * operator, optionally followed by sources.
1664 *
1665 * The nodes of the sources are linked as children to the nodes of the
1666 * targets. Nodes are created as necessary.
1667 *
1668 * The operator is applied to each node in the global 'targets' list,
1669 * which is where the nodes found for the targets are kept.
1670 *
1671 * The sources are parsed in much the same way as the targets, except
1672 * that they are expanded using the wildcarding scheme of the C-Shell,
1673 * and a target is created for each expanded word. Each of the resulting
1674 * nodes is then linked to each of the targets as one of its children.
1675 *
1676 * Certain targets and sources such as .PHONY or .PRECIOUS are handled
1677 * specially, see ParseSpecial.
1678 *
1679 * Transformation rules such as '.c.o' are also handled here, see
1680 * Suff_AddTransform.
1681 *
1682 * Upon return, the value of expandedLine is unspecified.
1683 */
1684 static void
1685 ParseDependency(char *expandedLine, const char *unexpandedLine)
1686 {
1687 char *p;
1688 SearchPathList *paths; /* search paths to alter when parsing a list
1689 * of .PATH targets */
1690 GNodeType targetAttr; /* from special sources */
1691 ParseSpecial special; /* in special targets, the children are
1692 * linked as children of the parent but not
1693 * vice versa */
1694 GNodeType op;
1695
1696 DEBUG1(PARSE, "ParseDependency(%s)\n", expandedLine);
1697 p = expandedLine;
1698 paths = NULL;
1699 targetAttr = OP_NONE;
1700 special = SP_NOT;
1701
1702 if (!ParseDependencyTargets(&p, expandedLine, &special, &targetAttr,
1703 &paths, unexpandedLine))
1704 goto out;
1705
1706 if (!Lst_IsEmpty(targets))
1707 CheckSpecialMundaneMixture(special);
1708
1709 op = ParseDependencyOp(&p);
1710 if (op == OP_NONE) {
1711 InvalidLineType(expandedLine, unexpandedLine);
1712 goto out;
1713 }
1714 ApplyDependencyOperator(op);
1715
1716 pp_skip_whitespace(&p);
1717
1718 ParseDependencySources(p, targetAttr, special, &paths);
1719
1720 out:
1721 if (paths != NULL)
1722 Lst_Free(paths);
1723 }
1724
1725 /*
1726 * Determine the assignment operator and adjust the end of the variable
1727 * name accordingly.
1728 */
1729 static VarAssign
1730 AdjustVarassignOp(const char *name, const char *nameEnd, const char *op,
1731 const char *value)
1732 {
1733 VarAssignOp type;
1734 VarAssign va;
1735
1736 if (op > name && op[-1] == '+') {
1737 op--;
1738 type = VAR_APPEND;
1739
1740 } else if (op > name && op[-1] == '?') {
1741 op--;
1742 type = VAR_DEFAULT;
1743
1744 } else if (op > name && op[-1] == ':') {
1745 op--;
1746 type = VAR_SUBST;
1747
1748 } else if (op > name && op[-1] == '!') {
1749 op--;
1750 type = VAR_SHELL;
1751
1752 } else {
1753 type = VAR_NORMAL;
1754 while (op > name && ch_isspace(op[-1]))
1755 op--;
1756
1757 if (op - name >= 3 && memcmp(op - 3, ":sh", 3) == 0) {
1758 op -= 3;
1759 type = VAR_SHELL;
1760 }
1761 }
1762
1763 va.varname = bmake_strsedup(name, nameEnd < op ? nameEnd : op);
1764 va.op = type;
1765 va.value = value;
1766 return va;
1767 }
1768
1769 /*
1770 * Parse a variable assignment, consisting of a single-word variable name,
1771 * optional whitespace, an assignment operator, optional whitespace and the
1772 * variable value.
1773 *
1774 * Note: There is a lexical ambiguity with assignment modifier characters
1775 * in variable names. This routine interprets the character before the =
1776 * as a modifier. Therefore, an assignment like
1777 * C++=/usr/bin/CC
1778 * is interpreted as "C+ +=" instead of "C++ =".
1779 *
1780 * Used for both lines in a file and command line arguments.
1781 */
1782 static bool
1783 Parse_IsVar(const char *p, VarAssign *out_var)
1784 {
1785 const char *nameStart, *nameEnd, *firstSpace, *eq;
1786 int level = 0;
1787
1788 cpp_skip_hspace(&p); /* Skip to variable name */
1789
1790 /*
1791 * During parsing, the '+' of the operator '+=' is initially parsed
1792 * as part of the variable name. It is later corrected, as is the
1793 * ':sh' modifier. Of these two (nameEnd and eq), the earlier one
1794 * determines the actual end of the variable name.
1795 */
1796
1797 nameStart = p;
1798 firstSpace = NULL;
1799
1800 /* Scan for one of the assignment operators outside an expression. */
1801 while (*p != '\0') {
1802 char ch = *p++;
1803 if (ch == '(' || ch == '{') {
1804 level++;
1805 continue;
1806 }
1807 if (ch == ')' || ch == '}') {
1808 level--;
1809 continue;
1810 }
1811
1812 if (level != 0)
1813 continue;
1814
1815 if ((ch == ' ' || ch == '\t') && firstSpace == NULL)
1816 firstSpace = p - 1;
1817 while (ch == ' ' || ch == '\t')
1818 ch = *p++;
1819
1820 if (ch == '\0')
1821 return false;
1822 if (ch == ':' && p[0] == 's' && p[1] == 'h') {
1823 p += 2;
1824 continue;
1825 }
1826 if (ch == '=')
1827 eq = p - 1;
1828 else if (*p == '=' &&
1829 (ch == '+' || ch == ':' || ch == '?' || ch == '!'))
1830 eq = p;
1831 else if (firstSpace != NULL)
1832 return false;
1833 else
1834 continue;
1835
1836 nameEnd = firstSpace != NULL ? firstSpace : eq;
1837 p = eq + 1;
1838 cpp_skip_whitespace(&p);
1839 *out_var = AdjustVarassignOp(nameStart, nameEnd, eq, p);
1840 return true;
1841 }
1842
1843 return false;
1844 }
1845
1846 /*
1847 * Check for syntax errors such as unclosed expressions or unknown modifiers.
1848 */
1849 static void
1850 VarCheckSyntax(VarAssignOp op, const char *uvalue, GNode *scope)
1851 {
1852 if (opts.strict) {
1853 if (op != VAR_SUBST && strchr(uvalue, '$') != NULL) {
1854 char *parsedValue = Var_Subst(uvalue,
1855 scope, VARE_PARSE);
1856 /* TODO: handle errors */
1857 free(parsedValue);
1858 }
1859 }
1860 }
1861
1862 /* Perform a variable assignment that uses the operator ':='. */
1863 static void
1864 VarAssign_EvalSubst(GNode *scope, const char *name, const char *uvalue,
1865 FStr *out_avalue)
1866 {
1867 char *evalue;
1868
1869 /*
1870 * Make sure that we set the variable the first time to nothing
1871 * so that it gets substituted.
1872 *
1873 * TODO: Add a test that demonstrates why this code is needed,
1874 * apart from making the debug log longer.
1875 *
1876 * XXX: The variable name is expanded up to 3 times.
1877 */
1878 if (!Var_ExistsExpand(scope, name))
1879 Var_SetExpand(scope, name, "");
1880
1881 evalue = Var_Subst(uvalue, scope,
1882 VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED);
1883 /* TODO: handle errors */
1884
1885 Var_SetExpand(scope, name, evalue);
1886
1887 *out_avalue = FStr_InitOwn(evalue);
1888 }
1889
1890 /* Perform a variable assignment that uses the operator '!='. */
1891 static void
1892 VarAssign_EvalShell(const char *name, const char *uvalue, GNode *scope,
1893 FStr *out_avalue)
1894 {
1895 FStr cmd;
1896 char *output, *error;
1897
1898 cmd = FStr_InitRefer(uvalue);
1899 Var_Expand(&cmd, SCOPE_CMDLINE, VARE_EVAL);
1900
1901 output = Cmd_Exec(cmd.str, &error);
1902 Var_SetExpand(scope, name, output);
1903 *out_avalue = FStr_InitOwn(output);
1904 if (error != NULL) {
1905 Parse_Error(PARSE_WARNING, "%s", error);
1906 free(error);
1907 }
1908
1909 FStr_Done(&cmd);
1910 }
1911
1912 /*
1913 * Perform a variable assignment.
1914 *
1915 * The actual value of the variable is returned in *out_true_avalue.
1916 * Especially for VAR_SUBST and VAR_SHELL this can differ from the literal
1917 * value.
1918 *
1919 * Return whether the assignment was actually performed, which is usually
1920 * the case. It is only skipped if the operator is '?=' and the variable
1921 * already exists.
1922 */
1923 static bool
1924 VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
1925 GNode *scope, FStr *out_true_avalue)
1926 {
1927 FStr avalue = FStr_InitRefer(uvalue);
1928
1929 if (op == VAR_APPEND)
1930 Var_AppendExpand(scope, name, uvalue);
1931 else if (op == VAR_SUBST)
1932 VarAssign_EvalSubst(scope, name, uvalue, &avalue);
1933 else if (op == VAR_SHELL)
1934 VarAssign_EvalShell(name, uvalue, scope, &avalue);
1935 else {
1936 /* XXX: The variable name is expanded up to 2 times. */
1937 if (op == VAR_DEFAULT && Var_ExistsExpand(scope, name))
1938 return false;
1939
1940 /* Normal assignment -- just do it. */
1941 Var_SetExpand(scope, name, uvalue);
1942 }
1943
1944 *out_true_avalue = avalue;
1945 return true;
1946 }
1947
1948 static void
1949 VarAssignSpecial(const char *name, const char *avalue)
1950 {
1951 if (strcmp(name, ".MAKEOVERRIDES") == 0)
1952 Main_ExportMAKEFLAGS(false); /* re-export MAKEFLAGS */
1953 else if (strcmp(name, ".CURDIR") == 0) {
1954 /*
1955 * Someone is being (too?) clever...
1956 * Let's pretend they know what they are doing and
1957 * re-initialize the 'cur' CachedDir.
1958 */
1959 Dir_InitCur(avalue);
1960 Dir_SetPATH();
1961 } else if (strcmp(name, ".MAKE.JOB.PREFIX") == 0)
1962 Job_SetPrefix();
1963 else if (strcmp(name, ".MAKE.EXPORTED") == 0)
1964 Var_ExportVars(avalue);
1965 }
1966
1967 /* Perform the variable assignment in the given scope. */
1968 static void
1969 Parse_Var(VarAssign *var, GNode *scope)
1970 {
1971 FStr avalue; /* actual value (maybe expanded) */
1972
1973 VarCheckSyntax(var->op, var->value, scope);
1974 if (VarAssign_Eval(var->varname, var->op, var->value, scope, &avalue)) {
1975 VarAssignSpecial(var->varname, avalue.str);
1976 FStr_Done(&avalue);
1977 }
1978 }
1979
1980
1981 /*
1982 * See if the command possibly calls a sub-make by using the
1983 * expressions ${.MAKE}, ${MAKE} or the plain word "make".
1984 */
1985 static bool
1986 MaybeSubMake(const char *cmd)
1987 {
1988 const char *start;
1989
1990 for (start = cmd; *start != '\0'; start++) {
1991 const char *p = start;
1992 char endc;
1993
1994 /* XXX: What if progname != "make"? */
1995 if (strncmp(p, "make", 4) == 0)
1996 if (start == cmd || !ch_isalnum(p[-1]))
1997 if (!ch_isalnum(p[4]))
1998 return true;
1999
2000 if (*p != '$')
2001 continue;
2002 p++;
2003
2004 if (*p == '{')
2005 endc = '}';
2006 else if (*p == '(')
2007 endc = ')';
2008 else
2009 continue;
2010 p++;
2011
2012 if (*p == '.') /* Accept either ${.MAKE} or ${MAKE}. */
2013 p++;
2014
2015 if (strncmp(p, "MAKE", 4) == 0 && p[4] == endc)
2016 return true;
2017 }
2018 return false;
2019 }
2020
2021 /* Append the command to the target node. */
2022 static void
2023 GNode_AddCommand(GNode *gn, char *cmd)
2024 {
2025 if ((gn->type & OP_DOUBLEDEP) && gn->cohorts.last != NULL)
2026 gn = gn->cohorts.last->datum;
2027
2028 /* if target already supplied, ignore commands */
2029 if (!(gn->type & OP_HAS_COMMANDS)) {
2030 Lst_Append(&gn->commands, cmd);
2031 if (MaybeSubMake(cmd))
2032 gn->type |= OP_SUBMAKE;
2033 RememberLocation(gn);
2034 } else {
2035 Parse_Error(PARSE_WARNING,
2036 "duplicate script for target \"%s\" ignored",
2037 gn->name);
2038 ParseErrorInternal(gn, PARSE_WARNING,
2039 "using previous script for \"%s\" defined here",
2040 gn->name);
2041 }
2042 }
2043
2044 /*
2045 * Parse a directive like '.include' or '.-include'.
2046 *
2047 * .include "user-makefile.mk"
2048 * .include <system-makefile.mk>
2049 */
2050 static void
2051 ParseInclude(char *directive)
2052 {
2053 char endc; /* '>' or '"' */
2054 char *p;
2055 bool silent = directive[0] != 'i';
2056 FStr file;
2057
2058 p = directive + (silent ? 8 : 7);
2059 pp_skip_hspace(&p);
2060
2061 if (*p != '"' && *p != '<') {
2062 Parse_Error(PARSE_FATAL,
2063 ".include filename must be delimited by '\"' or '<'");
2064 return;
2065 }
2066
2067 endc = *p++ == '<' ? '>' : '"';
2068 file = FStr_InitRefer(p);
2069
2070 while (*p != '\0' && *p != endc)
2071 p++;
2072
2073 if (*p != endc) {
2074 Parse_Error(PARSE_FATAL,
2075 "Unclosed .include filename. '%c' expected", endc);
2076 return;
2077 }
2078
2079 *p = '\0';
2080
2081 Var_Expand(&file, SCOPE_CMDLINE, VARE_EVAL);
2082 IncludeFile(file.str, endc == '>', directive[0] == 'd', silent);
2083 FStr_Done(&file);
2084 }
2085
2086 /*
2087 * Split filename into dirname + basename, then assign these to the
2088 * given variables.
2089 */
2090 static void
2091 SetFilenameVars(const char *filename, const char *dirvar, const char *filevar)
2092 {
2093 const char *slash, *basename;
2094 FStr dirname;
2095
2096 slash = strrchr(filename, '/');
2097 if (slash == NULL) {
2098 dirname = FStr_InitRefer(curdir);
2099 basename = filename;
2100 } else {
2101 dirname = FStr_InitOwn(bmake_strsedup(filename, slash));
2102 basename = slash + 1;
2103 }
2104
2105 Global_Set(dirvar, dirname.str);
2106 Global_Set(filevar, basename);
2107
2108 DEBUG4(PARSE, "SetFilenameVars: ${%s} = `%s' ${%s} = `%s'\n",
2109 dirvar, dirname.str, filevar, basename);
2110 FStr_Done(&dirname);
2111 }
2112
2113 /*
2114 * Return the immediately including file.
2115 *
2116 * This is made complicated since the .for loop is implemented as a special
2117 * kind of .include; see For_Run.
2118 */
2119 static const char *
2120 GetActuallyIncludingFile(void)
2121 {
2122 size_t i;
2123 const IncludedFile *incs = GetInclude(0);
2124
2125 for (i = includes.len; i >= 2; i--)
2126 if (incs[i - 1].forLoop == NULL)
2127 return incs[i - 2].name.str;
2128 return NULL;
2129 }
2130
2131 /* Set .PARSEDIR, .PARSEFILE, .INCLUDEDFROMDIR and .INCLUDEDFROMFILE. */
2132 static void
2133 SetParseFile(const char *filename)
2134 {
2135 const char *including;
2136
2137 SetFilenameVars(filename, ".PARSEDIR", ".PARSEFILE");
2138
2139 including = GetActuallyIncludingFile();
2140 if (including != NULL) {
2141 SetFilenameVars(including,
2142 ".INCLUDEDFROMDIR", ".INCLUDEDFROMFILE");
2143 } else {
2144 Global_Delete(".INCLUDEDFROMDIR");
2145 Global_Delete(".INCLUDEDFROMFILE");
2146 }
2147 }
2148
2149 static bool
2150 StrContainsWord(const char *str, const char *word)
2151 {
2152 size_t strLen = strlen(str);
2153 size_t wordLen = strlen(word);
2154 const char *p;
2155
2156 if (strLen < wordLen)
2157 return false;
2158
2159 for (p = str; p != NULL; p = strchr(p, ' ')) {
2160 if (*p == ' ')
2161 p++;
2162 if (p > str + strLen - wordLen)
2163 return false;
2164
2165 if (memcmp(p, word, wordLen) == 0 &&
2166 (p[wordLen] == '\0' || p[wordLen] == ' '))
2167 return true;
2168 }
2169 return false;
2170 }
2171
2172 /*
2173 * XXX: Searching through a set of words with this linear search is
2174 * inefficient for variables that contain thousands of words.
2175 *
2176 * XXX: The paths in this list don't seem to be normalized in any way.
2177 */
2178 static bool
2179 VarContainsWord(const char *varname, const char *word)
2180 {
2181 FStr val = Var_Value(SCOPE_GLOBAL, varname);
2182 bool found = val.str != NULL && StrContainsWord(val.str, word);
2183 FStr_Done(&val);
2184 return found;
2185 }
2186
2187 /*
2188 * Track the makefiles we read - so makefiles can set dependencies on them.
2189 * Avoid adding anything more than once.
2190 *
2191 * Time complexity: O(n) per call, in total O(n^2), where n is the number
2192 * of makefiles that have been loaded.
2193 */
2194 static void
2195 TrackInput(const char *name)
2196 {
2197 if (!VarContainsWord(".MAKE.MAKEFILES", name))
2198 Global_Append(".MAKE.MAKEFILES", name);
2199 }
2200
2201
2202 /* Parse from the given buffer, later return to the current file. */
2203 void
2204 Parse_PushInput(const char *name, unsigned lineno, unsigned readLines,
2205 Buffer buf, struct ForLoop *forLoop)
2206 {
2207 IncludedFile *curFile;
2208
2209 if (forLoop != NULL)
2210 name = CurFile()->name.str;
2211 else
2212 TrackInput(name);
2213
2214 DEBUG3(PARSE, "Parse_PushInput: %s%s:%u\n",
2215 forLoop != NULL ? ".for loop in ": "", name, lineno);
2216
2217 curFile = Vector_Push(&includes);
2218 curFile->name = FStr_InitOwn(bmake_strdup(name));
2219 curFile->lineno = lineno;
2220 curFile->readLines = readLines;
2221 curFile->forHeadLineno = lineno;
2222 curFile->forBodyReadLines = readLines;
2223 curFile->buf = buf;
2224 curFile->depending = doing_depend; /* restore this on EOF */
2225 curFile->guardState = forLoop == NULL ? GS_START : GS_NO;
2226 curFile->guard = NULL;
2227 curFile->forLoop = forLoop;
2228
2229 if (forLoop != NULL && !For_NextIteration(forLoop, &curFile->buf))
2230 abort(); /* see For_Run */
2231
2232 curFile->buf_ptr = curFile->buf.data;
2233 curFile->buf_end = curFile->buf.data + curFile->buf.len;
2234 curFile->condMinDepth = cond_depth;
2235 SetParseFile(name);
2236 }
2237
2238 /* Check if the directive is an include directive. */
2239 static bool
2240 IsInclude(const char *dir, bool sysv)
2241 {
2242 if (dir[0] == 's' || dir[0] == '-' || (dir[0] == 'd' && !sysv))
2243 dir++;
2244
2245 if (strncmp(dir, "include", 7) != 0)
2246 return false;
2247
2248 /* Space is not mandatory for BSD .include */
2249 return !sysv || ch_isspace(dir[7]);
2250 }
2251
2252
2253 /* Check if the line is a SYSV include directive. */
2254 static bool
2255 IsSysVInclude(const char *line)
2256 {
2257 const char *p;
2258
2259 if (!IsInclude(line, true))
2260 return false;
2261
2262 /* Avoid interpreting a dependency line as an include */
2263 for (p = line; (p = strchr(p, ':')) != NULL;) {
2264
2265 /* end of line -> it's a dependency */
2266 if (*++p == '\0')
2267 return false;
2268
2269 /* '::' operator or ': ' -> it's a dependency */
2270 if (*p == ':' || ch_isspace(*p))
2271 return false;
2272 }
2273 return true;
2274 }
2275
2276 /* Push to another file. The line points to the word "include". */
2277 static void
2278 ParseTraditionalInclude(char *line)
2279 {
2280 char *p; /* current position in file spec */
2281 bool done = false;
2282 bool silent = line[0] != 'i';
2283 char *file = line + (silent ? 8 : 7);
2284 char *all_files;
2285
2286 DEBUG1(PARSE, "ParseTraditionalInclude: %s\n", file);
2287
2288 pp_skip_whitespace(&file);
2289
2290 all_files = Var_Subst(file, SCOPE_CMDLINE, VARE_EVAL);
2291 /* TODO: handle errors */
2292
2293 for (file = all_files; !done; file = p + 1) {
2294 /* Skip to end of line or next whitespace */
2295 for (p = file; *p != '\0' && !ch_isspace(*p); p++)
2296 continue;
2297
2298 if (*p != '\0')
2299 *p = '\0';
2300 else
2301 done = true;
2302
2303 IncludeFile(file, false, false, silent);
2304 }
2305
2306 free(all_files);
2307 }
2308
2309 /* Parse "export <variable>=<value>", and actually export it. */
2310 static void
2311 ParseGmakeExport(char *line)
2312 {
2313 char *variable = line + 6;
2314 char *value;
2315
2316 DEBUG1(PARSE, "ParseGmakeExport: %s\n", variable);
2317
2318 pp_skip_whitespace(&variable);
2319
2320 for (value = variable; *value != '\0' && *value != '='; value++)
2321 continue;
2322
2323 if (*value != '=') {
2324 Parse_Error(PARSE_FATAL,
2325 "Variable/Value missing from \"export\"");
2326 return;
2327 }
2328 *value++ = '\0'; /* terminate variable */
2329
2330 /*
2331 * Expand the value before putting it in the environment.
2332 */
2333 value = Var_Subst(value, SCOPE_CMDLINE, VARE_EVAL);
2334 /* TODO: handle errors */
2335
2336 setenv(variable, value, 1);
2337 free(value);
2338 }
2339
2340 /*
2341 * When the end of the current file or .for loop is reached, continue reading
2342 * the previous file at the previous location.
2343 *
2344 * Results:
2345 * true to continue parsing, i.e. it had only reached the end of an
2346 * included file, false if the main file has been parsed completely.
2347 */
2348 static bool
2349 ParseEOF(void)
2350 {
2351 IncludedFile *curFile = CurFile();
2352
2353 doing_depend = curFile->depending;
2354 if (curFile->forLoop != NULL &&
2355 For_NextIteration(curFile->forLoop, &curFile->buf)) {
2356 curFile->buf_ptr = curFile->buf.data;
2357 curFile->buf_end = curFile->buf.data + curFile->buf.len;
2358 curFile->readLines = curFile->forBodyReadLines;
2359 return true;
2360 }
2361
2362 Cond_EndFile();
2363
2364 if (curFile->guardState == GS_DONE) {
2365 HashEntry *he = HashTable_CreateEntry(&guards,
2366 curFile->name.str, NULL);
2367 if (he->value != NULL) {
2368 free(((Guard *)he->value)->name);
2369 free(he->value);
2370 }
2371 HashEntry_Set(he, curFile->guard);
2372 } else if (curFile->guard != NULL) {
2373 free(curFile->guard->name);
2374 free(curFile->guard);
2375 }
2376
2377 FStr_Done(&curFile->name);
2378 Buf_Done(&curFile->buf);
2379 if (curFile->forLoop != NULL)
2380 ForLoop_Free(curFile->forLoop);
2381 Vector_Pop(&includes);
2382
2383 if (includes.len == 0) {
2384 /* We've run out of input */
2385 Global_Delete(".PARSEDIR");
2386 Global_Delete(".PARSEFILE");
2387 Global_Delete(".INCLUDEDFROMDIR");
2388 Global_Delete(".INCLUDEDFROMFILE");
2389 return false;
2390 }
2391
2392 curFile = CurFile();
2393 DEBUG2(PARSE, "ParseEOF: returning to %s:%u\n",
2394 curFile->name.str, curFile->readLines + 1);
2395
2396 SetParseFile(curFile->name.str);
2397 return true;
2398 }
2399
2400 typedef enum ParseRawLineResult {
2401 PRLR_LINE,
2402 PRLR_EOF,
2403 PRLR_ERROR
2404 } ParseRawLineResult;
2405
2406 /*
2407 * Parse until the end of a line, taking into account lines that end with
2408 * backslash-newline. The resulting line goes from out_line to out_line_end;
2409 * the line is not null-terminated.
2410 */
2411 static ParseRawLineResult
2412 ParseRawLine(IncludedFile *curFile, char **out_line, char **out_line_end,
2413 char **out_firstBackslash, char **out_commentLineEnd)
2414 {
2415 char *line = curFile->buf_ptr;
2416 char *buf_end = curFile->buf_end;
2417 char *p = line;
2418 char *line_end = line;
2419 char *firstBackslash = NULL;
2420 char *commentLineEnd = NULL;
2421 ParseRawLineResult res = PRLR_LINE;
2422
2423 curFile->readLines++;
2424
2425 for (;;) {
2426 char ch;
2427
2428 if (p == buf_end) {
2429 res = PRLR_EOF;
2430 break;
2431 }
2432
2433 ch = *p;
2434 if (ch == '\0' || (ch == '\\' && p[1] == '\0')) {
2435 Parse_Error(PARSE_FATAL, "Zero byte read from file");
2436 exit(2);
2437 }
2438
2439 /* Treat next character after '\' as literal. */
2440 if (ch == '\\') {
2441 if (firstBackslash == NULL)
2442 firstBackslash = p;
2443 if (p[1] == '\n') {
2444 curFile->readLines++;
2445 if (p + 2 == buf_end) {
2446 line_end = p;
2447 *line_end = '\n';
2448 p += 2;
2449 continue;
2450 }
2451 }
2452 p += 2;
2453 line_end = p;
2454 assert(p <= buf_end);
2455 continue;
2456 }
2457
2458 /*
2459 * Remember the first '#' for comment stripping, unless
2460 * the previous char was '[', as in the modifier ':[#]'.
2461 */
2462 if (ch == '#' && commentLineEnd == NULL &&
2463 !(p > line && p[-1] == '['))
2464 commentLineEnd = line_end;
2465
2466 p++;
2467 if (ch == '\n')
2468 break;
2469
2470 /* We are not interested in trailing whitespace. */
2471 if (!ch_isspace(ch))
2472 line_end = p;
2473 }
2474
2475 curFile->buf_ptr = p;
2476 *out_line = line;
2477 *out_line_end = line_end;
2478 *out_firstBackslash = firstBackslash;
2479 *out_commentLineEnd = commentLineEnd;
2480 return res;
2481 }
2482
2483 /*
2484 * Beginning at start, unescape '\#' to '#' and replace backslash-newline
2485 * with a single space.
2486 */
2487 static void
2488 UnescapeBackslash(char *line, char *start)
2489 {
2490 const char *src = start;
2491 char *dst = start;
2492 char *spaceStart = line;
2493
2494 for (;;) {
2495 char ch = *src++;
2496 if (ch != '\\') {
2497 if (ch == '\0')
2498 break;
2499 *dst++ = ch;
2500 continue;
2501 }
2502
2503 ch = *src++;
2504 if (ch == '\0') {
2505 /* Delete '\\' at the end of the buffer. */
2506 dst--;
2507 break;
2508 }
2509
2510 /* Delete '\\' from before '#' on non-command lines. */
2511 if (ch == '#' && line[0] != '\t')
2512 *dst++ = ch;
2513 else if (ch == '\n') {
2514 cpp_skip_hspace(&src);
2515 *dst++ = ' ';
2516 } else {
2517 /* Leave '\\' in the buffer for later. */
2518 *dst++ = '\\';
2519 *dst++ = ch;
2520 /* Keep an escaped ' ' at the line end. */
2521 spaceStart = dst;
2522 }
2523 }
2524
2525 /* Delete any trailing spaces - eg from empty continuations */
2526 while (dst > spaceStart && ch_isspace(dst[-1]))
2527 dst--;
2528 *dst = '\0';
2529 }
2530
2531 typedef enum LineKind {
2532 /*
2533 * Return the next line that is neither empty nor a comment.
2534 * Backslash line continuations are folded into a single space.
2535 * A trailing comment, if any, is discarded.
2536 */
2537 LK_NONEMPTY,
2538
2539 /*
2540 * Return the next line, even if it is empty or a comment.
2541 * Preserve backslash-newline to keep the line numbers correct.
2542 *
2543 * Used in .for loops to collect the body of the loop while waiting
2544 * for the corresponding .endfor.
2545 */
2546 LK_FOR_BODY,
2547
2548 /*
2549 * Return the next line that starts with a dot.
2550 * Backslash line continuations are folded into a single space.
2551 * A trailing comment, if any, is discarded.
2552 *
2553 * Used in .if directives to skip over irrelevant branches while
2554 * waiting for the corresponding .endif.
2555 */
2556 LK_DOT
2557 } LineKind;
2558
2559 /*
2560 * Return the next "interesting" logical line from the current file. The
2561 * returned string will be freed at the end of including the file.
2562 */
2563 static char *
2564 ReadLowLevelLine(LineKind kind)
2565 {
2566 IncludedFile *curFile = CurFile();
2567 ParseRawLineResult res;
2568 char *line;
2569 char *line_end;
2570 char *firstBackslash;
2571 char *commentLineEnd;
2572
2573 for (;;) {
2574 curFile->lineno = curFile->readLines + 1;
2575 res = ParseRawLine(curFile,
2576 &line, &line_end, &firstBackslash, &commentLineEnd);
2577 if (res == PRLR_ERROR)
2578 return NULL;
2579
2580 if (line == line_end || line == commentLineEnd) {
2581 if (res == PRLR_EOF)
2582 return NULL;
2583 if (kind != LK_FOR_BODY)
2584 continue;
2585 }
2586
2587 /* We now have a line of data */
2588 assert(ch_isspace(*line_end));
2589 *line_end = '\0';
2590
2591 if (kind == LK_FOR_BODY)
2592 return line; /* Don't join the physical lines. */
2593
2594 if (kind == LK_DOT && line[0] != '.')
2595 continue;
2596 break;
2597 }
2598
2599 if (commentLineEnd != NULL && line[0] != '\t')
2600 *commentLineEnd = '\0';
2601 if (firstBackslash != NULL)
2602 UnescapeBackslash(line, firstBackslash);
2603 return line;
2604 }
2605
2606 static bool
2607 SkipIrrelevantBranches(void)
2608 {
2609 const char *line;
2610
2611 while ((line = ReadLowLevelLine(LK_DOT)) != NULL)
2612 if (Cond_EvalLine(line) == CR_TRUE)
2613 return true;
2614 return false;
2615 }
2616
2617 static bool
2618 ParseForLoop(const char *line)
2619 {
2620 int rval;
2621 unsigned forHeadLineno;
2622 unsigned bodyReadLines;
2623 int forLevel;
2624
2625 rval = For_Eval(line);
2626 if (rval == 0)
2627 return false; /* Not a .for line */
2628 if (rval < 0)
2629 return true; /* Syntax error - error printed, ignore line */
2630
2631 forHeadLineno = CurFile()->lineno;
2632 bodyReadLines = CurFile()->readLines;
2633
2634 /* Accumulate the loop body until the matching '.endfor'. */
2635 forLevel = 1;
2636 do {
2637 line = ReadLowLevelLine(LK_FOR_BODY);
2638 if (line == NULL) {
2639 Parse_Error(PARSE_FATAL,
2640 "Unexpected end of file in .for loop");
2641 break;
2642 }
2643 } while (For_Accum(line, &forLevel));
2644
2645 For_Run(forHeadLineno, bodyReadLines);
2646 return true;
2647 }
2648
2649 /*
2650 * Read an entire line from the input file.
2651 *
2652 * Empty lines, .if and .for are handled by this function, while variable
2653 * assignments, other directives, dependency lines and shell commands are
2654 * handled by the caller.
2655 *
2656 * Return a line without trailing whitespace, or NULL for EOF. The returned
2657 * string will be freed at the end of including the file.
2658 */
2659 static char *
2660 ReadHighLevelLine(void)
2661 {
2662 char *line;
2663 CondResult condResult;
2664
2665 for (;;) {
2666 IncludedFile *curFile = CurFile();
2667 line = ReadLowLevelLine(LK_NONEMPTY);
2668 if (posix_state == PS_MAYBE_NEXT_LINE)
2669 posix_state = PS_NOW_OR_NEVER;
2670 else if (posix_state != PS_SET)
2671 posix_state = PS_TOO_LATE;
2672 if (line == NULL)
2673 return NULL;
2674
2675 DEBUG3(PARSE, "Parsing %s:%u: %s\n",
2676 curFile->name.str, curFile->lineno, line);
2677 if (curFile->guardState != GS_NO
2678 && ((curFile->guardState == GS_START && line[0] != '.')
2679 || curFile->guardState == GS_DONE))
2680 curFile->guardState = GS_NO;
2681 if (line[0] != '.')
2682 return line;
2683
2684 condResult = Cond_EvalLine(line);
2685 if (curFile->guardState == GS_START) {
2686 Guard *guard;
2687 if (condResult != CR_ERROR
2688 && (guard = Cond_ExtractGuard(line)) != NULL) {
2689 curFile->guardState = GS_COND;
2690 curFile->guard = guard;
2691 } else
2692 curFile->guardState = GS_NO;
2693 }
2694 switch (condResult) {
2695 case CR_FALSE: /* May also mean a syntax error. */
2696 if (!SkipIrrelevantBranches())
2697 return NULL;
2698 continue;
2699 case CR_TRUE:
2700 continue;
2701 case CR_ERROR: /* Not a conditional line */
2702 if (ParseForLoop(line))
2703 continue;
2704 break;
2705 }
2706 return line;
2707 }
2708 }
2709
2710 static void
2711 FinishDependencyGroup(void)
2712 {
2713 GNodeListNode *ln;
2714
2715 if (targets == NULL)
2716 return;
2717
2718 for (ln = targets->first; ln != NULL; ln = ln->next) {
2719 GNode *gn = ln->datum;
2720
2721 Suff_EndTransform(gn);
2722
2723 /*
2724 * Mark the target as already having commands if it does, to
2725 * keep from having shell commands on multiple dependency
2726 * lines.
2727 */
2728 if (!Lst_IsEmpty(&gn->commands))
2729 gn->type |= OP_HAS_COMMANDS;
2730 }
2731
2732 Lst_Free(targets);
2733 targets = NULL;
2734 }
2735
2736 #ifdef CLEANUP
2737 void Parse_RegisterCommand(char *cmd)
2738 {
2739 Lst_Append(&targCmds, cmd);
2740 }
2741 #endif
2742
2743 /* Add the command to each target from the current dependency spec. */
2744 static void
2745 ParseLine_ShellCommand(const char *p)
2746 {
2747 cpp_skip_whitespace(&p);
2748 if (*p == '\0')
2749 return; /* skip empty commands */
2750
2751 if (targets == NULL) {
2752 Parse_Error(PARSE_FATAL,
2753 "Unassociated shell command \"%s\"", p);
2754 return;
2755 }
2756
2757 {
2758 char *cmd = bmake_strdup(p);
2759 GNodeListNode *ln;
2760
2761 for (ln = targets->first; ln != NULL; ln = ln->next) {
2762 GNode *gn = ln->datum;
2763 GNode_AddCommand(gn, cmd);
2764 }
2765 Parse_RegisterCommand(cmd);
2766 }
2767 }
2768
2769 static void
2770 HandleBreak(const char *arg)
2771 {
2772 IncludedFile *curFile = CurFile();
2773
2774 if (arg[0] != '\0')
2775 Parse_Error(PARSE_FATAL,
2776 "The .break directive does not take arguments");
2777
2778 if (curFile->forLoop != NULL) {
2779 /* pretend we reached EOF */
2780 For_Break(curFile->forLoop);
2781 cond_depth = CurFile_CondMinDepth();
2782 ParseEOF();
2783 } else
2784 Parse_Error(PARSE_FATAL, "break outside of for loop");
2785 }
2786
2787 /*
2788 * See if the line starts with one of the known directives, and if so, handle
2789 * the directive.
2790 */
2791 static bool
2792 ParseDirective(char *line)
2793 {
2794 char *p = line + 1;
2795 const char *arg;
2796 Substring dir;
2797
2798 pp_skip_whitespace(&p);
2799 if (IsInclude(p, false)) {
2800 ParseInclude(p);
2801 return true;
2802 }
2803
2804 dir.start = p;
2805 while (ch_islower(*p) || *p == '-')
2806 p++;
2807 dir.end = p;
2808
2809 if (*p != '\0' && !ch_isspace(*p))
2810 return false;
2811
2812 pp_skip_whitespace(&p);
2813 arg = p;
2814
2815 if (Substring_Equals(dir, "break"))
2816 HandleBreak(arg);
2817 else if (Substring_Equals(dir, "undef"))
2818 Var_Undef(arg);
2819 else if (Substring_Equals(dir, "export"))
2820 Var_Export(VEM_PLAIN, arg);
2821 else if (Substring_Equals(dir, "export-all"))
2822 Var_Export(VEM_ALL, arg);
2823 else if (Substring_Equals(dir, "export-env"))
2824 Var_Export(VEM_ENV, arg);
2825 else if (Substring_Equals(dir, "export-literal"))
2826 Var_Export(VEM_LITERAL, arg);
2827 else if (Substring_Equals(dir, "unexport"))
2828 Var_UnExport(false, arg);
2829 else if (Substring_Equals(dir, "unexport-env"))
2830 Var_UnExport(true, arg);
2831 else if (Substring_Equals(dir, "info"))
2832 HandleMessage(PARSE_INFO, "info", arg);
2833 else if (Substring_Equals(dir, "warning"))
2834 HandleMessage(PARSE_WARNING, "warning", arg);
2835 else if (Substring_Equals(dir, "error"))
2836 HandleMessage(PARSE_FATAL, "error", arg);
2837 else
2838 return false;
2839 return true;
2840 }
2841
2842 bool
2843 Parse_VarAssign(const char *line, bool finishDependencyGroup, GNode *scope)
2844 {
2845 VarAssign var;
2846
2847 if (!Parse_IsVar(line, &var))
2848 return false;
2849 if (finishDependencyGroup)
2850 FinishDependencyGroup();
2851 Parse_Var(&var, scope);
2852 free(var.varname);
2853 return true;
2854 }
2855
2856 void
2857 Parse_GuardElse(void)
2858 {
2859 IncludedFile *curFile = CurFile();
2860 if (cond_depth == curFile->condMinDepth + 1)
2861 curFile->guardState = GS_NO;
2862 }
2863
2864 void
2865 Parse_GuardEndif(void)
2866 {
2867 IncludedFile *curFile = CurFile();
2868 if (cond_depth == curFile->condMinDepth
2869 && curFile->guardState == GS_COND)
2870 curFile->guardState = GS_DONE;
2871 }
2872
2873 static char *
2874 FindSemicolon(char *p)
2875 {
2876 int depth = 0;
2877
2878 for (; *p != '\0'; p++) {
2879 if (*p == '\\' && p[1] != '\0') {
2880 p++;
2881 continue;
2882 }
2883
2884 if (*p == '$' && (p[1] == '(' || p[1] == '{'))
2885 depth++;
2886 else if (depth > 0 && (*p == ')' || *p == '}'))
2887 depth--;
2888 else if (depth == 0 && *p == ';')
2889 break;
2890 }
2891 return p;
2892 }
2893
2894 static void
2895 ParseDependencyLine(char *line)
2896 {
2897 char *expanded_line;
2898 const char *shellcmd = NULL;
2899
2900 {
2901 char *semicolon = FindSemicolon(line);
2902 if (*semicolon != '\0') {
2903 /* Terminate the dependency list at the ';' */
2904 *semicolon = '\0';
2905 shellcmd = semicolon + 1;
2906 }
2907 }
2908
2909 expanded_line = Var_Subst(line, SCOPE_CMDLINE, VARE_EVAL);
2910 /* TODO: handle errors */
2911
2912 /* Need a fresh list for the target nodes */
2913 if (targets != NULL)
2914 Lst_Free(targets);
2915 targets = Lst_New();
2916
2917 ParseDependency(expanded_line, line);
2918 free(expanded_line);
2919
2920 if (shellcmd != NULL)
2921 ParseLine_ShellCommand(shellcmd);
2922 }
2923
2924 static void
2925 ParseLine(char *line)
2926 {
2927 if (line[0] == '.' && ParseDirective(line))
2928 return;
2929
2930 if (line[0] == '\t') {
2931 ParseLine_ShellCommand(line + 1);
2932 return;
2933 }
2934
2935 if (IsSysVInclude(line)) {
2936 ParseTraditionalInclude(line);
2937 return;
2938 }
2939
2940 if (strncmp(line, "export", 6) == 0 && ch_isspace(line[6]) &&
2941 strchr(line, ':') == NULL) {
2942 ParseGmakeExport(line);
2943 return;
2944 }
2945
2946 if (Parse_VarAssign(line, true, SCOPE_GLOBAL))
2947 return;
2948
2949 FinishDependencyGroup();
2950
2951 ParseDependencyLine(line);
2952 }
2953
2954 /* Interpret a top-level makefile. */
2955 void
2956 Parse_File(const char *name, int fd)
2957 {
2958 char *line;
2959 Buffer buf;
2960
2961 buf = LoadFile(name, fd != -1 ? fd : STDIN_FILENO);
2962 if (fd != -1)
2963 (void)close(fd);
2964
2965 assert(targets == NULL);
2966
2967 Parse_PushInput(name, 1, 0, buf, NULL);
2968
2969 do {
2970 while ((line = ReadHighLevelLine()) != NULL) {
2971 ParseLine(line);
2972 }
2973 } while (ParseEOF());
2974
2975 FinishDependencyGroup();
2976
2977 if (parseErrors != 0) {
2978 (void)fflush(stdout);
2979 (void)fprintf(stderr,
2980 "%s: Fatal errors encountered -- cannot continue\n",
2981 progname);
2982 PrintOnError(NULL, "");
2983 exit(1);
2984 }
2985 }
2986
2987 /* Initialize the parsing module. */
2988 void
2989 Parse_Init(void)
2990 {
2991 mainNode = NULL;
2992 parseIncPath = SearchPath_New();
2993 sysIncPath = SearchPath_New();
2994 defSysIncPath = SearchPath_New();
2995 Vector_Init(&includes, sizeof(IncludedFile));
2996 HashTable_Init(&guards);
2997 }
2998
2999 #ifdef CLEANUP
3000 /* Clean up the parsing module. */
3001 void
3002 Parse_End(void)
3003 {
3004 HashIter hi;
3005
3006 Lst_DoneFree(&targCmds);
3007 assert(targets == NULL);
3008 SearchPath_Free(defSysIncPath);
3009 SearchPath_Free(sysIncPath);
3010 SearchPath_Free(parseIncPath);
3011 assert(includes.len == 0);
3012 Vector_Done(&includes);
3013 HashIter_Init(&hi, &guards);
3014 while (HashIter_Next(&hi)) {
3015 Guard *guard = hi.entry->value;
3016 free(guard->name);
3017 free(guard);
3018 }
3019 HashTable_Done(&guards);
3020 }
3021 #endif
3022
3023
3024 /* Populate the list with the single main target to create, or error out. */
3025 void
3026 Parse_MainName(GNodeList *mainList)
3027 {
3028 if (mainNode == NULL)
3029 Punt("no target to make.");
3030
3031 Lst_Append(mainList, mainNode);
3032 if (mainNode->type & OP_DOUBLEDEP)
3033 Lst_AppendAll(mainList, &mainNode->cohorts);
3034
3035 Global_Append(".TARGETS", mainNode->name);
3036 }
3037