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