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