1 /* $NetBSD: parse.c,v 1.696 2023/02/15 06:52:58 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.696 2023/02/15 06:52:58 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 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 xmsg = Var_Subst(umsg, SCOPE_CMDLINE, VARE_WANTRES); 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 = Var_Parse(&cp, SCOPE_CMDLINE, 901 VARE_PARSE_ONLY); 902 FStr_Done(&val); 903 } else 904 cp++; 905 } 906 907 *pp += cp - *pp; 908 } 909 910 /* 911 * Handle special targets like .PATH, .DEFAULT, .BEGIN, .ORDER. 912 * 913 * See the tests deptgt-*.mk. 914 */ 915 static void 916 HandleDependencyTargetSpecial(const char *targetName, 917 ParseSpecial *inout_special, 918 SearchPathList **inout_paths) 919 { 920 switch (*inout_special) { 921 case SP_PATH: 922 if (*inout_paths == NULL) 923 *inout_paths = Lst_New(); 924 Lst_Append(*inout_paths, &dirSearchPath); 925 break; 926 case SP_SYSPATH: 927 if (*inout_paths == NULL) 928 *inout_paths = Lst_New(); 929 Lst_Append(*inout_paths, sysIncPath); 930 break; 931 case SP_MAIN: 932 /* 933 * Allow targets from the command line to override the 934 * .MAIN node. 935 */ 936 if (!Lst_IsEmpty(&opts.create)) 937 *inout_special = SP_NOT; 938 break; 939 case SP_BEGIN: 940 case SP_END: 941 case SP_STALE: 942 case SP_ERROR: 943 case SP_INTERRUPT: { 944 GNode *gn = Targ_GetNode(targetName); 945 if (doing_depend) 946 RememberLocation(gn); 947 gn->type |= OP_NOTMAIN | OP_SPECIAL; 948 Lst_Append(targets, gn); 949 break; 950 } 951 case SP_DEFAULT: { 952 /* 953 * Need to create a node to hang commands on, but we don't 954 * want it in the graph, nor do we want it to be the Main 955 * Target. We claim the node is a transformation rule to make 956 * life easier later, when we'll use Make_HandleUse to 957 * actually apply the .DEFAULT commands. 958 */ 959 GNode *gn = GNode_New(".DEFAULT"); 960 gn->type |= OP_NOTMAIN | OP_TRANSFORM; 961 Lst_Append(targets, gn); 962 defaultNode = gn; 963 break; 964 } 965 case SP_DELETE_ON_ERROR: 966 deleteOnError = true; 967 break; 968 case SP_NOTPARALLEL: 969 opts.maxJobs = 1; 970 break; 971 case SP_SINGLESHELL: 972 opts.compatMake = true; 973 break; 974 case SP_ORDER: 975 order_pred = NULL; 976 break; 977 default: 978 break; 979 } 980 } 981 982 static bool 983 HandleDependencyTargetPath(const char *suffixName, 984 SearchPathList **inout_paths) 985 { 986 SearchPath *path; 987 988 path = Suff_GetPath(suffixName); 989 if (path == NULL) { 990 Parse_Error(PARSE_FATAL, 991 "Suffix '%s' not defined (yet)", suffixName); 992 return false; 993 } 994 995 if (*inout_paths == NULL) 996 *inout_paths = Lst_New(); 997 Lst_Append(*inout_paths, path); 998 999 return true; 1000 } 1001 1002 /* See if it's a special target and if so set inout_special to match it. */ 1003 static bool 1004 HandleDependencyTarget(const char *targetName, 1005 ParseSpecial *inout_special, 1006 GNodeType *inout_targetAttr, 1007 SearchPathList **inout_paths) 1008 { 1009 int keywd; 1010 1011 if (!(targetName[0] == '.' && ch_isupper(targetName[1]))) 1012 return true; 1013 1014 /* 1015 * See if the target is a special target that must have it 1016 * or its sources handled specially. 1017 */ 1018 keywd = FindKeyword(targetName); 1019 if (keywd != -1) { 1020 if (*inout_special == SP_PATH && 1021 parseKeywords[keywd].special != SP_PATH) { 1022 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 1023 return false; 1024 } 1025 1026 *inout_special = parseKeywords[keywd].special; 1027 *inout_targetAttr = parseKeywords[keywd].targetAttr; 1028 1029 HandleDependencyTargetSpecial(targetName, inout_special, 1030 inout_paths); 1031 1032 } else if (strncmp(targetName, ".PATH", 5) == 0) { 1033 *inout_special = SP_PATH; 1034 if (!HandleDependencyTargetPath(targetName + 5, inout_paths)) 1035 return false; 1036 } 1037 return true; 1038 } 1039 1040 static void 1041 HandleSingleDependencyTargetMundane(const char *name) 1042 { 1043 GNode *gn = Suff_IsTransform(name) 1044 ? Suff_AddTransform(name) 1045 : Targ_GetNode(name); 1046 if (doing_depend) 1047 RememberLocation(gn); 1048 1049 Lst_Append(targets, gn); 1050 } 1051 1052 static void 1053 HandleDependencyTargetMundane(const char *targetName) 1054 { 1055 if (Dir_HasWildcards(targetName)) { 1056 StringList targetNames = LST_INIT; 1057 1058 SearchPath *emptyPath = SearchPath_New(); 1059 SearchPath_Expand(emptyPath, targetName, &targetNames); 1060 SearchPath_Free(emptyPath); 1061 1062 while (!Lst_IsEmpty(&targetNames)) { 1063 char *targName = Lst_Dequeue(&targetNames); 1064 HandleSingleDependencyTargetMundane(targName); 1065 free(targName); 1066 } 1067 } else 1068 HandleSingleDependencyTargetMundane(targetName); 1069 } 1070 1071 static void 1072 SkipExtraTargets(char **pp, const char *lstart) 1073 { 1074 bool warning = false; 1075 const char *p = *pp; 1076 1077 while (*p != '\0') { 1078 if (!IsEscaped(lstart, p) && (*p == '!' || *p == ':')) 1079 break; 1080 if (IsEscaped(lstart, p) || (*p != ' ' && *p != '\t')) 1081 warning = true; 1082 p++; 1083 } 1084 if (warning) { 1085 const char *start = *pp; 1086 cpp_skip_whitespace(&start); 1087 Parse_Error(PARSE_WARNING, "Extra target '%.*s' ignored", 1088 (int)(p - start), start); 1089 } 1090 1091 *pp += p - *pp; 1092 } 1093 1094 static void 1095 CheckSpecialMundaneMixture(ParseSpecial special) 1096 { 1097 switch (special) { 1098 case SP_DEFAULT: 1099 case SP_STALE: 1100 case SP_BEGIN: 1101 case SP_END: 1102 case SP_ERROR: 1103 case SP_INTERRUPT: 1104 /* 1105 * These create nodes on which to hang commands, so targets 1106 * shouldn't be empty. 1107 */ 1108 case SP_NOT: 1109 /* Nothing special here -- targets may be empty. */ 1110 break; 1111 default: 1112 Parse_Error(PARSE_WARNING, 1113 "Special and mundane targets don't mix. " 1114 "Mundane ones ignored"); 1115 break; 1116 } 1117 } 1118 1119 /* 1120 * In a dependency line like 'targets: sources' or 'targets! sources', parse 1121 * the operator ':', '::' or '!' from between the targets and the sources. 1122 */ 1123 static GNodeType 1124 ParseDependencyOp(char **pp) 1125 { 1126 if (**pp == '!') 1127 return (*pp)++, OP_FORCE; 1128 if (**pp == ':' && (*pp)[1] == ':') 1129 return *pp += 2, OP_DOUBLEDEP; 1130 else if (**pp == ':') 1131 return (*pp)++, OP_DEPENDS; 1132 else 1133 return OP_NONE; 1134 } 1135 1136 static void 1137 ClearPaths(ParseSpecial special, SearchPathList *paths) 1138 { 1139 if (paths != NULL) { 1140 SearchPathListNode *ln; 1141 for (ln = paths->first; ln != NULL; ln = ln->next) 1142 SearchPath_Clear(ln->datum); 1143 } 1144 if (special == SP_SYSPATH) 1145 Dir_SetSYSPATH(); 1146 else 1147 Dir_SetPATH(); 1148 } 1149 1150 static char * 1151 FindInDirOfIncludingFile(const char *file) 1152 { 1153 char *fullname, *incdir, *slash, *newName; 1154 int i; 1155 1156 fullname = NULL; 1157 incdir = bmake_strdup(CurFile()->name.str); 1158 slash = strrchr(incdir, '/'); 1159 if (slash != NULL) { 1160 *slash = '\0'; 1161 /* 1162 * Now do lexical processing of leading "../" on the 1163 * filename. 1164 */ 1165 for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) { 1166 slash = strrchr(incdir + 1, '/'); 1167 if (slash == NULL || strcmp(slash, "/..") == 0) 1168 break; 1169 *slash = '\0'; 1170 } 1171 newName = str_concat3(incdir, "/", file + i); 1172 fullname = Dir_FindFile(newName, parseIncPath); 1173 if (fullname == NULL) 1174 fullname = Dir_FindFile(newName, &dirSearchPath); 1175 free(newName); 1176 } 1177 free(incdir); 1178 return fullname; 1179 } 1180 1181 static char * 1182 FindInQuotPath(const char *file) 1183 { 1184 const char *suff; 1185 SearchPath *suffPath; 1186 char *fullname; 1187 1188 fullname = FindInDirOfIncludingFile(file); 1189 if (fullname == NULL && 1190 (suff = strrchr(file, '.')) != NULL && 1191 (suffPath = Suff_GetPath(suff)) != NULL) 1192 fullname = Dir_FindFile(file, suffPath); 1193 if (fullname == NULL) 1194 fullname = Dir_FindFile(file, parseIncPath); 1195 if (fullname == NULL) 1196 fullname = Dir_FindFile(file, &dirSearchPath); 1197 return fullname; 1198 } 1199 1200 /* 1201 * Handle one of the .[-ds]include directives by remembering the current file 1202 * and pushing the included file on the stack. After the included file has 1203 * finished, parsing continues with the including file; see Parse_PushInput 1204 * and ParseEOF. 1205 * 1206 * System includes are looked up in sysIncPath, any other includes are looked 1207 * up in the parsedir and then in the directories specified by the -I command 1208 * line options. 1209 */ 1210 static void 1211 IncludeFile(const char *file, bool isSystem, bool depinc, bool silent) 1212 { 1213 Buffer buf; 1214 char *fullname; /* full pathname of file */ 1215 int fd; 1216 1217 fullname = file[0] == '/' ? bmake_strdup(file) : NULL; 1218 1219 if (fullname == NULL && !isSystem) 1220 fullname = FindInQuotPath(file); 1221 1222 if (fullname == NULL) { 1223 SearchPath *path = Lst_IsEmpty(&sysIncPath->dirs) 1224 ? defSysIncPath : sysIncPath; 1225 fullname = Dir_FindFile(file, path); 1226 } 1227 1228 if (fullname == NULL) { 1229 if (!silent) 1230 Parse_Error(PARSE_FATAL, "Could not find %s", file); 1231 return; 1232 } 1233 1234 if ((fd = open(fullname, O_RDONLY)) == -1) { 1235 if (!silent) 1236 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 1237 free(fullname); 1238 return; 1239 } 1240 1241 buf = LoadFile(fullname, fd); 1242 (void)close(fd); 1243 1244 Parse_PushInput(fullname, 1, 0, buf, NULL); 1245 if (depinc) 1246 doing_depend = depinc; /* only turn it on */ 1247 free(fullname); 1248 } 1249 1250 /* Handle a "dependency" line like '.SPECIAL:' without any sources. */ 1251 static void 1252 HandleDependencySourcesEmpty(ParseSpecial special, SearchPathList *paths) 1253 { 1254 switch (special) { 1255 case SP_SUFFIXES: 1256 Suff_ClearSuffixes(); 1257 break; 1258 case SP_PRECIOUS: 1259 allPrecious = true; 1260 break; 1261 case SP_IGNORE: 1262 opts.ignoreErrors = true; 1263 break; 1264 case SP_SILENT: 1265 opts.silent = true; 1266 break; 1267 case SP_PATH: 1268 case SP_SYSPATH: 1269 ClearPaths(special, paths); 1270 break; 1271 #ifdef POSIX 1272 case SP_POSIX: 1273 if (posix_state == PS_NOW_OR_NEVER) { 1274 /* 1275 * With '-r', 'posix.mk' (if it exists) 1276 * can effectively substitute for 'sys.mk', 1277 * otherwise it is an extension. 1278 */ 1279 Global_Set("%POSIX", "1003.2"); 1280 IncludeFile("posix.mk", true, false, true); 1281 } 1282 break; 1283 #endif 1284 default: 1285 break; 1286 } 1287 } 1288 1289 static void 1290 AddToPaths(const char *dir, SearchPathList *paths) 1291 { 1292 if (paths != NULL) { 1293 SearchPathListNode *ln; 1294 for (ln = paths->first; ln != NULL; ln = ln->next) 1295 (void)SearchPath_Add(ln->datum, dir); 1296 } 1297 } 1298 1299 /* 1300 * If the target was one that doesn't take files as its sources but takes 1301 * something like suffixes, we take each space-separated word on the line as 1302 * a something and deal with it accordingly. 1303 */ 1304 static void 1305 ParseDependencySourceSpecial(ParseSpecial special, const char *word, 1306 SearchPathList *paths) 1307 { 1308 switch (special) { 1309 case SP_SUFFIXES: 1310 Suff_AddSuffix(word); 1311 break; 1312 case SP_PATH: 1313 AddToPaths(word, paths); 1314 break; 1315 case SP_INCLUDES: 1316 Suff_AddInclude(word); 1317 break; 1318 case SP_LIBS: 1319 Suff_AddLib(word); 1320 break; 1321 case SP_NOREADONLY: 1322 Var_ReadOnly(word, false); 1323 break; 1324 case SP_NULL: 1325 Suff_SetNull(word); 1326 break; 1327 case SP_OBJDIR: 1328 Main_SetObjdir(false, "%s", word); 1329 break; 1330 case SP_READONLY: 1331 Var_ReadOnly(word, true); 1332 break; 1333 case SP_SYSPATH: 1334 AddToPaths(word, paths); 1335 break; 1336 default: 1337 break; 1338 } 1339 } 1340 1341 static bool 1342 ApplyDependencyTarget(char *name, char *nameEnd, ParseSpecial *inout_special, 1343 GNodeType *inout_targetAttr, 1344 SearchPathList **inout_paths) 1345 { 1346 char savec = *nameEnd; 1347 *nameEnd = '\0'; 1348 1349 if (!HandleDependencyTarget(name, inout_special, 1350 inout_targetAttr, inout_paths)) 1351 return false; 1352 1353 if (*inout_special == SP_NOT && *name != '\0') 1354 HandleDependencyTargetMundane(name); 1355 else if (*inout_special == SP_PATH && *name != '.' && *name != '\0') 1356 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", name); 1357 1358 *nameEnd = savec; 1359 return true; 1360 } 1361 1362 static bool 1363 ParseDependencyTargets(char **pp, 1364 const char *lstart, 1365 ParseSpecial *inout_special, 1366 GNodeType *inout_targetAttr, 1367 SearchPathList **inout_paths) 1368 { 1369 char *p = *pp; 1370 1371 for (;;) { 1372 char *tgt = p; 1373 1374 ParseDependencyTargetWord(&p, lstart); 1375 1376 /* 1377 * If the word is followed by a left parenthesis, it's the 1378 * name of one or more files inside an archive. 1379 */ 1380 if (!IsEscaped(lstart, p) && *p == '(') { 1381 p = tgt; 1382 if (!Arch_ParseArchive(&p, targets, SCOPE_CMDLINE)) { 1383 Parse_Error(PARSE_FATAL, 1384 "Error in archive specification: \"%s\"", 1385 tgt); 1386 return false; 1387 } 1388 continue; 1389 } 1390 1391 if (*p == '\0') { 1392 InvalidLineType(lstart); 1393 return false; 1394 } 1395 1396 if (!ApplyDependencyTarget(tgt, p, inout_special, 1397 inout_targetAttr, inout_paths)) 1398 return false; 1399 1400 if (*inout_special != SP_NOT && *inout_special != SP_PATH) 1401 SkipExtraTargets(&p, lstart); 1402 else 1403 pp_skip_whitespace(&p); 1404 1405 if (*p == '\0') 1406 break; 1407 if ((*p == '!' || *p == ':') && !IsEscaped(lstart, p)) 1408 break; 1409 } 1410 1411 *pp = p; 1412 return true; 1413 } 1414 1415 static void 1416 ParseDependencySourcesSpecial(char *start, 1417 ParseSpecial special, SearchPathList *paths) 1418 { 1419 char savec; 1420 1421 while (*start != '\0') { 1422 char *end = start; 1423 while (*end != '\0' && !ch_isspace(*end)) 1424 end++; 1425 savec = *end; 1426 *end = '\0'; 1427 ParseDependencySourceSpecial(special, start, paths); 1428 *end = savec; 1429 if (savec != '\0') 1430 end++; 1431 pp_skip_whitespace(&end); 1432 start = end; 1433 } 1434 } 1435 1436 static void 1437 LinkVarToTargets(VarAssign *var) 1438 { 1439 GNodeListNode *ln; 1440 1441 for (ln = targets->first; ln != NULL; ln = ln->next) 1442 Parse_Var(var, ln->datum); 1443 } 1444 1445 static bool 1446 ParseDependencySourcesMundane(char *start, 1447 ParseSpecial special, GNodeType targetAttr) 1448 { 1449 while (*start != '\0') { 1450 char *end = start; 1451 VarAssign var; 1452 1453 /* 1454 * Check for local variable assignment, 1455 * rest of the line is the value. 1456 */ 1457 if (Parse_IsVar(start, &var)) { 1458 /* 1459 * Check if this makefile has disabled 1460 * setting local variables. 1461 */ 1462 bool target_vars = GetBooleanExpr( 1463 "${.MAKE.TARGET_LOCAL_VARIABLES}", true); 1464 1465 if (target_vars) 1466 LinkVarToTargets(&var); 1467 free(var.varname); 1468 if (target_vars) 1469 return true; 1470 } 1471 1472 /* 1473 * The targets take real sources, so we must beware of archive 1474 * specifications (i.e. things with left parentheses in them) 1475 * and handle them accordingly. 1476 */ 1477 for (; *end != '\0' && !ch_isspace(*end); end++) { 1478 if (*end == '(' && end > start && end[-1] != '$') { 1479 /* 1480 * Only stop for a left parenthesis if it 1481 * isn't at the start of a word (that'll be 1482 * for variable changes later) and isn't 1483 * preceded by a dollar sign (a dynamic 1484 * source). 1485 */ 1486 break; 1487 } 1488 } 1489 1490 if (*end == '(') { 1491 GNodeList sources = LST_INIT; 1492 if (!Arch_ParseArchive(&start, &sources, 1493 SCOPE_CMDLINE)) { 1494 Parse_Error(PARSE_FATAL, 1495 "Error in source archive spec \"%s\"", 1496 start); 1497 return false; 1498 } 1499 1500 while (!Lst_IsEmpty(&sources)) { 1501 GNode *gn = Lst_Dequeue(&sources); 1502 ApplyDependencySource(targetAttr, gn->name, 1503 special); 1504 } 1505 Lst_Done(&sources); 1506 end = start; 1507 } else { 1508 if (*end != '\0') { 1509 *end = '\0'; 1510 end++; 1511 } 1512 1513 ApplyDependencySource(targetAttr, start, special); 1514 } 1515 pp_skip_whitespace(&end); 1516 start = end; 1517 } 1518 return true; 1519 } 1520 1521 /* 1522 * From a dependency line like 'targets: sources', parse the sources. 1523 * 1524 * See the tests depsrc-*.mk. 1525 */ 1526 static void 1527 ParseDependencySources(char *p, GNodeType targetAttr, 1528 ParseSpecial special, SearchPathList **inout_paths) 1529 { 1530 if (*p == '\0') { 1531 HandleDependencySourcesEmpty(special, *inout_paths); 1532 } else if (special == SP_MFLAGS) { 1533 Main_ParseArgLine(p); 1534 return; 1535 } else if (special == SP_SHELL) { 1536 if (!Job_ParseShell(p)) { 1537 Parse_Error(PARSE_FATAL, 1538 "improper shell specification"); 1539 return; 1540 } 1541 return; 1542 } else if (special == SP_NOTPARALLEL || special == SP_SINGLESHELL || 1543 special == SP_DELETE_ON_ERROR) { 1544 return; 1545 } 1546 1547 /* Now go for the sources. */ 1548 switch (special) { 1549 case SP_INCLUDES: 1550 case SP_LIBS: 1551 case SP_NOREADONLY: 1552 case SP_NULL: 1553 case SP_OBJDIR: 1554 case SP_PATH: 1555 case SP_READONLY: 1556 case SP_SUFFIXES: 1557 case SP_SYSPATH: 1558 ParseDependencySourcesSpecial(p, special, *inout_paths); 1559 if (*inout_paths != NULL) { 1560 Lst_Free(*inout_paths); 1561 *inout_paths = NULL; 1562 } 1563 if (special == SP_PATH) 1564 Dir_SetPATH(); 1565 if (special == SP_SYSPATH) 1566 Dir_SetSYSPATH(); 1567 break; 1568 default: 1569 assert(*inout_paths == NULL); 1570 if (!ParseDependencySourcesMundane(p, special, targetAttr)) 1571 return; 1572 break; 1573 } 1574 1575 MaybeUpdateMainTarget(); 1576 } 1577 1578 /* 1579 * Parse a dependency line consisting of targets, followed by a dependency 1580 * operator, optionally followed by sources. 1581 * 1582 * The nodes of the sources are linked as children to the nodes of the 1583 * targets. Nodes are created as necessary. 1584 * 1585 * The operator is applied to each node in the global 'targets' list, 1586 * which is where the nodes found for the targets are kept. 1587 * 1588 * The sources are parsed in much the same way as the targets, except 1589 * that they are expanded using the wildcarding scheme of the C-Shell, 1590 * and a target is created for each expanded word. Each of the resulting 1591 * nodes is then linked to each of the targets as one of its children. 1592 * 1593 * Certain targets and sources such as .PHONY or .PRECIOUS are handled 1594 * specially, see ParseSpecial. 1595 * 1596 * Transformation rules such as '.c.o' are also handled here, see 1597 * Suff_AddTransform. 1598 * 1599 * Upon return, the value of the line is unspecified. 1600 */ 1601 static void 1602 ParseDependency(char *line) 1603 { 1604 char *p; 1605 SearchPathList *paths; /* search paths to alter when parsing a list 1606 * of .PATH targets */ 1607 GNodeType targetAttr; /* from special sources */ 1608 ParseSpecial special; /* in special targets, the children are 1609 * linked as children of the parent but not 1610 * vice versa */ 1611 GNodeType op; 1612 1613 DEBUG1(PARSE, "ParseDependency(%s)\n", line); 1614 p = line; 1615 paths = NULL; 1616 targetAttr = OP_NONE; 1617 special = SP_NOT; 1618 1619 if (!ParseDependencyTargets(&p, line, &special, &targetAttr, &paths)) 1620 goto out; 1621 1622 if (!Lst_IsEmpty(targets)) 1623 CheckSpecialMundaneMixture(special); 1624 1625 op = ParseDependencyOp(&p); 1626 if (op == OP_NONE) { 1627 InvalidLineType(line); 1628 goto out; 1629 } 1630 ApplyDependencyOperator(op); 1631 1632 pp_skip_whitespace(&p); 1633 1634 ParseDependencySources(p, targetAttr, special, &paths); 1635 1636 out: 1637 if (paths != NULL) 1638 Lst_Free(paths); 1639 } 1640 1641 /* 1642 * Determine the assignment operator and adjust the end of the variable 1643 * name accordingly. 1644 */ 1645 static VarAssign 1646 AdjustVarassignOp(const char *name, const char *nameEnd, const char *op, 1647 const char *value) 1648 { 1649 VarAssignOp type; 1650 VarAssign va; 1651 1652 if (op > name && op[-1] == '+') { 1653 op--; 1654 type = VAR_APPEND; 1655 1656 } else if (op > name && op[-1] == '?') { 1657 op--; 1658 type = VAR_DEFAULT; 1659 1660 } else if (op > name && op[-1] == ':') { 1661 op--; 1662 type = VAR_SUBST; 1663 1664 } else if (op > name && op[-1] == '!') { 1665 op--; 1666 type = VAR_SHELL; 1667 1668 } else { 1669 type = VAR_NORMAL; 1670 #ifdef SUNSHCMD 1671 while (op > name && ch_isspace(op[-1])) 1672 op--; 1673 1674 if (op - name >= 3 && memcmp(op - 3, ":sh", 3) == 0) { 1675 op -= 3; 1676 type = VAR_SHELL; 1677 } 1678 #endif 1679 } 1680 1681 va.varname = bmake_strsedup(name, nameEnd < op ? nameEnd : op); 1682 va.op = type; 1683 va.value = value; 1684 return va; 1685 } 1686 1687 /* 1688 * Parse a variable assignment, consisting of a single-word variable name, 1689 * optional whitespace, an assignment operator, optional whitespace and the 1690 * variable value. 1691 * 1692 * Note: There is a lexical ambiguity with assignment modifier characters 1693 * in variable names. This routine interprets the character before the = 1694 * as a modifier. Therefore, an assignment like 1695 * C++=/usr/bin/CC 1696 * is interpreted as "C+ +=" instead of "C++ =". 1697 * 1698 * Used for both lines in a file and command line arguments. 1699 */ 1700 static bool 1701 Parse_IsVar(const char *p, VarAssign *out_var) 1702 { 1703 const char *nameStart, *nameEnd, *firstSpace, *eq; 1704 int level = 0; 1705 1706 cpp_skip_hspace(&p); /* Skip to variable name */ 1707 1708 /* 1709 * During parsing, the '+' of the operator '+=' is initially parsed 1710 * as part of the variable name. It is later corrected, as is the 1711 * ':sh' modifier. Of these two (nameEnd and eq), the earlier one 1712 * determines the actual end of the variable name. 1713 */ 1714 1715 nameStart = p; 1716 firstSpace = NULL; 1717 1718 /* 1719 * Scan for one of the assignment operators outside a variable 1720 * expansion. 1721 */ 1722 while (*p != '\0') { 1723 char ch = *p++; 1724 if (ch == '(' || ch == '{') { 1725 level++; 1726 continue; 1727 } 1728 if (ch == ')' || ch == '}') { 1729 level--; 1730 continue; 1731 } 1732 1733 if (level != 0) 1734 continue; 1735 1736 if ((ch == ' ' || ch == '\t') && firstSpace == NULL) 1737 firstSpace = p - 1; 1738 while (ch == ' ' || ch == '\t') 1739 ch = *p++; 1740 1741 if (ch == '\0') 1742 return false; 1743 #ifdef SUNSHCMD 1744 if (ch == ':' && p[0] == 's' && p[1] == 'h') { 1745 p += 2; 1746 continue; 1747 } 1748 #endif 1749 if (ch == '=') 1750 eq = p - 1; 1751 else if (*p == '=' && 1752 (ch == '+' || ch == ':' || ch == '?' || ch == '!')) 1753 eq = p; 1754 else if (firstSpace != NULL) 1755 return false; 1756 else 1757 continue; 1758 1759 nameEnd = firstSpace != NULL ? firstSpace : eq; 1760 p = eq + 1; 1761 cpp_skip_whitespace(&p); 1762 *out_var = AdjustVarassignOp(nameStart, nameEnd, eq, p); 1763 return true; 1764 } 1765 1766 return false; 1767 } 1768 1769 /* 1770 * Check for syntax errors such as unclosed expressions or unknown modifiers. 1771 */ 1772 static void 1773 VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *scope) 1774 { 1775 if (opts.strict) { 1776 if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) { 1777 char *expandedValue = Var_Subst(uvalue, 1778 scope, VARE_PARSE_ONLY); 1779 /* TODO: handle errors */ 1780 free(expandedValue); 1781 } 1782 } 1783 } 1784 1785 /* Perform a variable assignment that uses the operator ':='. */ 1786 static void 1787 VarAssign_EvalSubst(GNode *scope, const char *name, const char *uvalue, 1788 FStr *out_avalue) 1789 { 1790 char *evalue; 1791 1792 /* 1793 * make sure that we set the variable the first time to nothing 1794 * so that it gets substituted. 1795 * 1796 * TODO: Add a test that demonstrates why this code is needed, 1797 * apart from making the debug log longer. 1798 * 1799 * XXX: The variable name is expanded up to 3 times. 1800 */ 1801 if (!Var_ExistsExpand(scope, name)) 1802 Var_SetExpand(scope, name, ""); 1803 1804 evalue = Var_Subst(uvalue, scope, VARE_KEEP_DOLLAR_UNDEF); 1805 /* TODO: handle errors */ 1806 1807 Var_SetExpand(scope, name, evalue); 1808 1809 *out_avalue = FStr_InitOwn(evalue); 1810 } 1811 1812 /* Perform a variable assignment that uses the operator '!='. */ 1813 static void 1814 VarAssign_EvalShell(const char *name, const char *uvalue, GNode *scope, 1815 FStr *out_avalue) 1816 { 1817 FStr cmd; 1818 char *output, *error; 1819 1820 cmd = FStr_InitRefer(uvalue); 1821 Var_Expand(&cmd, SCOPE_CMDLINE, VARE_UNDEFERR); 1822 1823 output = Cmd_Exec(cmd.str, &error); 1824 Var_SetExpand(scope, name, output); 1825 *out_avalue = FStr_InitOwn(output); 1826 if (error != NULL) { 1827 Parse_Error(PARSE_WARNING, "%s", error); 1828 free(error); 1829 } 1830 1831 FStr_Done(&cmd); 1832 } 1833 1834 /* 1835 * Perform a variable assignment. 1836 * 1837 * The actual value of the variable is returned in *out_true_avalue. 1838 * Especially for VAR_SUBST and VAR_SHELL this can differ from the literal 1839 * value. 1840 * 1841 * Return whether the assignment was actually performed, which is usually 1842 * the case. It is only skipped if the operator is '?=' and the variable 1843 * already exists. 1844 */ 1845 static bool 1846 VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue, 1847 GNode *scope, FStr *out_true_avalue) 1848 { 1849 FStr avalue = FStr_InitRefer(uvalue); 1850 1851 if (op == VAR_APPEND) 1852 Var_AppendExpand(scope, name, uvalue); 1853 else if (op == VAR_SUBST) 1854 VarAssign_EvalSubst(scope, name, uvalue, &avalue); 1855 else if (op == VAR_SHELL) 1856 VarAssign_EvalShell(name, uvalue, scope, &avalue); 1857 else { 1858 /* XXX: The variable name is expanded up to 2 times. */ 1859 if (op == VAR_DEFAULT && Var_ExistsExpand(scope, name)) 1860 return false; 1861 1862 /* Normal assignment -- just do it. */ 1863 Var_SetExpand(scope, name, uvalue); 1864 } 1865 1866 *out_true_avalue = avalue; 1867 return true; 1868 } 1869 1870 static void 1871 VarAssignSpecial(const char *name, const char *avalue) 1872 { 1873 if (strcmp(name, ".MAKEOVERRIDES") == 0) 1874 Main_ExportMAKEFLAGS(false); /* re-export MAKEFLAGS */ 1875 else if (strcmp(name, ".CURDIR") == 0) { 1876 /* 1877 * Someone is being (too?) clever... 1878 * Let's pretend they know what they are doing and 1879 * re-initialize the 'cur' CachedDir. 1880 */ 1881 Dir_InitCur(avalue); 1882 Dir_SetPATH(); 1883 } else if (strcmp(name, ".MAKE.JOB.PREFIX") == 0) 1884 Job_SetPrefix(); 1885 else if (strcmp(name, ".MAKE.EXPORTED") == 0) 1886 Var_ExportVars(avalue); 1887 } 1888 1889 /* Perform the variable assignment in the given scope. */ 1890 static void 1891 Parse_Var(VarAssign *var, GNode *scope) 1892 { 1893 FStr avalue; /* actual value (maybe expanded) */ 1894 1895 VarCheckSyntax(var->op, var->value, scope); 1896 if (VarAssign_Eval(var->varname, var->op, var->value, scope, &avalue)) { 1897 VarAssignSpecial(var->varname, avalue.str); 1898 FStr_Done(&avalue); 1899 } 1900 } 1901 1902 1903 /* 1904 * See if the command possibly calls a sub-make by using the variable 1905 * expressions ${.MAKE}, ${MAKE} or the plain word "make". 1906 */ 1907 static bool 1908 MaybeSubMake(const char *cmd) 1909 { 1910 const char *start; 1911 1912 for (start = cmd; *start != '\0'; start++) { 1913 const char *p = start; 1914 char endc; 1915 1916 /* XXX: What if progname != "make"? */ 1917 if (strncmp(p, "make", 4) == 0) 1918 if (start == cmd || !ch_isalnum(p[-1])) 1919 if (!ch_isalnum(p[4])) 1920 return true; 1921 1922 if (*p != '$') 1923 continue; 1924 p++; 1925 1926 if (*p == '{') 1927 endc = '}'; 1928 else if (*p == '(') 1929 endc = ')'; 1930 else 1931 continue; 1932 p++; 1933 1934 if (*p == '.') /* Accept either ${.MAKE} or ${MAKE}. */ 1935 p++; 1936 1937 if (strncmp(p, "MAKE", 4) == 0 && p[4] == endc) 1938 return true; 1939 } 1940 return false; 1941 } 1942 1943 /* 1944 * Append the command to the target node. 1945 * 1946 * The node may be marked as a submake node if the command is determined to 1947 * be that. 1948 */ 1949 static void 1950 GNode_AddCommand(GNode *gn, char *cmd) 1951 { 1952 /* Add to last (ie current) cohort for :: targets */ 1953 if ((gn->type & OP_DOUBLEDEP) && gn->cohorts.last != NULL) 1954 gn = gn->cohorts.last->datum; 1955 1956 /* if target already supplied, ignore commands */ 1957 if (!(gn->type & OP_HAS_COMMANDS)) { 1958 Lst_Append(&gn->commands, cmd); 1959 if (MaybeSubMake(cmd)) 1960 gn->type |= OP_SUBMAKE; 1961 RememberLocation(gn); 1962 } else { 1963 #if 0 1964 /* XXX: We cannot do this until we fix the tree */ 1965 Lst_Append(&gn->commands, cmd); 1966 Parse_Error(PARSE_WARNING, 1967 "overriding commands for target \"%s\"; " 1968 "previous commands defined at %s: %u ignored", 1969 gn->name, gn->fname, gn->lineno); 1970 #else 1971 Parse_Error(PARSE_WARNING, 1972 "duplicate script for target \"%s\" ignored", 1973 gn->name); 1974 ParseErrorInternal(gn, PARSE_WARNING, 1975 "using previous script for \"%s\" defined here", 1976 gn->name); 1977 #endif 1978 } 1979 } 1980 1981 /* 1982 * Add a directory to the path searched for included makefiles bracketed 1983 * by double-quotes. 1984 */ 1985 void 1986 Parse_AddIncludeDir(const char *dir) 1987 { 1988 (void)SearchPath_Add(parseIncPath, dir); 1989 } 1990 1991 1992 /* 1993 * Parse a directive like '.include' or '.-include'. 1994 * 1995 * .include "user-makefile.mk" 1996 * .include <system-makefile.mk> 1997 */ 1998 static void 1999 ParseInclude(char *directive) 2000 { 2001 char endc; /* '>' or '"' */ 2002 char *p; 2003 bool silent = directive[0] != 'i'; 2004 FStr file; 2005 2006 p = directive + (silent ? 8 : 7); 2007 pp_skip_hspace(&p); 2008 2009 if (*p != '"' && *p != '<') { 2010 Parse_Error(PARSE_FATAL, 2011 ".include filename must be delimited by '\"' or '<'"); 2012 return; 2013 } 2014 2015 if (*p++ == '<') 2016 endc = '>'; 2017 else 2018 endc = '"'; 2019 file = FStr_InitRefer(p); 2020 2021 /* Skip to matching delimiter */ 2022 while (*p != '\0' && *p != endc) 2023 p++; 2024 2025 if (*p != endc) { 2026 Parse_Error(PARSE_FATAL, 2027 "Unclosed .include filename. '%c' expected", endc); 2028 return; 2029 } 2030 2031 *p = '\0'; 2032 2033 Var_Expand(&file, SCOPE_CMDLINE, VARE_WANTRES); 2034 IncludeFile(file.str, endc == '>', directive[0] == 'd', silent); 2035 FStr_Done(&file); 2036 } 2037 2038 /* 2039 * Split filename into dirname + basename, then assign these to the 2040 * given variables. 2041 */ 2042 static void 2043 SetFilenameVars(const char *filename, const char *dirvar, const char *filevar) 2044 { 2045 const char *slash, *basename; 2046 FStr dirname; 2047 2048 slash = strrchr(filename, '/'); 2049 if (slash == NULL) { 2050 dirname = FStr_InitRefer(curdir); 2051 basename = filename; 2052 } else { 2053 dirname = FStr_InitOwn(bmake_strsedup(filename, slash)); 2054 basename = slash + 1; 2055 } 2056 2057 Global_Set(dirvar, dirname.str); 2058 Global_Set(filevar, basename); 2059 2060 DEBUG4(PARSE, "SetFilenameVars: ${%s} = `%s' ${%s} = `%s'\n", 2061 dirvar, dirname.str, filevar, basename); 2062 FStr_Done(&dirname); 2063 } 2064 2065 /* 2066 * Return the immediately including file. 2067 * 2068 * This is made complicated since the .for loop is implemented as a special 2069 * kind of .include; see For_Run. 2070 */ 2071 static const char * 2072 GetActuallyIncludingFile(void) 2073 { 2074 size_t i; 2075 const IncludedFile *incs = GetInclude(0); 2076 2077 for (i = includes.len; i >= 2; i--) 2078 if (incs[i - 1].forLoop == NULL) 2079 return incs[i - 2].name.str; 2080 return NULL; 2081 } 2082 2083 /* Set .PARSEDIR, .PARSEFILE, .INCLUDEDFROMDIR and .INCLUDEDFROMFILE. */ 2084 static void 2085 SetParseFile(const char *filename) 2086 { 2087 const char *including; 2088 2089 SetFilenameVars(filename, ".PARSEDIR", ".PARSEFILE"); 2090 2091 including = GetActuallyIncludingFile(); 2092 if (including != NULL) { 2093 SetFilenameVars(including, 2094 ".INCLUDEDFROMDIR", ".INCLUDEDFROMFILE"); 2095 } else { 2096 Global_Delete(".INCLUDEDFROMDIR"); 2097 Global_Delete(".INCLUDEDFROMFILE"); 2098 } 2099 } 2100 2101 static bool 2102 StrContainsWord(const char *str, const char *word) 2103 { 2104 size_t strLen = strlen(str); 2105 size_t wordLen = strlen(word); 2106 const char *p; 2107 2108 if (strLen < wordLen) 2109 return false; 2110 2111 for (p = str; p != NULL; p = strchr(p, ' ')) { 2112 if (*p == ' ') 2113 p++; 2114 if (p > str + strLen - wordLen) 2115 return false; 2116 2117 if (memcmp(p, word, wordLen) == 0 && 2118 (p[wordLen] == '\0' || p[wordLen] == ' ')) 2119 return true; 2120 } 2121 return false; 2122 } 2123 2124 /* 2125 * XXX: Searching through a set of words with this linear search is 2126 * inefficient for variables that contain thousands of words. 2127 * 2128 * XXX: The paths in this list don't seem to be normalized in any way. 2129 */ 2130 static bool 2131 VarContainsWord(const char *varname, const char *word) 2132 { 2133 FStr val = Var_Value(SCOPE_GLOBAL, varname); 2134 bool found = val.str != NULL && StrContainsWord(val.str, word); 2135 FStr_Done(&val); 2136 return found; 2137 } 2138 2139 /* 2140 * Track the makefiles we read - so makefiles can set dependencies on them. 2141 * Avoid adding anything more than once. 2142 * 2143 * Time complexity: O(n) per call, in total O(n^2), where n is the number 2144 * of makefiles that have been loaded. 2145 */ 2146 static void 2147 TrackInput(const char *name) 2148 { 2149 if (!VarContainsWord(".MAKE.MAKEFILES", name)) 2150 Global_Append(".MAKE.MAKEFILES", name); 2151 } 2152 2153 2154 /* Parse from the given buffer, later return to the current file. */ 2155 void 2156 Parse_PushInput(const char *name, unsigned lineno, unsigned readLines, 2157 Buffer buf, struct ForLoop *forLoop) 2158 { 2159 IncludedFile *curFile; 2160 2161 if (forLoop != NULL) 2162 name = CurFile()->name.str; 2163 else 2164 TrackInput(name); 2165 2166 DEBUG3(PARSE, "Parse_PushInput: %s %s, line %u\n", 2167 forLoop != NULL ? ".for loop in": "file", name, lineno); 2168 2169 curFile = Vector_Push(&includes); 2170 curFile->name = FStr_InitOwn(bmake_strdup(name)); 2171 curFile->lineno = lineno; 2172 curFile->readLines = readLines; 2173 curFile->forHeadLineno = lineno; 2174 curFile->forBodyReadLines = readLines; 2175 curFile->buf = buf; 2176 curFile->depending = doing_depend; /* restore this on EOF */ 2177 curFile->forLoop = forLoop; 2178 2179 if (forLoop != NULL && !For_NextIteration(forLoop, &curFile->buf)) 2180 abort(); /* see For_Run */ 2181 2182 curFile->buf_ptr = curFile->buf.data; 2183 curFile->buf_end = curFile->buf.data + curFile->buf.len; 2184 curFile->condMinDepth = cond_depth; 2185 SetParseFile(name); 2186 } 2187 2188 /* Check if the directive is an include directive. */ 2189 static bool 2190 IsInclude(const char *dir, bool sysv) 2191 { 2192 if (dir[0] == 's' || dir[0] == '-' || (dir[0] == 'd' && !sysv)) 2193 dir++; 2194 2195 if (strncmp(dir, "include", 7) != 0) 2196 return false; 2197 2198 /* Space is not mandatory for BSD .include */ 2199 return !sysv || ch_isspace(dir[7]); 2200 } 2201 2202 2203 #ifdef SYSVINCLUDE 2204 /* Check if the line is a SYSV include directive. */ 2205 static bool 2206 IsSysVInclude(const char *line) 2207 { 2208 const char *p; 2209 2210 if (!IsInclude(line, true)) 2211 return false; 2212 2213 /* Avoid interpreting a dependency line as an include */ 2214 for (p = line; (p = strchr(p, ':')) != NULL;) { 2215 2216 /* end of line -> it's a dependency */ 2217 if (*++p == '\0') 2218 return false; 2219 2220 /* '::' operator or ': ' -> it's a dependency */ 2221 if (*p == ':' || ch_isspace(*p)) 2222 return false; 2223 } 2224 return true; 2225 } 2226 2227 /* Push to another file. The line points to the word "include". */ 2228 static void 2229 ParseTraditionalInclude(char *line) 2230 { 2231 char *cp; /* current position in file spec */ 2232 bool done = false; 2233 bool silent = line[0] != 'i'; 2234 char *file = line + (silent ? 8 : 7); 2235 char *all_files; 2236 2237 DEBUG1(PARSE, "ParseTraditionalInclude: %s\n", file); 2238 2239 pp_skip_whitespace(&file); 2240 2241 all_files = Var_Subst(file, SCOPE_CMDLINE, VARE_WANTRES); 2242 /* TODO: handle errors */ 2243 2244 for (file = all_files; !done; file = cp + 1) { 2245 /* Skip to end of line or next whitespace */ 2246 for (cp = file; *cp != '\0' && !ch_isspace(*cp); cp++) 2247 continue; 2248 2249 if (*cp != '\0') 2250 *cp = '\0'; 2251 else 2252 done = true; 2253 2254 IncludeFile(file, false, false, silent); 2255 } 2256 2257 free(all_files); 2258 } 2259 #endif 2260 2261 #ifdef GMAKEEXPORT 2262 /* Parse "export <variable>=<value>", and actually export it. */ 2263 static void 2264 ParseGmakeExport(char *line) 2265 { 2266 char *variable = line + 6; 2267 char *value; 2268 2269 DEBUG1(PARSE, "ParseGmakeExport: %s\n", variable); 2270 2271 pp_skip_whitespace(&variable); 2272 2273 for (value = variable; *value != '\0' && *value != '='; value++) 2274 continue; 2275 2276 if (*value != '=') { 2277 Parse_Error(PARSE_FATAL, 2278 "Variable/Value missing from \"export\""); 2279 return; 2280 } 2281 *value++ = '\0'; /* terminate variable */ 2282 2283 /* 2284 * Expand the value before putting it in the environment. 2285 */ 2286 value = Var_Subst(value, SCOPE_CMDLINE, VARE_WANTRES); 2287 /* TODO: handle errors */ 2288 2289 setenv(variable, value, 1); 2290 free(value); 2291 } 2292 #endif 2293 2294 /* 2295 * Called when EOF is reached in the current file. If we were reading an 2296 * include file or a .for loop, the includes stack is popped and things set 2297 * up to go back to reading the previous file at the previous location. 2298 * 2299 * Results: 2300 * true to continue parsing, i.e. it had only reached the end of an 2301 * included file, false if the main file has been parsed completely. 2302 */ 2303 static bool 2304 ParseEOF(void) 2305 { 2306 IncludedFile *curFile = CurFile(); 2307 2308 doing_depend = curFile->depending; 2309 if (curFile->forLoop != NULL && 2310 For_NextIteration(curFile->forLoop, &curFile->buf)) { 2311 curFile->buf_ptr = curFile->buf.data; 2312 curFile->buf_end = curFile->buf.data + curFile->buf.len; 2313 curFile->readLines = curFile->forBodyReadLines; 2314 return true; 2315 } 2316 2317 Cond_EndFile(); 2318 2319 FStr_Done(&curFile->name); 2320 Buf_Done(&curFile->buf); 2321 if (curFile->forLoop != NULL) 2322 ForLoop_Free(curFile->forLoop); 2323 Vector_Pop(&includes); 2324 2325 if (includes.len == 0) { 2326 /* We've run out of input */ 2327 Global_Delete(".PARSEDIR"); 2328 Global_Delete(".PARSEFILE"); 2329 Global_Delete(".INCLUDEDFROMDIR"); 2330 Global_Delete(".INCLUDEDFROMFILE"); 2331 return false; 2332 } 2333 2334 curFile = CurFile(); 2335 DEBUG2(PARSE, "ParseEOF: returning to file %s, line %u\n", 2336 curFile->name.str, curFile->readLines + 1); 2337 2338 SetParseFile(curFile->name.str); 2339 return true; 2340 } 2341 2342 typedef enum ParseRawLineResult { 2343 PRLR_LINE, 2344 PRLR_EOF, 2345 PRLR_ERROR 2346 } ParseRawLineResult; 2347 2348 /* 2349 * Parse until the end of a line, taking into account lines that end with 2350 * backslash-newline. The resulting line goes from out_line to out_line_end; 2351 * the line is not null-terminated. 2352 */ 2353 static ParseRawLineResult 2354 ParseRawLine(IncludedFile *curFile, char **out_line, char **out_line_end, 2355 char **out_firstBackslash, char **out_commentLineEnd) 2356 { 2357 char *line = curFile->buf_ptr; 2358 char *buf_end = curFile->buf_end; 2359 char *p = line; 2360 char *line_end = line; 2361 char *firstBackslash = NULL; 2362 char *commentLineEnd = NULL; 2363 ParseRawLineResult res = PRLR_LINE; 2364 2365 curFile->readLines++; 2366 2367 for (;;) { 2368 char ch; 2369 2370 if (p == buf_end) { 2371 res = PRLR_EOF; 2372 break; 2373 } 2374 2375 ch = *p; 2376 if (ch == '\0' || (ch == '\\' && p[1] == '\0')) { 2377 Parse_Error(PARSE_FATAL, "Zero byte read from file"); 2378 return PRLR_ERROR; 2379 } 2380 2381 /* Treat next character after '\' as literal. */ 2382 if (ch == '\\') { 2383 if (firstBackslash == NULL) 2384 firstBackslash = p; 2385 if (p[1] == '\n') { 2386 curFile->readLines++; 2387 if (p + 2 == buf_end) { 2388 line_end = p; 2389 *line_end = '\n'; 2390 p += 2; 2391 continue; 2392 } 2393 } 2394 p += 2; 2395 line_end = p; 2396 assert(p <= buf_end); 2397 continue; 2398 } 2399 2400 /* 2401 * Remember the first '#' for comment stripping, unless 2402 * the previous char was '[', as in the modifier ':[#]'. 2403 */ 2404 if (ch == '#' && commentLineEnd == NULL && 2405 !(p > line && p[-1] == '[')) 2406 commentLineEnd = line_end; 2407 2408 p++; 2409 if (ch == '\n') 2410 break; 2411 2412 /* We are not interested in trailing whitespace. */ 2413 if (!ch_isspace(ch)) 2414 line_end = p; 2415 } 2416 2417 curFile->buf_ptr = p; 2418 *out_line = line; 2419 *out_line_end = line_end; 2420 *out_firstBackslash = firstBackslash; 2421 *out_commentLineEnd = commentLineEnd; 2422 return res; 2423 } 2424 2425 /* 2426 * Beginning at start, unescape '\#' to '#' and replace backslash-newline 2427 * with a single space. 2428 */ 2429 static void 2430 UnescapeBackslash(char *line, char *start) 2431 { 2432 const char *src = start; 2433 char *dst = start; 2434 char *spaceStart = line; 2435 2436 for (;;) { 2437 char ch = *src++; 2438 if (ch != '\\') { 2439 if (ch == '\0') 2440 break; 2441 *dst++ = ch; 2442 continue; 2443 } 2444 2445 ch = *src++; 2446 if (ch == '\0') { 2447 /* Delete '\\' at the end of the buffer. */ 2448 dst--; 2449 break; 2450 } 2451 2452 /* Delete '\\' from before '#' on non-command lines. */ 2453 if (ch == '#' && line[0] != '\t') 2454 *dst++ = ch; 2455 else if (ch == '\n') { 2456 cpp_skip_hspace(&src); 2457 *dst++ = ' '; 2458 } else { 2459 /* Leave '\\' in the buffer for later. */ 2460 *dst++ = '\\'; 2461 *dst++ = ch; 2462 /* Keep an escaped ' ' at the line end. */ 2463 spaceStart = dst; 2464 } 2465 } 2466 2467 /* Delete any trailing spaces - eg from empty continuations */ 2468 while (dst > spaceStart && ch_isspace(dst[-1])) 2469 dst--; 2470 *dst = '\0'; 2471 } 2472 2473 typedef enum LineKind { 2474 /* 2475 * Return the next line that is neither empty nor a comment. 2476 * Backslash line continuations are folded into a single space. 2477 * A trailing comment, if any, is discarded. 2478 */ 2479 LK_NONEMPTY, 2480 2481 /* 2482 * Return the next line, even if it is empty or a comment. 2483 * Preserve backslash-newline to keep the line numbers correct. 2484 * 2485 * Used in .for loops to collect the body of the loop while waiting 2486 * for the corresponding .endfor. 2487 */ 2488 LK_FOR_BODY, 2489 2490 /* 2491 * Return the next line that starts with a dot. 2492 * Backslash line continuations are folded into a single space. 2493 * A trailing comment, if any, is discarded. 2494 * 2495 * Used in .if directives to skip over irrelevant branches while 2496 * waiting for the corresponding .endif. 2497 */ 2498 LK_DOT 2499 } LineKind; 2500 2501 /* 2502 * Return the next "interesting" logical line from the current file. The 2503 * returned string will be freed at the end of including the file. 2504 */ 2505 static char * 2506 ReadLowLevelLine(LineKind kind) 2507 { 2508 IncludedFile *curFile = CurFile(); 2509 ParseRawLineResult res; 2510 char *line; 2511 char *line_end; 2512 char *firstBackslash; 2513 char *commentLineEnd; 2514 2515 for (;;) { 2516 curFile->lineno = curFile->readLines + 1; 2517 res = ParseRawLine(curFile, 2518 &line, &line_end, &firstBackslash, &commentLineEnd); 2519 if (res == PRLR_ERROR) 2520 return NULL; 2521 2522 if (line == line_end || line == commentLineEnd) { 2523 if (res == PRLR_EOF) 2524 return NULL; 2525 if (kind != LK_FOR_BODY) 2526 continue; 2527 } 2528 2529 /* We now have a line of data */ 2530 assert(ch_isspace(*line_end)); 2531 *line_end = '\0'; 2532 2533 if (kind == LK_FOR_BODY) 2534 return line; /* Don't join the physical lines. */ 2535 2536 if (kind == LK_DOT && line[0] != '.') 2537 continue; 2538 break; 2539 } 2540 2541 if (commentLineEnd != NULL && line[0] != '\t') 2542 *commentLineEnd = '\0'; 2543 if (firstBackslash != NULL) 2544 UnescapeBackslash(line, firstBackslash); 2545 return line; 2546 } 2547 2548 static bool 2549 SkipIrrelevantBranches(void) 2550 { 2551 const char *line; 2552 2553 while ((line = ReadLowLevelLine(LK_DOT)) != NULL) { 2554 if (Cond_EvalLine(line) == CR_TRUE) 2555 return true; 2556 /* 2557 * TODO: Check for typos in .elif directives such as .elsif 2558 * or .elseif. 2559 * 2560 * This check will probably duplicate some of the code in 2561 * ParseLine. Most of the code there cannot apply, only 2562 * ParseVarassign and ParseDependencyLine can, and to prevent 2563 * code duplication, these would need to be called with a 2564 * flag called onlyCheckSyntax. 2565 * 2566 * See directive-elif.mk for details. 2567 */ 2568 } 2569 2570 return false; 2571 } 2572 2573 static bool 2574 ParseForLoop(const char *line) 2575 { 2576 int rval; 2577 unsigned forHeadLineno; 2578 unsigned bodyReadLines; 2579 int forLevel; 2580 2581 rval = For_Eval(line); 2582 if (rval == 0) 2583 return false; /* Not a .for line */ 2584 if (rval < 0) 2585 return true; /* Syntax error - error printed, ignore line */ 2586 2587 forHeadLineno = CurFile()->lineno; 2588 bodyReadLines = CurFile()->readLines; 2589 2590 /* Accumulate the loop body until the matching '.endfor'. */ 2591 forLevel = 1; 2592 do { 2593 line = ReadLowLevelLine(LK_FOR_BODY); 2594 if (line == NULL) { 2595 Parse_Error(PARSE_FATAL, 2596 "Unexpected end of file in .for loop"); 2597 break; 2598 } 2599 } while (For_Accum(line, &forLevel)); 2600 2601 For_Run(forHeadLineno, bodyReadLines); 2602 return true; 2603 } 2604 2605 /* 2606 * Read an entire line from the input file. 2607 * 2608 * Empty lines, .if and .for are completely handled by this function, 2609 * leaving only variable assignments, other directives, dependency lines 2610 * and shell commands to the caller. 2611 * 2612 * Return a line without trailing whitespace, or NULL for EOF. The returned 2613 * string will be freed at the end of including the file. 2614 */ 2615 static char * 2616 ReadHighLevelLine(void) 2617 { 2618 char *line; 2619 2620 for (;;) { 2621 line = ReadLowLevelLine(LK_NONEMPTY); 2622 if (posix_state == PS_MAYBE_NEXT_LINE) 2623 posix_state = PS_NOW_OR_NEVER; 2624 else 2625 posix_state = PS_TOO_LATE; 2626 if (line == NULL) 2627 return NULL; 2628 2629 if (line[0] != '.') 2630 return line; 2631 2632 switch (Cond_EvalLine(line)) { 2633 case CR_FALSE: /* May also mean a syntax error. */ 2634 if (!SkipIrrelevantBranches()) 2635 return NULL; 2636 continue; 2637 case CR_TRUE: 2638 continue; 2639 case CR_ERROR: /* Not a conditional line */ 2640 if (ParseForLoop(line)) 2641 continue; 2642 break; 2643 } 2644 return line; 2645 } 2646 } 2647 2648 static void 2649 FinishDependencyGroup(void) 2650 { 2651 GNodeListNode *ln; 2652 2653 if (targets == NULL) 2654 return; 2655 2656 for (ln = targets->first; ln != NULL; ln = ln->next) { 2657 GNode *gn = ln->datum; 2658 2659 Suff_EndTransform(gn); 2660 2661 /* 2662 * Mark the target as already having commands if it does, to 2663 * keep from having shell commands on multiple dependency 2664 * lines. 2665 */ 2666 if (!Lst_IsEmpty(&gn->commands)) 2667 gn->type |= OP_HAS_COMMANDS; 2668 } 2669 2670 Lst_Free(targets); 2671 targets = NULL; 2672 } 2673 2674 /* Add the command to each target from the current dependency spec. */ 2675 static void 2676 ParseLine_ShellCommand(const char *p) 2677 { 2678 cpp_skip_whitespace(&p); 2679 if (*p == '\0') 2680 return; /* skip empty commands */ 2681 2682 if (targets == NULL) { 2683 Parse_Error(PARSE_FATAL, 2684 "Unassociated shell command \"%s\"", p); 2685 return; 2686 } 2687 2688 { 2689 char *cmd = bmake_strdup(p); 2690 GNodeListNode *ln; 2691 2692 for (ln = targets->first; ln != NULL; ln = ln->next) { 2693 GNode *gn = ln->datum; 2694 GNode_AddCommand(gn, cmd); 2695 } 2696 #ifdef CLEANUP 2697 Lst_Append(&targCmds, cmd); 2698 #endif 2699 } 2700 } 2701 2702 static void 2703 HandleBreak(void) 2704 { 2705 IncludedFile *curFile = CurFile(); 2706 2707 if (curFile->forLoop != NULL) { 2708 /* pretend we reached EOF */ 2709 For_Break(curFile->forLoop); 2710 cond_depth = CurFile_CondMinDepth(); 2711 ParseEOF(); 2712 } else 2713 Parse_Error(PARSE_FATAL, "break outside of for loop"); 2714 } 2715 2716 /* 2717 * See if the line starts with one of the known directives, and if so, handle 2718 * the directive. 2719 */ 2720 static bool 2721 ParseDirective(char *line) 2722 { 2723 char *cp = line + 1; 2724 const char *arg; 2725 Substring dir; 2726 2727 pp_skip_whitespace(&cp); 2728 if (IsInclude(cp, false)) { 2729 ParseInclude(cp); 2730 return true; 2731 } 2732 2733 dir.start = cp; 2734 while (ch_islower(*cp) || *cp == '-') 2735 cp++; 2736 dir.end = cp; 2737 2738 if (*cp != '\0' && !ch_isspace(*cp)) 2739 return false; 2740 2741 pp_skip_whitespace(&cp); 2742 arg = cp; 2743 2744 if (Substring_Equals(dir, "break")) 2745 HandleBreak(); 2746 else if (Substring_Equals(dir, "undef")) 2747 Var_Undef(arg); 2748 else if (Substring_Equals(dir, "export")) 2749 Var_Export(VEM_PLAIN, arg); 2750 else if (Substring_Equals(dir, "export-env")) 2751 Var_Export(VEM_ENV, arg); 2752 else if (Substring_Equals(dir, "export-literal")) 2753 Var_Export(VEM_LITERAL, arg); 2754 else if (Substring_Equals(dir, "unexport")) 2755 Var_UnExport(false, arg); 2756 else if (Substring_Equals(dir, "unexport-env")) 2757 Var_UnExport(true, arg); 2758 else if (Substring_Equals(dir, "info")) 2759 HandleMessage(PARSE_INFO, "info", arg); 2760 else if (Substring_Equals(dir, "warning")) 2761 HandleMessage(PARSE_WARNING, "warning", arg); 2762 else if (Substring_Equals(dir, "error")) 2763 HandleMessage(PARSE_FATAL, "error", arg); 2764 else 2765 return false; 2766 return true; 2767 } 2768 2769 bool 2770 Parse_VarAssign(const char *line, bool finishDependencyGroup, GNode *scope) 2771 { 2772 VarAssign var; 2773 2774 if (!Parse_IsVar(line, &var)) 2775 return false; 2776 if (finishDependencyGroup) 2777 FinishDependencyGroup(); 2778 Parse_Var(&var, scope); 2779 free(var.varname); 2780 return true; 2781 } 2782 2783 static char * 2784 FindSemicolon(char *p) 2785 { 2786 int level = 0; 2787 2788 for (; *p != '\0'; p++) { 2789 if (*p == '\\' && p[1] != '\0') { 2790 p++; 2791 continue; 2792 } 2793 2794 if (*p == '$' && (p[1] == '(' || p[1] == '{')) 2795 level++; 2796 else if (level > 0 && (*p == ')' || *p == '}')) 2797 level--; 2798 else if (level == 0 && *p == ';') 2799 break; 2800 } 2801 return p; 2802 } 2803 2804 /* 2805 * dependency -> [target...] op [source...] [';' command] 2806 * op -> ':' | '::' | '!' 2807 */ 2808 static void 2809 ParseDependencyLine(char *line) 2810 { 2811 VarEvalMode emode; 2812 char *expanded_line; 2813 const char *shellcmd = NULL; 2814 2815 /* 2816 * For some reason - probably to make the parser impossible - 2817 * a ';' can be used to separate commands from dependencies. 2818 * Attempt to skip over ';' inside substitution patterns. 2819 */ 2820 { 2821 char *semicolon = FindSemicolon(line); 2822 if (*semicolon != '\0') { 2823 /* Terminate the dependency list at the ';' */ 2824 *semicolon = '\0'; 2825 shellcmd = semicolon + 1; 2826 } 2827 } 2828 2829 /* 2830 * We now know it's a dependency line so it needs to have all 2831 * variables expanded before being parsed. 2832 * 2833 * XXX: Ideally the dependency line would first be split into 2834 * its left-hand side, dependency operator and right-hand side, 2835 * and then each side would be expanded on its own. This would 2836 * allow for the left-hand side to allow only defined variables 2837 * and to allow variables on the right-hand side to be undefined 2838 * as well. 2839 * 2840 * Parsing the line first would also prevent that targets 2841 * generated from variable expressions are interpreted as the 2842 * dependency operator, such as in "target${:U\:} middle: source", 2843 * in which the middle is interpreted as a source, not a target. 2844 */ 2845 2846 /* 2847 * In lint mode, allow undefined variables to appear in dependency 2848 * lines. 2849 * 2850 * Ideally, only the right-hand side would allow undefined variables 2851 * since it is common to have optional dependencies. Having undefined 2852 * variables on the left-hand side is more unusual though. Since 2853 * both sides are expanded in a single pass, there is not much choice 2854 * what to do here. 2855 * 2856 * In normal mode, it does not matter whether undefined variables are 2857 * allowed or not since as of 2020-09-14, Var_Parse does not print 2858 * any parse errors in such a case. It simply returns the special 2859 * empty string var_Error, which cannot be detected in the result of 2860 * Var_Subst. 2861 */ 2862 emode = opts.strict ? VARE_WANTRES : VARE_UNDEFERR; 2863 expanded_line = Var_Subst(line, SCOPE_CMDLINE, emode); 2864 /* TODO: handle errors */ 2865 2866 /* Need a fresh list for the target nodes */ 2867 if (targets != NULL) 2868 Lst_Free(targets); 2869 targets = Lst_New(); 2870 2871 ParseDependency(expanded_line); 2872 free(expanded_line); 2873 2874 if (shellcmd != NULL) 2875 ParseLine_ShellCommand(shellcmd); 2876 } 2877 2878 static void 2879 ParseLine(char *line) 2880 { 2881 /* 2882 * Lines that begin with '.' can be pretty much anything: 2883 * - directives like '.include' or '.if', 2884 * - suffix rules like '.c.o:', 2885 * - dependencies for filenames that start with '.', 2886 * - variable assignments like '.tmp=value'. 2887 */ 2888 if (line[0] == '.' && ParseDirective(line)) 2889 return; 2890 2891 if (line[0] == '\t') { 2892 ParseLine_ShellCommand(line + 1); 2893 return; 2894 } 2895 2896 #ifdef SYSVINCLUDE 2897 if (IsSysVInclude(line)) { 2898 /* 2899 * It's an S3/S5-style "include". 2900 */ 2901 ParseTraditionalInclude(line); 2902 return; 2903 } 2904 #endif 2905 2906 #ifdef GMAKEEXPORT 2907 if (strncmp(line, "export", 6) == 0 && ch_isspace(line[6]) && 2908 strchr(line, ':') == NULL) { 2909 /* 2910 * It's a Gmake "export". 2911 */ 2912 ParseGmakeExport(line); 2913 return; 2914 } 2915 #endif 2916 2917 if (Parse_VarAssign(line, true, SCOPE_GLOBAL)) 2918 return; 2919 2920 FinishDependencyGroup(); 2921 2922 ParseDependencyLine(line); 2923 } 2924 2925 /* 2926 * Parse a top-level makefile, incorporating its content into the global 2927 * dependency graph. 2928 */ 2929 void 2930 Parse_File(const char *name, int fd) 2931 { 2932 char *line; 2933 Buffer buf; 2934 2935 buf = LoadFile(name, fd != -1 ? fd : STDIN_FILENO); 2936 if (fd != -1) 2937 (void)close(fd); 2938 2939 assert(targets == NULL); 2940 2941 Parse_PushInput(name, 1, 0, buf, NULL); 2942 2943 do { 2944 while ((line = ReadHighLevelLine()) != NULL) { 2945 DEBUG2(PARSE, "Parsing line %u: %s\n", 2946 CurFile()->lineno, line); 2947 ParseLine(line); 2948 } 2949 /* Reached EOF, but it may be just EOF of an include file. */ 2950 } while (ParseEOF()); 2951 2952 FinishDependencyGroup(); 2953 2954 if (parseErrors != 0) { 2955 (void)fflush(stdout); 2956 (void)fprintf(stderr, 2957 "%s: Fatal errors encountered -- cannot continue\n", 2958 progname); 2959 PrintOnError(NULL, ""); 2960 exit(1); 2961 } 2962 } 2963 2964 /* Initialize the parsing module. */ 2965 void 2966 Parse_Init(void) 2967 { 2968 mainNode = NULL; 2969 parseIncPath = SearchPath_New(); 2970 sysIncPath = SearchPath_New(); 2971 defSysIncPath = SearchPath_New(); 2972 Vector_Init(&includes, sizeof(IncludedFile)); 2973 } 2974 2975 /* Clean up the parsing module. */ 2976 void 2977 Parse_End(void) 2978 { 2979 #ifdef CLEANUP 2980 Lst_DoneCall(&targCmds, free); 2981 assert(targets == NULL); 2982 SearchPath_Free(defSysIncPath); 2983 SearchPath_Free(sysIncPath); 2984 SearchPath_Free(parseIncPath); 2985 assert(includes.len == 0); 2986 Vector_Done(&includes); 2987 #endif 2988 } 2989 2990 2991 /* 2992 * Return a list containing the single main target to create. 2993 * If no such target exists, we Punt with an obnoxious error message. 2994 */ 2995 void 2996 Parse_MainName(GNodeList *mainList) 2997 { 2998 if (mainNode == NULL) 2999 Punt("no target to make."); 3000 3001 Lst_Append(mainList, mainNode); 3002 if (mainNode->type & OP_DOUBLEDEP) 3003 Lst_AppendAll(mainList, &mainNode->cohorts); 3004 3005 Global_Append(".TARGETS", mainNode->name); 3006 } 3007 3008 int 3009 Parse_NumErrors(void) 3010 { 3011 return parseErrors; 3012 } 3013