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