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