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