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