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