1 /* 2 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 3 * Copyright (c) 1988, 1989 by Adam de Boor 4 * Copyright (c) 1989 by Berkeley Softworks 5 * 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #ifndef lint 40 static char sccsid[] = "@(#)parse.c 5.18 (Berkeley) 2/19/91"; 41 #endif /* not lint */ 42 43 /*- 44 * parse.c -- 45 * Functions to parse a makefile. 46 * 47 * One function, Parse_Init, must be called before any functions 48 * in this module are used. After that, the function Parse_File is the 49 * main entry point and controls most of the other functions in this 50 * module. 51 * 52 * Most important structures are kept in Lsts. Directories for 53 * the #include "..." function are kept in the 'parseIncPath' Lst, while 54 * those for the #include <...> are kept in the 'sysIncPath' Lst. The 55 * targets currently being defined are kept in the 'targets' Lst. 56 * 57 * The variables 'fname' and 'lineno' are used to track the name 58 * of the current file and the line number in that file so that error 59 * messages can be more meaningful. 60 * 61 * Interface: 62 * Parse_Init Initialization function which must be 63 * called before anything else in this module 64 * is used. 65 * 66 * Parse_File Function used to parse a makefile. It must 67 * be given the name of the file, which should 68 * already have been opened, and a function 69 * to call to read a character from the file. 70 * 71 * Parse_IsVar Returns TRUE if the given line is a 72 * variable assignment. Used by MainParseArgs 73 * to determine if an argument is a target 74 * or a variable assignment. Used internally 75 * for pretty much the same thing... 76 * 77 * Parse_Error Function called when an error occurs in 78 * parsing. Used by the variable and 79 * conditional modules. 80 * Parse_MainName Returns a Lst of the main target to create. 81 */ 82 83 #include <varargs.h> 84 #include <stdio.h> 85 #include <ctype.h> 86 #include "make.h" 87 #include "buf.h" 88 #include "pathnames.h" 89 90 /* 91 * These values are returned by ParseEOF to tell Parse_File whether to 92 * CONTINUE parsing, i.e. it had only reached the end of an include file, 93 * or if it's DONE. 94 */ 95 #define CONTINUE 1 96 #define DONE 0 97 static int ParseEOF(); 98 99 static Lst targets; /* targets we're working on */ 100 static Boolean inLine; /* true if currently in a dependency 101 * line or its commands */ 102 103 static char *fname; /* name of current file (for errors) */ 104 static int lineno; /* line number in current file */ 105 static FILE *curFILE; /* current makefile */ 106 107 static int fatals = 0; 108 109 static GNode *mainNode; /* The main target to create. This is the 110 * first target on the first dependency 111 * line in the first makefile */ 112 /* 113 * Definitions for handling #include specifications 114 */ 115 typedef struct IFile { 116 char *fname; /* name of previous file */ 117 int lineno; /* saved line number */ 118 FILE * F; /* the open stream */ 119 } IFile; 120 121 static Lst includes; /* stack of IFiles generated by 122 * #includes */ 123 Lst parseIncPath; /* list of directories for "..." includes */ 124 Lst sysIncPath; /* list of directories for <...> includes */ 125 126 /*- 127 * specType contains the SPECial TYPE of the current target. It is 128 * Not if the target is unspecial. If it *is* special, however, the children 129 * are linked as children of the parent but not vice versa. This variable is 130 * set in ParseDoDependency 131 */ 132 typedef enum { 133 Begin, /* .BEGIN */ 134 Default, /* .DEFAULT */ 135 End, /* .END */ 136 Ignore, /* .IGNORE */ 137 Includes, /* .INCLUDES */ 138 Interrupt, /* .INTERRUPT */ 139 Libs, /* .LIBS */ 140 MFlags, /* .MFLAGS or .MAKEFLAGS */ 141 Main, /* .MAIN and we don't have anything user-specified to 142 * make */ 143 Not, /* Not special */ 144 NotParallel, /* .NOTPARALELL */ 145 Null, /* .NULL */ 146 Order, /* .ORDER */ 147 Path, /* .PATH */ 148 Precious, /* .PRECIOUS */ 149 Shell, /* .SHELL */ 150 Silent, /* .SILENT */ 151 SingleShell, /* .SINGLESHELL */ 152 Suffixes, /* .SUFFIXES */ 153 Attribute, /* Generic attribute */ 154 } ParseSpecial; 155 156 ParseSpecial specType; 157 158 /* 159 * Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER 160 * seen, then set to each successive source on the line. 161 */ 162 static GNode *predecessor; 163 164 /* 165 * The parseKeywords table is searched using binary search when deciding 166 * if a target or source is special. The 'spec' field is the ParseSpecial 167 * type of the keyword ("Not" if the keyword isn't special as a target) while 168 * the 'op' field is the operator to apply to the list of targets if the 169 * keyword is used as a source ("0" if the keyword isn't special as a source) 170 */ 171 static struct { 172 char *name; /* Name of keyword */ 173 ParseSpecial spec; /* Type when used as a target */ 174 int op; /* Operator when used as a source */ 175 } parseKeywords[] = { 176 { ".BEGIN", Begin, 0 }, 177 { ".DEFAULT", Default, 0 }, 178 { ".OPTIONAL", Attribute, OP_OPTIONAL }, 179 { ".END", End, 0 }, 180 { ".EXEC", Attribute, OP_EXEC }, 181 { ".IGNORE", Ignore, OP_IGNORE }, 182 { ".INCLUDES", Includes, 0 }, 183 { ".INTERRUPT", Interrupt, 0 }, 184 { ".INVISIBLE", Attribute, OP_INVISIBLE }, 185 { ".JOIN", Attribute, OP_JOIN }, 186 { ".LIBS", Libs, 0 }, 187 { ".MAIN", Main, 0 }, 188 { ".MAKE", Attribute, OP_MAKE }, 189 { ".MAKEFLAGS", MFlags, 0 }, 190 { ".MFLAGS", MFlags, 0 }, 191 { ".NOTMAIN", Attribute, OP_NOTMAIN }, 192 { ".NOTPARALLEL", NotParallel, 0 }, 193 { ".NULL", Null, 0 }, 194 { ".ORDER", Order, 0 }, 195 { ".PATH", Path, 0 }, 196 { ".PRECIOUS", Precious, OP_PRECIOUS }, 197 { ".RECURSIVE", Attribute, OP_MAKE }, 198 { ".SHELL", Shell, 0 }, 199 { ".SILENT", Silent, OP_SILENT }, 200 { ".SINGLESHELL", SingleShell, 0 }, 201 { ".SUFFIXES", Suffixes, 0 }, 202 { ".USE", Attribute, OP_USE }, 203 }; 204 205 /*- 206 *---------------------------------------------------------------------- 207 * ParseFindKeyword -- 208 * Look in the table of keywords for one matching the given string. 209 * 210 * Results: 211 * The index of the keyword, or -1 if it isn't there. 212 * 213 * Side Effects: 214 * None 215 *---------------------------------------------------------------------- 216 */ 217 static int 218 ParseFindKeyword (str) 219 char *str; /* String to find */ 220 { 221 register int start, 222 end, 223 cur; 224 register int diff; 225 226 start = 0; 227 end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1; 228 229 do { 230 cur = start + ((end - start) / 2); 231 diff = strcmp (str, parseKeywords[cur].name); 232 233 if (diff == 0) { 234 return (cur); 235 } else if (diff < 0) { 236 end = cur - 1; 237 } else { 238 start = cur + 1; 239 } 240 } while (start <= end); 241 return (-1); 242 } 243 244 /*- 245 * Parse_Error -- 246 * Error message abort function for parsing. Prints out the context 247 * of the error (line number and file) as well as the message with 248 * two optional arguments. 249 * 250 * Results: 251 * None 252 * 253 * Side Effects: 254 * "fatals" is incremented if the level is PARSE_FATAL. 255 */ 256 /* VARARGS */ 257 void 258 Parse_Error(type, va_alist) 259 int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */ 260 va_dcl 261 { 262 va_list ap; 263 char *fmt; 264 265 (void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno); 266 if (type == PARSE_WARNING) 267 (void)fprintf(stderr, "warning: "); 268 va_start(ap); 269 fmt = va_arg(ap, char *); 270 (void)vfprintf(stderr, fmt, ap); 271 va_end(ap); 272 (void)fprintf(stderr, "\n"); 273 (void)fflush(stderr); 274 if (type == PARSE_FATAL) 275 fatals += 1; 276 } 277 278 /*- 279 *--------------------------------------------------------------------- 280 * ParseLinkSrc -- 281 * Link the parent node to its new child. Used in a Lst_ForEach by 282 * ParseDoDependency. If the specType isn't 'Not', the parent 283 * isn't linked as a parent of the child. 284 * 285 * Results: 286 * Always = 0 287 * 288 * Side Effects: 289 * New elements are added to the parents list of cgn and the 290 * children list of cgn. the unmade field of pgn is updated 291 * to reflect the additional child. 292 *--------------------------------------------------------------------- 293 */ 294 static int 295 ParseLinkSrc (pgn, cgn) 296 GNode *pgn; /* The parent node */ 297 GNode *cgn; /* The child node */ 298 { 299 if (Lst_Member (pgn->children, (ClientData)cgn) == NILLNODE) { 300 (void)Lst_AtEnd (pgn->children, (ClientData)cgn); 301 if (specType == Not) { 302 (void)Lst_AtEnd (cgn->parents, (ClientData)pgn); 303 } 304 pgn->unmade += 1; 305 } 306 return (0); 307 } 308 309 /*- 310 *--------------------------------------------------------------------- 311 * ParseDoOp -- 312 * Apply the parsed operator to the given target node. Used in a 313 * Lst_ForEach call by ParseDoDependency once all targets have 314 * been found and their operator parsed. If the previous and new 315 * operators are incompatible, a major error is taken. 316 * 317 * Results: 318 * Always 0 319 * 320 * Side Effects: 321 * The type field of the node is altered to reflect any new bits in 322 * the op. 323 *--------------------------------------------------------------------- 324 */ 325 static int 326 ParseDoOp (gn, op) 327 GNode *gn; /* The node to which the operator is to be 328 * applied */ 329 int op; /* The operator to apply */ 330 { 331 /* 332 * If the dependency mask of the operator and the node don't match and 333 * the node has actually had an operator applied to it before, and 334 * the operator actually has some dependency information in it, complain. 335 */ 336 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 337 !OP_NOP(gn->type) && !OP_NOP(op)) 338 { 339 Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name); 340 return (1); 341 } 342 343 if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 344 /* 345 * If the node was the object of a :: operator, we need to create a 346 * new instance of it for the children and commands on this dependency 347 * line. The new instance is placed on the 'cohorts' list of the 348 * initial one (note the initial one is not on its own cohorts list) 349 * and the new instance is linked to all parents of the initial 350 * instance. 351 */ 352 register GNode *cohort; 353 LstNode ln; 354 355 cohort = Targ_NewGN(gn->name); 356 /* 357 * Duplicate links to parents so graph traversal is simple. Perhaps 358 * some type bits should be duplicated? 359 * 360 * Make the cohort invisible as well to avoid duplicating it into 361 * other variables. True, parents of this target won't tend to do 362 * anything with their local variables, but better safe than 363 * sorry. 364 */ 365 Lst_ForEach(gn->parents, ParseLinkSrc, (ClientData)cohort); 366 cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 367 (void)Lst_AtEnd(gn->cohorts, (ClientData)cohort); 368 369 /* 370 * Replace the node in the targets list with the new copy 371 */ 372 ln = Lst_Member(targets, (ClientData)gn); 373 Lst_Replace(ln, (ClientData)cohort); 374 gn = cohort; 375 } 376 /* 377 * We don't want to nuke any previous flags (whatever they were) so we 378 * just OR the new operator into the old 379 */ 380 gn->type |= op; 381 382 return (0); 383 } 384 385 /*- 386 *--------------------------------------------------------------------- 387 * ParseDoSrc -- 388 * Given the name of a source, figure out if it is an attribute 389 * and apply it to the targets if it is. Else decide if there is 390 * some attribute which should be applied *to* the source because 391 * of some special target and apply it if so. Otherwise, make the 392 * source be a child of the targets in the list 'targets' 393 * 394 * Results: 395 * None 396 * 397 * Side Effects: 398 * Operator bits may be added to the list of targets or to the source. 399 * The targets may have a new source added to their lists of children. 400 *--------------------------------------------------------------------- 401 */ 402 static void 403 ParseDoSrc (tOp, src) 404 int tOp; /* operator (if any) from special targets */ 405 char *src; /* name of the source to handle */ 406 { 407 int op; /* operator (if any) from special source */ 408 GNode *gn; 409 410 op = 0; 411 if (*src == '.' && isupper (src[1])) { 412 int keywd = ParseFindKeyword(src); 413 if (keywd != -1) { 414 op = parseKeywords[keywd].op; 415 } 416 } 417 if (op != 0) { 418 Lst_ForEach (targets, ParseDoOp, (ClientData)op); 419 } else if (specType == Main) { 420 /* 421 * If we have noted the existence of a .MAIN, it means we need 422 * to add the sources of said target to the list of things 423 * to create. The string 'src' is likely to be free, so we 424 * must make a new copy of it. Note that this will only be 425 * invoked if the user didn't specify a target on the command 426 * line. This is to allow #ifmake's to succeed, or something... 427 */ 428 (void) Lst_AtEnd (create, (ClientData)strdup(src)); 429 /* 430 * Add the name to the .TARGETS variable as well, so the user cna 431 * employ that, if desired. 432 */ 433 Var_Append(".TARGETS", src, VAR_GLOBAL); 434 } else if (specType == Order) { 435 /* 436 * Create proper predecessor/successor links between the previous 437 * source and the current one. 438 */ 439 gn = Targ_FindNode(src, TARG_CREATE); 440 if (predecessor != NILGNODE) { 441 (void)Lst_AtEnd(predecessor->successors, (ClientData)gn); 442 (void)Lst_AtEnd(gn->preds, (ClientData)predecessor); 443 } 444 /* 445 * The current source now becomes the predecessor for the next one. 446 */ 447 predecessor = gn; 448 } else { 449 /* 450 * If the source is not an attribute, we need to find/create 451 * a node for it. After that we can apply any operator to it 452 * from a special target or link it to its parents, as 453 * appropriate. 454 * 455 * In the case of a source that was the object of a :: operator, 456 * the attribute is applied to all of its instances (as kept in 457 * the 'cohorts' list of the node) or all the cohorts are linked 458 * to all the targets. 459 */ 460 gn = Targ_FindNode (src, TARG_CREATE); 461 if (tOp) { 462 gn->type |= tOp; 463 } else { 464 Lst_ForEach (targets, ParseLinkSrc, (ClientData)gn); 465 } 466 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 467 register GNode *cohort; 468 register LstNode ln; 469 470 for (ln=Lst_First(gn->cohorts); ln != NILLNODE; ln = Lst_Succ(ln)){ 471 cohort = (GNode *)Lst_Datum(ln); 472 if (tOp) { 473 cohort->type |= tOp; 474 } else { 475 Lst_ForEach(targets, ParseLinkSrc, (ClientData)cohort); 476 } 477 } 478 } 479 } 480 } 481 482 /*- 483 *----------------------------------------------------------------------- 484 * ParseFindMain -- 485 * Find a real target in the list and set it to be the main one. 486 * Called by ParseDoDependency when a main target hasn't been found 487 * yet. 488 * 489 * Results: 490 * 0 if main not found yet, 1 if it is. 491 * 492 * Side Effects: 493 * mainNode is changed and Targ_SetMain is called. 494 * 495 *----------------------------------------------------------------------- 496 */ 497 static int 498 ParseFindMain(gn) 499 GNode *gn; /* Node to examine */ 500 { 501 if ((gn->type & (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)) == 0) { 502 mainNode = gn; 503 Targ_SetMain(gn); 504 return (1); 505 } else { 506 return (0); 507 } 508 } 509 510 /*- 511 *----------------------------------------------------------------------- 512 * ParseAddDir -- 513 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going 514 * 515 * Results: 516 * === 0 517 * 518 * Side Effects: 519 * See Dir_AddDir. 520 * 521 *----------------------------------------------------------------------- 522 */ 523 static int 524 ParseAddDir(path, name) 525 Lst path; 526 char *name; 527 { 528 Dir_AddDir(path, name); 529 return(0); 530 } 531 532 /*- 533 *----------------------------------------------------------------------- 534 * ParseClearPath -- 535 * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going 536 * 537 * Results: 538 * === 0 539 * 540 * Side Effects: 541 * See Dir_ClearPath 542 * 543 *----------------------------------------------------------------------- 544 */ 545 static int 546 ParseClearPath(path) 547 Lst path; 548 { 549 Dir_ClearPath(path); 550 return(0); 551 } 552 553 /*- 554 *--------------------------------------------------------------------- 555 * ParseDoDependency -- 556 * Parse the dependency line in line. 557 * 558 * Results: 559 * None 560 * 561 * Side Effects: 562 * The nodes of the sources are linked as children to the nodes of the 563 * targets. Some nodes may be created. 564 * 565 * We parse a dependency line by first extracting words from the line and 566 * finding nodes in the list of all targets with that name. This is done 567 * until a character is encountered which is an operator character. Currently 568 * these are only ! and :. At this point the operator is parsed and the 569 * pointer into the line advanced until the first source is encountered. 570 * The parsed operator is applied to each node in the 'targets' list, 571 * which is where the nodes found for the targets are kept, by means of 572 * the ParseDoOp function. 573 * The sources are read in much the same way as the targets were except 574 * that now they are expanded using the wildcarding scheme of the C-Shell 575 * and all instances of the resulting words in the list of all targets 576 * are found. Each of the resulting nodes is then linked to each of the 577 * targets as one of its children. 578 * Certain targets are handled specially. These are the ones detailed 579 * by the specType variable. 580 * The storing of transformation rules is also taken care of here. 581 * A target is recognized as a transformation rule by calling 582 * Suff_IsTransform. If it is a transformation rule, its node is gotten 583 * from the suffix module via Suff_AddTransform rather than the standard 584 * Targ_FindNode in the target module. 585 *--------------------------------------------------------------------- 586 */ 587 static void 588 ParseDoDependency (line) 589 char *line; /* the line to parse */ 590 { 591 register char *cp; /* our current position */ 592 register GNode *gn; /* a general purpose temporary node */ 593 register int op; /* the operator on the line */ 594 char savec; /* a place to save a character */ 595 Lst paths; /* List of search paths to alter when parsing 596 * a list of .PATH targets */ 597 int tOp; /* operator from special target */ 598 Lst sources; /* list of source names after expansion */ 599 Lst curTargs; /* list of target names to be found and added 600 * to the targets list */ 601 602 tOp = 0; 603 604 specType = Not; 605 paths = (Lst)NULL; 606 607 curTargs = Lst_Init(FALSE); 608 609 do { 610 for (cp = line; 611 *cp && !isspace (*cp) && 612 (*cp != '!') && (*cp != ':') && (*cp != '('); 613 cp++) 614 { 615 if (*cp == '$') { 616 /* 617 * Must be a dynamic source (would have been expanded 618 * otherwise), so call the Var module to parse the puppy 619 * so we can safely advance beyond it...There should be 620 * no errors in this, as they would have been discovered 621 * in the initial Var_Subst and we wouldn't be here. 622 */ 623 int length; 624 Boolean freeIt; 625 char *result; 626 627 result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt); 628 629 if (freeIt) { 630 free(result); 631 } 632 cp += length-1; 633 } 634 continue; 635 } 636 if (*cp == '(') { 637 /* 638 * Archives must be handled specially to make sure the OP_ARCHV 639 * flag is set in their 'type' field, for one thing, and because 640 * things like "archive(file1.o file2.o file3.o)" are permissible. 641 * Arch_ParseArchive will set 'line' to be the first non-blank 642 * after the archive-spec. It creates/finds nodes for the members 643 * and places them on the given list, returning SUCCESS if all 644 * went well and FAILURE if there was an error in the 645 * specification. On error, line should remain untouched. 646 */ 647 if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) { 648 Parse_Error (PARSE_FATAL, 649 "Error in archive specification: \"%s\"", line); 650 return; 651 } else { 652 continue; 653 } 654 } 655 savec = *cp; 656 657 if (!*cp) { 658 /* 659 * Ending a dependency line without an operator is a Bozo 660 * no-no 661 */ 662 Parse_Error (PARSE_FATAL, "Need an operator"); 663 return; 664 } 665 *cp = '\0'; 666 /* 667 * Have a word in line. See if it's a special target and set 668 * specType to match it. 669 */ 670 if (*line == '.' && isupper (line[1])) { 671 /* 672 * See if the target is a special target that must have it 673 * or its sources handled specially. 674 */ 675 int keywd = ParseFindKeyword(line); 676 if (keywd != -1) { 677 if (specType == Path && parseKeywords[keywd].spec != Path) { 678 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 679 return; 680 } 681 682 specType = parseKeywords[keywd].spec; 683 tOp = parseKeywords[keywd].op; 684 685 /* 686 * Certain special targets have special semantics: 687 * .PATH Have to set the dirSearchPath 688 * variable too 689 * .MAIN Its sources are only used if 690 * nothing has been specified to 691 * create. 692 * .DEFAULT Need to create a node to hang 693 * commands on, but we don't want 694 * it in the graph, nor do we want 695 * it to be the Main Target, so we 696 * create it, set OP_NOTMAIN and 697 * add it to the list, setting 698 * DEFAULT to the new node for 699 * later use. We claim the node is 700 * A transformation rule to make 701 * life easier later, when we'll 702 * use Make_HandleUse to actually 703 * apply the .DEFAULT commands. 704 * .BEGIN 705 * .END 706 * .INTERRUPT Are not to be considered the 707 * main target. 708 * .NOTPARALLEL Make only one target at a time. 709 * .SINGLESHELL Create a shell for each command. 710 * .ORDER Must set initial predecessor to NIL 711 */ 712 switch (specType) { 713 case Path: 714 if (paths == NULL) { 715 paths = Lst_Init(FALSE); 716 } 717 (void)Lst_AtEnd(paths, (ClientData)dirSearchPath); 718 break; 719 case Main: 720 if (!Lst_IsEmpty(create)) { 721 specType = Not; 722 } 723 break; 724 case Begin: 725 case End: 726 case Interrupt: 727 gn = Targ_FindNode(line, TARG_CREATE); 728 gn->type |= OP_NOTMAIN; 729 (void)Lst_AtEnd(targets, (ClientData)gn); 730 break; 731 case Default: 732 gn = Targ_NewGN(".DEFAULT"); 733 gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 734 (void)Lst_AtEnd(targets, (ClientData)gn); 735 DEFAULT = gn; 736 break; 737 case NotParallel: 738 { 739 extern int maxJobs; 740 741 maxJobs = 1; 742 break; 743 } 744 case SingleShell: 745 /* backwards = 1; */ 746 break; 747 case Order: 748 predecessor = NILGNODE; 749 break; 750 } 751 } else if (strncmp (line, ".PATH", 5) == 0) { 752 /* 753 * .PATH<suffix> has to be handled specially. 754 * Call on the suffix module to give us a path to 755 * modify. 756 */ 757 Lst path; 758 759 specType = Path; 760 path = Suff_GetPath (&line[5]); 761 if (path == NILLST) { 762 Parse_Error (PARSE_FATAL, 763 "Suffix '%s' not defined (yet)", 764 &line[5]); 765 return; 766 } else { 767 if (paths == (Lst)NULL) { 768 paths = Lst_Init(FALSE); 769 } 770 (void)Lst_AtEnd(paths, (ClientData)path); 771 } 772 } 773 } 774 775 /* 776 * Have word in line. Get or create its node and stick it at 777 * the end of the targets list 778 */ 779 if ((specType == Not) && (*line != '\0')) { 780 if (Dir_HasWildcards(line)) { 781 /* 782 * Targets are to be sought only in the current directory, 783 * so create an empty path for the thing. Note we need to 784 * use Dir_Destroy in the destruction of the path as the 785 * Dir module could have added a directory to the path... 786 */ 787 Lst emptyPath = Lst_Init(FALSE); 788 789 Dir_Expand(line, emptyPath, curTargs); 790 791 Lst_Destroy(emptyPath, Dir_Destroy); 792 } else { 793 /* 794 * No wildcards, but we want to avoid code duplication, 795 * so create a list with the word on it. 796 */ 797 (void)Lst_AtEnd(curTargs, (ClientData)line); 798 } 799 800 while(!Lst_IsEmpty(curTargs)) { 801 char *targName = (char *)Lst_DeQueue(curTargs); 802 803 if (!Suff_IsTransform (targName)) { 804 gn = Targ_FindNode (targName, TARG_CREATE); 805 } else { 806 gn = Suff_AddTransform (targName); 807 } 808 809 (void)Lst_AtEnd (targets, (ClientData)gn); 810 } 811 } else if (specType == Path && *line != '.' && *line != '\0') { 812 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 813 } 814 815 *cp = savec; 816 /* 817 * If it is a special type and not .PATH, it's the only target we 818 * allow on this line... 819 */ 820 if (specType != Not && specType != Path) { 821 Boolean warn = FALSE; 822 823 while ((*cp != '!') && (*cp != ':') && *cp) { 824 if (*cp != ' ' && *cp != '\t') { 825 warn = TRUE; 826 } 827 cp++; 828 } 829 if (warn) { 830 Parse_Error(PARSE_WARNING, "Extra target ignored"); 831 } 832 } else { 833 while (*cp && isspace (*cp)) { 834 cp++; 835 } 836 } 837 line = cp; 838 } while ((*line != '!') && (*line != ':') && *line); 839 840 /* 841 * Don't need the list of target names anymore... 842 */ 843 Lst_Destroy(curTargs, NOFREE); 844 845 if (!Lst_IsEmpty(targets)) { 846 switch(specType) { 847 default: 848 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); 849 break; 850 case Default: 851 case Begin: 852 case End: 853 case Interrupt: 854 /* 855 * These four create nodes on which to hang commands, so 856 * targets shouldn't be empty... 857 */ 858 case Not: 859 /* 860 * Nothing special here -- targets can be empty if it wants. 861 */ 862 break; 863 } 864 } 865 866 /* 867 * Have now parsed all the target names. Must parse the operator next. The 868 * result is left in op . 869 */ 870 if (*cp == '!') { 871 op = OP_FORCE; 872 } else if (*cp == ':') { 873 if (cp[1] == ':') { 874 op = OP_DOUBLEDEP; 875 cp++; 876 } else { 877 op = OP_DEPENDS; 878 } 879 } else { 880 Parse_Error (PARSE_FATAL, "Missing dependency operator"); 881 return; 882 } 883 884 cp++; /* Advance beyond operator */ 885 886 Lst_ForEach (targets, ParseDoOp, (ClientData)op); 887 888 /* 889 * Get to the first source 890 */ 891 while (*cp && isspace (*cp)) { 892 cp++; 893 } 894 line = cp; 895 896 /* 897 * Several special targets take different actions if present with no 898 * sources: 899 * a .SUFFIXES line with no sources clears out all old suffixes 900 * a .PRECIOUS line makes all targets precious 901 * a .IGNORE line ignores errors for all targets 902 * a .SILENT line creates silence when making all targets 903 * a .PATH removes all directories from the search path(s). 904 */ 905 if (!*line) { 906 switch (specType) { 907 case Suffixes: 908 Suff_ClearSuffixes (); 909 break; 910 case Precious: 911 allPrecious = TRUE; 912 break; 913 case Ignore: 914 ignoreErrors = TRUE; 915 break; 916 case Silent: 917 beSilent = TRUE; 918 break; 919 case Path: 920 Lst_ForEach(paths, ParseClearPath, (ClientData)NULL); 921 break; 922 } 923 } else if (specType == MFlags) { 924 /* 925 * Call on functions in main.c to deal with these arguments and 926 * set the initial character to a null-character so the loop to 927 * get sources won't get anything 928 */ 929 Main_ParseArgLine (line); 930 *line = '\0'; 931 } else if (specType == Shell) { 932 if (Job_ParseShell (line) != SUCCESS) { 933 Parse_Error (PARSE_FATAL, "improper shell specification"); 934 return; 935 } 936 *line = '\0'; 937 } else if ((specType == NotParallel) || (specType == SingleShell)) { 938 *line = '\0'; 939 } 940 941 /* 942 * NOW GO FOR THE SOURCES 943 */ 944 if ((specType == Suffixes) || (specType == Path) || 945 (specType == Includes) || (specType == Libs) || 946 (specType == Null)) 947 { 948 while (*line) { 949 /* 950 * If the target was one that doesn't take files as its sources 951 * but takes something like suffixes, we take each 952 * space-separated word on the line as a something and deal 953 * with it accordingly. 954 * 955 * If the target was .SUFFIXES, we take each source as a 956 * suffix and add it to the list of suffixes maintained by the 957 * Suff module. 958 * 959 * If the target was a .PATH, we add the source as a directory 960 * to search on the search path. 961 * 962 * If it was .INCLUDES, the source is taken to be the suffix of 963 * files which will be #included and whose search path should 964 * be present in the .INCLUDES variable. 965 * 966 * If it was .LIBS, the source is taken to be the suffix of 967 * files which are considered libraries and whose search path 968 * should be present in the .LIBS variable. 969 * 970 * If it was .NULL, the source is the suffix to use when a file 971 * has no valid suffix. 972 */ 973 char savec; 974 while (*cp && !isspace (*cp)) { 975 cp++; 976 } 977 savec = *cp; 978 *cp = '\0'; 979 switch (specType) { 980 case Suffixes: 981 Suff_AddSuffix (line); 982 break; 983 case Path: 984 Lst_ForEach(paths, ParseAddDir, (ClientData)line); 985 break; 986 case Includes: 987 Suff_AddInclude (line); 988 break; 989 case Libs: 990 Suff_AddLib (line); 991 break; 992 case Null: 993 Suff_SetNull (line); 994 break; 995 } 996 *cp = savec; 997 if (savec != '\0') { 998 cp++; 999 } 1000 while (*cp && isspace (*cp)) { 1001 cp++; 1002 } 1003 line = cp; 1004 } 1005 if (paths) { 1006 Lst_Destroy(paths, NOFREE); 1007 } 1008 } else { 1009 while (*line) { 1010 /* 1011 * The targets take real sources, so we must beware of archive 1012 * specifications (i.e. things with left parentheses in them) 1013 * and handle them accordingly. 1014 */ 1015 while (*cp && !isspace (*cp)) { 1016 if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) { 1017 /* 1018 * Only stop for a left parenthesis if it isn't at the 1019 * start of a word (that'll be for variable changes 1020 * later) and isn't preceded by a dollar sign (a dynamic 1021 * source). 1022 */ 1023 break; 1024 } else { 1025 cp++; 1026 } 1027 } 1028 1029 if (*cp == '(') { 1030 GNode *gn; 1031 1032 sources = Lst_Init (FALSE); 1033 if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) { 1034 Parse_Error (PARSE_FATAL, 1035 "Error in source archive spec \"%s\"", line); 1036 return; 1037 } 1038 1039 while (!Lst_IsEmpty (sources)) { 1040 gn = (GNode *) Lst_DeQueue (sources); 1041 ParseDoSrc (tOp, gn->name); 1042 } 1043 Lst_Destroy (sources, NOFREE); 1044 cp = line; 1045 } else { 1046 if (*cp) { 1047 *cp = '\0'; 1048 cp += 1; 1049 } 1050 1051 ParseDoSrc (tOp, line); 1052 } 1053 while (*cp && isspace (*cp)) { 1054 cp++; 1055 } 1056 line = cp; 1057 } 1058 } 1059 1060 if (mainNode == NILGNODE) { 1061 /* 1062 * If we have yet to decide on a main target to make, in the 1063 * absence of any user input, we want the first target on 1064 * the first dependency line that is actually a real target 1065 * (i.e. isn't a .USE or .EXEC rule) to be made. 1066 */ 1067 Lst_ForEach (targets, ParseFindMain, (ClientData)0); 1068 } 1069 1070 } 1071 1072 /*- 1073 *--------------------------------------------------------------------- 1074 * Parse_IsVar -- 1075 * Return TRUE if the passed line is a variable assignment. A variable 1076 * assignment consists of a single word followed by optional whitespace 1077 * followed by either a += or an = operator. 1078 * This function is used both by the Parse_File function and main when 1079 * parsing the command-line arguments. 1080 * 1081 * Results: 1082 * TRUE if it is. FALSE if it ain't 1083 * 1084 * Side Effects: 1085 * none 1086 *--------------------------------------------------------------------- 1087 */ 1088 Boolean 1089 Parse_IsVar (line) 1090 register char *line; /* the line to check */ 1091 { 1092 register Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1093 register Boolean haveName = FALSE; /* Set TRUE if have a variable name */ 1094 1095 /* 1096 * Skip to variable name 1097 */ 1098 while ((*line == ' ') || (*line == '\t')) { 1099 line++; 1100 } 1101 1102 while (*line != '=') { 1103 if (*line == '\0') { 1104 /* 1105 * end-of-line -- can't be a variable assignment. 1106 */ 1107 return (FALSE); 1108 } else if ((*line == ' ') || (*line == '\t')) { 1109 /* 1110 * there can be as much white space as desired so long as there is 1111 * only one word before the operator 1112 */ 1113 wasSpace = TRUE; 1114 } else if (wasSpace && haveName) { 1115 /* 1116 * Stop when an = operator is found. 1117 */ 1118 if ((*line == '+') || (*line == ':') || (*line == '?') || 1119 (*line == '!')) { 1120 break; 1121 } 1122 1123 /* 1124 * This is the start of another word, so not assignment. 1125 */ 1126 return (FALSE); 1127 } else { 1128 haveName = TRUE; 1129 wasSpace = FALSE; 1130 } 1131 line++; 1132 } 1133 1134 /* 1135 * A final check: if we stopped on a +, ?, ! or :, the next character must 1136 * be an = or it ain't a valid assignment 1137 */ 1138 if (((*line == '+') || 1139 (*line == '?') || 1140 (*line == ':') || 1141 (*line == '!')) && 1142 (line[1] != '=')) 1143 { 1144 return (FALSE); 1145 } else { 1146 return (haveName); 1147 } 1148 } 1149 1150 /*- 1151 *--------------------------------------------------------------------- 1152 * Parse_DoVar -- 1153 * Take the variable assignment in the passed line and do it in the 1154 * global context. 1155 * 1156 * Note: There is a lexical ambiguity with assignment modifier characters 1157 * in variable names. This routine interprets the character before the = 1158 * as a modifier. Therefore, an assignment like 1159 * C++=/usr/bin/CC 1160 * is interpreted as "C+ +=" instead of "C++ =". 1161 * 1162 * Results: 1163 * none 1164 * 1165 * Side Effects: 1166 * the variable structure of the given variable name is altered in the 1167 * global context. 1168 *--------------------------------------------------------------------- 1169 */ 1170 void 1171 Parse_DoVar (line, ctxt) 1172 char *line; /* a line guaranteed to be a variable 1173 * assignment. This reduces error checks */ 1174 GNode *ctxt; /* Context in which to do the assignment */ 1175 { 1176 register char *cp; /* pointer into line */ 1177 enum { 1178 VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL 1179 } type; /* Type of assignment */ 1180 char *opc; /* ptr to operator character to 1181 * null-terminate the variable name */ 1182 1183 /* 1184 * Skip to variable name 1185 */ 1186 while ((*line == ' ') || (*line == '\t')) { 1187 line++; 1188 } 1189 1190 /* 1191 * Skip to operator character, nulling out whitespace as we go 1192 */ 1193 for (cp = line + 1; *cp != '='; cp++) { 1194 if (isspace (*cp)) { 1195 *cp = '\0'; 1196 } 1197 } 1198 opc = cp-1; /* operator is the previous character */ 1199 *cp++ = '\0'; /* nuke the = */ 1200 1201 /* 1202 * Check operator type 1203 */ 1204 switch (*opc) { 1205 case '+': 1206 type = VAR_APPEND; 1207 *opc = '\0'; 1208 break; 1209 1210 case '?': 1211 /* 1212 * If the variable already has a value, we don't do anything. 1213 */ 1214 *opc = '\0'; 1215 if (Var_Exists(line, ctxt)) { 1216 return; 1217 } else { 1218 type = VAR_NORMAL; 1219 } 1220 break; 1221 1222 case ':': 1223 type = VAR_SUBST; 1224 *opc = '\0'; 1225 break; 1226 1227 case '!': 1228 type = VAR_SHELL; 1229 *opc = '\0'; 1230 break; 1231 1232 default: 1233 type = VAR_NORMAL; 1234 break; 1235 } 1236 1237 while (isspace (*cp)) { 1238 cp++; 1239 } 1240 1241 if (type == VAR_APPEND) { 1242 Var_Append (line, cp, ctxt); 1243 } else if (type == VAR_SUBST) { 1244 /* 1245 * Allow variables in the old value to be undefined, but leave their 1246 * invocation alone -- this is done by forcing oldVars to be false. 1247 * XXX: This can cause recursive variables, but that's not hard to do, 1248 * and this allows someone to do something like 1249 * 1250 * CFLAGS = $(.INCLUDES) 1251 * CFLAGS := -I.. $(CFLAGS) 1252 * 1253 * And not get an error. 1254 */ 1255 Boolean oldOldVars = oldVars; 1256 1257 oldVars = FALSE; 1258 cp = Var_Subst(cp, ctxt, FALSE); 1259 oldVars = oldOldVars; 1260 1261 Var_Set(line, cp, ctxt); 1262 free(cp); 1263 } else if (type == VAR_SHELL) { 1264 char result[BUFSIZ]; /* Result of command */ 1265 char *args[4]; /* Args for invoking the shell */ 1266 int fds[2]; /* Pipe streams */ 1267 int cpid; /* Child PID */ 1268 int pid; /* PID from wait() */ 1269 Boolean freeCmd; /* TRUE if the command needs to be freed, i.e. 1270 * if any variable expansion was performed */ 1271 1272 /* 1273 * Set up arguments for shell 1274 */ 1275 args[0] = "sh"; 1276 args[1] = "-c"; 1277 if (index(cp, '$') != (char *)NULL) { 1278 /* 1279 * There's a dollar sign in the command, so perform variable 1280 * expansion on the whole thing. The resulting string will need 1281 * freeing when we're done, so set freeCmd to TRUE. 1282 */ 1283 args[2] = Var_Subst(cp, VAR_CMD, TRUE); 1284 freeCmd = TRUE; 1285 } else { 1286 args[2] = cp; 1287 freeCmd = FALSE; 1288 } 1289 args[3] = (char *)NULL; 1290 1291 /* 1292 * Open a pipe for fetching its output 1293 */ 1294 pipe(fds); 1295 1296 /* 1297 * Fork 1298 */ 1299 cpid = vfork(); 1300 if (cpid == 0) { 1301 /* 1302 * Close input side of pipe 1303 */ 1304 close(fds[0]); 1305 1306 /* 1307 * Duplicate the output stream to the shell's output, then 1308 * shut the extra thing down. Note we don't fetch the error 1309 * stream...why not? Why? 1310 */ 1311 dup2(fds[1], 1); 1312 close(fds[1]); 1313 1314 execv("/bin/sh", args); 1315 _exit(1); 1316 } else if (cpid < 0) { 1317 /* 1318 * Couldn't fork -- tell the user and make the variable null 1319 */ 1320 Parse_Error(PARSE_WARNING, "Couldn't exec \"%s\"", cp); 1321 Var_Set(line, "", ctxt); 1322 } else { 1323 int status; 1324 int cc; 1325 1326 /* 1327 * No need for the writing half 1328 */ 1329 close(fds[1]); 1330 1331 /* 1332 * Wait for the process to exit. 1333 * 1334 * XXX: If the child writes more than a pipe's worth, we will 1335 * deadlock. 1336 */ 1337 while(((pid = wait(&status)) != cpid) && (pid >= 0)) { 1338 ; 1339 } 1340 1341 /* 1342 * Read all the characters the child wrote. 1343 */ 1344 cc = read(fds[0], result, sizeof(result)); 1345 1346 if (cc < 0) { 1347 /* 1348 * Couldn't read the child's output -- tell the user and 1349 * set the variable to null 1350 */ 1351 Parse_Error(PARSE_WARNING, "Couldn't read shell's output"); 1352 cc = 0; 1353 } 1354 1355 if (status) { 1356 /* 1357 * Child returned an error -- tell the user but still use 1358 * the result. 1359 */ 1360 Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp); 1361 } 1362 /* 1363 * Null-terminate the result, convert newlines to spaces and 1364 * install it in the variable. 1365 */ 1366 result[cc] = '\0'; 1367 cp = &result[cc] - 1; 1368 1369 if (*cp == '\n') { 1370 /* 1371 * A final newline is just stripped 1372 */ 1373 *cp-- = '\0'; 1374 } 1375 while (cp >= result) { 1376 if (*cp == '\n') { 1377 *cp = ' '; 1378 } 1379 cp--; 1380 } 1381 Var_Set(line, result, ctxt); 1382 1383 /* 1384 * Close the input side of the pipe. 1385 */ 1386 close(fds[0]); 1387 } 1388 if (freeCmd) { 1389 free(args[2]); 1390 } 1391 } else { 1392 /* 1393 * Normal assignment -- just do it. 1394 */ 1395 Var_Set (line, cp, ctxt); 1396 } 1397 } 1398 1399 /*- 1400 * ParseAddCmd -- 1401 * Lst_ForEach function to add a command line to all targets 1402 * 1403 * Results: 1404 * Always 0 1405 * 1406 * Side Effects: 1407 * A new element is added to the commands list of the node. 1408 */ 1409 static 1410 ParseAddCmd(gn, cmd) 1411 GNode *gn; /* the node to which the command is to be added */ 1412 char *cmd; /* the command to add */ 1413 { 1414 /* if target already supplied, ignore commands */ 1415 if (!(gn->type & OP_HAS_COMMANDS)) 1416 (void)Lst_AtEnd(gn->commands, (ClientData)cmd); 1417 return(0); 1418 } 1419 1420 /*- 1421 *----------------------------------------------------------------------- 1422 * ParseHasCommands -- 1423 * Callback procedure for Parse_File when destroying the list of 1424 * targets on the last dependency line. Marks a target as already 1425 * having commands if it does, to keep from having shell commands 1426 * on multiple dependency lines. 1427 * 1428 * Results: 1429 * Always 0. 1430 * 1431 * Side Effects: 1432 * OP_HAS_COMMANDS may be set for the target. 1433 * 1434 *----------------------------------------------------------------------- 1435 */ 1436 static int 1437 ParseHasCommands(gn) 1438 GNode *gn; /* Node to examine */ 1439 { 1440 if (!Lst_IsEmpty(gn->commands)) { 1441 gn->type |= OP_HAS_COMMANDS; 1442 } 1443 return(0); 1444 } 1445 1446 /*- 1447 *----------------------------------------------------------------------- 1448 * Parse_AddIncludeDir -- 1449 * Add a directory to the path searched for included makefiles 1450 * bracketed by double-quotes. Used by functions in main.c 1451 * 1452 * Results: 1453 * None. 1454 * 1455 * Side Effects: 1456 * The directory is appended to the list. 1457 * 1458 *----------------------------------------------------------------------- 1459 */ 1460 void 1461 Parse_AddIncludeDir (dir) 1462 char *dir; /* The name of the directory to add */ 1463 { 1464 Dir_AddDir (parseIncPath, dir); 1465 } 1466 1467 /*- 1468 *--------------------------------------------------------------------- 1469 * ParseDoInclude -- 1470 * Push to another file. 1471 * 1472 * The input is the line minus the #include. A file spec is a string 1473 * enclosed in <> or "". The former is looked for only in sysIncPath. 1474 * The latter in . and the directories specified by -I command line 1475 * options 1476 * 1477 * Results: 1478 * None 1479 * 1480 * Side Effects: 1481 * A structure is added to the includes Lst and readProc, lineno, 1482 * fname and curFILE are altered for the new file 1483 *--------------------------------------------------------------------- 1484 */ 1485 static void 1486 ParseDoInclude (file) 1487 char *file; /* file specification */ 1488 { 1489 char *fullname; /* full pathname of file */ 1490 IFile *oldFile; /* state associated with current file */ 1491 Lst path; /* the path to use to find the file */ 1492 char endc; /* the character which ends the file spec */ 1493 char *cp; /* current position in file spec */ 1494 Boolean isSystem; /* TRUE if makefile is a system makefile */ 1495 1496 /* 1497 * Skip to delimiter character so we know where to look 1498 */ 1499 while ((*file == ' ') || (*file == '\t')) { 1500 file++; 1501 } 1502 1503 if ((*file != '"') && (*file != '<')) { 1504 Parse_Error (PARSE_FATAL, 1505 ".include filename must be delimited by '\"' or '<'"); 1506 return; 1507 } 1508 1509 /* 1510 * Set the search path on which to find the include file based on the 1511 * characters which bracket its name. Angle-brackets imply it's 1512 * a system Makefile while double-quotes imply it's a user makefile 1513 */ 1514 if (*file == '<') { 1515 isSystem = TRUE; 1516 endc = '>'; 1517 } else { 1518 isSystem = FALSE; 1519 endc = '"'; 1520 } 1521 1522 /* 1523 * Skip to matching delimiter 1524 */ 1525 for (cp = ++file; *cp && *cp != endc; cp++) { 1526 continue; 1527 } 1528 1529 if (*cp != endc) { 1530 Parse_Error (PARSE_FATAL, 1531 "Unclosed .include filename. '%c' expected", endc); 1532 return; 1533 } 1534 *cp = '\0'; 1535 1536 /* 1537 * Substitute for any variables in the file name before trying to 1538 * find the thing. 1539 */ 1540 file = Var_Subst (file, VAR_CMD, FALSE); 1541 1542 /* 1543 * Now we know the file's name and its search path, we attempt to 1544 * find the durn thing. A return of NULL indicates the file don't 1545 * exist. 1546 */ 1547 if (!isSystem) { 1548 /* 1549 * Include files contained in double-quotes are first searched for 1550 * relative to the including file's location. We don't want to 1551 * cd there, of course, so we just tack on the old file's 1552 * leading path components and call Dir_FindFile to see if 1553 * we can locate the beast. 1554 */ 1555 char *prefEnd; 1556 1557 prefEnd = rindex (fname, '/'); 1558 if (prefEnd != (char *)NULL) { 1559 char *newName; 1560 1561 *prefEnd = '\0'; 1562 newName = str_concat (fname, file, STR_ADDSLASH); 1563 fullname = Dir_FindFile (newName, parseIncPath); 1564 if (fullname == (char *)NULL) { 1565 fullname = Dir_FindFile(newName, dirSearchPath); 1566 } 1567 free (newName); 1568 *prefEnd = '/'; 1569 } else { 1570 fullname = (char *)NULL; 1571 } 1572 } else { 1573 fullname = (char *)NULL; 1574 } 1575 1576 if (fullname == (char *)NULL) { 1577 /* 1578 * System makefile or makefile wasn't found in same directory as 1579 * included makefile. Search for it first on the -I search path, 1580 * then on the .PATH search path, if not found in a -I directory. 1581 * XXX: Suffix specific? 1582 */ 1583 fullname = Dir_FindFile (file, parseIncPath); 1584 if (fullname == (char *)NULL) { 1585 fullname = Dir_FindFile(file, dirSearchPath); 1586 } 1587 } 1588 1589 if (fullname == (char *)NULL) { 1590 /* 1591 * Still haven't found the makefile. Look for it on the system 1592 * path as a last resort. 1593 */ 1594 fullname = Dir_FindFile(file, sysIncPath); 1595 } 1596 1597 if (fullname == (char *) NULL) { 1598 *cp = endc; 1599 Parse_Error (PARSE_FATAL, "Could not find %s", file); 1600 return; 1601 } 1602 1603 /* 1604 * Once we find the absolute path to the file, we get to save all the 1605 * state from the current file before we can start reading this 1606 * include file. The state is stored in an IFile structure which 1607 * is placed on a list with other IFile structures. The list makes 1608 * a very nice stack to track how we got here... 1609 */ 1610 oldFile = (IFile *) emalloc (sizeof (IFile)); 1611 oldFile->fname = fname; 1612 1613 oldFile->F = curFILE; 1614 oldFile->lineno = lineno; 1615 1616 (void) Lst_AtFront (includes, (ClientData)oldFile); 1617 1618 /* 1619 * Once the previous state has been saved, we can get down to reading 1620 * the new file. We set up the name of the file to be the absolute 1621 * name of the include file so error messages refer to the right 1622 * place. Naturally enough, we start reading at line number 0. 1623 */ 1624 fname = fullname; 1625 lineno = 0; 1626 1627 curFILE = fopen (fullname, "r"); 1628 if (curFILE == (FILE * ) NULL) { 1629 Parse_Error (PARSE_FATAL, "Cannot open %s", fullname); 1630 /* 1631 * Pop to previous file 1632 */ 1633 (void) ParseEOF(0); 1634 } 1635 } 1636 1637 /*- 1638 *--------------------------------------------------------------------- 1639 * ParseEOF -- 1640 * Called when EOF is reached in the current file. If we were reading 1641 * an include file, the includes stack is popped and things set up 1642 * to go back to reading the previous file at the previous location. 1643 * 1644 * Results: 1645 * CONTINUE if there's more to do. DONE if not. 1646 * 1647 * Side Effects: 1648 * The old curFILE, is closed. The includes list is shortened. 1649 * lineno, curFILE, and fname are changed if CONTINUE is returned. 1650 *--------------------------------------------------------------------- 1651 */ 1652 static int 1653 ParseEOF (opened) 1654 int opened; 1655 { 1656 IFile *ifile; /* the state on the top of the includes stack */ 1657 1658 if (Lst_IsEmpty (includes)) { 1659 return (DONE); 1660 } 1661 1662 ifile = (IFile *) Lst_DeQueue (includes); 1663 free (fname); 1664 fname = ifile->fname; 1665 lineno = ifile->lineno; 1666 if (opened) 1667 (void) fclose (curFILE); 1668 curFILE = ifile->F; 1669 free ((Address)ifile); 1670 return (CONTINUE); 1671 } 1672 1673 /*- 1674 *--------------------------------------------------------------------- 1675 * ParseReadc -- 1676 * Read a character from the current file and update the line number 1677 * counter as necessary 1678 * 1679 * Results: 1680 * The character that was read 1681 * 1682 * Side Effects: 1683 * The lineno counter is incremented if the character is a newline 1684 *--------------------------------------------------------------------- 1685 */ 1686 #ifdef notdef 1687 static int parseReadChar; 1688 1689 #define ParseReadc() (((parseReadChar = getc(curFILE)) == '\n') ? \ 1690 (lineno++, '\n') : parseReadChar) 1691 #else 1692 #define ParseReadc() (getc(curFILE)) 1693 #endif /* notdef */ 1694 1695 1696 /*- 1697 *--------------------------------------------------------------------- 1698 * ParseReadLine -- 1699 * Read an entire line from the input file. Called only by Parse_File. 1700 * To facilitate escaped newlines and what have you, a character is 1701 * buffered in 'lastc', which is '\0' when no characters have been 1702 * read. When we break out of the loop, c holds the terminating 1703 * character and lastc holds a character that should be added to 1704 * the line (unless we don't read anything but a terminator). 1705 * 1706 * Results: 1707 * A line w/o its newline 1708 * 1709 * Side Effects: 1710 * Only those associated with reading a character 1711 *--------------------------------------------------------------------- 1712 */ 1713 static char * 1714 ParseReadLine () 1715 { 1716 Buffer buf; /* Buffer for current line */ 1717 register int c; /* the current character */ 1718 register int lastc; /* The most-recent character */ 1719 Boolean semiNL; /* treat semi-colons as newlines */ 1720 Boolean ignDepOp; /* TRUE if should ignore dependency operators 1721 * for the purposes of setting semiNL */ 1722 Boolean ignComment; /* TRUE if should ignore comments (in a 1723 * shell command */ 1724 char *line; /* Result */ 1725 int lineLength; /* Length of result */ 1726 1727 semiNL = FALSE; 1728 ignDepOp = FALSE; 1729 ignComment = FALSE; 1730 1731 /* 1732 * Handle special-characters at the beginning of the line. Either a 1733 * leading tab (shell command) or pound-sign (possible conditional) 1734 * forces us to ignore comments and dependency operators and treat 1735 * semi-colons as semi-colons (by leaving semiNL FALSE). This also 1736 * discards completely blank lines. 1737 */ 1738 while(1) { 1739 c = ParseReadc(); 1740 1741 if (c == '\t') { 1742 ignComment = ignDepOp = TRUE; 1743 break; 1744 } else if (c == '.') { 1745 ignComment = TRUE; 1746 break; 1747 } else if (c == '\n') { 1748 lineno++; 1749 } else if (c == '#') { 1750 ungetc(c, curFILE); 1751 break; 1752 } else { 1753 /* 1754 * Anything else breaks out without doing anything 1755 */ 1756 break; 1757 } 1758 } 1759 1760 if (c != EOF) { 1761 lastc = c; 1762 buf = Buf_Init(BSIZE); 1763 1764 while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) && 1765 (c != EOF)) 1766 { 1767 test_char: 1768 switch(c) { 1769 case '\n': 1770 /* 1771 * Escaped newline: read characters until a non-space or an 1772 * unescaped newline and replace them all by a single space. 1773 * This is done by storing the space over the backslash and 1774 * dropping through with the next nonspace. If it is a 1775 * semi-colon and semiNL is TRUE, it will be recognized as a 1776 * newline in the code below this... 1777 */ 1778 lineno++; 1779 lastc = ' '; 1780 while ((c = ParseReadc ()) == ' ' || c == '\t') { 1781 continue; 1782 } 1783 if (c == EOF || c == '\n') { 1784 goto line_read; 1785 } else { 1786 /* 1787 * Check for comments, semiNL's, etc. -- easier than 1788 * ungetc(c, curFILE); continue; 1789 */ 1790 goto test_char; 1791 } 1792 break; 1793 case ';': 1794 /* 1795 * Semi-colon: Need to see if it should be interpreted as a 1796 * newline 1797 */ 1798 if (semiNL) { 1799 /* 1800 * To make sure the command that may be following this 1801 * semi-colon begins with a tab, we push one back into the 1802 * input stream. This will overwrite the semi-colon in the 1803 * buffer. If there is no command following, this does no 1804 * harm, since the newline remains in the buffer and the 1805 * whole line is ignored. 1806 */ 1807 ungetc('\t', curFILE); 1808 goto line_read; 1809 } 1810 break; 1811 case '=': 1812 if (!semiNL) { 1813 /* 1814 * Haven't seen a dependency operator before this, so this 1815 * must be a variable assignment -- don't pay attention to 1816 * dependency operators after this. 1817 */ 1818 ignDepOp = TRUE; 1819 } else if (lastc == ':' || lastc == '!') { 1820 /* 1821 * Well, we've seen a dependency operator already, but it 1822 * was the previous character, so this is really just an 1823 * expanded variable assignment. Revert semi-colons to 1824 * being just semi-colons again and ignore any more 1825 * dependency operators. 1826 * 1827 * XXX: Note that a line like "foo : a:=b" will blow up, 1828 * but who'd write a line like that anyway? 1829 */ 1830 ignDepOp = TRUE; semiNL = FALSE; 1831 } 1832 break; 1833 case '#': 1834 if (!ignComment) { 1835 /* 1836 * If the character is a hash mark and it isn't escaped 1837 * (or we're being compatible), the thing is a comment. 1838 * Skip to the end of the line. 1839 */ 1840 do { 1841 c = ParseReadc(); 1842 } while ((c != '\n') && (c != EOF)); 1843 goto line_read; 1844 } 1845 break; 1846 case ':': 1847 case '!': 1848 if (!ignDepOp && (c == ':' || c == '!')) { 1849 /* 1850 * A semi-colon is recognized as a newline only on 1851 * dependency lines. Dependency lines are lines with a 1852 * colon or an exclamation point. Ergo... 1853 */ 1854 semiNL = TRUE; 1855 } 1856 break; 1857 } 1858 /* 1859 * Copy in the previous character and save this one in lastc. 1860 */ 1861 Buf_AddByte (buf, (Byte)lastc); 1862 lastc = c; 1863 1864 } 1865 line_read: 1866 lineno++; 1867 1868 if (lastc != '\0') { 1869 Buf_AddByte (buf, (Byte)lastc); 1870 } 1871 Buf_AddByte (buf, (Byte)'\0'); 1872 line = (char *)Buf_GetAll (buf, &lineLength); 1873 Buf_Destroy (buf, FALSE); 1874 1875 if (line[0] == '.') { 1876 /* 1877 * The line might be a conditional. Ask the conditional module 1878 * about it and act accordingly 1879 */ 1880 switch (Cond_Eval (line)) { 1881 case COND_SKIP: 1882 do { 1883 /* 1884 * Skip to next conditional that evaluates to COND_PARSE. 1885 */ 1886 free (line); 1887 c = ParseReadc(); 1888 /* 1889 * Skip lines until get to one that begins with a 1890 * special char. 1891 */ 1892 while ((c != '.') && (c != EOF)) { 1893 while (((c != '\n') || (lastc == '\\')) && 1894 (c != EOF)) 1895 { 1896 /* 1897 * Advance to next unescaped newline 1898 */ 1899 if ((lastc = c) == '\n') { 1900 lineno++; 1901 } 1902 c = ParseReadc(); 1903 } 1904 lineno++; 1905 1906 lastc = c; 1907 c = ParseReadc (); 1908 } 1909 1910 if (c == EOF) { 1911 Parse_Error (PARSE_FATAL, "Unclosed conditional"); 1912 return ((char *)NULL); 1913 } 1914 1915 /* 1916 * Read the entire line into buf 1917 */ 1918 buf = Buf_Init (BSIZE); 1919 do { 1920 Buf_AddByte (buf, (Byte)c); 1921 c = ParseReadc(); 1922 } while ((c != '\n') && (c != EOF)); 1923 lineno++; 1924 1925 Buf_AddByte (buf, (Byte)'\0'); 1926 line = (char *)Buf_GetAll (buf, &lineLength); 1927 Buf_Destroy (buf, FALSE); 1928 } while (Cond_Eval(line) != COND_PARSE); 1929 /*FALLTHRU*/ 1930 case COND_PARSE: 1931 free (line); 1932 line = ParseReadLine(); 1933 break; 1934 } 1935 } 1936 1937 return (line); 1938 } else { 1939 /* 1940 * Hit end-of-file, so return a NULL line to indicate this. 1941 */ 1942 return((char *)NULL); 1943 } 1944 } 1945 1946 /*- 1947 *----------------------------------------------------------------------- 1948 * ParseFinishLine -- 1949 * Handle the end of a dependency group. 1950 * 1951 * Results: 1952 * Nothing. 1953 * 1954 * Side Effects: 1955 * inLine set FALSE. 'targets' list destroyed. 1956 * 1957 *----------------------------------------------------------------------- 1958 */ 1959 static void 1960 ParseFinishLine() 1961 { 1962 extern int Suff_EndTransform(); 1963 1964 if (inLine) { 1965 Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL); 1966 Lst_Destroy (targets, ParseHasCommands); 1967 inLine = FALSE; 1968 } 1969 } 1970 1971 1972 /*- 1973 *--------------------------------------------------------------------- 1974 * Parse_File -- 1975 * Parse a file into its component parts, incorporating it into the 1976 * current dependency graph. This is the main function and controls 1977 * almost every other function in this module 1978 * 1979 * Results: 1980 * None 1981 * 1982 * Side Effects: 1983 * Loads. Nodes are added to the list of all targets, nodes and links 1984 * are added to the dependency graph. etc. etc. etc. 1985 *--------------------------------------------------------------------- 1986 */ 1987 void 1988 Parse_File(name, stream) 1989 char *name; /* the name of the file being read */ 1990 FILE * stream; /* Stream open to makefile to parse */ 1991 { 1992 register char *cp, /* pointer into the line */ 1993 *line; /* the line we're working on */ 1994 1995 inLine = FALSE; 1996 fname = name; 1997 curFILE = stream; 1998 lineno = 0; 1999 fatals = 0; 2000 2001 do { 2002 while (line = ParseReadLine ()) { 2003 if (*line == '.') { 2004 /* 2005 * Lines that begin with the special character are either 2006 * include or undef directives. 2007 */ 2008 for (cp = line + 1; isspace (*cp); cp++) { 2009 continue; 2010 } 2011 if (strncmp (cp, "include", 7) == 0) { 2012 ParseDoInclude (cp + 7); 2013 goto nextLine; 2014 } else if (strncmp(cp, "undef", 5) == 0) { 2015 char *cp2; 2016 for (cp += 5; isspace(*cp); cp++) { 2017 continue; 2018 } 2019 2020 for (cp2 = cp; !isspace(*cp2) && (*cp2 != '\0'); cp2++) { 2021 continue; 2022 } 2023 2024 *cp2 = '\0'; 2025 2026 Var_Delete(cp, VAR_GLOBAL); 2027 goto nextLine; 2028 } 2029 } 2030 if (*line == '#') { 2031 /* If we're this far, the line must be a comment. */ 2032 goto nextLine; 2033 } 2034 2035 if (*line == '\t' 2036 #ifdef POSIX 2037 || *line == ' ' 2038 #endif 2039 ) 2040 { 2041 /* 2042 * If a line starts with a tab (or space in POSIX-land), it 2043 * can only hope to be a creation command. 2044 */ 2045 shellCommand: 2046 for (cp = line + 1; isspace (*cp); cp++) { 2047 continue; 2048 } 2049 if (*cp) { 2050 if (inLine) { 2051 /* 2052 * So long as it's not a blank line and we're actually 2053 * in a dependency spec, add the command to the list of 2054 * commands of all targets in the dependency spec 2055 */ 2056 Lst_ForEach (targets, ParseAddCmd, (ClientData)cp); 2057 continue; 2058 } else { 2059 Parse_Error (PARSE_FATAL, 2060 "Unassociated shell command \"%.20s\"", 2061 cp); 2062 } 2063 } 2064 } else if (Parse_IsVar (line)) { 2065 ParseFinishLine(); 2066 Parse_DoVar (line, VAR_GLOBAL); 2067 } else { 2068 /* 2069 * We now know it's a dependency line so it needs to have all 2070 * variables expanded before being parsed. Tell the variable 2071 * module to complain if some variable is undefined... 2072 * To make life easier on novices, if the line is indented we 2073 * first make sure the line has a dependency operator in it. 2074 * If it doesn't have an operator and we're in a dependency 2075 * line's script, we assume it's actually a shell command 2076 * and add it to the current list of targets. 2077 * 2078 * Note that POSIX declares all lines that start with 2079 * whitespace are shell commands, so there's no need to check 2080 * here... 2081 */ 2082 Boolean nonSpace = FALSE; 2083 2084 cp = line; 2085 #ifndef POSIX 2086 if (line[0] == ' ') { 2087 while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) { 2088 if (!isspace(*cp)) { 2089 nonSpace = TRUE; 2090 } 2091 cp++; 2092 } 2093 } 2094 2095 if (*cp == '\0') { 2096 if (inLine) { 2097 Parse_Error (PARSE_WARNING, 2098 "Shell command needs a leading tab"); 2099 goto shellCommand; 2100 } else if (nonSpace) { 2101 Parse_Error (PARSE_FATAL, "Missing operator"); 2102 } 2103 } else { 2104 #endif 2105 ParseFinishLine(); 2106 2107 cp = Var_Subst (line, VAR_CMD, TRUE); 2108 free (line); 2109 line = cp; 2110 2111 /* 2112 * Need a non-circular list for the target nodes 2113 */ 2114 targets = Lst_Init (FALSE); 2115 inLine = TRUE; 2116 2117 ParseDoDependency (line); 2118 #ifndef POSIX 2119 } 2120 #endif 2121 } 2122 2123 nextLine: 2124 2125 free (line); 2126 } 2127 /* 2128 * Reached EOF, but it may be just EOF of an include file... 2129 */ 2130 } while (ParseEOF(1) == CONTINUE); 2131 2132 /* 2133 * Make sure conditionals are clean 2134 */ 2135 Cond_End(); 2136 2137 if (fatals) { 2138 fprintf (stderr, "Fatal errors encountered -- cannot continue\n"); 2139 exit (1); 2140 } 2141 } 2142 2143 /*- 2144 *--------------------------------------------------------------------- 2145 * Parse_Init -- 2146 * initialize the parsing module 2147 * 2148 * Results: 2149 * none 2150 * 2151 * Side Effects: 2152 * the parseIncPath list is initialized... 2153 *--------------------------------------------------------------------- 2154 */ 2155 Parse_Init () 2156 { 2157 char *cp, *start; 2158 /* avoid faults on read-only strings */ 2159 static char syspath[] = _PATH_DEFSYSPATH; 2160 2161 mainNode = NILGNODE; 2162 parseIncPath = Lst_Init (FALSE); 2163 sysIncPath = Lst_Init (FALSE); 2164 includes = Lst_Init (FALSE); 2165 2166 /* 2167 * Add the directories from the DEFSYSPATH (more than one may be given 2168 * as dir1:...:dirn) to the system include path. 2169 */ 2170 for (start = syspath; *start != '\0'; start = cp) { 2171 for (cp = start; *cp != '\0' && *cp != ':'; cp++) { 2172 ; 2173 } 2174 if (*cp == '\0') { 2175 Dir_AddDir(sysIncPath, start); 2176 } else { 2177 *cp++ = '\0'; 2178 Dir_AddDir(sysIncPath, start); 2179 } 2180 } 2181 } 2182 2183 /*- 2184 *----------------------------------------------------------------------- 2185 * Parse_MainName -- 2186 * Return a Lst of the main target to create for main()'s sake. If 2187 * no such target exists, we Punt with an obnoxious error message. 2188 * 2189 * Results: 2190 * A Lst of the single node to create. 2191 * 2192 * Side Effects: 2193 * None. 2194 * 2195 *----------------------------------------------------------------------- 2196 */ 2197 Lst 2198 Parse_MainName() 2199 { 2200 Lst main; /* result list */ 2201 2202 main = Lst_Init (FALSE); 2203 2204 if (mainNode == NILGNODE) { 2205 Punt ("make: no target to make.\n"); 2206 /*NOTREACHED*/ 2207 } else if (mainNode->type & OP_DOUBLEDEP) { 2208 Lst_Concat(main, mainNode->cohorts, LST_CONCNEW); 2209 } 2210 (void) Lst_AtEnd (main, (ClientData)mainNode); 2211 return (main); 2212 } 2213