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