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