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