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