1 /* $NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg 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 #ifndef MAKE_NATIVE 72 static char rcsid[] = "$NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg Exp $"; 73 #else 74 #include <sys/cdefs.h> 75 #ifndef lint 76 #if 0 77 static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; 78 #else 79 __RCSID("$NetBSD: parse.c,v 1.185 2012/06/12 19:21:51 joerg Exp $"); 80 #endif 81 #endif /* not lint */ 82 #endif 83 84 /*- 85 * parse.c -- 86 * Functions to parse a makefile. 87 * 88 * One function, Parse_Init, must be called before any functions 89 * in this module are used. After that, the function Parse_File is the 90 * main entry point and controls most of the other functions in this 91 * module. 92 * 93 * Most important structures are kept in Lsts. Directories for 94 * the .include "..." function are kept in the 'parseIncPath' Lst, while 95 * those for the .include <...> are kept in the 'sysIncPath' Lst. The 96 * targets currently being defined are kept in the 'targets' Lst. 97 * 98 * The variables 'fname' and 'lineno' are used to track the name 99 * of the current file and the line number in that file so that error 100 * messages can be more meaningful. 101 * 102 * Interface: 103 * Parse_Init Initialization function which must be 104 * called before anything else in this module 105 * is used. 106 * 107 * Parse_End Cleanup the module 108 * 109 * Parse_File Function used to parse a makefile. It must 110 * be given the name of the file, which should 111 * already have been opened, and a function 112 * to call to read a character from the file. 113 * 114 * Parse_IsVar Returns TRUE if the given line is a 115 * variable assignment. Used by MainParseArgs 116 * to determine if an argument is a target 117 * or a variable assignment. Used internally 118 * for pretty much the same thing... 119 * 120 * Parse_Error Function called when an error occurs in 121 * parsing. Used by the variable and 122 * conditional modules. 123 * Parse_MainName Returns a Lst of the main target to create. 124 */ 125 126 #include <sys/types.h> 127 #include <sys/mman.h> 128 #include <sys/stat.h> 129 #include <assert.h> 130 #include <ctype.h> 131 #include <errno.h> 132 #include <fcntl.h> 133 #include <stdarg.h> 134 #include <stdio.h> 135 136 #ifndef MAP_FILE 137 #define MAP_FILE 0 138 #endif 139 #ifndef MAP_COPY 140 #define MAP_COPY MAP_PRIVATE 141 #endif 142 143 #include "make.h" 144 #include "hash.h" 145 #include "dir.h" 146 #include "job.h" 147 #include "buf.h" 148 #include "pathnames.h" 149 150 //////////////////////////////////////////////////////////// 151 // types and constants 152 153 /* 154 * Structure for a file being read ("included file") 155 */ 156 typedef struct IFile { 157 const char *fname; /* name of file */ 158 int lineno; /* current line number in file */ 159 int first_lineno; /* line number of start of text */ 160 int cond_depth; /* 'if' nesting when file opened */ 161 char *P_str; /* point to base of string buffer */ 162 char *P_ptr; /* point to next char of string buffer */ 163 char *P_end; /* point to the end of string buffer */ 164 char *(*nextbuf)(void *, size_t *); /* Function to get more data */ 165 void *nextbuf_arg; /* Opaque arg for nextbuf() */ 166 struct loadedfile *lf; /* loadedfile object, if any */ 167 } IFile; 168 169 170 /* 171 * These values are returned by ParseEOF to tell Parse_File whether to 172 * CONTINUE parsing, i.e. it had only reached the end of an include file, 173 * or if it's DONE. 174 */ 175 #define CONTINUE 1 176 #define DONE 0 177 178 /* 179 * Tokens for target attributes 180 */ 181 typedef enum { 182 Begin, /* .BEGIN */ 183 Default, /* .DEFAULT */ 184 End, /* .END */ 185 dotError, /* .ERROR */ 186 Ignore, /* .IGNORE */ 187 Includes, /* .INCLUDES */ 188 Interrupt, /* .INTERRUPT */ 189 Libs, /* .LIBS */ 190 Meta, /* .META */ 191 MFlags, /* .MFLAGS or .MAKEFLAGS */ 192 Main, /* .MAIN and we don't have anything user-specified to 193 * make */ 194 NoExport, /* .NOEXPORT */ 195 NoMeta, /* .NOMETA */ 196 NoMetaCmp, /* .NOMETA_CMP */ 197 NoPath, /* .NOPATH */ 198 Not, /* Not special */ 199 NotParallel, /* .NOTPARALLEL */ 200 Null, /* .NULL */ 201 ExObjdir, /* .OBJDIR */ 202 Order, /* .ORDER */ 203 Parallel, /* .PARALLEL */ 204 ExPath, /* .PATH */ 205 Phony, /* .PHONY */ 206 #ifdef POSIX 207 Posix, /* .POSIX */ 208 #endif 209 Precious, /* .PRECIOUS */ 210 ExShell, /* .SHELL */ 211 Silent, /* .SILENT */ 212 SingleShell, /* .SINGLESHELL */ 213 Suffixes, /* .SUFFIXES */ 214 Wait, /* .WAIT */ 215 Attribute /* Generic attribute */ 216 } ParseSpecial; 217 218 /* 219 * Other tokens 220 */ 221 #define LPAREN '(' 222 #define RPAREN ')' 223 224 225 //////////////////////////////////////////////////////////// 226 // result data 227 228 /* 229 * The main target to create. This is the first target on the first 230 * dependency line in the first makefile. 231 */ 232 static GNode *mainNode; 233 234 //////////////////////////////////////////////////////////// 235 // eval state 236 237 /* targets we're working on */ 238 static Lst targets; 239 240 #ifdef CLEANUP 241 /* command lines for targets */ 242 static Lst targCmds; 243 #endif 244 245 /* 246 * specType contains the SPECial TYPE of the current target. It is 247 * Not if the target is unspecial. If it *is* special, however, the children 248 * are linked as children of the parent but not vice versa. This variable is 249 * set in ParseDoDependency 250 */ 251 static ParseSpecial specType; 252 253 /* 254 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 255 * seen, then set to each successive source on the line. 256 */ 257 static GNode *predecessor; 258 259 //////////////////////////////////////////////////////////// 260 // parser state 261 262 /* true if currently in a dependency line or its commands */ 263 static Boolean inLine; 264 265 /* number of fatal errors */ 266 static int fatals = 0; 267 268 /* 269 * Variables for doing includes 270 */ 271 272 /* current file being read */ 273 static IFile *curFile; 274 275 /* stack of IFiles generated by .includes */ 276 static Lst includes; 277 278 /* include paths (lists of directories) */ 279 Lst parseIncPath; /* dirs for "..." includes */ 280 Lst sysIncPath; /* dirs for <...> includes */ 281 Lst defIncPath; /* default for sysIncPath */ 282 283 //////////////////////////////////////////////////////////// 284 // parser tables 285 286 /* 287 * The parseKeywords table is searched using binary search when deciding 288 * if a target or source is special. The 'spec' field is the ParseSpecial 289 * type of the keyword ("Not" if the keyword isn't special as a target) while 290 * the 'op' field is the operator to apply to the list of targets if the 291 * keyword is used as a source ("0" if the keyword isn't special as a source) 292 */ 293 static const struct { 294 const char *name; /* Name of keyword */ 295 ParseSpecial spec; /* Type when used as a target */ 296 int op; /* Operator when used as a source */ 297 } parseKeywords[] = { 298 { ".BEGIN", Begin, 0 }, 299 { ".DEFAULT", Default, 0 }, 300 { ".END", End, 0 }, 301 { ".ERROR", dotError, 0 }, 302 { ".EXEC", Attribute, OP_EXEC }, 303 { ".IGNORE", Ignore, OP_IGNORE }, 304 { ".INCLUDES", Includes, 0 }, 305 { ".INTERRUPT", Interrupt, 0 }, 306 { ".INVISIBLE", Attribute, OP_INVISIBLE }, 307 { ".JOIN", Attribute, OP_JOIN }, 308 { ".LIBS", Libs, 0 }, 309 { ".MADE", Attribute, OP_MADE }, 310 { ".MAIN", Main, 0 }, 311 { ".MAKE", Attribute, OP_MAKE }, 312 { ".MAKEFLAGS", MFlags, 0 }, 313 { ".META", Meta, OP_META }, 314 { ".MFLAGS", MFlags, 0 }, 315 { ".NOMETA", NoMeta, OP_NOMETA }, 316 { ".NOMETA_CMP", NoMetaCmp, OP_NOMETA_CMP }, 317 { ".NOPATH", NoPath, OP_NOPATH }, 318 { ".NOTMAIN", Attribute, OP_NOTMAIN }, 319 { ".NOTPARALLEL", NotParallel, 0 }, 320 { ".NO_PARALLEL", NotParallel, 0 }, 321 { ".NULL", Null, 0 }, 322 { ".OBJDIR", ExObjdir, 0 }, 323 { ".OPTIONAL", Attribute, OP_OPTIONAL }, 324 { ".ORDER", Order, 0 }, 325 { ".PARALLEL", Parallel, 0 }, 326 { ".PATH", ExPath, 0 }, 327 { ".PHONY", Phony, OP_PHONY }, 328 #ifdef POSIX 329 { ".POSIX", Posix, 0 }, 330 #endif 331 { ".PRECIOUS", Precious, OP_PRECIOUS }, 332 { ".RECURSIVE", Attribute, OP_MAKE }, 333 { ".SHELL", ExShell, 0 }, 334 { ".SILENT", Silent, OP_SILENT }, 335 { ".SINGLESHELL", SingleShell, 0 }, 336 { ".SUFFIXES", Suffixes, 0 }, 337 { ".USE", Attribute, OP_USE }, 338 { ".USEBEFORE", Attribute, OP_USEBEFORE }, 339 { ".WAIT", Wait, 0 }, 340 }; 341 342 //////////////////////////////////////////////////////////// 343 // local functions 344 345 static int ParseIsEscaped(const char *, const char *); 346 static void ParseErrorInternal(const char *, size_t, int, const char *, ...) 347 MAKE_ATTR_PRINTFLIKE(4,5); 348 static void ParseVErrorInternal(FILE *, const char *, size_t, int, const char *, va_list) 349 MAKE_ATTR_PRINTFLIKE(5, 0); 350 static int ParseFindKeyword(const char *); 351 static int ParseLinkSrc(void *, void *); 352 static int ParseDoOp(void *, void *); 353 static void ParseDoSrc(int, const char *); 354 static int ParseFindMain(void *, void *); 355 static int ParseAddDir(void *, void *); 356 static int ParseClearPath(void *, void *); 357 static void ParseDoDependency(char *); 358 static int ParseAddCmd(void *, void *); 359 static void ParseHasCommands(void *); 360 static void ParseDoInclude(char *); 361 static void ParseSetParseFile(const char *); 362 #ifdef SYSVINCLUDE 363 static void ParseTraditionalInclude(char *); 364 #endif 365 #ifdef GMAKEEXPORT 366 static void ParseGmakeExport(char *); 367 #endif 368 static int ParseEOF(void); 369 static char *ParseReadLine(void); 370 static void ParseFinishLine(void); 371 static void ParseMark(GNode *); 372 373 //////////////////////////////////////////////////////////// 374 // file loader 375 376 struct loadedfile { 377 const char *path; /* name, for error reports */ 378 char *buf; /* contents buffer */ 379 size_t len; /* length of contents */ 380 size_t maplen; /* length of mmap area, or 0 */ 381 Boolean used; /* XXX: have we used the data yet */ 382 }; 383 384 /* 385 * Constructor/destructor for loadedfile 386 */ 387 static struct loadedfile * 388 loadedfile_create(const char *path) 389 { 390 struct loadedfile *lf; 391 392 lf = bmake_malloc(sizeof(*lf)); 393 lf->path = (path == NULL ? "(stdin)" : path); 394 lf->buf = NULL; 395 lf->len = 0; 396 lf->maplen = 0; 397 lf->used = FALSE; 398 return lf; 399 } 400 401 static void 402 loadedfile_destroy(struct loadedfile *lf) 403 { 404 if (lf->buf != NULL) { 405 if (lf->maplen > 0) { 406 munmap(lf->buf, lf->maplen); 407 } else { 408 free(lf->buf); 409 } 410 } 411 free(lf); 412 } 413 414 /* 415 * nextbuf() operation for loadedfile, as needed by the weird and twisted 416 * logic below. Once that's cleaned up, we can get rid of lf->used... 417 */ 418 static char * 419 loadedfile_nextbuf(void *x, size_t *len) 420 { 421 struct loadedfile *lf = x; 422 423 if (lf->used) { 424 return NULL; 425 } 426 lf->used = TRUE; 427 *len = lf->len; 428 return lf->buf; 429 } 430 431 /* 432 * Try to get the size of a file. 433 */ 434 static ReturnStatus 435 load_getsize(int fd, size_t *ret) 436 { 437 struct stat st; 438 439 if (fstat(fd, &st) < 0) { 440 return FAILURE; 441 } 442 443 if (!S_ISREG(st.st_mode)) { 444 return FAILURE; 445 } 446 447 /* 448 * st_size is an off_t, which is 64 bits signed; *ret is 449 * size_t, which might be 32 bits unsigned or 64 bits 450 * unsigned. Rather than being elaborate, just punt on 451 * files that are more than 2^31 bytes. We should never 452 * see a makefile that size in practice... 453 * 454 * While we're at it reject negative sizes too, just in case. 455 */ 456 if (st.st_size < 0 || st.st_size > 0x7fffffff) { 457 return FAILURE; 458 } 459 460 *ret = (size_t) st.st_size; 461 return SUCCESS; 462 } 463 464 /* 465 * Read in a file. 466 * 467 * Until the path search logic can be moved under here instead of 468 * being in the caller in another source file, we need to have the fd 469 * passed in already open. Bleh. 470 * 471 * If the path is NULL use stdin and (to insure against fd leaks) 472 * assert that the caller passed in -1. 473 */ 474 static struct loadedfile * 475 loadfile(const char *path, int fd) 476 { 477 struct loadedfile *lf; 478 long pagesize; 479 ssize_t result; 480 size_t bufpos; 481 482 lf = loadedfile_create(path); 483 484 if (path == NULL) { 485 assert(fd == -1); 486 fd = STDIN_FILENO; 487 } else { 488 #if 0 /* notyet */ 489 fd = open(path, O_RDONLY); 490 if (fd < 0) { 491 ... 492 Error("%s: %s", path, strerror(errno)); 493 exit(1); 494 } 495 #endif 496 } 497 498 if (load_getsize(fd, &lf->len) == SUCCESS) { 499 /* found a size, try mmap */ 500 pagesize = sysconf(_SC_PAGESIZE); 501 if (pagesize <= 0) { 502 pagesize = 0x1000; 503 } 504 /* round size up to a page */ 505 lf->maplen = pagesize * ((lf->len + pagesize - 1)/pagesize); 506 507 /* 508 * XXX hack for dealing with empty files; remove when 509 * we're no longer limited by interfacing to the old 510 * logic elsewhere in this file. 511 */ 512 if (lf->maplen == 0) { 513 lf->maplen = pagesize; 514 } 515 516 /* 517 * FUTURE: remove PROT_WRITE when the parser no longer 518 * needs to scribble on the input. 519 */ 520 lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE, 521 MAP_FILE|MAP_COPY, fd, 0); 522 if (lf->buf != MAP_FAILED) { 523 /* succeeded */ 524 if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') { 525 char *b = malloc(lf->len + 1); 526 b[lf->len] = '\n'; 527 memcpy(b, lf->buf, lf->len++); 528 munmap(lf->buf, lf->maplen); 529 lf->maplen = 0; 530 lf->buf = b; 531 } 532 goto done; 533 } 534 } 535 536 /* cannot mmap; load the traditional way */ 537 538 lf->maplen = 0; 539 lf->len = 1024; 540 lf->buf = bmake_malloc(lf->len); 541 542 bufpos = 0; 543 while (1) { 544 assert(bufpos <= lf->len); 545 if (bufpos == lf->len) { 546 lf->len *= 2; 547 lf->buf = bmake_realloc(lf->buf, lf->len); 548 } 549 result = read(fd, lf->buf + bufpos, lf->len - bufpos); 550 if (result < 0) { 551 Error("%s: read error: %s", path, strerror(errno)); 552 exit(1); 553 } 554 if (result == 0) { 555 break; 556 } 557 bufpos += result; 558 } 559 assert(bufpos <= lf->len); 560 lf->len = bufpos; 561 562 /* truncate malloc region to actual length (maybe not useful) */ 563 if (lf->len > 0) { 564 lf->buf = bmake_realloc(lf->buf, lf->len); 565 } 566 567 done: 568 if (path != NULL) { 569 close(fd); 570 } 571 return lf; 572 } 573 574 //////////////////////////////////////////////////////////// 575 // old code 576 577 /*- 578 *---------------------------------------------------------------------- 579 * ParseIsEscaped -- 580 * Check if the current character is escaped on the current line 581 * 582 * Results: 583 * 0 if the character is not backslash escaped, 1 otherwise 584 * 585 * Side Effects: 586 * None 587 *---------------------------------------------------------------------- 588 */ 589 static int 590 ParseIsEscaped(const char *line, const char *c) 591 { 592 int active = 0; 593 for (;;) { 594 if (line == c) 595 return active; 596 if (*--c != '\\') 597 return active; 598 active = !active; 599 } 600 } 601 602 /*- 603 *---------------------------------------------------------------------- 604 * ParseFindKeyword -- 605 * Look in the table of keywords for one matching the given string. 606 * 607 * Input: 608 * str String to find 609 * 610 * Results: 611 * The index of the keyword, or -1 if it isn't there. 612 * 613 * Side Effects: 614 * None 615 *---------------------------------------------------------------------- 616 */ 617 static int 618 ParseFindKeyword(const char *str) 619 { 620 int start, end, cur; 621 int diff; 622 623 start = 0; 624 end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1; 625 626 do { 627 cur = start + ((end - start) / 2); 628 diff = strcmp(str, parseKeywords[cur].name); 629 630 if (diff == 0) { 631 return (cur); 632 } else if (diff < 0) { 633 end = cur - 1; 634 } else { 635 start = cur + 1; 636 } 637 } while (start <= end); 638 return (-1); 639 } 640 641 /*- 642 * ParseVErrorInternal -- 643 * Error message abort function for parsing. Prints out the context 644 * of the error (line number and file) as well as the message with 645 * two optional arguments. 646 * 647 * Results: 648 * None 649 * 650 * Side Effects: 651 * "fatals" is incremented if the level is PARSE_FATAL. 652 */ 653 /* VARARGS */ 654 static void 655 ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type, 656 const char *fmt, va_list ap) 657 { 658 static Boolean fatal_warning_error_printed = FALSE; 659 660 (void)fprintf(f, "%s: ", progname); 661 662 if (cfname != NULL) { 663 (void)fprintf(f, "\""); 664 if (*cfname != '/' && strcmp(cfname, "(stdin)") != 0) { 665 char *cp; 666 const char *dir; 667 668 /* 669 * Nothing is more annoying than not knowing 670 * which Makefile is the culprit. 671 */ 672 dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &cp); 673 if (dir == NULL || *dir == '\0' || 674 (*dir == '.' && dir[1] == '\0')) 675 dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp); 676 if (dir == NULL) 677 dir = "."; 678 679 (void)fprintf(f, "%s/%s", dir, cfname); 680 } else 681 (void)fprintf(f, "%s", cfname); 682 683 (void)fprintf(f, "\" line %d: ", (int)clineno); 684 } 685 if (type == PARSE_WARNING) 686 (void)fprintf(f, "warning: "); 687 (void)vfprintf(f, fmt, ap); 688 (void)fprintf(f, "\n"); 689 (void)fflush(f); 690 if (type == PARSE_FATAL || parseWarnFatal) 691 fatals += 1; 692 if (parseWarnFatal && !fatal_warning_error_printed) { 693 Error("parsing warnings being treated as errors"); 694 fatal_warning_error_printed = TRUE; 695 } 696 } 697 698 /*- 699 * ParseErrorInternal -- 700 * Error function 701 * 702 * Results: 703 * None 704 * 705 * Side Effects: 706 * None 707 */ 708 /* VARARGS */ 709 static void 710 ParseErrorInternal(const char *cfname, size_t clineno, int type, 711 const char *fmt, ...) 712 { 713 va_list ap; 714 715 va_start(ap, fmt); 716 (void)fflush(stdout); 717 ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap); 718 va_end(ap); 719 720 if (debug_file != stderr && debug_file != stdout) { 721 va_start(ap, fmt); 722 ParseVErrorInternal(debug_file, cfname, clineno, type, fmt, ap); 723 va_end(ap); 724 } 725 } 726 727 /*- 728 * Parse_Error -- 729 * External interface to ParseErrorInternal; uses the default filename 730 * Line number. 731 * 732 * Results: 733 * None 734 * 735 * Side Effects: 736 * None 737 */ 738 /* VARARGS */ 739 void 740 Parse_Error(int type, const char *fmt, ...) 741 { 742 va_list ap; 743 const char *fname; 744 size_t lineno; 745 746 if (curFile == NULL) { 747 fname = NULL; 748 lineno = 0; 749 } else { 750 fname = curFile->fname; 751 lineno = curFile->lineno; 752 } 753 754 va_start(ap, fmt); 755 (void)fflush(stdout); 756 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap); 757 va_end(ap); 758 759 if (debug_file != stderr && debug_file != stdout) { 760 va_start(ap, fmt); 761 ParseVErrorInternal(debug_file, fname, lineno, type, fmt, ap); 762 va_end(ap); 763 } 764 } 765 766 767 /* 768 * ParseMessage 769 * Parse a .info .warning or .error directive 770 * 771 * The input is the line minus the ".". We substitute 772 * variables, print the message and exit(1) (for .error) or just print 773 * a warning if the directive is malformed. 774 */ 775 static Boolean 776 ParseMessage(char *line) 777 { 778 int mtype; 779 780 switch(*line) { 781 case 'i': 782 mtype = 0; 783 break; 784 case 'w': 785 mtype = PARSE_WARNING; 786 break; 787 case 'e': 788 mtype = PARSE_FATAL; 789 break; 790 default: 791 Parse_Error(PARSE_WARNING, "invalid syntax: \".%s\"", line); 792 return FALSE; 793 } 794 795 while (isalpha((u_char)*line)) 796 line++; 797 if (!isspace((u_char)*line)) 798 return FALSE; /* not for us */ 799 while (isspace((u_char)*line)) 800 line++; 801 802 line = Var_Subst(NULL, line, VAR_CMD, 0); 803 Parse_Error(mtype, "%s", line); 804 free(line); 805 806 if (mtype == PARSE_FATAL) { 807 /* Terminate immediately. */ 808 exit(1); 809 } 810 return TRUE; 811 } 812 813 /*- 814 *--------------------------------------------------------------------- 815 * ParseLinkSrc -- 816 * Link the parent node to its new child. Used in a Lst_ForEach by 817 * ParseDoDependency. If the specType isn't 'Not', the parent 818 * isn't linked as a parent of the child. 819 * 820 * Input: 821 * pgnp The parent node 822 * cgpn The child node 823 * 824 * Results: 825 * Always = 0 826 * 827 * Side Effects: 828 * New elements are added to the parents list of cgn and the 829 * children list of cgn. the unmade field of pgn is updated 830 * to reflect the additional child. 831 *--------------------------------------------------------------------- 832 */ 833 static int 834 ParseLinkSrc(void *pgnp, void *cgnp) 835 { 836 GNode *pgn = (GNode *)pgnp; 837 GNode *cgn = (GNode *)cgnp; 838 839 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (pgn->cohorts)) 840 pgn = (GNode *)Lst_Datum(Lst_Last(pgn->cohorts)); 841 (void)Lst_AtEnd(pgn->children, cgn); 842 if (specType == Not) 843 (void)Lst_AtEnd(cgn->parents, pgn); 844 pgn->unmade += 1; 845 if (DEBUG(PARSE)) { 846 fprintf(debug_file, "# ParseLinkSrc: added child %s - %s\n", pgn->name, cgn->name); 847 Targ_PrintNode(pgn, 0); 848 Targ_PrintNode(cgn, 0); 849 } 850 return (0); 851 } 852 853 /*- 854 *--------------------------------------------------------------------- 855 * ParseDoOp -- 856 * Apply the parsed operator to the given target node. Used in a 857 * Lst_ForEach call by ParseDoDependency once all targets have 858 * been found and their operator parsed. If the previous and new 859 * operators are incompatible, a major error is taken. 860 * 861 * Input: 862 * gnp The node to which the operator is to be applied 863 * opp The operator to apply 864 * 865 * Results: 866 * Always 0 867 * 868 * Side Effects: 869 * The type field of the node is altered to reflect any new bits in 870 * the op. 871 *--------------------------------------------------------------------- 872 */ 873 static int 874 ParseDoOp(void *gnp, void *opp) 875 { 876 GNode *gn = (GNode *)gnp; 877 int op = *(int *)opp; 878 /* 879 * If the dependency mask of the operator and the node don't match and 880 * the node has actually had an operator applied to it before, and 881 * the operator actually has some dependency information in it, complain. 882 */ 883 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 884 !OP_NOP(gn->type) && !OP_NOP(op)) 885 { 886 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); 887 return (1); 888 } 889 890 if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 891 /* 892 * If the node was the object of a :: operator, we need to create a 893 * new instance of it for the children and commands on this dependency 894 * line. The new instance is placed on the 'cohorts' list of the 895 * initial one (note the initial one is not on its own cohorts list) 896 * and the new instance is linked to all parents of the initial 897 * instance. 898 */ 899 GNode *cohort; 900 901 /* 902 * Propagate copied bits to the initial node. They'll be propagated 903 * back to the rest of the cohorts later. 904 */ 905 gn->type |= op & ~OP_OPMASK; 906 907 cohort = Targ_FindNode(gn->name, TARG_NOHASH); 908 /* 909 * Make the cohort invisible as well to avoid duplicating it into 910 * other variables. True, parents of this target won't tend to do 911 * anything with their local variables, but better safe than 912 * sorry. (I think this is pointless now, since the relevant list 913 * traversals will no longer see this node anyway. -mycroft) 914 */ 915 cohort->type = op | OP_INVISIBLE; 916 (void)Lst_AtEnd(gn->cohorts, cohort); 917 cohort->centurion = gn; 918 gn->unmade_cohorts += 1; 919 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d", 920 gn->unmade_cohorts); 921 } else { 922 /* 923 * We don't want to nuke any previous flags (whatever they were) so we 924 * just OR the new operator into the old 925 */ 926 gn->type |= op; 927 } 928 929 return (0); 930 } 931 932 /*- 933 *--------------------------------------------------------------------- 934 * ParseDoSrc -- 935 * Given the name of a source, figure out if it is an attribute 936 * and apply it to the targets if it is. Else decide if there is 937 * some attribute which should be applied *to* the source because 938 * of some special target and apply it if so. Otherwise, make the 939 * source be a child of the targets in the list 'targets' 940 * 941 * Input: 942 * tOp operator (if any) from special targets 943 * src name of the source to handle 944 * 945 * Results: 946 * None 947 * 948 * Side Effects: 949 * Operator bits may be added to the list of targets or to the source. 950 * The targets may have a new source added to their lists of children. 951 *--------------------------------------------------------------------- 952 */ 953 static void 954 ParseDoSrc(int tOp, const char *src) 955 { 956 GNode *gn = NULL; 957 static int wait_number = 0; 958 char wait_src[16]; 959 960 if (*src == '.' && isupper ((unsigned char)src[1])) { 961 int keywd = ParseFindKeyword(src); 962 if (keywd != -1) { 963 int op = parseKeywords[keywd].op; 964 if (op != 0) { 965 Lst_ForEach(targets, ParseDoOp, &op); 966 return; 967 } 968 if (parseKeywords[keywd].spec == Wait) { 969 /* 970 * We add a .WAIT node in the dependency list. 971 * After any dynamic dependencies (and filename globbing) 972 * have happened, it is given a dependency on the each 973 * previous child back to and previous .WAIT node. 974 * The next child won't be scheduled until the .WAIT node 975 * is built. 976 * We give each .WAIT node a unique name (mainly for diag). 977 */ 978 snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number); 979 gn = Targ_FindNode(wait_src, TARG_NOHASH); 980 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN; 981 Lst_ForEach(targets, ParseLinkSrc, gn); 982 return; 983 } 984 } 985 } 986 987 switch (specType) { 988 case Main: 989 /* 990 * If we have noted the existence of a .MAIN, it means we need 991 * to add the sources of said target to the list of things 992 * to create. The string 'src' is likely to be free, so we 993 * must make a new copy of it. Note that this will only be 994 * invoked if the user didn't specify a target on the command 995 * line. This is to allow #ifmake's to succeed, or something... 996 */ 997 (void)Lst_AtEnd(create, bmake_strdup(src)); 998 /* 999 * Add the name to the .TARGETS variable as well, so the user can 1000 * employ that, if desired. 1001 */ 1002 Var_Append(".TARGETS", src, VAR_GLOBAL); 1003 return; 1004 1005 case Order: 1006 /* 1007 * Create proper predecessor/successor links between the previous 1008 * source and the current one. 1009 */ 1010 gn = Targ_FindNode(src, TARG_CREATE); 1011 if (predecessor != NULL) { 1012 (void)Lst_AtEnd(predecessor->order_succ, gn); 1013 (void)Lst_AtEnd(gn->order_pred, predecessor); 1014 if (DEBUG(PARSE)) { 1015 fprintf(debug_file, "# ParseDoSrc: added Order dependency %s - %s\n", 1016 predecessor->name, gn->name); 1017 Targ_PrintNode(predecessor, 0); 1018 Targ_PrintNode(gn, 0); 1019 } 1020 } 1021 /* 1022 * The current source now becomes the predecessor for the next one. 1023 */ 1024 predecessor = gn; 1025 break; 1026 1027 default: 1028 /* 1029 * If the source is not an attribute, we need to find/create 1030 * a node for it. After that we can apply any operator to it 1031 * from a special target or link it to its parents, as 1032 * appropriate. 1033 * 1034 * In the case of a source that was the object of a :: operator, 1035 * the attribute is applied to all of its instances (as kept in 1036 * the 'cohorts' list of the node) or all the cohorts are linked 1037 * to all the targets. 1038 */ 1039 1040 /* Find/create the 'src' node and attach to all targets */ 1041 gn = Targ_FindNode(src, TARG_CREATE); 1042 if (tOp) { 1043 gn->type |= tOp; 1044 } else { 1045 Lst_ForEach(targets, ParseLinkSrc, gn); 1046 } 1047 break; 1048 } 1049 } 1050 1051 /*- 1052 *----------------------------------------------------------------------- 1053 * ParseFindMain -- 1054 * Find a real target in the list and set it to be the main one. 1055 * Called by ParseDoDependency when a main target hasn't been found 1056 * yet. 1057 * 1058 * Input: 1059 * gnp Node to examine 1060 * 1061 * Results: 1062 * 0 if main not found yet, 1 if it is. 1063 * 1064 * Side Effects: 1065 * mainNode is changed and Targ_SetMain is called. 1066 * 1067 *----------------------------------------------------------------------- 1068 */ 1069 static int 1070 ParseFindMain(void *gnp, void *dummy) 1071 { 1072 GNode *gn = (GNode *)gnp; 1073 if ((gn->type & OP_NOTARGET) == 0) { 1074 mainNode = gn; 1075 Targ_SetMain(gn); 1076 return (dummy ? 1 : 1); 1077 } else { 1078 return (dummy ? 0 : 0); 1079 } 1080 } 1081 1082 /*- 1083 *----------------------------------------------------------------------- 1084 * ParseAddDir -- 1085 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going 1086 * 1087 * Results: 1088 * === 0 1089 * 1090 * Side Effects: 1091 * See Dir_AddDir. 1092 * 1093 *----------------------------------------------------------------------- 1094 */ 1095 static int 1096 ParseAddDir(void *path, void *name) 1097 { 1098 (void)Dir_AddDir((Lst) path, (char *)name); 1099 return(0); 1100 } 1101 1102 /*- 1103 *----------------------------------------------------------------------- 1104 * ParseClearPath -- 1105 * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going 1106 * 1107 * Results: 1108 * === 0 1109 * 1110 * Side Effects: 1111 * See Dir_ClearPath 1112 * 1113 *----------------------------------------------------------------------- 1114 */ 1115 static int 1116 ParseClearPath(void *path, void *dummy) 1117 { 1118 Dir_ClearPath((Lst) path); 1119 return(dummy ? 0 : 0); 1120 } 1121 1122 /*- 1123 *--------------------------------------------------------------------- 1124 * ParseDoDependency -- 1125 * Parse the dependency line in line. 1126 * 1127 * Input: 1128 * line the line to parse 1129 * 1130 * Results: 1131 * None 1132 * 1133 * Side Effects: 1134 * The nodes of the sources are linked as children to the nodes of the 1135 * targets. Some nodes may be created. 1136 * 1137 * We parse a dependency line by first extracting words from the line and 1138 * finding nodes in the list of all targets with that name. This is done 1139 * until a character is encountered which is an operator character. Currently 1140 * these are only ! and :. At this point the operator is parsed and the 1141 * pointer into the line advanced until the first source is encountered. 1142 * The parsed operator is applied to each node in the 'targets' list, 1143 * which is where the nodes found for the targets are kept, by means of 1144 * the ParseDoOp function. 1145 * The sources are read in much the same way as the targets were except 1146 * that now they are expanded using the wildcarding scheme of the C-Shell 1147 * and all instances of the resulting words in the list of all targets 1148 * are found. Each of the resulting nodes is then linked to each of the 1149 * targets as one of its children. 1150 * Certain targets are handled specially. These are the ones detailed 1151 * by the specType variable. 1152 * The storing of transformation rules is also taken care of here. 1153 * A target is recognized as a transformation rule by calling 1154 * Suff_IsTransform. If it is a transformation rule, its node is gotten 1155 * from the suffix module via Suff_AddTransform rather than the standard 1156 * Targ_FindNode in the target module. 1157 *--------------------------------------------------------------------- 1158 */ 1159 static void 1160 ParseDoDependency(char *line) 1161 { 1162 char *cp; /* our current position */ 1163 GNode *gn = NULL; /* a general purpose temporary node */ 1164 int op; /* the operator on the line */ 1165 char savec; /* a place to save a character */ 1166 Lst paths; /* List of search paths to alter when parsing 1167 * a list of .PATH targets */ 1168 int tOp; /* operator from special target */ 1169 Lst sources; /* list of archive source names after 1170 * expansion */ 1171 Lst curTargs; /* list of target names to be found and added 1172 * to the targets list */ 1173 char *lstart = line; 1174 1175 if (DEBUG(PARSE)) 1176 fprintf(debug_file, "ParseDoDependency(%s)\n", line); 1177 tOp = 0; 1178 1179 specType = Not; 1180 paths = NULL; 1181 1182 curTargs = Lst_Init(FALSE); 1183 1184 do { 1185 for (cp = line; *cp && (ParseIsEscaped(lstart, cp) || 1186 !(isspace((unsigned char)*cp) || 1187 *cp == '!' || *cp == ':' || *cp == LPAREN)); 1188 cp++) { 1189 if (*cp == '$') { 1190 /* 1191 * Must be a dynamic source (would have been expanded 1192 * otherwise), so call the Var module to parse the puppy 1193 * so we can safely advance beyond it...There should be 1194 * no errors in this, as they would have been discovered 1195 * in the initial Var_Subst and we wouldn't be here. 1196 */ 1197 int length; 1198 void *freeIt; 1199 char *result; 1200 1201 result = Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt); 1202 if (freeIt) 1203 free(freeIt); 1204 cp += length-1; 1205 } 1206 } 1207 1208 if (!ParseIsEscaped(lstart, cp) && *cp == LPAREN) { 1209 /* 1210 * Archives must be handled specially to make sure the OP_ARCHV 1211 * flag is set in their 'type' field, for one thing, and because 1212 * things like "archive(file1.o file2.o file3.o)" are permissible. 1213 * Arch_ParseArchive will set 'line' to be the first non-blank 1214 * after the archive-spec. It creates/finds nodes for the members 1215 * and places them on the given list, returning SUCCESS if all 1216 * went well and FAILURE if there was an error in the 1217 * specification. On error, line should remain untouched. 1218 */ 1219 if (Arch_ParseArchive(&line, targets, VAR_CMD) != SUCCESS) { 1220 Parse_Error(PARSE_FATAL, 1221 "Error in archive specification: \"%s\"", line); 1222 goto out; 1223 } else { 1224 continue; 1225 } 1226 } 1227 savec = *cp; 1228 1229 if (!*cp) { 1230 /* 1231 * Ending a dependency line without an operator is a Bozo 1232 * no-no. As a heuristic, this is also often triggered by 1233 * undetected conflicts from cvs/rcs merges. 1234 */ 1235 if ((strncmp(line, "<<<<<<", 6) == 0) || 1236 (strncmp(line, "======", 6) == 0) || 1237 (strncmp(line, ">>>>>>", 6) == 0)) 1238 Parse_Error(PARSE_FATAL, 1239 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts"); 1240 else 1241 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive" 1242 : "Need an operator"); 1243 goto out; 1244 } 1245 *cp = '\0'; 1246 1247 /* 1248 * Have a word in line. See if it's a special target and set 1249 * specType to match it. 1250 */ 1251 if (*line == '.' && isupper ((unsigned char)line[1])) { 1252 /* 1253 * See if the target is a special target that must have it 1254 * or its sources handled specially. 1255 */ 1256 int keywd = ParseFindKeyword(line); 1257 if (keywd != -1) { 1258 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { 1259 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 1260 goto out; 1261 } 1262 1263 specType = parseKeywords[keywd].spec; 1264 tOp = parseKeywords[keywd].op; 1265 1266 /* 1267 * Certain special targets have special semantics: 1268 * .PATH Have to set the dirSearchPath 1269 * variable too 1270 * .MAIN Its sources are only used if 1271 * nothing has been specified to 1272 * create. 1273 * .DEFAULT Need to create a node to hang 1274 * commands on, but we don't want 1275 * it in the graph, nor do we want 1276 * it to be the Main Target, so we 1277 * create it, set OP_NOTMAIN and 1278 * add it to the list, setting 1279 * DEFAULT to the new node for 1280 * later use. We claim the node is 1281 * A transformation rule to make 1282 * life easier later, when we'll 1283 * use Make_HandleUse to actually 1284 * apply the .DEFAULT commands. 1285 * .PHONY The list of targets 1286 * .NOPATH Don't search for file in the path 1287 * .BEGIN 1288 * .END 1289 * .ERROR 1290 * .INTERRUPT Are not to be considered the 1291 * main target. 1292 * .NOTPARALLEL Make only one target at a time. 1293 * .SINGLESHELL Create a shell for each command. 1294 * .ORDER Must set initial predecessor to NULL 1295 */ 1296 switch (specType) { 1297 case ExPath: 1298 if (paths == NULL) { 1299 paths = Lst_Init(FALSE); 1300 } 1301 (void)Lst_AtEnd(paths, dirSearchPath); 1302 break; 1303 case Main: 1304 if (!Lst_IsEmpty(create)) { 1305 specType = Not; 1306 } 1307 break; 1308 case Begin: 1309 case End: 1310 case dotError: 1311 case Interrupt: 1312 gn = Targ_FindNode(line, TARG_CREATE); 1313 gn->type |= OP_NOTMAIN|OP_SPECIAL; 1314 (void)Lst_AtEnd(targets, gn); 1315 break; 1316 case Default: 1317 gn = Targ_NewGN(".DEFAULT"); 1318 gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 1319 (void)Lst_AtEnd(targets, gn); 1320 DEFAULT = gn; 1321 break; 1322 case NotParallel: 1323 maxJobs = 1; 1324 break; 1325 case SingleShell: 1326 compatMake = TRUE; 1327 break; 1328 case Order: 1329 predecessor = NULL; 1330 break; 1331 default: 1332 break; 1333 } 1334 } else if (strncmp(line, ".PATH", 5) == 0) { 1335 /* 1336 * .PATH<suffix> has to be handled specially. 1337 * Call on the suffix module to give us a path to 1338 * modify. 1339 */ 1340 Lst path; 1341 1342 specType = ExPath; 1343 path = Suff_GetPath(&line[5]); 1344 if (path == NULL) { 1345 Parse_Error(PARSE_FATAL, 1346 "Suffix '%s' not defined (yet)", 1347 &line[5]); 1348 goto out; 1349 } else { 1350 if (paths == NULL) { 1351 paths = Lst_Init(FALSE); 1352 } 1353 (void)Lst_AtEnd(paths, path); 1354 } 1355 } 1356 } 1357 1358 /* 1359 * Have word in line. Get or create its node and stick it at 1360 * the end of the targets list 1361 */ 1362 if ((specType == Not) && (*line != '\0')) { 1363 if (Dir_HasWildcards(line)) { 1364 /* 1365 * Targets are to be sought only in the current directory, 1366 * so create an empty path for the thing. Note we need to 1367 * use Dir_Destroy in the destruction of the path as the 1368 * Dir module could have added a directory to the path... 1369 */ 1370 Lst emptyPath = Lst_Init(FALSE); 1371 1372 Dir_Expand(line, emptyPath, curTargs); 1373 1374 Lst_Destroy(emptyPath, Dir_Destroy); 1375 } else { 1376 /* 1377 * No wildcards, but we want to avoid code duplication, 1378 * so create a list with the word on it. 1379 */ 1380 (void)Lst_AtEnd(curTargs, line); 1381 } 1382 1383 while(!Lst_IsEmpty(curTargs)) { 1384 char *targName = (char *)Lst_DeQueue(curTargs); 1385 1386 if (!Suff_IsTransform (targName)) { 1387 gn = Targ_FindNode(targName, TARG_CREATE); 1388 } else { 1389 gn = Suff_AddTransform(targName); 1390 } 1391 1392 (void)Lst_AtEnd(targets, gn); 1393 } 1394 } else if (specType == ExPath && *line != '.' && *line != '\0') { 1395 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 1396 } 1397 1398 *cp = savec; 1399 /* 1400 * If it is a special type and not .PATH, it's the only target we 1401 * allow on this line... 1402 */ 1403 if (specType != Not && specType != ExPath) { 1404 Boolean warning = FALSE; 1405 1406 while (*cp && (ParseIsEscaped(lstart, cp) || 1407 ((*cp != '!') && (*cp != ':')))) { 1408 if (ParseIsEscaped(lstart, cp) || 1409 (*cp != ' ' && *cp != '\t')) { 1410 warning = TRUE; 1411 } 1412 cp++; 1413 } 1414 if (warning) { 1415 Parse_Error(PARSE_WARNING, "Extra target ignored"); 1416 } 1417 } else { 1418 while (*cp && isspace ((unsigned char)*cp)) { 1419 cp++; 1420 } 1421 } 1422 line = cp; 1423 } while (*line && (ParseIsEscaped(lstart, line) || 1424 ((*line != '!') && (*line != ':')))); 1425 1426 /* 1427 * Don't need the list of target names anymore... 1428 */ 1429 Lst_Destroy(curTargs, NULL); 1430 curTargs = NULL; 1431 1432 if (!Lst_IsEmpty(targets)) { 1433 switch(specType) { 1434 default: 1435 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); 1436 break; 1437 case Default: 1438 case Begin: 1439 case End: 1440 case dotError: 1441 case Interrupt: 1442 /* 1443 * These four create nodes on which to hang commands, so 1444 * targets shouldn't be empty... 1445 */ 1446 case Not: 1447 /* 1448 * Nothing special here -- targets can be empty if it wants. 1449 */ 1450 break; 1451 } 1452 } 1453 1454 /* 1455 * Have now parsed all the target names. Must parse the operator next. The 1456 * result is left in op . 1457 */ 1458 if (*cp == '!') { 1459 op = OP_FORCE; 1460 } else if (*cp == ':') { 1461 if (cp[1] == ':') { 1462 op = OP_DOUBLEDEP; 1463 cp++; 1464 } else { 1465 op = OP_DEPENDS; 1466 } 1467 } else { 1468 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive" 1469 : "Missing dependency operator"); 1470 goto out; 1471 } 1472 1473 cp++; /* Advance beyond operator */ 1474 1475 Lst_ForEach(targets, ParseDoOp, &op); 1476 1477 /* 1478 * Get to the first source 1479 */ 1480 while (*cp && isspace ((unsigned char)*cp)) { 1481 cp++; 1482 } 1483 line = cp; 1484 1485 /* 1486 * Several special targets take different actions if present with no 1487 * sources: 1488 * a .SUFFIXES line with no sources clears out all old suffixes 1489 * a .PRECIOUS line makes all targets precious 1490 * a .IGNORE line ignores errors for all targets 1491 * a .SILENT line creates silence when making all targets 1492 * a .PATH removes all directories from the search path(s). 1493 */ 1494 if (!*line) { 1495 switch (specType) { 1496 case Suffixes: 1497 Suff_ClearSuffixes(); 1498 break; 1499 case Precious: 1500 allPrecious = TRUE; 1501 break; 1502 case Ignore: 1503 ignoreErrors = TRUE; 1504 break; 1505 case Silent: 1506 beSilent = TRUE; 1507 break; 1508 case ExPath: 1509 Lst_ForEach(paths, ParseClearPath, NULL); 1510 Dir_SetPATH(); 1511 break; 1512 #ifdef POSIX 1513 case Posix: 1514 Var_Set("%POSIX", "1003.2", VAR_GLOBAL, 0); 1515 break; 1516 #endif 1517 default: 1518 break; 1519 } 1520 } else if (specType == MFlags) { 1521 /* 1522 * Call on functions in main.c to deal with these arguments and 1523 * set the initial character to a null-character so the loop to 1524 * get sources won't get anything 1525 */ 1526 Main_ParseArgLine(line); 1527 *line = '\0'; 1528 } else if (specType == ExShell) { 1529 if (Job_ParseShell(line) != SUCCESS) { 1530 Parse_Error(PARSE_FATAL, "improper shell specification"); 1531 goto out; 1532 } 1533 *line = '\0'; 1534 } else if ((specType == NotParallel) || (specType == SingleShell)) { 1535 *line = '\0'; 1536 } 1537 1538 /* 1539 * NOW GO FOR THE SOURCES 1540 */ 1541 if ((specType == Suffixes) || (specType == ExPath) || 1542 (specType == Includes) || (specType == Libs) || 1543 (specType == Null) || (specType == ExObjdir)) 1544 { 1545 while (*line) { 1546 /* 1547 * If the target was one that doesn't take files as its sources 1548 * but takes something like suffixes, we take each 1549 * space-separated word on the line as a something and deal 1550 * with it accordingly. 1551 * 1552 * If the target was .SUFFIXES, we take each source as a 1553 * suffix and add it to the list of suffixes maintained by the 1554 * Suff module. 1555 * 1556 * If the target was a .PATH, we add the source as a directory 1557 * to search on the search path. 1558 * 1559 * If it was .INCLUDES, the source is taken to be the suffix of 1560 * files which will be #included and whose search path should 1561 * be present in the .INCLUDES variable. 1562 * 1563 * If it was .LIBS, the source is taken to be the suffix of 1564 * files which are considered libraries and whose search path 1565 * should be present in the .LIBS variable. 1566 * 1567 * If it was .NULL, the source is the suffix to use when a file 1568 * has no valid suffix. 1569 * 1570 * If it was .OBJDIR, the source is a new definition for .OBJDIR, 1571 * and will cause make to do a new chdir to that path. 1572 */ 1573 while (*cp && !isspace ((unsigned char)*cp)) { 1574 cp++; 1575 } 1576 savec = *cp; 1577 *cp = '\0'; 1578 switch (specType) { 1579 case Suffixes: 1580 Suff_AddSuffix(line, &mainNode); 1581 break; 1582 case ExPath: 1583 Lst_ForEach(paths, ParseAddDir, line); 1584 break; 1585 case Includes: 1586 Suff_AddInclude(line); 1587 break; 1588 case Libs: 1589 Suff_AddLib(line); 1590 break; 1591 case Null: 1592 Suff_SetNull(line); 1593 break; 1594 case ExObjdir: 1595 Main_SetObjdir(line); 1596 break; 1597 default: 1598 break; 1599 } 1600 *cp = savec; 1601 if (savec != '\0') { 1602 cp++; 1603 } 1604 while (*cp && isspace ((unsigned char)*cp)) { 1605 cp++; 1606 } 1607 line = cp; 1608 } 1609 if (paths) { 1610 Lst_Destroy(paths, NULL); 1611 } 1612 if (specType == ExPath) 1613 Dir_SetPATH(); 1614 } else { 1615 while (*line) { 1616 /* 1617 * The targets take real sources, so we must beware of archive 1618 * specifications (i.e. things with left parentheses in them) 1619 * and handle them accordingly. 1620 */ 1621 for (; *cp && !isspace ((unsigned char)*cp); cp++) { 1622 if ((*cp == LPAREN) && (cp > line) && (cp[-1] != '$')) { 1623 /* 1624 * Only stop for a left parenthesis if it isn't at the 1625 * start of a word (that'll be for variable changes 1626 * later) and isn't preceded by a dollar sign (a dynamic 1627 * source). 1628 */ 1629 break; 1630 } 1631 } 1632 1633 if (*cp == LPAREN) { 1634 sources = Lst_Init(FALSE); 1635 if (Arch_ParseArchive(&line, sources, VAR_CMD) != SUCCESS) { 1636 Parse_Error(PARSE_FATAL, 1637 "Error in source archive spec \"%s\"", line); 1638 goto out; 1639 } 1640 1641 while (!Lst_IsEmpty (sources)) { 1642 gn = (GNode *)Lst_DeQueue(sources); 1643 ParseDoSrc(tOp, gn->name); 1644 } 1645 Lst_Destroy(sources, NULL); 1646 cp = line; 1647 } else { 1648 if (*cp) { 1649 *cp = '\0'; 1650 cp += 1; 1651 } 1652 1653 ParseDoSrc(tOp, line); 1654 } 1655 while (*cp && isspace ((unsigned char)*cp)) { 1656 cp++; 1657 } 1658 line = cp; 1659 } 1660 } 1661 1662 if (mainNode == NULL) { 1663 /* 1664 * If we have yet to decide on a main target to make, in the 1665 * absence of any user input, we want the first target on 1666 * the first dependency line that is actually a real target 1667 * (i.e. isn't a .USE or .EXEC rule) to be made. 1668 */ 1669 Lst_ForEach(targets, ParseFindMain, NULL); 1670 } 1671 1672 out: 1673 if (curTargs) 1674 Lst_Destroy(curTargs, NULL); 1675 } 1676 1677 /*- 1678 *--------------------------------------------------------------------- 1679 * Parse_IsVar -- 1680 * Return TRUE if the passed line is a variable assignment. A variable 1681 * assignment consists of a single word followed by optional whitespace 1682 * followed by either a += or an = operator. 1683 * This function is used both by the Parse_File function and main when 1684 * parsing the command-line arguments. 1685 * 1686 * Input: 1687 * line the line to check 1688 * 1689 * Results: 1690 * TRUE if it is. FALSE if it ain't 1691 * 1692 * Side Effects: 1693 * none 1694 *--------------------------------------------------------------------- 1695 */ 1696 Boolean 1697 Parse_IsVar(char *line) 1698 { 1699 Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1700 char ch; 1701 int level = 0; 1702 #define ISEQOPERATOR(c) \ 1703 (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!')) 1704 1705 /* 1706 * Skip to variable name 1707 */ 1708 for (;(*line == ' ') || (*line == '\t'); line++) 1709 continue; 1710 1711 /* Scan for one of the assignment operators outside a variable expansion */ 1712 while ((ch = *line++) != 0) { 1713 if (ch == '(' || ch == '{') { 1714 level++; 1715 continue; 1716 } 1717 if (ch == ')' || ch == '}') { 1718 level--; 1719 continue; 1720 } 1721 if (level != 0) 1722 continue; 1723 while (ch == ' ' || ch == '\t') { 1724 ch = *line++; 1725 wasSpace = TRUE; 1726 } 1727 if (ch == '=') 1728 return TRUE; 1729 if (*line == '=' && ISEQOPERATOR(ch)) 1730 return TRUE; 1731 if (wasSpace) 1732 return FALSE; 1733 } 1734 1735 return FALSE; 1736 } 1737 1738 /*- 1739 *--------------------------------------------------------------------- 1740 * Parse_DoVar -- 1741 * Take the variable assignment in the passed line and do it in the 1742 * global context. 1743 * 1744 * Note: There is a lexical ambiguity with assignment modifier characters 1745 * in variable names. This routine interprets the character before the = 1746 * as a modifier. Therefore, an assignment like 1747 * C++=/usr/bin/CC 1748 * is interpreted as "C+ +=" instead of "C++ =". 1749 * 1750 * Input: 1751 * line a line guaranteed to be a variable assignment. 1752 * This reduces error checks 1753 * ctxt Context in which to do the assignment 1754 * 1755 * Results: 1756 * none 1757 * 1758 * Side Effects: 1759 * the variable structure of the given variable name is altered in the 1760 * global context. 1761 *--------------------------------------------------------------------- 1762 */ 1763 void 1764 Parse_DoVar(char *line, GNode *ctxt) 1765 { 1766 char *cp; /* pointer into line */ 1767 enum { 1768 VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL 1769 } type; /* Type of assignment */ 1770 char *opc; /* ptr to operator character to 1771 * null-terminate the variable name */ 1772 Boolean freeCp = FALSE; /* TRUE if cp needs to be freed, 1773 * i.e. if any variable expansion was 1774 * performed */ 1775 int depth; 1776 1777 /* 1778 * Skip to variable name 1779 */ 1780 while ((*line == ' ') || (*line == '\t')) { 1781 line++; 1782 } 1783 1784 /* 1785 * Skip to operator character, nulling out whitespace as we go 1786 * XXX Rather than counting () and {} we should look for $ and 1787 * then expand the variable. 1788 */ 1789 for (depth = 0, cp = line + 1; depth != 0 || *cp != '='; cp++) { 1790 if (*cp == '(' || *cp == '{') { 1791 depth++; 1792 continue; 1793 } 1794 if (*cp == ')' || *cp == '}') { 1795 depth--; 1796 continue; 1797 } 1798 if (depth == 0 && isspace ((unsigned char)*cp)) { 1799 *cp = '\0'; 1800 } 1801 } 1802 opc = cp-1; /* operator is the previous character */ 1803 *cp++ = '\0'; /* nuke the = */ 1804 1805 /* 1806 * Check operator type 1807 */ 1808 switch (*opc) { 1809 case '+': 1810 type = VAR_APPEND; 1811 *opc = '\0'; 1812 break; 1813 1814 case '?': 1815 /* 1816 * If the variable already has a value, we don't do anything. 1817 */ 1818 *opc = '\0'; 1819 if (Var_Exists(line, ctxt)) { 1820 return; 1821 } else { 1822 type = VAR_NORMAL; 1823 } 1824 break; 1825 1826 case ':': 1827 type = VAR_SUBST; 1828 *opc = '\0'; 1829 break; 1830 1831 case '!': 1832 type = VAR_SHELL; 1833 *opc = '\0'; 1834 break; 1835 1836 default: 1837 #ifdef SUNSHCMD 1838 while (opc > line && *opc != ':') 1839 opc--; 1840 1841 if (strncmp(opc, ":sh", 3) == 0) { 1842 type = VAR_SHELL; 1843 *opc = '\0'; 1844 break; 1845 } 1846 #endif 1847 type = VAR_NORMAL; 1848 break; 1849 } 1850 1851 while (isspace ((unsigned char)*cp)) { 1852 cp++; 1853 } 1854 1855 if (type == VAR_APPEND) { 1856 Var_Append(line, cp, ctxt); 1857 } else if (type == VAR_SUBST) { 1858 /* 1859 * Allow variables in the old value to be undefined, but leave their 1860 * invocation alone -- this is done by forcing oldVars to be false. 1861 * XXX: This can cause recursive variables, but that's not hard to do, 1862 * and this allows someone to do something like 1863 * 1864 * CFLAGS = $(.INCLUDES) 1865 * CFLAGS := -I.. $(CFLAGS) 1866 * 1867 * And not get an error. 1868 */ 1869 Boolean oldOldVars = oldVars; 1870 1871 oldVars = FALSE; 1872 1873 /* 1874 * make sure that we set the variable the first time to nothing 1875 * so that it gets substituted! 1876 */ 1877 if (!Var_Exists(line, ctxt)) 1878 Var_Set(line, "", ctxt, 0); 1879 1880 cp = Var_Subst(NULL, cp, ctxt, FALSE); 1881 oldVars = oldOldVars; 1882 freeCp = TRUE; 1883 1884 Var_Set(line, cp, ctxt, 0); 1885 } else if (type == VAR_SHELL) { 1886 char *res; 1887 const char *error; 1888 1889 if (strchr(cp, '$') != NULL) { 1890 /* 1891 * There's a dollar sign in the command, so perform variable 1892 * expansion on the whole thing. The resulting string will need 1893 * freeing when we're done, so set freeCmd to TRUE. 1894 */ 1895 cp = Var_Subst(NULL, cp, VAR_CMD, TRUE); 1896 freeCp = TRUE; 1897 } 1898 1899 res = Cmd_Exec(cp, &error); 1900 Var_Set(line, res, ctxt, 0); 1901 free(res); 1902 1903 if (error) 1904 Parse_Error(PARSE_WARNING, error, cp); 1905 } else { 1906 /* 1907 * Normal assignment -- just do it. 1908 */ 1909 Var_Set(line, cp, ctxt, 0); 1910 } 1911 if (strcmp(line, MAKEOVERRIDES) == 0) 1912 Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */ 1913 else if (strcmp(line, ".CURDIR") == 0) { 1914 /* 1915 * Somone is being (too?) clever... 1916 * Let's pretend they know what they are doing and 1917 * re-initialize the 'cur' Path. 1918 */ 1919 Dir_InitCur(cp); 1920 Dir_SetPATH(); 1921 } else if (strcmp(line, MAKE_JOB_PREFIX) == 0) { 1922 Job_SetPrefix(); 1923 } else if (strcmp(line, MAKE_EXPORTED) == 0) { 1924 Var_Export(cp, 0); 1925 } 1926 if (freeCp) 1927 free(cp); 1928 } 1929 1930 1931 /*- 1932 * ParseAddCmd -- 1933 * Lst_ForEach function to add a command line to all targets 1934 * 1935 * Input: 1936 * gnp the node to which the command is to be added 1937 * cmd the command to add 1938 * 1939 * Results: 1940 * Always 0 1941 * 1942 * Side Effects: 1943 * A new element is added to the commands list of the node. 1944 */ 1945 static int 1946 ParseAddCmd(void *gnp, void *cmd) 1947 { 1948 GNode *gn = (GNode *)gnp; 1949 1950 /* Add to last (ie current) cohort for :: targets */ 1951 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (gn->cohorts)) 1952 gn = (GNode *)Lst_Datum(Lst_Last(gn->cohorts)); 1953 1954 /* if target already supplied, ignore commands */ 1955 if (!(gn->type & OP_HAS_COMMANDS)) { 1956 (void)Lst_AtEnd(gn->commands, cmd); 1957 ParseMark(gn); 1958 } else { 1959 #ifdef notyet 1960 /* XXX: We cannot do this until we fix the tree */ 1961 (void)Lst_AtEnd(gn->commands, cmd); 1962 Parse_Error(PARSE_WARNING, 1963 "overriding commands for target \"%s\"; " 1964 "previous commands defined at %s: %d ignored", 1965 gn->name, gn->fname, gn->lineno); 1966 #else 1967 Parse_Error(PARSE_WARNING, 1968 "duplicate script for target \"%s\" ignored", 1969 gn->name); 1970 ParseErrorInternal(gn->fname, gn->lineno, PARSE_WARNING, 1971 "using previous script for \"%s\" defined here", 1972 gn->name); 1973 #endif 1974 } 1975 return(0); 1976 } 1977 1978 /*- 1979 *----------------------------------------------------------------------- 1980 * ParseHasCommands -- 1981 * Callback procedure for Parse_File when destroying the list of 1982 * targets on the last dependency line. Marks a target as already 1983 * having commands if it does, to keep from having shell commands 1984 * on multiple dependency lines. 1985 * 1986 * Input: 1987 * gnp Node to examine 1988 * 1989 * Results: 1990 * None 1991 * 1992 * Side Effects: 1993 * OP_HAS_COMMANDS may be set for the target. 1994 * 1995 *----------------------------------------------------------------------- 1996 */ 1997 static void 1998 ParseHasCommands(void *gnp) 1999 { 2000 GNode *gn = (GNode *)gnp; 2001 if (!Lst_IsEmpty(gn->commands)) { 2002 gn->type |= OP_HAS_COMMANDS; 2003 } 2004 } 2005 2006 /*- 2007 *----------------------------------------------------------------------- 2008 * Parse_AddIncludeDir -- 2009 * Add a directory to the path searched for included makefiles 2010 * bracketed by double-quotes. Used by functions in main.c 2011 * 2012 * Input: 2013 * dir The name of the directory to add 2014 * 2015 * Results: 2016 * None. 2017 * 2018 * Side Effects: 2019 * The directory is appended to the list. 2020 * 2021 *----------------------------------------------------------------------- 2022 */ 2023 void 2024 Parse_AddIncludeDir(char *dir) 2025 { 2026 (void)Dir_AddDir(parseIncPath, dir); 2027 } 2028 2029 /*- 2030 *--------------------------------------------------------------------- 2031 * ParseDoInclude -- 2032 * Push to another file. 2033 * 2034 * The input is the line minus the `.'. A file spec is a string 2035 * enclosed in <> or "". The former is looked for only in sysIncPath. 2036 * The latter in . and the directories specified by -I command line 2037 * options 2038 * 2039 * Results: 2040 * None 2041 * 2042 * Side Effects: 2043 * A structure is added to the includes Lst and readProc, lineno, 2044 * fname and curFILE are altered for the new file 2045 *--------------------------------------------------------------------- 2046 */ 2047 2048 static void 2049 Parse_include_file(char *file, Boolean isSystem, int silent) 2050 { 2051 struct loadedfile *lf; 2052 char *fullname; /* full pathname of file */ 2053 char *newName; 2054 char *prefEnd, *incdir; 2055 int fd; 2056 int i; 2057 2058 /* 2059 * Now we know the file's name and its search path, we attempt to 2060 * find the durn thing. A return of NULL indicates the file don't 2061 * exist. 2062 */ 2063 fullname = file[0] == '/' ? bmake_strdup(file) : NULL; 2064 2065 if (fullname == NULL && !isSystem) { 2066 /* 2067 * Include files contained in double-quotes are first searched for 2068 * relative to the including file's location. We don't want to 2069 * cd there, of course, so we just tack on the old file's 2070 * leading path components and call Dir_FindFile to see if 2071 * we can locate the beast. 2072 */ 2073 2074 incdir = bmake_strdup(curFile->fname); 2075 prefEnd = strrchr(incdir, '/'); 2076 if (prefEnd != NULL) { 2077 *prefEnd = '\0'; 2078 /* Now do lexical processing of leading "../" on the filename */ 2079 for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) { 2080 prefEnd = strrchr(incdir + 1, '/'); 2081 if (prefEnd == NULL || strcmp(prefEnd, "/..") == 0) 2082 break; 2083 *prefEnd = '\0'; 2084 } 2085 newName = str_concat(incdir, file + i, STR_ADDSLASH); 2086 fullname = Dir_FindFile(newName, parseIncPath); 2087 if (fullname == NULL) 2088 fullname = Dir_FindFile(newName, dirSearchPath); 2089 free(newName); 2090 } 2091 free(incdir); 2092 2093 if (fullname == NULL) { 2094 /* 2095 * Makefile wasn't found in same directory as included makefile. 2096 * Search for it first on the -I search path, 2097 * then on the .PATH search path, if not found in a -I directory. 2098 * If we have a suffix specific path we should use that. 2099 */ 2100 char *suff; 2101 Lst suffPath = NULL; 2102 2103 if ((suff = strrchr(file, '.'))) { 2104 suffPath = Suff_GetPath(suff); 2105 if (suffPath != NULL) { 2106 fullname = Dir_FindFile(file, suffPath); 2107 } 2108 } 2109 if (fullname == NULL) { 2110 fullname = Dir_FindFile(file, parseIncPath); 2111 if (fullname == NULL) { 2112 fullname = Dir_FindFile(file, dirSearchPath); 2113 } 2114 } 2115 } 2116 } 2117 2118 /* Looking for a system file or file still not found */ 2119 if (fullname == NULL) { 2120 /* 2121 * Look for it on the system path 2122 */ 2123 fullname = Dir_FindFile(file, 2124 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath); 2125 } 2126 2127 if (fullname == NULL) { 2128 if (!silent) 2129 Parse_Error(PARSE_FATAL, "Could not find %s", file); 2130 return; 2131 } 2132 2133 /* Actually open the file... */ 2134 fd = open(fullname, O_RDONLY); 2135 if (fd == -1) { 2136 if (!silent) 2137 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 2138 free(fullname); 2139 return; 2140 } 2141 2142 /* load it */ 2143 lf = loadfile(fullname, fd); 2144 2145 /* Start reading from this file next */ 2146 Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf); 2147 curFile->lf = lf; 2148 } 2149 2150 static void 2151 ParseDoInclude(char *line) 2152 { 2153 char endc; /* the character which ends the file spec */ 2154 char *cp; /* current position in file spec */ 2155 int silent = (*line != 'i') ? 1 : 0; 2156 char *file = &line[7 + silent]; 2157 2158 /* Skip to delimiter character so we know where to look */ 2159 while (*file == ' ' || *file == '\t') 2160 file++; 2161 2162 if (*file != '"' && *file != '<') { 2163 Parse_Error(PARSE_FATAL, 2164 ".include filename must be delimited by '\"' or '<'"); 2165 return; 2166 } 2167 2168 /* 2169 * Set the search path on which to find the include file based on the 2170 * characters which bracket its name. Angle-brackets imply it's 2171 * a system Makefile while double-quotes imply it's a user makefile 2172 */ 2173 if (*file == '<') { 2174 endc = '>'; 2175 } else { 2176 endc = '"'; 2177 } 2178 2179 /* Skip to matching delimiter */ 2180 for (cp = ++file; *cp && *cp != endc; cp++) 2181 continue; 2182 2183 if (*cp != endc) { 2184 Parse_Error(PARSE_FATAL, 2185 "Unclosed %cinclude filename. '%c' expected", 2186 '.', endc); 2187 return; 2188 } 2189 *cp = '\0'; 2190 2191 /* 2192 * Substitute for any variables in the file name before trying to 2193 * find the thing. 2194 */ 2195 file = Var_Subst(NULL, file, VAR_CMD, FALSE); 2196 2197 Parse_include_file(file, endc == '>', silent); 2198 free(file); 2199 } 2200 2201 2202 /*- 2203 *--------------------------------------------------------------------- 2204 * ParseSetParseFile -- 2205 * Set the .PARSEDIR and .PARSEFILE variables to the dirname and 2206 * basename of the given filename 2207 * 2208 * Results: 2209 * None 2210 * 2211 * Side Effects: 2212 * The .PARSEDIR and .PARSEFILE variables are overwritten by the 2213 * dirname and basename of the given filename. 2214 *--------------------------------------------------------------------- 2215 */ 2216 static void 2217 ParseSetParseFile(const char *filename) 2218 { 2219 char *slash, *dirname; 2220 const char *pd, *pf; 2221 int len; 2222 2223 slash = strrchr(filename, '/'); 2224 if (slash == NULL) { 2225 Var_Set(".PARSEDIR", pd = curdir, VAR_GLOBAL, 0); 2226 Var_Set(".PARSEFILE", pf = filename, VAR_GLOBAL, 0); 2227 dirname= NULL; 2228 } else { 2229 len = slash - filename; 2230 dirname = bmake_malloc(len + 1); 2231 memcpy(dirname, filename, len); 2232 dirname[len] = '\0'; 2233 Var_Set(".PARSEDIR", pd = dirname, VAR_GLOBAL, 0); 2234 Var_Set(".PARSEFILE", pf = slash + 1, VAR_GLOBAL, 0); 2235 } 2236 if (DEBUG(PARSE)) 2237 fprintf(debug_file, "ParseSetParseFile: ${.PARSEDIR} = `%s' " 2238 "${.PARSEFILE} = `%s'\n", pd, pf); 2239 free(dirname); 2240 } 2241 2242 /* 2243 * Track the makefiles we read - so makefiles can 2244 * set dependencies on them. 2245 * Avoid adding anything more than once. 2246 */ 2247 2248 static void 2249 ParseTrackInput(const char *name) 2250 { 2251 char *old; 2252 char *fp = NULL; 2253 size_t name_len = strlen(name); 2254 2255 old = Var_Value(MAKE_MAKEFILES, VAR_GLOBAL, &fp); 2256 if (old) { 2257 /* does it contain name? */ 2258 for (; old != NULL; old = strchr(old, ' ')) { 2259 if (*old == ' ') 2260 old++; 2261 if (memcmp(old, name, name_len) == 0 2262 && (old[name_len] == 0 || old[name_len] == ' ')) 2263 goto cleanup; 2264 } 2265 } 2266 Var_Append (MAKE_MAKEFILES, name, VAR_GLOBAL); 2267 cleanup: 2268 if (fp) { 2269 free(fp); 2270 } 2271 } 2272 2273 2274 /*- 2275 *--------------------------------------------------------------------- 2276 * Parse_setInput -- 2277 * Start Parsing from the given source 2278 * 2279 * Results: 2280 * None 2281 * 2282 * Side Effects: 2283 * A structure is added to the includes Lst and readProc, lineno, 2284 * fname and curFile are altered for the new file 2285 *--------------------------------------------------------------------- 2286 */ 2287 void 2288 Parse_SetInput(const char *name, int line, int fd, 2289 char *(*nextbuf)(void *, size_t *), void *arg) 2290 { 2291 char *buf; 2292 size_t len; 2293 2294 if (name == NULL) 2295 name = curFile->fname; 2296 else 2297 ParseTrackInput(name); 2298 2299 if (DEBUG(PARSE)) 2300 fprintf(debug_file, "Parse_SetInput: file %s, line %d, fd %d, nextbuf %p, arg %p\n", 2301 name, line, fd, nextbuf, arg); 2302 2303 if (fd == -1 && nextbuf == NULL) 2304 /* sanity */ 2305 return; 2306 2307 if (curFile != NULL) 2308 /* Save exiting file info */ 2309 Lst_AtFront(includes, curFile); 2310 2311 /* Allocate and fill in new structure */ 2312 curFile = bmake_malloc(sizeof *curFile); 2313 2314 /* 2315 * Once the previous state has been saved, we can get down to reading 2316 * the new file. We set up the name of the file to be the absolute 2317 * name of the include file so error messages refer to the right 2318 * place. 2319 */ 2320 curFile->fname = name; 2321 curFile->lineno = line; 2322 curFile->first_lineno = line; 2323 curFile->nextbuf = nextbuf; 2324 curFile->nextbuf_arg = arg; 2325 curFile->lf = NULL; 2326 2327 assert(nextbuf != NULL); 2328 2329 /* Get first block of input data */ 2330 buf = curFile->nextbuf(curFile->nextbuf_arg, &len); 2331 if (buf == NULL) { 2332 /* Was all a waste of time ... */ 2333 free(curFile); 2334 return; 2335 } 2336 curFile->P_str = buf; 2337 curFile->P_ptr = buf; 2338 curFile->P_end = buf+len; 2339 2340 curFile->cond_depth = Cond_save_depth(); 2341 ParseSetParseFile(name); 2342 } 2343 2344 #ifdef SYSVINCLUDE 2345 /*- 2346 *--------------------------------------------------------------------- 2347 * ParseTraditionalInclude -- 2348 * Push to another file. 2349 * 2350 * The input is the current line. The file name(s) are 2351 * following the "include". 2352 * 2353 * Results: 2354 * None 2355 * 2356 * Side Effects: 2357 * A structure is added to the includes Lst and readProc, lineno, 2358 * fname and curFILE are altered for the new file 2359 *--------------------------------------------------------------------- 2360 */ 2361 static void 2362 ParseTraditionalInclude(char *line) 2363 { 2364 char *cp; /* current position in file spec */ 2365 int done = 0; 2366 int silent = (line[0] != 'i') ? 1 : 0; 2367 char *file = &line[silent + 7]; 2368 char *all_files; 2369 2370 if (DEBUG(PARSE)) { 2371 fprintf(debug_file, "ParseTraditionalInclude: %s\n", file); 2372 } 2373 2374 /* 2375 * Skip over whitespace 2376 */ 2377 while (isspace((unsigned char)*file)) 2378 file++; 2379 2380 /* 2381 * Substitute for any variables in the file name before trying to 2382 * find the thing. 2383 */ 2384 all_files = Var_Subst(NULL, file, VAR_CMD, FALSE); 2385 2386 if (*file == '\0') { 2387 Parse_Error(PARSE_FATAL, 2388 "Filename missing from \"include\""); 2389 return; 2390 } 2391 2392 for (file = all_files; !done; file = cp + 1) { 2393 /* Skip to end of line or next whitespace */ 2394 for (cp = file; *cp && !isspace((unsigned char) *cp); cp++) 2395 continue; 2396 2397 if (*cp) 2398 *cp = '\0'; 2399 else 2400 done = 1; 2401 2402 Parse_include_file(file, FALSE, silent); 2403 } 2404 free(all_files); 2405 } 2406 #endif 2407 2408 #ifdef GMAKEEXPORT 2409 /*- 2410 *--------------------------------------------------------------------- 2411 * ParseGmakeExport -- 2412 * Parse export <variable>=<value> 2413 * 2414 * And set the environment with it. 2415 * 2416 * Results: 2417 * None 2418 * 2419 * Side Effects: 2420 * None 2421 *--------------------------------------------------------------------- 2422 */ 2423 static void 2424 ParseGmakeExport(char *line) 2425 { 2426 char *variable = &line[6]; 2427 char *value; 2428 2429 if (DEBUG(PARSE)) { 2430 fprintf(debug_file, "ParseGmakeExport: %s\n", variable); 2431 } 2432 2433 /* 2434 * Skip over whitespace 2435 */ 2436 while (isspace((unsigned char)*variable)) 2437 variable++; 2438 2439 for (value = variable; *value && *value != '='; value++) 2440 continue; 2441 2442 if (*value != '=') { 2443 Parse_Error(PARSE_FATAL, 2444 "Variable/Value missing from \"export\""); 2445 return; 2446 } 2447 2448 /* 2449 * Expand the value before putting it in the environment. 2450 */ 2451 value = Var_Subst(NULL, value, VAR_CMD, FALSE); 2452 setenv(variable, value, 1); 2453 } 2454 #endif 2455 2456 /*- 2457 *--------------------------------------------------------------------- 2458 * ParseEOF -- 2459 * Called when EOF is reached in the current file. If we were reading 2460 * an include file, the includes stack is popped and things set up 2461 * to go back to reading the previous file at the previous location. 2462 * 2463 * Results: 2464 * CONTINUE if there's more to do. DONE if not. 2465 * 2466 * Side Effects: 2467 * The old curFILE, is closed. The includes list is shortened. 2468 * lineno, curFILE, and fname are changed if CONTINUE is returned. 2469 *--------------------------------------------------------------------- 2470 */ 2471 static int 2472 ParseEOF(void) 2473 { 2474 char *ptr; 2475 size_t len; 2476 2477 assert(curFile->nextbuf != NULL); 2478 2479 /* get next input buffer, if any */ 2480 ptr = curFile->nextbuf(curFile->nextbuf_arg, &len); 2481 curFile->P_ptr = ptr; 2482 curFile->P_str = ptr; 2483 curFile->P_end = ptr + len; 2484 curFile->lineno = curFile->first_lineno; 2485 if (ptr != NULL) { 2486 /* Iterate again */ 2487 return CONTINUE; 2488 } 2489 2490 /* Ensure the makefile (or loop) didn't have mismatched conditionals */ 2491 Cond_restore_depth(curFile->cond_depth); 2492 2493 if (curFile->lf != NULL) { 2494 loadedfile_destroy(curFile->lf); 2495 curFile->lf = NULL; 2496 } 2497 2498 /* Dispose of curFile info */ 2499 /* Leak curFile->fname because all the gnodes have pointers to it */ 2500 free(curFile->P_str); 2501 free(curFile); 2502 2503 curFile = Lst_DeQueue(includes); 2504 2505 if (curFile == NULL) { 2506 /* We've run out of input */ 2507 Var_Delete(".PARSEDIR", VAR_GLOBAL); 2508 Var_Delete(".PARSEFILE", VAR_GLOBAL); 2509 return DONE; 2510 } 2511 2512 if (DEBUG(PARSE)) 2513 fprintf(debug_file, "ParseEOF: returning to file %s, line %d\n", 2514 curFile->fname, curFile->lineno); 2515 2516 /* Restore the PARSEDIR/PARSEFILE variables */ 2517 ParseSetParseFile(curFile->fname); 2518 return (CONTINUE); 2519 } 2520 2521 #define PARSE_RAW 1 2522 #define PARSE_SKIP 2 2523 2524 static char * 2525 ParseGetLine(int flags, int *length) 2526 { 2527 IFile *cf = curFile; 2528 char *ptr; 2529 char ch; 2530 char *line; 2531 char *line_end; 2532 char *escaped; 2533 char *comment; 2534 char *tp; 2535 2536 /* Loop through blank lines and comment lines */ 2537 for (;;) { 2538 cf->lineno++; 2539 line = cf->P_ptr; 2540 ptr = line; 2541 line_end = line; 2542 escaped = NULL; 2543 comment = NULL; 2544 for (;;) { 2545 if (cf->P_end != NULL && ptr == cf->P_end) { 2546 /* end of buffer */ 2547 ch = 0; 2548 break; 2549 } 2550 ch = *ptr; 2551 if (ch == 0 || (ch == '\\' && ptr[1] == 0)) { 2552 if (cf->P_end == NULL) 2553 /* End of string (aka for loop) data */ 2554 break; 2555 if (cf->nextbuf != NULL) { 2556 /* 2557 * End of this buffer; return EOF and outer logic 2558 * will get the next one. (eww) 2559 */ 2560 break; 2561 } 2562 Parse_Error(PARSE_FATAL, "Zero byte read from file"); 2563 return NULL; 2564 } 2565 2566 if (ch == '\\') { 2567 /* Don't treat next character as special, remember first one */ 2568 if (escaped == NULL) 2569 escaped = ptr; 2570 if (ptr[1] == '\n') 2571 cf->lineno++; 2572 ptr += 2; 2573 line_end = ptr; 2574 continue; 2575 } 2576 if (ch == '#' && comment == NULL) { 2577 /* Remember first '#' for comment stripping */ 2578 /* Unless previous char was '[', as in modifier :[#] */ 2579 if (!(ptr > line && ptr[-1] == '[')) 2580 comment = line_end; 2581 } 2582 ptr++; 2583 if (ch == '\n') 2584 break; 2585 if (!isspace((unsigned char)ch)) 2586 /* We are not interested in trailing whitespace */ 2587 line_end = ptr; 2588 } 2589 2590 /* Save next 'to be processed' location */ 2591 cf->P_ptr = ptr; 2592 2593 /* Check we have a non-comment, non-blank line */ 2594 if (line_end == line || comment == line) { 2595 if (ch == 0) 2596 /* At end of file */ 2597 return NULL; 2598 /* Parse another line */ 2599 continue; 2600 } 2601 2602 /* We now have a line of data */ 2603 *line_end = 0; 2604 2605 if (flags & PARSE_RAW) { 2606 /* Leave '\' (etc) in line buffer (eg 'for' lines) */ 2607 *length = line_end - line; 2608 return line; 2609 } 2610 2611 if (flags & PARSE_SKIP) { 2612 /* Completely ignore non-directives */ 2613 if (line[0] != '.') 2614 continue; 2615 /* We could do more of the .else/.elif/.endif checks here */ 2616 } 2617 break; 2618 } 2619 2620 /* Brutally ignore anything after a non-escaped '#' in non-commands */ 2621 if (comment != NULL && line[0] != '\t') { 2622 line_end = comment; 2623 *line_end = 0; 2624 } 2625 2626 /* If we didn't see a '\\' then the in-situ data is fine */ 2627 if (escaped == NULL) { 2628 *length = line_end - line; 2629 return line; 2630 } 2631 2632 /* Remove escapes from '\n' and '#' */ 2633 tp = ptr = escaped; 2634 escaped = line; 2635 for (; ; *tp++ = ch) { 2636 ch = *ptr++; 2637 if (ch != '\\') { 2638 if (ch == 0) 2639 break; 2640 continue; 2641 } 2642 2643 ch = *ptr++; 2644 if (ch == 0) { 2645 /* Delete '\\' at end of buffer */ 2646 tp--; 2647 break; 2648 } 2649 2650 if (ch == '#' && line[0] != '\t') 2651 /* Delete '\\' from before '#' on non-command lines */ 2652 continue; 2653 2654 if (ch != '\n') { 2655 /* Leave '\\' in buffer for later */ 2656 *tp++ = '\\'; 2657 /* Make sure we don't delete an escaped ' ' from the line end */ 2658 escaped = tp + 1; 2659 continue; 2660 } 2661 2662 /* Escaped '\n' replace following whitespace with a single ' ' */ 2663 while (ptr[0] == ' ' || ptr[0] == '\t') 2664 ptr++; 2665 ch = ' '; 2666 } 2667 2668 /* Delete any trailing spaces - eg from empty continuations */ 2669 while (tp > escaped && isspace((unsigned char)tp[-1])) 2670 tp--; 2671 2672 *tp = 0; 2673 *length = tp - line; 2674 return line; 2675 } 2676 2677 /*- 2678 *--------------------------------------------------------------------- 2679 * ParseReadLine -- 2680 * Read an entire line from the input file. Called only by Parse_File. 2681 * 2682 * Results: 2683 * A line w/o its newline 2684 * 2685 * Side Effects: 2686 * Only those associated with reading a character 2687 *--------------------------------------------------------------------- 2688 */ 2689 static char * 2690 ParseReadLine(void) 2691 { 2692 char *line; /* Result */ 2693 int lineLength; /* Length of result */ 2694 int lineno; /* Saved line # */ 2695 int rval; 2696 2697 for (;;) { 2698 line = ParseGetLine(0, &lineLength); 2699 if (line == NULL) 2700 return NULL; 2701 2702 if (line[0] != '.') 2703 return line; 2704 2705 /* 2706 * The line might be a conditional. Ask the conditional module 2707 * about it and act accordingly 2708 */ 2709 switch (Cond_Eval(line)) { 2710 case COND_SKIP: 2711 /* Skip to next conditional that evaluates to COND_PARSE. */ 2712 do { 2713 line = ParseGetLine(PARSE_SKIP, &lineLength); 2714 } while (line && Cond_Eval(line) != COND_PARSE); 2715 if (line == NULL) 2716 break; 2717 continue; 2718 case COND_PARSE: 2719 continue; 2720 case COND_INVALID: /* Not a conditional line */ 2721 /* Check for .for loops */ 2722 rval = For_Eval(line); 2723 if (rval == 0) 2724 /* Not a .for line */ 2725 break; 2726 if (rval < 0) 2727 /* Syntax error - error printed, ignore line */ 2728 continue; 2729 /* Start of a .for loop */ 2730 lineno = curFile->lineno; 2731 /* Accumulate loop lines until matching .endfor */ 2732 do { 2733 line = ParseGetLine(PARSE_RAW, &lineLength); 2734 if (line == NULL) { 2735 Parse_Error(PARSE_FATAL, 2736 "Unexpected end of file in for loop."); 2737 break; 2738 } 2739 } while (For_Accum(line)); 2740 /* Stash each iteration as a new 'input file' */ 2741 For_Run(lineno); 2742 /* Read next line from for-loop buffer */ 2743 continue; 2744 } 2745 return (line); 2746 } 2747 } 2748 2749 /*- 2750 *----------------------------------------------------------------------- 2751 * ParseFinishLine -- 2752 * Handle the end of a dependency group. 2753 * 2754 * Results: 2755 * Nothing. 2756 * 2757 * Side Effects: 2758 * inLine set FALSE. 'targets' list destroyed. 2759 * 2760 *----------------------------------------------------------------------- 2761 */ 2762 static void 2763 ParseFinishLine(void) 2764 { 2765 if (inLine) { 2766 Lst_ForEach(targets, Suff_EndTransform, NULL); 2767 Lst_Destroy(targets, ParseHasCommands); 2768 targets = NULL; 2769 inLine = FALSE; 2770 } 2771 } 2772 2773 2774 /*- 2775 *--------------------------------------------------------------------- 2776 * Parse_File -- 2777 * Parse a file into its component parts, incorporating it into the 2778 * current dependency graph. This is the main function and controls 2779 * almost every other function in this module 2780 * 2781 * Input: 2782 * name the name of the file being read 2783 * fd Open file to makefile to parse 2784 * 2785 * Results: 2786 * None 2787 * 2788 * Side Effects: 2789 * closes fd. 2790 * Loads. Nodes are added to the list of all targets, nodes and links 2791 * are added to the dependency graph. etc. etc. etc. 2792 *--------------------------------------------------------------------- 2793 */ 2794 void 2795 Parse_File(const char *name, int fd) 2796 { 2797 char *cp; /* pointer into the line */ 2798 char *line; /* the line we're working on */ 2799 struct loadedfile *lf; 2800 2801 lf = loadfile(name, fd); 2802 2803 inLine = FALSE; 2804 fatals = 0; 2805 2806 if (name == NULL) { 2807 name = "(stdin)"; 2808 } 2809 2810 Parse_SetInput(name, 0, -1, loadedfile_nextbuf, lf); 2811 curFile->lf = lf; 2812 2813 do { 2814 for (; (line = ParseReadLine()) != NULL; ) { 2815 if (DEBUG(PARSE)) 2816 fprintf(debug_file, "ParseReadLine (%d): '%s'\n", 2817 curFile->lineno, line); 2818 if (*line == '.') { 2819 /* 2820 * Lines that begin with the special character may be 2821 * include or undef directives. 2822 * On the other hand they can be suffix rules (.c.o: ...) 2823 * or just dependencies for filenames that start '.'. 2824 */ 2825 for (cp = line + 1; isspace((unsigned char)*cp); cp++) { 2826 continue; 2827 } 2828 if (strncmp(cp, "include", 7) == 0 || 2829 ((cp[0] == 's' || cp[0] == '-') && 2830 strncmp(&cp[1], "include", 7) == 0)) { 2831 ParseDoInclude(cp); 2832 continue; 2833 } 2834 if (strncmp(cp, "undef", 5) == 0) { 2835 char *cp2; 2836 for (cp += 5; isspace((unsigned char) *cp); cp++) 2837 continue; 2838 for (cp2 = cp; !isspace((unsigned char) *cp2) && 2839 (*cp2 != '\0'); cp2++) 2840 continue; 2841 *cp2 = '\0'; 2842 Var_Delete(cp, VAR_GLOBAL); 2843 continue; 2844 } else if (strncmp(cp, "export", 6) == 0) { 2845 for (cp += 6; isspace((unsigned char) *cp); cp++) 2846 continue; 2847 Var_Export(cp, 1); 2848 continue; 2849 } else if (strncmp(cp, "unexport", 8) == 0) { 2850 Var_UnExport(cp); 2851 continue; 2852 } else if (strncmp(cp, "info", 4) == 0 || 2853 strncmp(cp, "error", 5) == 0 || 2854 strncmp(cp, "warning", 7) == 0) { 2855 if (ParseMessage(cp)) 2856 continue; 2857 } 2858 } 2859 2860 if (*line == '\t') { 2861 /* 2862 * If a line starts with a tab, it can only hope to be 2863 * a creation command. 2864 */ 2865 cp = line + 1; 2866 shellCommand: 2867 for (; isspace ((unsigned char)*cp); cp++) { 2868 continue; 2869 } 2870 if (*cp) { 2871 if (!inLine) 2872 Parse_Error(PARSE_FATAL, 2873 "Unassociated shell command \"%s\"", 2874 cp); 2875 /* 2876 * So long as it's not a blank line and we're actually 2877 * in a dependency spec, add the command to the list of 2878 * commands of all targets in the dependency spec 2879 */ 2880 if (targets) { 2881 cp = bmake_strdup(cp); 2882 Lst_ForEach(targets, ParseAddCmd, cp); 2883 #ifdef CLEANUP 2884 Lst_AtEnd(targCmds, cp); 2885 #endif 2886 } 2887 } 2888 continue; 2889 } 2890 2891 #ifdef SYSVINCLUDE 2892 if (((strncmp(line, "include", 7) == 0 && 2893 isspace((unsigned char) line[7])) || 2894 ((line[0] == 's' || line[0] == '-') && 2895 strncmp(&line[1], "include", 7) == 0 && 2896 isspace((unsigned char) line[8]))) && 2897 strchr(line, ':') == NULL) { 2898 /* 2899 * It's an S3/S5-style "include". 2900 */ 2901 ParseTraditionalInclude(line); 2902 continue; 2903 } 2904 #endif 2905 #ifdef GMAKEEXPORT 2906 if (strncmp(line, "export", 6) == 0 && 2907 isspace((unsigned char) line[6]) && 2908 strchr(line, ':') == NULL) { 2909 /* 2910 * It's a Gmake "export". 2911 */ 2912 ParseGmakeExport(line); 2913 continue; 2914 } 2915 #endif 2916 if (Parse_IsVar(line)) { 2917 ParseFinishLine(); 2918 Parse_DoVar(line, VAR_GLOBAL); 2919 continue; 2920 } 2921 2922 #ifndef POSIX 2923 /* 2924 * To make life easier on novices, if the line is indented we 2925 * first make sure the line has a dependency operator in it. 2926 * If it doesn't have an operator and we're in a dependency 2927 * line's script, we assume it's actually a shell command 2928 * and add it to the current list of targets. 2929 */ 2930 cp = line; 2931 if (isspace((unsigned char) line[0])) { 2932 while ((*cp != '\0') && isspace((unsigned char) *cp)) 2933 cp++; 2934 while (*cp && (ParseIsEscaped(line, cp) || 2935 (*cp != ':') && (*cp != '!'))) { 2936 cp++; 2937 } 2938 if (*cp == '\0') { 2939 if (inLine) { 2940 Parse_Error(PARSE_WARNING, 2941 "Shell command needs a leading tab"); 2942 goto shellCommand; 2943 } 2944 } 2945 } 2946 #endif 2947 ParseFinishLine(); 2948 2949 /* 2950 * For some reason - probably to make the parser impossible - 2951 * a ';' can be used to separate commands from dependencies. 2952 * Attempt to avoid ';' inside substitution patterns. 2953 */ 2954 { 2955 int level = 0; 2956 2957 for (cp = line; *cp != 0; cp++) { 2958 if (*cp == '\\' && cp[1] != 0) { 2959 cp++; 2960 continue; 2961 } 2962 if (*cp == '$' && 2963 (cp[1] == '(' || cp[1] == '{')) { 2964 level++; 2965 continue; 2966 } 2967 if (level > 0) { 2968 if (*cp == ')' || *cp == '}') { 2969 level--; 2970 continue; 2971 } 2972 } else if (*cp == ';') { 2973 break; 2974 } 2975 } 2976 } 2977 if (*cp != 0) 2978 /* Terminate the dependency list at the ';' */ 2979 *cp++ = 0; 2980 else 2981 cp = NULL; 2982 2983 /* 2984 * We now know it's a dependency line so it needs to have all 2985 * variables expanded before being parsed. Tell the variable 2986 * module to complain if some variable is undefined... 2987 */ 2988 line = Var_Subst(NULL, line, VAR_CMD, TRUE); 2989 2990 /* 2991 * Need a non-circular list for the target nodes 2992 */ 2993 if (targets) 2994 Lst_Destroy(targets, NULL); 2995 2996 targets = Lst_Init(FALSE); 2997 inLine = TRUE; 2998 2999 ParseDoDependency(line); 3000 free(line); 3001 3002 /* If there were commands after a ';', add them now */ 3003 if (cp != NULL) { 3004 goto shellCommand; 3005 } 3006 } 3007 /* 3008 * Reached EOF, but it may be just EOF of an include file... 3009 */ 3010 } while (ParseEOF() == CONTINUE); 3011 3012 if (fatals) { 3013 (void)fflush(stdout); 3014 (void)fprintf(stderr, 3015 "%s: Fatal errors encountered -- cannot continue", 3016 progname); 3017 PrintOnError(NULL, NULL); 3018 exit(1); 3019 } 3020 } 3021 3022 /*- 3023 *--------------------------------------------------------------------- 3024 * Parse_Init -- 3025 * initialize the parsing module 3026 * 3027 * Results: 3028 * none 3029 * 3030 * Side Effects: 3031 * the parseIncPath list is initialized... 3032 *--------------------------------------------------------------------- 3033 */ 3034 void 3035 Parse_Init(void) 3036 { 3037 mainNode = NULL; 3038 parseIncPath = Lst_Init(FALSE); 3039 sysIncPath = Lst_Init(FALSE); 3040 defIncPath = Lst_Init(FALSE); 3041 includes = Lst_Init(FALSE); 3042 #ifdef CLEANUP 3043 targCmds = Lst_Init(FALSE); 3044 #endif 3045 } 3046 3047 void 3048 Parse_End(void) 3049 { 3050 #ifdef CLEANUP 3051 Lst_Destroy(targCmds, (FreeProc *)free); 3052 if (targets) 3053 Lst_Destroy(targets, NULL); 3054 Lst_Destroy(defIncPath, Dir_Destroy); 3055 Lst_Destroy(sysIncPath, Dir_Destroy); 3056 Lst_Destroy(parseIncPath, Dir_Destroy); 3057 Lst_Destroy(includes, NULL); /* Should be empty now */ 3058 #endif 3059 } 3060 3061 3062 /*- 3063 *----------------------------------------------------------------------- 3064 * Parse_MainName -- 3065 * Return a Lst of the main target to create for main()'s sake. If 3066 * no such target exists, we Punt with an obnoxious error message. 3067 * 3068 * Results: 3069 * A Lst of the single node to create. 3070 * 3071 * Side Effects: 3072 * None. 3073 * 3074 *----------------------------------------------------------------------- 3075 */ 3076 Lst 3077 Parse_MainName(void) 3078 { 3079 Lst mainList; /* result list */ 3080 3081 mainList = Lst_Init(FALSE); 3082 3083 if (mainNode == NULL) { 3084 Punt("no target to make."); 3085 /*NOTREACHED*/ 3086 } else if (mainNode->type & OP_DOUBLEDEP) { 3087 (void)Lst_AtEnd(mainList, mainNode); 3088 Lst_Concat(mainList, mainNode->cohorts, LST_CONCNEW); 3089 } 3090 else 3091 (void)Lst_AtEnd(mainList, mainNode); 3092 Var_Append(".TARGETS", mainNode->name, VAR_GLOBAL); 3093 return (mainList); 3094 } 3095 3096 /*- 3097 *----------------------------------------------------------------------- 3098 * ParseMark -- 3099 * Add the filename and lineno to the GNode so that we remember 3100 * where it was first defined. 3101 * 3102 * Side Effects: 3103 * None. 3104 * 3105 *----------------------------------------------------------------------- 3106 */ 3107 static void 3108 ParseMark(GNode *gn) 3109 { 3110 gn->fname = curFile->fname; 3111 gn->lineno = curFile->lineno; 3112 } 3113