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