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