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