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