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