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