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