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