1 /* $NetBSD: parse.c,v 1.25 1996/09/13 04:22:09 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 5 * Copyright (c) 1988, 1989 by Adam de Boor 6 * Copyright (c) 1989 by Berkeley Softworks 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Adam de Boor. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #ifndef lint 42 #if 0 43 static char sccsid[] = "@(#)parse.c 5.18 (Berkeley) 2/19/91"; 44 #else 45 static char rcsid[] = "$NetBSD: parse.c,v 1.25 1996/09/13 04:22:09 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 = '\0', lineLength; 2010 Buffer buf; 2011 2012 c = ParseReadc(); 2013 2014 if (skip) { 2015 /* 2016 * Skip lines until get to one that begins with a 2017 * special char. 2018 */ 2019 while ((c != '.') && (c != EOF)) { 2020 while (((c != '\n') || (lastc == '\\')) && (c != EOF)) { 2021 /* 2022 * Advance to next unescaped newline 2023 */ 2024 if ((lastc = c) == '\n') { 2025 lineno++; 2026 } 2027 c = ParseReadc(); 2028 } 2029 lineno++; 2030 2031 lastc = c; 2032 c = ParseReadc (); 2033 } 2034 } 2035 2036 if (c == EOF) { 2037 Parse_Error (PARSE_FATAL, "Unclosed conditional/for loop"); 2038 return ((char *)NULL); 2039 } 2040 2041 /* 2042 * Read the entire line into buf 2043 */ 2044 buf = Buf_Init (MAKE_BSIZE); 2045 if (c != '\n') { 2046 lastc = '\0'; 2047 do { 2048 if (lastc != '\0' && lastc != '\n') 2049 Buf_AddByte (buf, (Byte) lastc); 2050 if ((lastc = c) == '\n') 2051 lineno++; 2052 c = ParseReadc(); 2053 if (c == '\n' && lastc == '\\') 2054 lastc = '\0'; 2055 } while (((c != '\n') || (lastc == '\0')) && (c != EOF)); 2056 if (lastc != '\0' && lastc != '\n') 2057 Buf_AddByte (buf, (Byte) lastc); 2058 } 2059 lineno++; 2060 2061 Buf_AddByte (buf, (Byte)'\0'); 2062 line = (char *)Buf_GetAll (buf, &lineLength); 2063 Buf_Destroy (buf, FALSE); 2064 return line; 2065 } 2066 2067 2068 /*- 2069 *--------------------------------------------------------------------- 2070 * ParseReadLine -- 2071 * Read an entire line from the input file. Called only by Parse_File. 2072 * To facilitate escaped newlines and what have you, a character is 2073 * buffered in 'lastc', which is '\0' when no characters have been 2074 * read. When we break out of the loop, c holds the terminating 2075 * character and lastc holds a character that should be added to 2076 * the line (unless we don't read anything but a terminator). 2077 * 2078 * Results: 2079 * A line w/o its newline 2080 * 2081 * Side Effects: 2082 * Only those associated with reading a character 2083 *--------------------------------------------------------------------- 2084 */ 2085 static char * 2086 ParseReadLine () 2087 { 2088 Buffer buf; /* Buffer for current line */ 2089 register int c; /* the current character */ 2090 register int lastc; /* The most-recent character */ 2091 Boolean semiNL; /* treat semi-colons as newlines */ 2092 Boolean ignDepOp; /* TRUE if should ignore dependency operators 2093 * for the purposes of setting semiNL */ 2094 Boolean ignComment; /* TRUE if should ignore comments (in a 2095 * shell command */ 2096 char *line; /* Result */ 2097 char *ep; /* to strip trailing blanks */ 2098 int lineLength; /* Length of result */ 2099 2100 semiNL = FALSE; 2101 ignDepOp = FALSE; 2102 ignComment = FALSE; 2103 2104 /* 2105 * Handle special-characters at the beginning of the line. Either a 2106 * leading tab (shell command) or pound-sign (possible conditional) 2107 * forces us to ignore comments and dependency operators and treat 2108 * semi-colons as semi-colons (by leaving semiNL FALSE). This also 2109 * discards completely blank lines. 2110 */ 2111 for (;;) { 2112 c = ParseReadc(); 2113 2114 if (c == '\t') { 2115 ignComment = ignDepOp = TRUE; 2116 break; 2117 } else if (c == '\n') { 2118 lineno++; 2119 } else if (c == '#') { 2120 ParseUnreadc(c); 2121 break; 2122 } else { 2123 /* 2124 * Anything else breaks out without doing anything 2125 */ 2126 break; 2127 } 2128 } 2129 2130 if (c != EOF) { 2131 lastc = c; 2132 buf = Buf_Init(MAKE_BSIZE); 2133 2134 while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) && 2135 (c != EOF)) 2136 { 2137 test_char: 2138 switch(c) { 2139 case '\n': 2140 /* 2141 * Escaped newline: read characters until a non-space or an 2142 * unescaped newline and replace them all by a single space. 2143 * This is done by storing the space over the backslash and 2144 * dropping through with the next nonspace. If it is a 2145 * semi-colon and semiNL is TRUE, it will be recognized as a 2146 * newline in the code below this... 2147 */ 2148 lineno++; 2149 lastc = ' '; 2150 while ((c = ParseReadc ()) == ' ' || c == '\t') { 2151 continue; 2152 } 2153 if (c == EOF || c == '\n') { 2154 goto line_read; 2155 } else { 2156 /* 2157 * Check for comments, semiNL's, etc. -- easier than 2158 * ParseUnreadc(c); continue; 2159 */ 2160 goto test_char; 2161 } 2162 /*NOTREACHED*/ 2163 break; 2164 2165 case ';': 2166 /* 2167 * Semi-colon: Need to see if it should be interpreted as a 2168 * newline 2169 */ 2170 if (semiNL) { 2171 /* 2172 * To make sure the command that may be following this 2173 * semi-colon begins with a tab, we push one back into the 2174 * input stream. This will overwrite the semi-colon in the 2175 * buffer. If there is no command following, this does no 2176 * harm, since the newline remains in the buffer and the 2177 * whole line is ignored. 2178 */ 2179 ParseUnreadc('\t'); 2180 goto line_read; 2181 } 2182 break; 2183 case '=': 2184 if (!semiNL) { 2185 /* 2186 * Haven't seen a dependency operator before this, so this 2187 * must be a variable assignment -- don't pay attention to 2188 * dependency operators after this. 2189 */ 2190 ignDepOp = TRUE; 2191 } else if (lastc == ':' || lastc == '!') { 2192 /* 2193 * Well, we've seen a dependency operator already, but it 2194 * was the previous character, so this is really just an 2195 * expanded variable assignment. Revert semi-colons to 2196 * being just semi-colons again and ignore any more 2197 * dependency operators. 2198 * 2199 * XXX: Note that a line like "foo : a:=b" will blow up, 2200 * but who'd write a line like that anyway? 2201 */ 2202 ignDepOp = TRUE; semiNL = FALSE; 2203 } 2204 break; 2205 case '#': 2206 if (!ignComment) { 2207 if ( 2208 #if 0 2209 compatMake && 2210 #endif 2211 (lastc != '\\')) { 2212 /* 2213 * If the character is a hash mark and it isn't escaped 2214 * (or we're being compatible), the thing is a comment. 2215 * Skip to the end of the line. 2216 */ 2217 do { 2218 c = ParseReadc(); 2219 } while ((c != '\n') && (c != EOF)); 2220 goto line_read; 2221 } else { 2222 /* 2223 * Don't add the backslash. Just let the # get copied 2224 * over. 2225 */ 2226 lastc = c; 2227 continue; 2228 } 2229 } 2230 break; 2231 case ':': 2232 case '!': 2233 if (!ignDepOp && (c == ':' || c == '!')) { 2234 /* 2235 * A semi-colon is recognized as a newline only on 2236 * dependency lines. Dependency lines are lines with a 2237 * colon or an exclamation point. Ergo... 2238 */ 2239 semiNL = TRUE; 2240 } 2241 break; 2242 } 2243 /* 2244 * Copy in the previous character and save this one in lastc. 2245 */ 2246 Buf_AddByte (buf, (Byte)lastc); 2247 lastc = c; 2248 2249 } 2250 line_read: 2251 lineno++; 2252 2253 if (lastc != '\0') { 2254 Buf_AddByte (buf, (Byte)lastc); 2255 } 2256 Buf_AddByte (buf, (Byte)'\0'); 2257 line = (char *)Buf_GetAll (buf, &lineLength); 2258 Buf_Destroy (buf, FALSE); 2259 2260 /* 2261 * Strip trailing blanks and tabs from the line. 2262 * Do not strip a blank or tab that is preceeded by 2263 * a '\' 2264 */ 2265 ep = line; 2266 while (*ep) 2267 ++ep; 2268 while (ep > line && (ep[-1] == ' ' || ep[-1] == '\t')) { 2269 if (ep > line + 1 && ep[-2] == '\\') 2270 break; 2271 --ep; 2272 } 2273 *ep = 0; 2274 2275 if (line[0] == '.') { 2276 /* 2277 * The line might be a conditional. Ask the conditional module 2278 * about it and act accordingly 2279 */ 2280 switch (Cond_Eval (line)) { 2281 case COND_SKIP: 2282 /* 2283 * Skip to next conditional that evaluates to COND_PARSE. 2284 */ 2285 do { 2286 free (line); 2287 line = ParseSkipLine(1); 2288 } while (line && Cond_Eval(line) != COND_PARSE); 2289 if (line == NULL) 2290 break; 2291 /*FALLTHRU*/ 2292 case COND_PARSE: 2293 free ((Address) line); 2294 line = ParseReadLine(); 2295 break; 2296 case COND_INVALID: 2297 if (For_Eval(line)) { 2298 int ok; 2299 free(line); 2300 do { 2301 /* 2302 * Skip after the matching end 2303 */ 2304 line = ParseSkipLine(0); 2305 if (line == NULL) { 2306 Parse_Error (PARSE_FATAL, 2307 "Unexpected end of file in for loop.\n"); 2308 break; 2309 } 2310 ok = For_Eval(line); 2311 free(line); 2312 } 2313 while (ok); 2314 if (line != NULL) 2315 For_Run(); 2316 line = ParseReadLine(); 2317 } 2318 break; 2319 } 2320 } 2321 return (line); 2322 2323 } else { 2324 /* 2325 * Hit end-of-file, so return a NULL line to indicate this. 2326 */ 2327 return((char *)NULL); 2328 } 2329 } 2330 2331 /*- 2332 *----------------------------------------------------------------------- 2333 * ParseFinishLine -- 2334 * Handle the end of a dependency group. 2335 * 2336 * Results: 2337 * Nothing. 2338 * 2339 * Side Effects: 2340 * inLine set FALSE. 'targets' list destroyed. 2341 * 2342 *----------------------------------------------------------------------- 2343 */ 2344 static void 2345 ParseFinishLine() 2346 { 2347 if (inLine) { 2348 Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL); 2349 Lst_Destroy (targets, ParseHasCommands); 2350 targets = NULL; 2351 inLine = FALSE; 2352 } 2353 } 2354 2355 2356 /*- 2357 *--------------------------------------------------------------------- 2358 * Parse_File -- 2359 * Parse a file into its component parts, incorporating it into the 2360 * current dependency graph. This is the main function and controls 2361 * almost every other function in this module 2362 * 2363 * Results: 2364 * None 2365 * 2366 * Side Effects: 2367 * Loads. Nodes are added to the list of all targets, nodes and links 2368 * are added to the dependency graph. etc. etc. etc. 2369 *--------------------------------------------------------------------- 2370 */ 2371 void 2372 Parse_File(name, stream) 2373 char *name; /* the name of the file being read */ 2374 FILE * stream; /* Stream open to makefile to parse */ 2375 { 2376 register char *cp, /* pointer into the line */ 2377 *line; /* the line we're working on */ 2378 2379 inLine = FALSE; 2380 fname = name; 2381 curFILE = stream; 2382 lineno = 0; 2383 fatals = 0; 2384 2385 do { 2386 while ((line = ParseReadLine ()) != NULL) { 2387 if (*line == '.') { 2388 /* 2389 * Lines that begin with the special character are either 2390 * include or undef directives. 2391 */ 2392 for (cp = line + 1; isspace (*cp); cp++) { 2393 continue; 2394 } 2395 if (strncmp (cp, "include", 7) == 0) { 2396 ParseDoInclude (cp + 7); 2397 goto nextLine; 2398 } else if (strncmp(cp, "undef", 5) == 0) { 2399 char *cp2; 2400 for (cp += 5; isspace((unsigned char) *cp); cp++) { 2401 continue; 2402 } 2403 2404 for (cp2 = cp; !isspace((unsigned char) *cp2) && 2405 (*cp2 != '\0'); cp2++) { 2406 continue; 2407 } 2408 2409 *cp2 = '\0'; 2410 2411 Var_Delete(cp, VAR_GLOBAL); 2412 goto nextLine; 2413 } 2414 } 2415 if (*line == '#' || *line == '\0') { 2416 /* If we're this far, the line must be a comment. 2417 (Empty lines are ignored as well) */ 2418 goto nextLine; 2419 } 2420 2421 if (*line == '\t') { 2422 /* 2423 * If a line starts with a tab, it can only hope to be 2424 * a creation command. 2425 */ 2426 #ifndef POSIX 2427 shellCommand: 2428 #endif 2429 for (cp = line + 1; isspace (*cp); cp++) { 2430 continue; 2431 } 2432 if (*cp) { 2433 if (inLine) { 2434 /* 2435 * So long as it's not a blank line and we're actually 2436 * in a dependency spec, add the command to the list of 2437 * commands of all targets in the dependency spec 2438 */ 2439 Lst_ForEach (targets, ParseAddCmd, cp); 2440 Lst_AtEnd(targCmds, (ClientData) line); 2441 continue; 2442 } else { 2443 Parse_Error (PARSE_FATAL, 2444 "Unassociated shell command \"%s\"", 2445 cp); 2446 } 2447 } 2448 #ifdef SYSVINCLUDE 2449 } else if (strncmp (line, "include", 7) == 0 && 2450 isspace((unsigned char) line[7]) && 2451 strchr(line, ':') == NULL) { 2452 /* 2453 * It's an S3/S5-style "include". 2454 */ 2455 ParseTraditionalInclude (line + 7); 2456 goto nextLine; 2457 #endif 2458 } else if (Parse_IsVar (line)) { 2459 ParseFinishLine(); 2460 Parse_DoVar (line, VAR_GLOBAL); 2461 } else { 2462 /* 2463 * We now know it's a dependency line so it needs to have all 2464 * variables expanded before being parsed. Tell the variable 2465 * module to complain if some variable is undefined... 2466 * To make life easier on novices, if the line is indented we 2467 * first make sure the line has a dependency operator in it. 2468 * If it doesn't have an operator and we're in a dependency 2469 * line's script, we assume it's actually a shell command 2470 * and add it to the current list of targets. 2471 */ 2472 #ifndef POSIX 2473 Boolean nonSpace = FALSE; 2474 #endif 2475 2476 cp = line; 2477 if (isspace((unsigned char) line[0])) { 2478 while ((*cp != '\0') && isspace((unsigned char) *cp)) { 2479 cp++; 2480 } 2481 if (*cp == '\0') { 2482 goto nextLine; 2483 } 2484 #ifndef POSIX 2485 while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) { 2486 nonSpace = TRUE; 2487 cp++; 2488 } 2489 #endif 2490 } 2491 2492 #ifndef POSIX 2493 if (*cp == '\0') { 2494 if (inLine) { 2495 Parse_Error (PARSE_WARNING, 2496 "Shell command needs a leading tab"); 2497 goto shellCommand; 2498 } else if (nonSpace) { 2499 Parse_Error (PARSE_FATAL, "Missing operator"); 2500 } 2501 } else { 2502 #endif 2503 ParseFinishLine(); 2504 2505 cp = Var_Subst (NULL, line, VAR_CMD, TRUE); 2506 free (line); 2507 line = cp; 2508 2509 /* 2510 * Need a non-circular list for the target nodes 2511 */ 2512 if (targets) 2513 Lst_Destroy(targets, NOFREE); 2514 2515 targets = Lst_Init (FALSE); 2516 inLine = TRUE; 2517 2518 ParseDoDependency (line); 2519 #ifndef POSIX 2520 } 2521 #endif 2522 } 2523 2524 nextLine: 2525 2526 free (line); 2527 } 2528 /* 2529 * Reached EOF, but it may be just EOF of an include file... 2530 */ 2531 } while (ParseEOF(1) == CONTINUE); 2532 2533 /* 2534 * Make sure conditionals are clean 2535 */ 2536 Cond_End(); 2537 2538 if (fatals) { 2539 fprintf (stderr, "Fatal errors encountered -- cannot continue\n"); 2540 exit (1); 2541 } 2542 } 2543 2544 /*- 2545 *--------------------------------------------------------------------- 2546 * Parse_Init -- 2547 * initialize the parsing module 2548 * 2549 * Results: 2550 * none 2551 * 2552 * Side Effects: 2553 * the parseIncPath list is initialized... 2554 *--------------------------------------------------------------------- 2555 */ 2556 void 2557 Parse_Init () 2558 { 2559 mainNode = NILGNODE; 2560 parseIncPath = Lst_Init (FALSE); 2561 sysIncPath = Lst_Init (FALSE); 2562 includes = Lst_Init (FALSE); 2563 targCmds = Lst_Init (FALSE); 2564 } 2565 2566 void 2567 Parse_End() 2568 { 2569 Lst_Destroy(targCmds, (void (*) __P((ClientData))) free); 2570 if (targets) 2571 Lst_Destroy(targets, NOFREE); 2572 Lst_Destroy(sysIncPath, Dir_Destroy); 2573 Lst_Destroy(parseIncPath, Dir_Destroy); 2574 Lst_Destroy(includes, NOFREE); /* Should be empty now */ 2575 } 2576 2577 2578 /*- 2579 *----------------------------------------------------------------------- 2580 * Parse_MainName -- 2581 * Return a Lst of the main target to create for main()'s sake. If 2582 * no such target exists, we Punt with an obnoxious error message. 2583 * 2584 * Results: 2585 * A Lst of the single node to create. 2586 * 2587 * Side Effects: 2588 * None. 2589 * 2590 *----------------------------------------------------------------------- 2591 */ 2592 Lst 2593 Parse_MainName() 2594 { 2595 Lst main; /* result list */ 2596 2597 main = Lst_Init (FALSE); 2598 2599 if (mainNode == NILGNODE) { 2600 Punt ("make: no target to make.\n"); 2601 /*NOTREACHED*/ 2602 } else if (mainNode->type & OP_DOUBLEDEP) { 2603 (void) Lst_AtEnd (main, (ClientData)mainNode); 2604 Lst_Concat(main, mainNode->cohorts, LST_CONCNEW); 2605 } 2606 else 2607 (void) Lst_AtEnd (main, (ClientData)mainNode); 2608 return (main); 2609 } 2610