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