1 /* $OpenPackages$ */ 2 /* $OpenBSD: parse.c,v 1.70 2007/01/18 17:49:51 espie Exp $ */ 3 /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ 4 5 /* 6 * Copyright (c) 1999 Marc Espie. 7 * 8 * Extensive code changes for the OpenBSD project. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 23 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (c) 1988, 1989, 1990, 1993 33 * The Regents of the University of California. All rights reserved. 34 * Copyright (c) 1989 by Berkeley Softworks 35 * All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * Adam de Boor. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 */ 64 65 #include <assert.h> 66 #include <ctype.h> 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <string.h> 70 #include "config.h" 71 #include "defines.h" 72 #include "dir.h" 73 #include "job.h" 74 #include "buf.h" 75 #include "for.h" 76 #include "lowparse.h" 77 #include "arch.h" 78 #include "cond.h" 79 #include "suff.h" 80 #include "parse.h" 81 #include "var.h" 82 #include "targ.h" 83 #include "error.h" 84 #include "str.h" 85 #include "main.h" 86 #include "gnode.h" 87 #include "memory.h" 88 #include "extern.h" 89 #include "lst.h" 90 #include "parsevar.h" 91 #include "stats.h" 92 #include "garray.h" 93 94 95 static struct growableArray gsources, gtargets; 96 #define SOURCES_SIZE 128 97 #define TARGETS_SIZE 32 98 99 static LIST theParseIncPath;/* list of directories for "..." includes */ 100 static LIST theSysIncPath; /* list of directories for <...> includes */ 101 Lst sysIncPath = &theSysIncPath; 102 Lst parseIncPath = &theParseIncPath; 103 104 #ifdef CLEANUP 105 static LIST targCmds; /* command lines for targets */ 106 #endif 107 108 static GNode *mainNode; /* The main target to create. This is the 109 * first target on the first dependency 110 * line in the first makefile */ 111 /*- 112 * specType contains the SPECial TYPE of the current target. It is 113 * Not if the target is unspecial. If it *is* special, however, the children 114 * are linked as children of the parent but not vice versa. This variable is 115 * set in ParseDoDependency 116 */ 117 typedef enum { 118 Begin, /* .BEGIN */ 119 Default, /* .DEFAULT */ 120 End, /* .END */ 121 Ignore, /* .IGNORE */ 122 Includes, /* .INCLUDES */ 123 Interrupt, /* .INTERRUPT */ 124 Libs, /* .LIBS */ 125 MFlags, /* .MFLAGS or .MAKEFLAGS */ 126 Main, /* .MAIN and we don't have anything user-specified to 127 * make */ 128 NoExport, /* .NOEXPORT */ 129 NoPath, /* .NOPATH */ 130 Not, /* Not special */ 131 NotParallel, /* .NOTPARALELL */ 132 Null, /* .NULL */ 133 Order, /* .ORDER */ 134 Parallel, /* .PARALLEL */ 135 ExPath, /* .PATH */ 136 Phony, /* .PHONY */ 137 Precious, /* .PRECIOUS */ 138 ExShell, /* .SHELL */ 139 Silent, /* .SILENT */ 140 SingleShell, /* .SINGLESHELL */ 141 Suffixes, /* .SUFFIXES */ 142 Wait, /* .WAIT */ 143 Attribute /* Generic attribute */ 144 } ParseSpecial; 145 146 static ParseSpecial specType; 147 static int waiting; 148 149 /* 150 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 151 * seen, then set to each successive source on the line. 152 */ 153 static GNode *predecessor; 154 155 /* 156 * The parseKeywords table is searched using binary search when deciding 157 * if a target or source is special. The 'spec' field is the ParseSpecial 158 * type of the keyword ("Not" if the keyword isn't special as a target) while 159 * the 'op' field is the operator to apply to the list of targets if the 160 * keyword is used as a source ("0" if the keyword isn't special as a source) 161 */ 162 static struct { 163 char *name; /* Name of keyword */ 164 ParseSpecial spec; /* Type when used as a target */ 165 int op; /* Operator when used as a source */ 166 } parseKeywords[] = { 167 { ".BEGIN", Begin, 0 }, 168 { ".DEFAULT", Default, 0 }, 169 { ".END", End, 0 }, 170 { ".EXEC", Attribute, OP_EXEC }, 171 { ".IGNORE", Ignore, OP_IGNORE }, 172 { ".INCLUDES", Includes, 0 }, 173 { ".INTERRUPT", Interrupt, 0 }, 174 { ".INVISIBLE", Attribute, OP_INVISIBLE }, 175 { ".JOIN", Attribute, OP_JOIN }, 176 { ".LIBS", Libs, 0 }, 177 { ".MADE", Attribute, OP_MADE }, 178 { ".MAIN", Main, 0 }, 179 { ".MAKE", Attribute, OP_MAKE }, 180 { ".MAKEFLAGS", MFlags, 0 }, 181 { ".MFLAGS", MFlags, 0 }, 182 #if 0 /* basic scaffolding for NOPATH, not working yet */ 183 { ".NOPATH", NoPath, OP_NOPATH }, 184 #endif 185 { ".NOTMAIN", Attribute, OP_NOTMAIN }, 186 { ".NOTPARALLEL", NotParallel, 0 }, 187 { ".NO_PARALLEL", NotParallel, 0 }, 188 { ".NULL", Null, 0 }, 189 { ".OPTIONAL", Attribute, OP_OPTIONAL }, 190 { ".ORDER", Order, 0 }, 191 { ".PARALLEL", Parallel, 0 }, 192 { ".PATH", ExPath, 0 }, 193 { ".PHONY", Phony, OP_PHONY }, 194 { ".PRECIOUS", Precious, OP_PRECIOUS }, 195 { ".RECURSIVE", Attribute, OP_MAKE }, 196 { ".SHELL", ExShell, 0 }, 197 { ".SILENT", Silent, OP_SILENT }, 198 { ".SINGLESHELL", SingleShell, 0 }, 199 { ".SUFFIXES", Suffixes, 0 }, 200 { ".USE", Attribute, OP_USE }, 201 { ".WAIT", Wait, 0 }, 202 }; 203 204 static int ParseFindKeyword(const char *); 205 static void ParseLinkSrc(GNode *, GNode *); 206 static int ParseDoOp(GNode *, int); 207 static int ParseAddDep(GNode *, GNode *); 208 static void ParseDoSrc(int, const char *); 209 static int ParseFindMain(void *, void *); 210 static void ParseAddDir(void *, void *); 211 static void ParseClearPath(void *); 212 static void ParseDoDependency(char *); 213 static void ParseAddCmd(void *, void *); 214 static void ParseHasCommands(void *); 215 static void ParseDoInclude(char *); 216 static void ParseTraditionalInclude(char *); 217 static void ParseConditionalInclude(char *); 218 static void ParseLookupIncludeFile(char *, char *, bool, bool); 219 #define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop") 220 static void ParseFinishDependency(void); 221 static bool ParseIsCond(Buffer, Buffer, char *); 222 static char *strip_comments(Buffer, const char *); 223 static char *find_include(const char *, bool); 224 225 static void ParseDoCommands(const char *); 226 227 /*- 228 *---------------------------------------------------------------------- 229 * ParseFindKeyword -- 230 * Look in the table of keywords for one matching the given string. 231 * 232 * Results: 233 * The index of the keyword, or -1 if it isn't there. 234 *---------------------------------------------------------------------- 235 */ 236 static int 237 ParseFindKeyword(const char *str) /* keyword to look up */ 238 { 239 int start, 240 end, 241 cur; 242 int diff; 243 244 start = 0; 245 end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1; 246 247 do { 248 cur = start + (end - start) / 2; 249 diff = strcmp(str, parseKeywords[cur].name); 250 251 if (diff == 0) { 252 return cur; 253 } else if (diff < 0) { 254 end = cur - 1; 255 } else { 256 start = cur + 1; 257 } 258 } while (start <= end); 259 return -1; 260 } 261 /*- 262 *--------------------------------------------------------------------- 263 * ParseLinkSrc -- 264 * Link the parent node to its new child. Used by 265 * ParseDoDependency. If the specType isn't 'Not', the parent 266 * isn't linked as a parent of the child. 267 * 268 * Side Effects: 269 * New elements are added to the parents list of cgn and the 270 * children list of cgn. the unmade field of pgn is updated 271 * to reflect the additional child. 272 *--------------------------------------------------------------------- 273 */ 274 static void 275 ParseLinkSrc( 276 GNode *pgn, /* The parent node */ 277 GNode *cgn) /* The child node */ 278 { 279 if (Lst_AddNew(&pgn->children, cgn)) { 280 if (specType == Not) 281 Lst_AtEnd(&cgn->parents, pgn); 282 pgn->unmade++; 283 } 284 } 285 286 /*- 287 *--------------------------------------------------------------------- 288 * ParseDoOp -- 289 * Apply the parsed operator to the given target node. Used in a 290 * Lst_Find call by ParseDoDependency once all targets have 291 * been found and their operator parsed. If the previous and new 292 * operators are incompatible, a major error is taken. 293 * 294 * Side Effects: 295 * The type field of the node is altered to reflect any new bits in 296 * the op. 297 *--------------------------------------------------------------------- 298 */ 299 static int 300 ParseDoOp( 301 GNode *gn, /* The node to which the operator is to be applied */ 302 int op) /* The operator to apply */ 303 { 304 /* 305 * If the dependency mask of the operator and the node don't match and 306 * the node has actually had an operator applied to it before, and 307 * the operator actually has some dependency information in it, complain. 308 */ 309 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 310 !OP_NOP(gn->type) && !OP_NOP(op)) { 311 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); 312 return 0; 313 } 314 315 if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 316 /* If the node was the object of a :: operator, we need to create a 317 * new instance of it for the children and commands on this dependency 318 * line. The new instance is placed on the 'cohorts' list of the 319 * initial one (note the initial one is not on its own cohorts list) 320 * and the new instance is linked to all parents of the initial 321 * instance. */ 322 GNode *cohort; 323 LstNode ln; 324 unsigned int i; 325 326 cohort = Targ_NewGN(gn->name); 327 /* Duplicate links to parents so graph traversal is simple. Perhaps 328 * some type bits should be duplicated? 329 * 330 * Make the cohort invisible as well to avoid duplicating it into 331 * other variables. True, parents of this target won't tend to do 332 * anything with their local variables, but better safe than 333 * sorry. */ 334 for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln)) 335 ParseLinkSrc((GNode *)Lst_Datum(ln), cohort); 336 cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 337 Lst_AtEnd(&gn->cohorts, cohort); 338 339 /* Replace the node in the targets list with the new copy */ 340 for (i = 0; i < gtargets.n; i++) 341 if (gtargets.a[i] == gn) 342 break; 343 gtargets.a[i] = cohort; 344 gn = cohort; 345 } 346 /* We don't want to nuke any previous flags (whatever they were) so we 347 * just OR the new operator into the old. */ 348 gn->type |= op; 349 return 1; 350 } 351 352 /*- 353 *--------------------------------------------------------------------- 354 * ParseAddDep -- 355 * Check if the pair of GNodes given needs to be synchronized. 356 * This has to be when two nodes are on different sides of a 357 * .WAIT directive. 358 * 359 * Results: 360 * Returns 0 if the two targets need to be ordered, 1 otherwise. 361 * If it returns 0, the search can stop. 362 * 363 * Side Effects: 364 * A dependency can be added between the two nodes. 365 * 366 *--------------------------------------------------------------------- 367 */ 368 static int 369 ParseAddDep(GNode *p, GNode *s) 370 { 371 if (p->order < s->order) { 372 /* XXX: This can cause loops, and loops can cause unmade targets, 373 * but checking is tedious, and the debugging output can show the 374 * problem. */ 375 Lst_AtEnd(&p->successors, s); 376 Lst_AtEnd(&s->preds, p); 377 return 1; 378 } 379 else 380 return 0; 381 } 382 383 384 /*- 385 *--------------------------------------------------------------------- 386 * ParseDoSrc -- 387 * Given the name of a source, figure out if it is an attribute 388 * and apply it to the targets if it is. Else decide if there is 389 * some attribute which should be applied *to* the source because 390 * of some special target and apply it if so. Otherwise, make the 391 * source be a child of the targets in the list 'targets' 392 * 393 * Side Effects: 394 * Operator bits may be added to the list of targets or to the source. 395 * The targets may have a new source added to their lists of children. 396 *--------------------------------------------------------------------- 397 */ 398 static void 399 ParseDoSrc( 400 int tOp, /* operator (if any) from special targets */ 401 const char *src) /* name of the source to handle */ 402 { 403 GNode *gn = NULL; 404 405 if (*src == '.' && isupper(src[1])) { 406 int keywd = ParseFindKeyword(src); 407 if (keywd != -1) { 408 int op = parseKeywords[keywd].op; 409 if (op != 0) { 410 Array_Find(>argets, ParseDoOp, op); 411 return; 412 } 413 if (parseKeywords[keywd].spec == Wait) { 414 waiting++; 415 return; 416 } 417 } 418 } 419 420 switch (specType) { 421 case Main: 422 /* 423 * If we have noted the existence of a .MAIN, it means we need 424 * to add the sources of said target to the list of things 425 * to create. The string 'src' is likely to be freed, so we 426 * must make a new copy of it. Note that this will only be 427 * invoked if the user didn't specify a target on the command 428 * line. This is to allow #ifmake's to succeed, or something... 429 */ 430 Lst_AtEnd(create, estrdup(src)); 431 /* 432 * Add the name to the .TARGETS variable as well, so the user can 433 * employ that, if desired. 434 */ 435 Var_Append(".TARGETS", src, VAR_GLOBAL); 436 return; 437 438 case Order: 439 /* 440 * Create proper predecessor/successor links between the previous 441 * source and the current one. 442 */ 443 gn = Targ_FindNode(src, TARG_CREATE); 444 if (predecessor != NULL) { 445 Lst_AtEnd(&predecessor->successors, gn); 446 Lst_AtEnd(&gn->preds, predecessor); 447 } 448 /* 449 * The current source now becomes the predecessor for the next one. 450 */ 451 predecessor = gn; 452 break; 453 454 default: 455 /* 456 * If the source is not an attribute, we need to find/create 457 * a node for it. After that we can apply any operator to it 458 * from a special target or link it to its parents, as 459 * appropriate. 460 * 461 * In the case of a source that was the object of a :: operator, 462 * the attribute is applied to all of its instances (as kept in 463 * the 'cohorts' list of the node) or all the cohorts are linked 464 * to all the targets. 465 */ 466 gn = Targ_FindNode(src, TARG_CREATE); 467 if (tOp) { 468 gn->type |= tOp; 469 } else { 470 Array_ForEach(>argets, ParseLinkSrc, gn); 471 } 472 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 473 GNode *cohort; 474 LstNode ln; 475 476 for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)){ 477 cohort = (GNode *)Lst_Datum(ln); 478 if (tOp) { 479 cohort->type |= tOp; 480 } else { 481 Array_ForEach(>argets, ParseLinkSrc, cohort); 482 } 483 } 484 } 485 break; 486 } 487 488 gn->order = waiting; 489 Array_AtEnd(&gsources, gn); 490 if (waiting) { 491 Array_Find(&gsources, ParseAddDep, gn); 492 } 493 } 494 495 /*- 496 *----------------------------------------------------------------------- 497 * ParseFindMain -- 498 * Find a real target in the list and set it to be the main one. 499 * Called by ParseDoDependency when a main target hasn't been found 500 * yet. 501 * 502 * Results: 503 * 1 if main not found yet, 0 if it is. 504 * 505 * Side Effects: 506 * mainNode is changed and Targ_SetMain is called. 507 *----------------------------------------------------------------------- 508 */ 509 static int 510 ParseFindMain( 511 void *gnp, /* Node to examine */ 512 void *dummy UNUSED) 513 { 514 GNode *gn = (GNode *)gnp; 515 if ((gn->type & OP_NOTARGET) == 0) { 516 mainNode = gn; 517 Targ_SetMain(gn); 518 return 0; 519 } else { 520 return 1; 521 } 522 } 523 524 /*- 525 *----------------------------------------------------------------------- 526 * ParseAddDir -- 527 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going 528 * 529 * Side Effects: 530 * See Dir_AddDir. 531 *----------------------------------------------------------------------- 532 */ 533 static void 534 ParseAddDir(void *path, void *name) 535 { 536 Dir_AddDir((Lst)path, (char *)name); 537 } 538 539 /*- 540 *----------------------------------------------------------------------- 541 * ParseClearPath -- 542 * Reinit path to an empty path 543 *----------------------------------------------------------------------- 544 */ 545 static void 546 ParseClearPath(void *p) 547 { 548 Lst path = (Lst)p; 549 550 Lst_Destroy(path, Dir_Destroy); 551 Lst_Init(path); 552 } 553 554 /*- 555 *--------------------------------------------------------------------- 556 * ParseDoDependency -- 557 * Parse the dependency line in line. 558 * 559 * Side Effects: 560 * The nodes of the sources are linked as children to the nodes of the 561 * targets. Some nodes may be created. 562 * 563 * We parse a dependency line by first extracting words from the line and 564 * finding nodes in the list of all targets with that name. This is done 565 * until a character is encountered which is an operator character. Currently 566 * these are only ! and :. At this point the operator is parsed and the 567 * pointer into the line advanced until the first source is encountered. 568 * The parsed operator is applied to each node in the 'targets' list, 569 * which is where the nodes found for the targets are kept, by means of 570 * the ParseDoOp function. 571 * The sources are read in much the same way as the targets were except 572 * that now they are expanded using the wildcarding scheme of the C-Shell 573 * and all instances of the resulting words in the list of all targets 574 * are found. Each of the resulting nodes is then linked to each of the 575 * targets as one of its children. 576 * Certain targets are handled specially. These are the ones detailed 577 * by the specType variable. 578 * The storing of transformation rules is also taken care of here. 579 * A target is recognized as a transformation rule by calling 580 * Suff_IsTransform. If it is a transformation rule, its node is gotten 581 * from the suffix module via Suff_AddTransform rather than the standard 582 * Targ_FindNode in the target module. 583 *--------------------------------------------------------------------- 584 */ 585 static void 586 ParseDoDependency(char *line) /* the line to parse */ 587 { 588 char *cp; /* our current position */ 589 GNode *gn; /* a general purpose temporary node */ 590 int op; /* the operator on the line */ 591 char savec; /* a place to save a character */ 592 LIST paths; /* List of search paths to alter when parsing 593 * a list of .PATH targets */ 594 int tOp; /* operator from special target */ 595 tOp = 0; 596 597 specType = Not; 598 waiting = 0; 599 Lst_Init(&paths); 600 601 Array_Reset(&gsources); 602 603 do { 604 for (cp = line; *cp && !isspace(*cp) && *cp != '(';) 605 if (*cp == '$') 606 /* Must be a dynamic source (would have been expanded 607 * otherwise), so call the Var module to parse the puppy 608 * so we can safely advance beyond it...There should be 609 * no errors in this, as they would have been discovered 610 * in the initial Var_Subst and we wouldn't be here. */ 611 cp += Var_ParseSkip(cp, NULL, NULL); 612 else { 613 /* We don't want to end a word on ':' or '!' if there is a 614 * better match later on in the string. By "better" I mean 615 * one that is followed by whitespace. This allows the user 616 * to have targets like: 617 * fie::fi:fo: fum 618 * where "fie::fi:fo" is the target. In real life this is used 619 * for perl5 library man pages where "::" separates an object 620 * from its class. Ie: "File::Spec::Unix". This behaviour 621 * is also consistent with other versions of make. */ 622 if (*cp == '!' || *cp == ':') { 623 char *p = cp + 1; 624 625 if (*cp == ':' && *p == ':') 626 p++; 627 628 /* Found the best match already. */ 629 if (isspace(*p) || *p == '\0') 630 break; 631 632 do { 633 p += strcspn(p, "!:"); 634 if (*p == '\0') 635 break; 636 p++; 637 } while (!isspace(*p)); 638 639 /* No better match later on... */ 640 if (*p == '\0') 641 break; 642 643 } 644 cp++; 645 } 646 if (*cp == '(') { 647 LIST temp; 648 Lst_Init(&temp); 649 /* Archives must be handled specially to make sure the OP_ARCHV 650 * flag is set in their 'type' field, for one thing, and because 651 * things like "archive(file1.o file2.o file3.o)" are permissible. 652 * Arch_ParseArchive will set 'line' to be the first non-blank 653 * after the archive-spec. It creates/finds nodes for the members 654 * and places them on the given list, returning true if all 655 * went well and false if there was an error in the 656 * specification. On error, line should remain untouched. */ 657 if (!Arch_ParseArchive(&line, &temp, NULL)) { 658 Parse_Error(PARSE_FATAL, 659 "Error in archive specification: \"%s\"", line); 660 return; 661 } else { 662 AppendList2Array(&temp, >argets); 663 Lst_Destroy(&temp, NOFREE); 664 continue; 665 } 666 } 667 savec = *cp; 668 669 if (*cp == '\0') { 670 /* Ending a dependency line without an operator is a Bozo no-no */ 671 Parse_Error(PARSE_FATAL, "Need an operator"); 672 return; 673 } 674 *cp = '\0'; 675 /* Have a word in line. See if it's a special target and set 676 * specType to match it. */ 677 if (*line == '.' && isupper(line[1])) { 678 /* See if the target is a special target that must have it 679 * or its sources handled specially. */ 680 int keywd = ParseFindKeyword(line); 681 if (keywd != -1) { 682 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { 683 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 684 return; 685 } 686 687 specType = parseKeywords[keywd].spec; 688 tOp = parseKeywords[keywd].op; 689 690 /* 691 * Certain special targets have special semantics: 692 * .PATH Have to set the dirSearchPath 693 * variable too 694 * .MAIN Its sources are only used if 695 * nothing has been specified to 696 * create. 697 * .DEFAULT Need to create a node to hang 698 * commands on, but we don't want 699 * it in the graph, nor do we want 700 * it to be the Main Target, so we 701 * create it, set OP_NOTMAIN and 702 * add it to the list, setting 703 * DEFAULT to the new node for 704 * later use. We claim the node is 705 * A transformation rule to make 706 * life easier later, when we'll 707 * use Make_HandleUse to actually 708 * apply the .DEFAULT commands. 709 * .PHONY The list of targets 710 * .NOPATH Don't search for file in the path 711 * .BEGIN 712 * .END 713 * .INTERRUPT Are not to be considered the 714 * main target. 715 * .NOTPARALLEL Make only one target at a time. 716 * .SINGLESHELL Create a shell for each command. 717 * .ORDER Must set initial predecessor to NULL 718 */ 719 switch (specType) { 720 case ExPath: 721 Lst_AtEnd(&paths, dirSearchPath); 722 break; 723 case Main: 724 if (!Lst_IsEmpty(create)) { 725 specType = Not; 726 } 727 break; 728 case Begin: 729 case End: 730 case Interrupt: 731 gn = Targ_FindNode(line, TARG_CREATE); 732 gn->type |= OP_NOTMAIN; 733 Array_AtEnd(>argets, gn); 734 break; 735 case Default: 736 gn = Targ_NewGN(".DEFAULT"); 737 gn->type |= OP_NOTMAIN|OP_TRANSFORM; 738 Array_AtEnd(>argets, gn); 739 DEFAULT = gn; 740 break; 741 case NotParallel: 742 { 743 extern int maxJobs; 744 745 maxJobs = 1; 746 break; 747 } 748 case SingleShell: 749 compatMake = 1; 750 break; 751 case Order: 752 predecessor = NULL; 753 break; 754 default: 755 break; 756 } 757 } else if (strncmp(line, ".PATH", 5) == 0) { 758 /* 759 * .PATH<suffix> has to be handled specially. 760 * Call on the suffix module to give us a path to 761 * modify. 762 */ 763 Lst path; 764 765 specType = ExPath; 766 path = Suff_GetPath(&line[5]); 767 if (path == NULL) { 768 Parse_Error(PARSE_FATAL, 769 "Suffix '%s' not defined (yet)", 770 &line[5]); 771 return; 772 } else { 773 Lst_AtEnd(&paths, path); 774 } 775 } 776 } 777 778 /* 779 * Have word in line. Get or create its node and stick it at 780 * the end of the targets list 781 */ 782 if (specType == Not && *line != '\0') { 783 char *targName; 784 785 if (Dir_HasWildcards(line)) { 786 /* 787 * Targets are to be sought only in the current directory, 788 * so create an empty path for the thing. Note we need to 789 * use Dir_Destroy in the destruction of the path as the 790 * Dir module could have added a directory to the path... 791 */ 792 LIST emptyPath; 793 LIST curTargs; /* list of target names to be found 794 * and added to the targets list */ 795 796 Lst_Init(&emptyPath); 797 Lst_Init(&curTargs); 798 Dir_Expand(line, &emptyPath, &curTargs); 799 Lst_Destroy(&emptyPath, Dir_Destroy); 800 while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) { 801 if (!Suff_IsTransform(targName)) 802 gn = Targ_FindNode(targName, TARG_CREATE); 803 else 804 gn = Suff_AddTransform(targName); 805 806 if (gn != NULL) 807 Array_AtEnd(>argets, gn); 808 } 809 Lst_Destroy(&curTargs, NOFREE); 810 } else { 811 if (!Suff_IsTransform(line)) 812 gn = Targ_FindNode(line, TARG_CREATE); 813 else 814 gn = Suff_AddTransform(line); 815 816 if (gn != NULL) 817 Array_AtEnd(>argets, gn); 818 /* Don't need the list of target names anymore... */ 819 } 820 } else if (specType == ExPath && *line != '.' && *line != '\0') 821 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 822 823 *cp = savec; 824 /* 825 * If it is a special type and not .PATH, it's the only target we 826 * allow on this line... 827 */ 828 if (specType != Not && specType != ExPath) { 829 bool warn = false; 830 831 while (*cp != '!' && *cp != ':' && *cp) { 832 if (*cp != ' ' && *cp != '\t') { 833 warn = true; 834 } 835 cp++; 836 } 837 if (warn) { 838 Parse_Error(PARSE_WARNING, "Extra target ignored"); 839 } 840 } else { 841 while (*cp && isspace(*cp)) { 842 cp++; 843 } 844 } 845 line = cp; 846 } while (*line != '!' && *line != ':' && *line); 847 848 if (!Array_IsEmpty(>argets)) { 849 switch (specType) { 850 default: 851 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); 852 break; 853 case Default: 854 case Begin: 855 case End: 856 case Interrupt: 857 /* These four create nodes on which to hang commands, so 858 * targets shouldn't be empty... */ 859 case Not: 860 /* Nothing special here -- targets can be empty if it wants. */ 861 break; 862 } 863 } 864 865 /* Have now parsed all the target names. Must parse the operator next. The 866 * result is left in op . */ 867 if (*cp == '!') { 868 op = OP_FORCE; 869 } else if (*cp == ':') { 870 if (cp[1] == ':') { 871 op = OP_DOUBLEDEP; 872 cp++; 873 } else { 874 op = OP_DEPENDS; 875 } 876 } else { 877 Parse_Error(PARSE_FATAL, "Missing dependency operator"); 878 return; 879 } 880 881 cp++; /* Advance beyond operator */ 882 883 Array_Find(>argets, ParseDoOp, op); 884 885 /* 886 * Get to the first source 887 */ 888 while (*cp && isspace(*cp)) { 889 cp++; 890 } 891 line = cp; 892 893 /* 894 * Several special targets take different actions if present with no 895 * sources: 896 * a .SUFFIXES line with no sources clears out all old suffixes 897 * a .PRECIOUS line makes all targets precious 898 * a .IGNORE line ignores errors for all targets 899 * a .SILENT line creates silence when making all targets 900 * a .PATH removes all directories from the search path(s). 901 */ 902 if (!*line) { 903 switch (specType) { 904 case Suffixes: 905 Suff_ClearSuffixes(); 906 break; 907 case Precious: 908 allPrecious = true; 909 break; 910 case Ignore: 911 ignoreErrors = true; 912 break; 913 case Silent: 914 beSilent = true; 915 break; 916 case ExPath: 917 Lst_Every(&paths, ParseClearPath); 918 break; 919 default: 920 break; 921 } 922 } else if (specType == MFlags) { 923 /* 924 * Call on functions in main.c to deal with these arguments and 925 * set the initial character to a null-character so the loop to 926 * get sources won't get anything 927 */ 928 Main_ParseArgLine(line); 929 *line = '\0'; 930 } else if (specType == ExShell) { 931 if (!Job_ParseShell(line)) { 932 Parse_Error(PARSE_FATAL, "improper shell specification"); 933 return; 934 } 935 *line = '\0'; 936 } else if (specType == NotParallel || specType == SingleShell) { 937 *line = '\0'; 938 } 939 940 /* 941 * NOW GO FOR THE SOURCES 942 */ 943 if (specType == Suffixes || specType == ExPath || 944 specType == Includes || specType == Libs || 945 specType == Null) { 946 while (*line) { 947 /* 948 * If the target was one that doesn't take files as its sources 949 * but takes something like suffixes, we take each 950 * space-separated word on the line as a something and deal 951 * with it accordingly. 952 * 953 * If the target was .SUFFIXES, we take each source as a 954 * suffix and add it to the list of suffixes maintained by the 955 * Suff module. 956 * 957 * If the target was a .PATH, we add the source as a directory 958 * to search on the search path. 959 * 960 * If it was .INCLUDES, the source is taken to be the suffix of 961 * files which will be #included and whose search path should 962 * be present in the .INCLUDES variable. 963 * 964 * If it was .LIBS, the source is taken to be the suffix of 965 * files which are considered libraries and whose search path 966 * should be present in the .LIBS variable. 967 * 968 * If it was .NULL, the source is the suffix to use when a file 969 * has no valid suffix. 970 */ 971 char savec; 972 while (*cp && !isspace(*cp)) { 973 cp++; 974 } 975 savec = *cp; 976 *cp = '\0'; 977 switch (specType) { 978 case Suffixes: 979 Suff_AddSuffix(line); 980 break; 981 case ExPath: 982 Lst_ForEach(&paths, ParseAddDir, line); 983 break; 984 case Includes: 985 Suff_AddInclude(line); 986 break; 987 case Libs: 988 Suff_AddLib(line); 989 break; 990 case Null: 991 Suff_SetNull(line); 992 break; 993 default: 994 break; 995 } 996 *cp = savec; 997 if (savec != '\0') { 998 cp++; 999 } 1000 while (*cp && isspace(*cp)) { 1001 cp++; 1002 } 1003 line = cp; 1004 } 1005 Lst_Destroy(&paths, NOFREE); 1006 } else { 1007 while (*line) { 1008 /* 1009 * The targets take real sources, so we must beware of archive 1010 * specifications (i.e. things with left parentheses in them) 1011 * and handle them accordingly. 1012 */ 1013 while (*cp && !isspace(*cp)) { 1014 if (*cp == '(' && cp > line && cp[-1] != '$') { 1015 /* 1016 * Only stop for a left parenthesis if it isn't at the 1017 * start of a word (that'll be for variable changes 1018 * later) and isn't preceded by a dollar sign (a dynamic 1019 * source). 1020 */ 1021 break; 1022 } else { 1023 cp++; 1024 } 1025 } 1026 1027 if (*cp == '(') { 1028 GNode *gn; 1029 LIST sources; /* list of archive source names after 1030 * expansion */ 1031 1032 Lst_Init(&sources); 1033 if (!Arch_ParseArchive(&line, &sources, NULL)) { 1034 Parse_Error(PARSE_FATAL, 1035 "Error in source archive spec \"%s\"", line); 1036 return; 1037 } 1038 1039 while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL) 1040 ParseDoSrc(tOp, gn->name); 1041 cp = line; 1042 } else { 1043 if (*cp) { 1044 *cp = '\0'; 1045 cp += 1; 1046 } 1047 1048 ParseDoSrc(tOp, line); 1049 } 1050 while (*cp && isspace(*cp)) { 1051 cp++; 1052 } 1053 line = cp; 1054 } 1055 } 1056 1057 if (mainNode == NULL) { 1058 /* If we have yet to decide on a main target to make, in the 1059 * absence of any user input, we want the first target on 1060 * the first dependency line that is actually a real target 1061 * (i.e. isn't a .USE or .EXEC rule) to be made. */ 1062 Array_Find(>argets, ParseFindMain, NULL); 1063 } 1064 1065 /* Finally, destroy the list of sources. */ 1066 } 1067 1068 /*- 1069 * ParseAddCmd -- 1070 * Lst_ForEach function to add a command line to all targets 1071 * 1072 * Side Effects: 1073 * A new element is added to the commands list of the node. 1074 */ 1075 static void 1076 ParseAddCmd( 1077 void *gnp, /* the node to which the command is to be added */ 1078 void *cmd) /* the command to add */ 1079 { 1080 GNode *gn = (GNode *)gnp; 1081 /* if target already supplied, ignore commands */ 1082 if (!(gn->type & OP_HAS_COMMANDS)) { 1083 Lst_AtEnd(&gn->commands, cmd); 1084 if (!gn->lineno) { 1085 gn->lineno = Parse_Getlineno(); 1086 gn->fname = Parse_Getfilename(); 1087 } 1088 } 1089 } 1090 1091 /*- 1092 *----------------------------------------------------------------------- 1093 * ParseHasCommands -- 1094 * Callback procedure for Parse_File when destroying the list of 1095 * targets on the last dependency line. Marks a target as already 1096 * having commands if it does, to keep from having shell commands 1097 * on multiple dependency lines. 1098 * 1099 * Side Effects: 1100 * OP_HAS_COMMANDS may be set for the target. 1101 *----------------------------------------------------------------------- 1102 */ 1103 static void 1104 ParseHasCommands(void *gnp) /* Node to examine */ 1105 { 1106 GNode *gn = (GNode *)gnp; 1107 if (!Lst_IsEmpty(&gn->commands)) { 1108 gn->type |= OP_HAS_COMMANDS; 1109 } 1110 } 1111 1112 /*- 1113 *----------------------------------------------------------------------- 1114 * Parse_AddIncludeDir -- 1115 * Add a directory to the path searched for included makefiles 1116 * bracketed by double-quotes. Used by functions in main.c 1117 *----------------------------------------------------------------------- 1118 */ 1119 void 1120 Parse_AddIncludeDir(const char *dir) /* The name of the directory to add */ 1121 { 1122 Dir_AddDir(parseIncPath, dir); 1123 } 1124 1125 /*- 1126 *--------------------------------------------------------------------- 1127 * ParseDoInclude -- 1128 * Push to another file. 1129 * 1130 * The input is the line minus the #include. A file spec is a string 1131 * enclosed in <> or "". The former is looked for only in sysIncPath. 1132 * The latter in . and the directories specified by -I command line 1133 * options 1134 * 1135 * Side Effects: 1136 * old parse context is pushed on the stack, new file becomes 1137 * current context. 1138 *--------------------------------------------------------------------- 1139 */ 1140 static void 1141 ParseDoInclude(char *file)/* file specification */ 1142 { 1143 char endc; /* the character which ends the file spec */ 1144 char *cp; /* current position in file spec */ 1145 bool isSystem; /* true if makefile is a system makefile */ 1146 1147 /* Skip to delimiter character so we know where to look. */ 1148 while (*file == ' ' || *file == '\t') 1149 file++; 1150 1151 if (*file != '"' && *file != '<') { 1152 Parse_Error(PARSE_FATAL, 1153 ".include filename must be delimited by '\"' or '<'"); 1154 return; 1155 } 1156 1157 /* Set the search path on which to find the include file based on the 1158 * characters which bracket its name. Angle-brackets imply it's 1159 * a system Makefile while double-quotes imply it's a user makefile */ 1160 if (*file == '<') { 1161 isSystem = true; 1162 endc = '>'; 1163 } else { 1164 isSystem = false; 1165 endc = '"'; 1166 } 1167 1168 /* Skip to matching delimiter. */ 1169 for (cp = ++file; *cp != endc; cp++) { 1170 if (*cp == '\0') { 1171 Parse_Error(PARSE_FATAL, 1172 "Unclosed %cinclude filename. '%c' expected", 1173 '.', endc); 1174 return; 1175 } 1176 } 1177 ParseLookupIncludeFile(file, cp, isSystem, true); 1178 } 1179 1180 /*- 1181 *--------------------------------------------------------------------- 1182 * ParseTraditionalInclude -- 1183 * Push to another file. 1184 * 1185 * The input is the line minus the "include". The file name is 1186 * the string following the "include". 1187 * 1188 * Side Effects: 1189 * old parse context is pushed on the stack, new file becomes 1190 * current context. 1191 * 1192 * XXX May wish to support multiple files and wildcards ? 1193 *--------------------------------------------------------------------- 1194 */ 1195 static void 1196 ParseTraditionalInclude(char *file) /* file specification */ 1197 { 1198 char *cp; /* current position in file spec */ 1199 1200 /* Skip over whitespace. */ 1201 while (isspace(*file)) 1202 file++; 1203 if (*file == '\0') { 1204 Parse_Error(PARSE_FATAL, 1205 "Filename missing from \"include\""); 1206 return; 1207 } 1208 /* Skip to end of line or next whitespace. */ 1209 for (cp = file; *cp != '\0' && !isspace(*cp);) 1210 cp++; 1211 1212 ParseLookupIncludeFile(file, cp, true, true); 1213 } 1214 1215 /*- 1216 *--------------------------------------------------------------------- 1217 * ParseConditionalInclude -- 1218 * May push to another file. 1219 * 1220 * No error if the file does not exist. 1221 * See ParseTraditionalInclude otherwise. 1222 *--------------------------------------------------------------------- 1223 */ 1224 static void 1225 ParseConditionalInclude(char *file)/* file specification */ 1226 { 1227 char *cp; /* current position in file spec */ 1228 1229 /* Skip over whitespace. */ 1230 while (isspace(*file)) 1231 file++; 1232 if (*file == '\0') { 1233 Parse_Error(PARSE_FATAL, 1234 "Filename missing from \"include\""); 1235 return; 1236 } 1237 /* Skip to end of line or next whitespace. */ 1238 for (cp = file; *cp != '\0' && !isspace(*cp);) 1239 cp++; 1240 1241 ParseLookupIncludeFile(file, cp, true, false); 1242 } 1243 1244 /* helper function for ParseLookupIncludeFile */ 1245 static char * 1246 find_include(const char *file, bool isSystem) 1247 { 1248 char *fullname; 1249 1250 /* Look up system files on the system path first */ 1251 if (isSystem) { 1252 fullname = Dir_FindFileNoDot(file, sysIncPath); 1253 if (fullname) 1254 return fullname; 1255 } 1256 1257 /* Handle non-system non-absolute files... */ 1258 if (!isSystem && file[0] != '/') { 1259 /* ... by first searching relative to the including file's 1260 * location. We don't want to cd there, of course, so we 1261 * just tack on the old file's leading path components 1262 * and call Dir_FindFile to see if we can locate the beast. */ 1263 char *slash; 1264 const char *fname; 1265 1266 fname = Parse_Getfilename(); 1267 1268 slash = strrchr(fname, '/'); 1269 if (slash != NULL) { 1270 char *newName; 1271 1272 newName = Str_concati(fname, slash, file, strchr(file, '\0'), '/'); 1273 fullname = Dir_FindFile(newName, parseIncPath); 1274 if (fullname == NULL) 1275 fullname = Dir_FindFile(newName, dirSearchPath); 1276 free(newName); 1277 if (fullname) 1278 return fullname; 1279 } 1280 } 1281 1282 /* Now look first on the -I search path, then on the .PATH 1283 * search path, if not found in a -I directory. 1284 * XXX: Suffix specific? */ 1285 fullname = Dir_FindFile(file, parseIncPath); 1286 if (fullname) 1287 return fullname; 1288 fullname = Dir_FindFile(file, dirSearchPath); 1289 if (fullname) 1290 return fullname; 1291 1292 /* Still haven't found the makefile. Look for it on the system 1293 * path as a last resort. */ 1294 if (isSystem) 1295 return NULL; 1296 else 1297 return Dir_FindFile(file, sysIncPath); 1298 } 1299 1300 /* Common part to lookup and read an include file. */ 1301 static void 1302 ParseLookupIncludeFile(char *spec, char *endSpec, bool isSystem, 1303 bool errIfNotFound) 1304 { 1305 char *file; 1306 char *fullname; 1307 char endc; 1308 1309 /* Substitute for any variables in the file name before trying to 1310 * find the thing. */ 1311 endc = *endSpec; 1312 *endSpec = '\0'; 1313 file = Var_Subst(spec, NULL, false); 1314 *endSpec = endc; 1315 1316 fullname = find_include(file, isSystem); 1317 if (fullname == NULL && errIfNotFound) 1318 Parse_Error(PARSE_FATAL, "Could not find %s", file); 1319 1320 1321 free(file); 1322 1323 if (fullname != NULL) { 1324 FILE *f; 1325 1326 f = fopen(fullname, "r"); 1327 if (f == NULL && errIfNotFound) { 1328 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 1329 } else { 1330 /* Once we find the absolute path to the file, we push the current 1331 * stream to the includes stack, and start reading from the new 1332 * file. We set up the file name to be its absolute name so that 1333 * error messages are informative. */ 1334 Parse_FromFile(fullname, f); 1335 } 1336 } 1337 } 1338 1339 1340 1341 1342 /* Strip comments from the line. May return either a copy of the line, or 1343 * the line itself. */ 1344 static char * 1345 strip_comments(Buffer copy, const char *line) 1346 { 1347 const char *comment; 1348 const char *p; 1349 1350 comment = strchr(line, '#'); 1351 assert(comment != line); 1352 if (comment == NULL) 1353 return (char *)line; 1354 else { 1355 Buf_Reset(copy); 1356 1357 for (p = line; *p != '\0'; p++) { 1358 if (*p == '\\') { 1359 if (p[1] == '#') { 1360 Buf_Addi(copy, line, p); 1361 Buf_AddChar(copy, '#'); 1362 line = p+2; 1363 } 1364 if (p[1] != '\0') 1365 p++; 1366 } else if (*p == '#') 1367 break; 1368 } 1369 Buf_Addi(copy, line, p); 1370 Buf_KillTrailingSpaces(copy); 1371 return Buf_Retrieve(copy); 1372 } 1373 } 1374 1375 static bool 1376 ParseIsCond(Buffer linebuf, Buffer copy, char *line) 1377 { 1378 1379 char *stripped; 1380 1381 while (*line != '\0' && isspace(*line)) 1382 line++; 1383 1384 /* The line might be a conditional. Ask the conditional module 1385 * about it and act accordingly. */ 1386 switch (Cond_Eval(line)) { 1387 case COND_SKIP: 1388 /* Skip to next conditional that evaluates to COND_PARSE. */ 1389 do { 1390 line = Parse_ReadNextConditionalLine(linebuf); 1391 if (line != NULL) { 1392 while (*line != '\0' && isspace(*line)) 1393 line++; 1394 stripped = strip_comments(copy, line); 1395 } 1396 } while (line != NULL && Cond_Eval(stripped) != COND_PARSE); 1397 /* FALLTHROUGH */ 1398 case COND_PARSE: 1399 return true; 1400 case COND_ISFOR: { 1401 For *loop; 1402 1403 loop = For_Eval(line+3); 1404 if (loop != NULL) { 1405 bool ok; 1406 do { 1407 /* Find the matching endfor. */ 1408 line = ParseReadLoopLine(linebuf); 1409 if (line == NULL) { 1410 Parse_Error(PARSE_FATAL, 1411 "Unexpected end of file in for loop.\n"); 1412 return false; 1413 } 1414 ok = For_Accumulate(loop, line); 1415 } while (ok); 1416 For_Run(loop); 1417 return true; 1418 } 1419 break; 1420 } 1421 case COND_ISINCLUDE: 1422 ParseDoInclude(line + 7); 1423 return true; 1424 case COND_ISUNDEF: { 1425 char *cp; 1426 1427 line+=5; 1428 while (*line != '\0' && isspace(*line)) 1429 line++; 1430 for (cp = line; !isspace(*cp) && *cp != '\0';) 1431 cp++; 1432 *cp = '\0'; 1433 Var_Delete(line); 1434 return true; 1435 } 1436 default: 1437 break; 1438 } 1439 1440 return false; 1441 } 1442 1443 /*- 1444 *----------------------------------------------------------------------- 1445 * ParseFinishDependency -- 1446 * Handle the end of a dependency group. 1447 * 1448 * Side Effects: 1449 * 'targets' list destroyed. 1450 * 1451 *----------------------------------------------------------------------- 1452 */ 1453 static void 1454 ParseFinishDependency(void) 1455 { 1456 Array_Every(>argets, Suff_EndTransform); 1457 Array_Every(>argets, ParseHasCommands); 1458 Array_Reset(>argets); 1459 } 1460 1461 static void 1462 ParseDoCommands(const char *line) 1463 { 1464 /* add the command to the list of 1465 * commands of all targets in the dependency spec */ 1466 char *cmd = estrdup(line); 1467 1468 Array_ForEach(>argets, ParseAddCmd, cmd); 1469 #ifdef CLEANUP 1470 Lst_AtEnd(&targCmds, cmd); 1471 #endif 1472 } 1473 1474 void 1475 Parse_File( 1476 const char *name, /* the name of the file being read */ 1477 FILE *stream) /* Stream open to makefile to parse */ 1478 { 1479 char *cp, /* pointer into the line */ 1480 *line; /* the line we're working on */ 1481 bool inDependency; /* true if currently in a dependency 1482 * line or its commands */ 1483 1484 BUFFER buf; 1485 BUFFER copy; 1486 1487 Buf_Init(&buf, MAKE_BSIZE); 1488 Buf_Init(©, MAKE_BSIZE); 1489 inDependency = false; 1490 Parse_FromFile(name, stream); 1491 1492 do { 1493 while ((line = Parse_ReadNormalLine(&buf)) != NULL) { 1494 if (*line == '\t') { 1495 if (inDependency) 1496 ParseDoCommands(line+1); 1497 else 1498 Parse_Error(PARSE_FATAL, 1499 "Unassociated shell command \"%s\"", 1500 line); 1501 } else { 1502 char *stripped; 1503 stripped = strip_comments(©, line); 1504 if (*stripped == '.' && ParseIsCond(&buf, ©, stripped+1)) 1505 ; 1506 else if (FEATURES(FEATURE_SYSVINCLUDE) && 1507 strncmp(stripped, "include", 7) == 0 && 1508 isspace(stripped[7]) && 1509 strchr(stripped, ':') == NULL) { 1510 /* It's an S3/S5-style "include". */ 1511 ParseTraditionalInclude(stripped + 7); 1512 } else if (FEATURES(FEATURE_CONDINCLUDE) && 1513 (*stripped == '-' || *stripped == 's') && 1514 strncmp(stripped+1, "include", 7) == 0 && 1515 isspace(stripped[8]) && 1516 strchr(stripped, ':') == NULL) { 1517 ParseConditionalInclude(stripped+8); 1518 } else { 1519 char *dep; 1520 1521 if (inDependency) 1522 ParseFinishDependency(); 1523 if (Parse_DoVar(stripped, VAR_GLOBAL)) 1524 inDependency = false; 1525 else { 1526 size_t pos; 1527 char *end; 1528 1529 /* Need a new list for the target nodes. */ 1530 Array_Reset(>argets); 1531 inDependency = true; 1532 1533 dep = NULL; 1534 /* First we need to find eventual dependencies */ 1535 pos = strcspn(stripped, ":!"); 1536 /* go over :!, and find ; */ 1537 if (stripped[pos] != '\0' && 1538 (end = strchr(stripped+pos+1, ';')) != NULL) { 1539 if (line != stripped) 1540 /* find matching ; in original... The 1541 * original might be slightly longer. */ 1542 dep = strchr(line+(end-stripped), ';'); 1543 else 1544 dep = end; 1545 /* kill end of line. */ 1546 *end = '\0'; 1547 } 1548 /* We now know it's a dependency line so it needs to 1549 * have all variables expanded before being parsed. 1550 * Tell the variable module to complain if some 1551 * variable is undefined... */ 1552 cp = Var_Subst(stripped, NULL, true); 1553 ParseDoDependency(cp); 1554 free(cp); 1555 1556 /* Parse dependency if it's not empty. */ 1557 if (dep != NULL) { 1558 do { 1559 dep++; 1560 } while (isspace(*dep)); 1561 if (*dep != '\0') 1562 ParseDoCommands(dep); 1563 } 1564 } 1565 } 1566 } 1567 } 1568 } while (Parse_NextFile()); 1569 1570 if (inDependency) 1571 ParseFinishDependency(); 1572 /* Make sure conditionals are clean. */ 1573 Cond_End(); 1574 1575 Parse_ReportErrors(); 1576 Buf_Destroy(&buf); 1577 Buf_Destroy(©); 1578 } 1579 1580 void 1581 Parse_Init(void) 1582 { 1583 mainNode = NULL; 1584 Static_Lst_Init(parseIncPath); 1585 Static_Lst_Init(sysIncPath); 1586 Array_Init(&gsources, SOURCES_SIZE); 1587 Array_Init(>argets, TARGETS_SIZE); 1588 1589 LowParse_Init(); 1590 #ifdef CLEANUP 1591 Static_Lst_Init(&targCmds); 1592 #endif 1593 } 1594 1595 #ifdef CLEANUP 1596 void 1597 Parse_End(void) 1598 { 1599 Lst_Destroy(&targCmds, (SimpleProc)free); 1600 Lst_Destroy(sysIncPath, Dir_Destroy); 1601 Lst_Destroy(parseIncPath, Dir_Destroy); 1602 LowParse_End(); 1603 } 1604 #endif 1605 1606 1607 void 1608 Parse_MainName(Lst listmain) /* result list */ 1609 { 1610 1611 if (mainNode == NULL) { 1612 Punt("no target to make."); 1613 /*NOTREACHED*/ 1614 } else if (mainNode->type & OP_DOUBLEDEP) { 1615 Lst_AtEnd(listmain, mainNode); 1616 Lst_Concat(listmain, &mainNode->cohorts); 1617 } 1618 else 1619 Lst_AtEnd(listmain, mainNode); 1620 } 1621 1622