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