1 /* $OpenPackages$ */ 2 /* $OpenBSD: parse.c,v 1.68 2003/06/03 02:56:12 millert 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 224 static void ParseDoCommands(const char *); 225 226 /*- 227 *---------------------------------------------------------------------- 228 * ParseFindKeyword -- 229 * Look in the table of keywords for one matching the given string. 230 * 231 * Results: 232 * The index of the keyword, or -1 if it isn't there. 233 *---------------------------------------------------------------------- 234 */ 235 static int 236 ParseFindKeyword(str) 237 const char *str; /* String to find */ 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(pgn, cgn) 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(gn, op) 301 GNode *gn; /* The node to which the operator is to be 302 * applied */ 303 int op; /* The operator to apply */ 304 { 305 /* 306 * If the dependency mask of the operator and the node don't match and 307 * the node has actually had an operator applied to it before, and 308 * the operator actually has some dependency information in it, complain. 309 */ 310 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 311 !OP_NOP(gn->type) && !OP_NOP(op)) { 312 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); 313 return 0; 314 } 315 316 if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 317 /* If the node was the object of a :: operator, we need to create a 318 * new instance of it for the children and commands on this dependency 319 * line. The new instance is placed on the 'cohorts' list of the 320 * initial one (note the initial one is not on its own cohorts list) 321 * and the new instance is linked to all parents of the initial 322 * instance. */ 323 GNode *cohort; 324 LstNode ln; 325 unsigned int i; 326 327 cohort = Targ_NewGN(gn->name); 328 /* Duplicate links to parents so graph traversal is simple. Perhaps 329 * some type bits should be duplicated? 330 * 331 * Make the cohort invisible as well to avoid duplicating it into 332 * other variables. True, parents of this target won't tend to do 333 * anything with their local variables, but better safe than 334 * sorry. */ 335 for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln)) 336 ParseLinkSrc((GNode *)Lst_Datum(ln), cohort); 337 cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 338 Lst_AtEnd(&gn->cohorts, cohort); 339 340 /* Replace the node in the targets list with the new copy */ 341 for (i = 0; i < gtargets.n; i++) 342 if (gtargets.a[i] == gn) 343 break; 344 gtargets.a[i] = cohort; 345 gn = cohort; 346 } 347 /* We don't want to nuke any previous flags (whatever they were) so we 348 * just OR the new operator into the old. */ 349 gn->type |= op; 350 return 1; 351 } 352 353 /*- 354 *--------------------------------------------------------------------- 355 * ParseAddDep -- 356 * Check if the pair of GNodes given needs to be synchronized. 357 * This has to be when two nodes are on different sides of a 358 * .WAIT directive. 359 * 360 * Results: 361 * Returns 0 if the two targets need to be ordered, 1 otherwise. 362 * If it returns 0, the search can stop. 363 * 364 * Side Effects: 365 * A dependency can be added between the two nodes. 366 * 367 *--------------------------------------------------------------------- 368 */ 369 static int 370 ParseAddDep(p, s) 371 GNode *p; 372 GNode *s; 373 { 374 if (p->order < s->order) { 375 /* XXX: This can cause loops, and loops can cause unmade targets, 376 * but checking is tedious, and the debugging output can show the 377 * problem. */ 378 Lst_AtEnd(&p->successors, s); 379 Lst_AtEnd(&s->preds, p); 380 return 1; 381 } 382 else 383 return 0; 384 } 385 386 387 /*- 388 *--------------------------------------------------------------------- 389 * ParseDoSrc -- 390 * Given the name of a source, figure out if it is an attribute 391 * and apply it to the targets if it is. Else decide if there is 392 * some attribute which should be applied *to* the source because 393 * of some special target and apply it if so. Otherwise, make the 394 * source be a child of the targets in the list 'targets' 395 * 396 * Side Effects: 397 * Operator bits may be added to the list of targets or to the source. 398 * The targets may have a new source added to their lists of children. 399 *--------------------------------------------------------------------- 400 */ 401 static void 402 ParseDoSrc(tOp, src) 403 int tOp; /* operator (if any) from special targets */ 404 const char *src; /* name of the source to handle */ 405 406 { 407 GNode *gn = NULL; 408 409 if (*src == '.' && isupper(src[1])) { 410 int keywd = ParseFindKeyword(src); 411 if (keywd != -1) { 412 int op = parseKeywords[keywd].op; 413 if (op != 0) { 414 Array_Find(>argets, ParseDoOp, op); 415 return; 416 } 417 if (parseKeywords[keywd].spec == Wait) { 418 waiting++; 419 return; 420 } 421 } 422 } 423 424 switch (specType) { 425 case Main: 426 /* 427 * If we have noted the existence of a .MAIN, it means we need 428 * to add the sources of said target to the list of things 429 * to create. The string 'src' is likely to be freed, so we 430 * must make a new copy of it. Note that this will only be 431 * invoked if the user didn't specify a target on the command 432 * line. This is to allow #ifmake's to succeed, or something... 433 */ 434 Lst_AtEnd(create, estrdup(src)); 435 /* 436 * Add the name to the .TARGETS variable as well, so the user can 437 * employ that, if desired. 438 */ 439 Var_Append(".TARGETS", src, VAR_GLOBAL); 440 return; 441 442 case Order: 443 /* 444 * Create proper predecessor/successor links between the previous 445 * source and the current one. 446 */ 447 gn = Targ_FindNode(src, TARG_CREATE); 448 if (predecessor != NULL) { 449 Lst_AtEnd(&predecessor->successors, gn); 450 Lst_AtEnd(&gn->preds, predecessor); 451 } 452 /* 453 * The current source now becomes the predecessor for the next one. 454 */ 455 predecessor = gn; 456 break; 457 458 default: 459 /* 460 * If the source is not an attribute, we need to find/create 461 * a node for it. After that we can apply any operator to it 462 * from a special target or link it to its parents, as 463 * appropriate. 464 * 465 * In the case of a source that was the object of a :: operator, 466 * the attribute is applied to all of its instances (as kept in 467 * the 'cohorts' list of the node) or all the cohorts are linked 468 * to all the targets. 469 */ 470 gn = Targ_FindNode(src, TARG_CREATE); 471 if (tOp) { 472 gn->type |= tOp; 473 } else { 474 Array_ForEach(>argets, ParseLinkSrc, gn); 475 } 476 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 477 GNode *cohort; 478 LstNode ln; 479 480 for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)){ 481 cohort = (GNode *)Lst_Datum(ln); 482 if (tOp) { 483 cohort->type |= tOp; 484 } else { 485 Array_ForEach(>argets, ParseLinkSrc, cohort); 486 } 487 } 488 } 489 break; 490 } 491 492 gn->order = waiting; 493 Array_AtEnd(&gsources, gn); 494 if (waiting) { 495 Array_Find(&gsources, ParseAddDep, gn); 496 } 497 } 498 499 /*- 500 *----------------------------------------------------------------------- 501 * ParseFindMain -- 502 * Find a real target in the list and set it to be the main one. 503 * Called by ParseDoDependency when a main target hasn't been found 504 * yet. 505 * 506 * Results: 507 * 1 if main not found yet, 0 if it is. 508 * 509 * Side Effects: 510 * mainNode is changed and Targ_SetMain is called. 511 *----------------------------------------------------------------------- 512 */ 513 static int 514 ParseFindMain(gnp, dummy) 515 void *gnp; /* Node to examine */ 516 void *dummy UNUSED; 517 { 518 GNode *gn = (GNode *)gnp; 519 if ((gn->type & OP_NOTARGET) == 0) { 520 mainNode = gn; 521 Targ_SetMain(gn); 522 return 0; 523 } else { 524 return 1; 525 } 526 } 527 528 /*- 529 *----------------------------------------------------------------------- 530 * ParseAddDir -- 531 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going 532 * 533 * Side Effects: 534 * See Dir_AddDir. 535 *----------------------------------------------------------------------- 536 */ 537 static void 538 ParseAddDir(path, name) 539 void *path; 540 void *name; 541 { 542 Dir_AddDir((Lst)path, (char *)name); 543 } 544 545 /*- 546 *----------------------------------------------------------------------- 547 * ParseClearPath -- 548 * Reinit path to an empty path 549 *----------------------------------------------------------------------- 550 */ 551 static void 552 ParseClearPath(p) 553 void *p; 554 { 555 Lst path = (Lst)p; 556 557 Lst_Destroy(path, Dir_Destroy); 558 Lst_Init(path); 559 } 560 561 /*- 562 *--------------------------------------------------------------------- 563 * ParseDoDependency -- 564 * Parse the dependency line in line. 565 * 566 * Side Effects: 567 * The nodes of the sources are linked as children to the nodes of the 568 * targets. Some nodes may be created. 569 * 570 * We parse a dependency line by first extracting words from the line and 571 * finding nodes in the list of all targets with that name. This is done 572 * until a character is encountered which is an operator character. Currently 573 * these are only ! and :. At this point the operator is parsed and the 574 * pointer into the line advanced until the first source is encountered. 575 * The parsed operator is applied to each node in the 'targets' list, 576 * which is where the nodes found for the targets are kept, by means of 577 * the ParseDoOp function. 578 * The sources are read in much the same way as the targets were except 579 * that now they are expanded using the wildcarding scheme of the C-Shell 580 * and all instances of the resulting words in the list of all targets 581 * are found. Each of the resulting nodes is then linked to each of the 582 * targets as one of its children. 583 * Certain targets are handled specially. These are the ones detailed 584 * by the specType variable. 585 * The storing of transformation rules is also taken care of here. 586 * A target is recognized as a transformation rule by calling 587 * Suff_IsTransform. If it is a transformation rule, its node is gotten 588 * from the suffix module via Suff_AddTransform rather than the standard 589 * Targ_FindNode in the target module. 590 *--------------------------------------------------------------------- 591 */ 592 static void 593 ParseDoDependency(line) 594 char *line; /* the line to parse */ 595 { 596 char *cp; /* our current position */ 597 GNode *gn; /* a general purpose temporary node */ 598 int op; /* the operator on the line */ 599 char savec; /* a place to save a character */ 600 LIST paths; /* List of search paths to alter when parsing 601 * a list of .PATH targets */ 602 int tOp; /* operator from special target */ 603 tOp = 0; 604 605 specType = Not; 606 waiting = 0; 607 Lst_Init(&paths); 608 609 Array_Reset(&gsources); 610 611 do { 612 for (cp = line; *cp && !isspace(*cp) && *cp != '(';) 613 if (*cp == '$') 614 /* Must be a dynamic source (would have been expanded 615 * otherwise), so call the Var module to parse the puppy 616 * so we can safely advance beyond it...There should be 617 * no errors in this, as they would have been discovered 618 * in the initial Var_Subst and we wouldn't be here. */ 619 cp += Var_ParseSkip(cp, NULL, NULL); 620 else { 621 /* We don't want to end a word on ':' or '!' if there is a 622 * better match later on in the string. By "better" I mean 623 * one that is followed by whitespace. This allows the user 624 * to have targets like: 625 * fie::fi:fo: fum 626 * where "fie::fi:fo" is the target. In real life this is used 627 * for perl5 library man pages where "::" separates an object 628 * from its class. Ie: "File::Spec::Unix". This behaviour 629 * is also consistent with other versions of make. */ 630 if (*cp == '!' || *cp == ':') { 631 char *p = cp + 1; 632 633 if (*cp == ':' && *p == ':') 634 p++; 635 636 /* Found the best match already. */ 637 if (isspace(*p) || *p == '\0') 638 break; 639 640 do { 641 p += strcspn(p, "!:"); 642 if (*p == '\0') 643 break; 644 p++; 645 } while (!isspace(*p)); 646 647 /* No better match later on... */ 648 if (*p == '\0') 649 break; 650 651 } 652 cp++; 653 } 654 if (*cp == '(') { 655 LIST temp; 656 Lst_Init(&temp); 657 /* Archives must be handled specially to make sure the OP_ARCHV 658 * flag is set in their 'type' field, for one thing, and because 659 * things like "archive(file1.o file2.o file3.o)" are permissible. 660 * Arch_ParseArchive will set 'line' to be the first non-blank 661 * after the archive-spec. It creates/finds nodes for the members 662 * and places them on the given list, returning true if all 663 * went well and false if there was an error in the 664 * specification. On error, line should remain untouched. */ 665 if (!Arch_ParseArchive(&line, &temp, NULL)) { 666 Parse_Error(PARSE_FATAL, 667 "Error in archive specification: \"%s\"", line); 668 return; 669 } else { 670 AppendList2Array(&temp, >argets); 671 Lst_Destroy(&temp, NOFREE); 672 continue; 673 } 674 } 675 savec = *cp; 676 677 if (*cp == '\0') { 678 /* Ending a dependency line without an operator is a Bozo no-no */ 679 Parse_Error(PARSE_FATAL, "Need an operator"); 680 return; 681 } 682 *cp = '\0'; 683 /* Have a word in line. See if it's a special target and set 684 * specType to match it. */ 685 if (*line == '.' && isupper(line[1])) { 686 /* See if the target is a special target that must have it 687 * or its sources handled specially. */ 688 int keywd = ParseFindKeyword(line); 689 if (keywd != -1) { 690 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { 691 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 692 return; 693 } 694 695 specType = parseKeywords[keywd].spec; 696 tOp = parseKeywords[keywd].op; 697 698 /* 699 * Certain special targets have special semantics: 700 * .PATH Have to set the dirSearchPath 701 * variable too 702 * .MAIN Its sources are only used if 703 * nothing has been specified to 704 * create. 705 * .DEFAULT Need to create a node to hang 706 * commands on, but we don't want 707 * it in the graph, nor do we want 708 * it to be the Main Target, so we 709 * create it, set OP_NOTMAIN and 710 * add it to the list, setting 711 * DEFAULT to the new node for 712 * later use. We claim the node is 713 * A transformation rule to make 714 * life easier later, when we'll 715 * use Make_HandleUse to actually 716 * apply the .DEFAULT commands. 717 * .PHONY The list of targets 718 * .NOPATH Don't search for file in the path 719 * .BEGIN 720 * .END 721 * .INTERRUPT Are not to be considered the 722 * main target. 723 * .NOTPARALLEL Make only one target at a time. 724 * .SINGLESHELL Create a shell for each command. 725 * .ORDER Must set initial predecessor to NULL 726 */ 727 switch (specType) { 728 case ExPath: 729 Lst_AtEnd(&paths, dirSearchPath); 730 break; 731 case Main: 732 if (!Lst_IsEmpty(create)) { 733 specType = Not; 734 } 735 break; 736 case Begin: 737 case End: 738 case Interrupt: 739 gn = Targ_FindNode(line, TARG_CREATE); 740 gn->type |= OP_NOTMAIN; 741 Array_AtEnd(>argets, gn); 742 break; 743 case Default: 744 gn = Targ_NewGN(".DEFAULT"); 745 gn->type |= OP_NOTMAIN|OP_TRANSFORM; 746 Array_AtEnd(>argets, gn); 747 DEFAULT = gn; 748 break; 749 case NotParallel: 750 { 751 extern int maxJobs; 752 753 maxJobs = 1; 754 break; 755 } 756 case SingleShell: 757 compatMake = 1; 758 break; 759 case Order: 760 predecessor = NULL; 761 break; 762 default: 763 break; 764 } 765 } else if (strncmp(line, ".PATH", 5) == 0) { 766 /* 767 * .PATH<suffix> has to be handled specially. 768 * Call on the suffix module to give us a path to 769 * modify. 770 */ 771 Lst path; 772 773 specType = ExPath; 774 path = Suff_GetPath(&line[5]); 775 if (path == NULL) { 776 Parse_Error(PARSE_FATAL, 777 "Suffix '%s' not defined (yet)", 778 &line[5]); 779 return; 780 } else { 781 Lst_AtEnd(&paths, path); 782 } 783 } 784 } 785 786 /* 787 * Have word in line. Get or create its node and stick it at 788 * the end of the targets list 789 */ 790 if (specType == Not && *line != '\0') { 791 char *targName; 792 793 if (Dir_HasWildcards(line)) { 794 /* 795 * Targets are to be sought only in the current directory, 796 * so create an empty path for the thing. Note we need to 797 * use Dir_Destroy in the destruction of the path as the 798 * Dir module could have added a directory to the path... 799 */ 800 LIST emptyPath; 801 LIST curTargs; /* list of target names to be found 802 * and added to the targets list */ 803 804 Lst_Init(&emptyPath); 805 Lst_Init(&curTargs); 806 Dir_Expand(line, &emptyPath, &curTargs); 807 Lst_Destroy(&emptyPath, Dir_Destroy); 808 while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) { 809 if (!Suff_IsTransform(targName)) 810 gn = Targ_FindNode(targName, TARG_CREATE); 811 else 812 gn = Suff_AddTransform(targName); 813 814 if (gn != NULL) 815 Array_AtEnd(>argets, gn); 816 } 817 Lst_Destroy(&curTargs, NOFREE); 818 } else { 819 if (!Suff_IsTransform(line)) 820 gn = Targ_FindNode(line, TARG_CREATE); 821 else 822 gn = Suff_AddTransform(line); 823 824 if (gn != NULL) 825 Array_AtEnd(>argets, gn); 826 /* Don't need the list of target names anymore... */ 827 } 828 } else if (specType == ExPath && *line != '.' && *line != '\0') 829 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 830 831 *cp = savec; 832 /* 833 * If it is a special type and not .PATH, it's the only target we 834 * allow on this line... 835 */ 836 if (specType != Not && specType != ExPath) { 837 bool warn = false; 838 839 while (*cp != '!' && *cp != ':' && *cp) { 840 if (*cp != ' ' && *cp != '\t') { 841 warn = true; 842 } 843 cp++; 844 } 845 if (warn) { 846 Parse_Error(PARSE_WARNING, "Extra target ignored"); 847 } 848 } else { 849 while (*cp && isspace(*cp)) { 850 cp++; 851 } 852 } 853 line = cp; 854 } while (*line != '!' && *line != ':' && *line); 855 856 if (!Array_IsEmpty(>argets)) { 857 switch (specType) { 858 default: 859 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); 860 break; 861 case Default: 862 case Begin: 863 case End: 864 case Interrupt: 865 /* These four create nodes on which to hang commands, so 866 * targets shouldn't be empty... */ 867 case Not: 868 /* Nothing special here -- targets can be empty if it wants. */ 869 break; 870 } 871 } 872 873 /* Have now parsed all the target names. Must parse the operator next. The 874 * result is left in op . */ 875 if (*cp == '!') { 876 op = OP_FORCE; 877 } else if (*cp == ':') { 878 if (cp[1] == ':') { 879 op = OP_DOUBLEDEP; 880 cp++; 881 } else { 882 op = OP_DEPENDS; 883 } 884 } else { 885 Parse_Error(PARSE_FATAL, "Missing dependency operator"); 886 return; 887 } 888 889 cp++; /* Advance beyond operator */ 890 891 Array_Find(>argets, ParseDoOp, op); 892 893 /* 894 * Get to the first source 895 */ 896 while (*cp && isspace(*cp)) { 897 cp++; 898 } 899 line = cp; 900 901 /* 902 * Several special targets take different actions if present with no 903 * sources: 904 * a .SUFFIXES line with no sources clears out all old suffixes 905 * a .PRECIOUS line makes all targets precious 906 * a .IGNORE line ignores errors for all targets 907 * a .SILENT line creates silence when making all targets 908 * a .PATH removes all directories from the search path(s). 909 */ 910 if (!*line) { 911 switch (specType) { 912 case Suffixes: 913 Suff_ClearSuffixes(); 914 break; 915 case Precious: 916 allPrecious = true; 917 break; 918 case Ignore: 919 ignoreErrors = true; 920 break; 921 case Silent: 922 beSilent = true; 923 break; 924 case ExPath: 925 Lst_Every(&paths, ParseClearPath); 926 break; 927 default: 928 break; 929 } 930 } else if (specType == MFlags) { 931 /* 932 * Call on functions in main.c to deal with these arguments and 933 * set the initial character to a null-character so the loop to 934 * get sources won't get anything 935 */ 936 Main_ParseArgLine(line); 937 *line = '\0'; 938 } else if (specType == ExShell) { 939 if (!Job_ParseShell(line)) { 940 Parse_Error(PARSE_FATAL, "improper shell specification"); 941 return; 942 } 943 *line = '\0'; 944 } else if (specType == NotParallel || specType == SingleShell) { 945 *line = '\0'; 946 } 947 948 /* 949 * NOW GO FOR THE SOURCES 950 */ 951 if (specType == Suffixes || specType == ExPath || 952 specType == Includes || specType == Libs || 953 specType == Null) { 954 while (*line) { 955 /* 956 * If the target was one that doesn't take files as its sources 957 * but takes something like suffixes, we take each 958 * space-separated word on the line as a something and deal 959 * with it accordingly. 960 * 961 * If the target was .SUFFIXES, we take each source as a 962 * suffix and add it to the list of suffixes maintained by the 963 * Suff module. 964 * 965 * If the target was a .PATH, we add the source as a directory 966 * to search on the search path. 967 * 968 * If it was .INCLUDES, the source is taken to be the suffix of 969 * files which will be #included and whose search path should 970 * be present in the .INCLUDES variable. 971 * 972 * If it was .LIBS, the source is taken to be the suffix of 973 * files which are considered libraries and whose search path 974 * should be present in the .LIBS variable. 975 * 976 * If it was .NULL, the source is the suffix to use when a file 977 * has no valid suffix. 978 */ 979 char savec; 980 while (*cp && !isspace(*cp)) { 981 cp++; 982 } 983 savec = *cp; 984 *cp = '\0'; 985 switch (specType) { 986 case Suffixes: 987 Suff_AddSuffix(line); 988 break; 989 case ExPath: 990 Lst_ForEach(&paths, ParseAddDir, line); 991 break; 992 case Includes: 993 Suff_AddInclude(line); 994 break; 995 case Libs: 996 Suff_AddLib(line); 997 break; 998 case Null: 999 Suff_SetNull(line); 1000 break; 1001 default: 1002 break; 1003 } 1004 *cp = savec; 1005 if (savec != '\0') { 1006 cp++; 1007 } 1008 while (*cp && isspace(*cp)) { 1009 cp++; 1010 } 1011 line = cp; 1012 } 1013 Lst_Destroy(&paths, NOFREE); 1014 } else { 1015 while (*line) { 1016 /* 1017 * The targets take real sources, so we must beware of archive 1018 * specifications (i.e. things with left parentheses in them) 1019 * and handle them accordingly. 1020 */ 1021 while (*cp && !isspace(*cp)) { 1022 if (*cp == '(' && cp > line && cp[-1] != '$') { 1023 /* 1024 * Only stop for a left parenthesis if it isn't at the 1025 * start of a word (that'll be for variable changes 1026 * later) and isn't preceded by a dollar sign (a dynamic 1027 * source). 1028 */ 1029 break; 1030 } else { 1031 cp++; 1032 } 1033 } 1034 1035 if (*cp == '(') { 1036 GNode *gn; 1037 LIST sources; /* list of archive source names after 1038 * expansion */ 1039 1040 Lst_Init(&sources); 1041 if (!Arch_ParseArchive(&line, &sources, NULL)) { 1042 Parse_Error(PARSE_FATAL, 1043 "Error in source archive spec \"%s\"", line); 1044 return; 1045 } 1046 1047 while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL) 1048 ParseDoSrc(tOp, gn->name); 1049 cp = line; 1050 } else { 1051 if (*cp) { 1052 *cp = '\0'; 1053 cp += 1; 1054 } 1055 1056 ParseDoSrc(tOp, line); 1057 } 1058 while (*cp && isspace(*cp)) { 1059 cp++; 1060 } 1061 line = cp; 1062 } 1063 } 1064 1065 if (mainNode == NULL) { 1066 /* If we have yet to decide on a main target to make, in the 1067 * absence of any user input, we want the first target on 1068 * the first dependency line that is actually a real target 1069 * (i.e. isn't a .USE or .EXEC rule) to be made. */ 1070 Array_Find(>argets, ParseFindMain, NULL); 1071 } 1072 1073 /* Finally, destroy the list of sources. */ 1074 } 1075 1076 /*- 1077 * ParseAddCmd -- 1078 * Lst_ForEach function to add a command line to all targets 1079 * 1080 * Side Effects: 1081 * A new element is added to the commands list of the node. 1082 */ 1083 static void 1084 ParseAddCmd(gnp, cmd) 1085 void *gnp; /* the node to which the command is to be added */ 1086 void *cmd; /* the command to add */ 1087 { 1088 GNode *gn = (GNode *)gnp; 1089 /* if target already supplied, ignore commands */ 1090 if (!(gn->type & OP_HAS_COMMANDS)) { 1091 Lst_AtEnd(&gn->commands, cmd); 1092 if (!gn->lineno) { 1093 gn->lineno = Parse_Getlineno(); 1094 gn->fname = Parse_Getfilename(); 1095 } 1096 } 1097 } 1098 1099 /*- 1100 *----------------------------------------------------------------------- 1101 * ParseHasCommands -- 1102 * Callback procedure for Parse_File when destroying the list of 1103 * targets on the last dependency line. Marks a target as already 1104 * having commands if it does, to keep from having shell commands 1105 * on multiple dependency lines. 1106 * 1107 * Side Effects: 1108 * OP_HAS_COMMANDS may be set for the target. 1109 *----------------------------------------------------------------------- 1110 */ 1111 static void 1112 ParseHasCommands(gnp) 1113 void *gnp; /* Node to examine */ 1114 { 1115 GNode *gn = (GNode *)gnp; 1116 if (!Lst_IsEmpty(&gn->commands)) { 1117 gn->type |= OP_HAS_COMMANDS; 1118 } 1119 } 1120 1121 /*- 1122 *----------------------------------------------------------------------- 1123 * Parse_AddIncludeDir -- 1124 * Add a directory to the path searched for included makefiles 1125 * bracketed by double-quotes. Used by functions in main.c 1126 *----------------------------------------------------------------------- 1127 */ 1128 void 1129 Parse_AddIncludeDir(dir) 1130 const char *dir; /* The name of the directory to add */ 1131 { 1132 Dir_AddDir(parseIncPath, dir); 1133 } 1134 1135 /*- 1136 *--------------------------------------------------------------------- 1137 * ParseDoInclude -- 1138 * Push to another file. 1139 * 1140 * The input is the line minus the #include. A file spec is a string 1141 * enclosed in <> or "". The former is looked for only in sysIncPath. 1142 * The latter in . and the directories specified by -I command line 1143 * options 1144 * 1145 * Side Effects: 1146 * old parse context is pushed on the stack, new file becomes 1147 * current context. 1148 *--------------------------------------------------------------------- 1149 */ 1150 static void 1151 ParseDoInclude(file) 1152 char *file; /* file specification */ 1153 { 1154 char endc; /* the character which ends the file spec */ 1155 char *cp; /* current position in file spec */ 1156 bool isSystem; /* true if makefile is a system makefile */ 1157 1158 /* Skip to delimiter character so we know where to look. */ 1159 while (*file == ' ' || *file == '\t') 1160 file++; 1161 1162 if (*file != '"' && *file != '<') { 1163 Parse_Error(PARSE_FATAL, 1164 ".include filename must be delimited by '\"' or '<'"); 1165 return; 1166 } 1167 1168 /* Set the search path on which to find the include file based on the 1169 * characters which bracket its name. Angle-brackets imply it's 1170 * a system Makefile while double-quotes imply it's a user makefile */ 1171 if (*file == '<') { 1172 isSystem = true; 1173 endc = '>'; 1174 } else { 1175 isSystem = false; 1176 endc = '"'; 1177 } 1178 1179 /* Skip to matching delimiter. */ 1180 for (cp = ++file; *cp != endc; cp++) { 1181 if (*cp == '\0') { 1182 Parse_Error(PARSE_FATAL, 1183 "Unclosed %cinclude filename. '%c' expected", 1184 '.', endc); 1185 return; 1186 } 1187 } 1188 ParseLookupIncludeFile(file, cp, isSystem, true); 1189 } 1190 1191 /*- 1192 *--------------------------------------------------------------------- 1193 * ParseTraditionalInclude -- 1194 * Push to another file. 1195 * 1196 * The input is the line minus the "include". The file name is 1197 * the string following the "include". 1198 * 1199 * Side Effects: 1200 * old parse context is pushed on the stack, new file becomes 1201 * current context. 1202 * 1203 * XXX May wish to support multiple files and wildcards ? 1204 *--------------------------------------------------------------------- 1205 */ 1206 static void 1207 ParseTraditionalInclude(file) 1208 char *file; /* file specification */ 1209 { 1210 char *cp; /* current position in file spec */ 1211 1212 /* Skip over whitespace. */ 1213 while (isspace(*file)) 1214 file++; 1215 if (*file == '\0') { 1216 Parse_Error(PARSE_FATAL, 1217 "Filename missing from \"include\""); 1218 return; 1219 } 1220 /* Skip to end of line or next whitespace. */ 1221 for (cp = file; *cp != '\0' && !isspace(*cp);) 1222 cp++; 1223 1224 ParseLookupIncludeFile(file, cp, true, true); 1225 } 1226 1227 /*- 1228 *--------------------------------------------------------------------- 1229 * ParseConditionalInclude -- 1230 * May push to another file. 1231 * 1232 * No error if the file does not exist. 1233 * See ParseTraditionalInclude otherwise. 1234 *--------------------------------------------------------------------- 1235 */ 1236 static void 1237 ParseConditionalInclude(file) 1238 char *file; /* file specification */ 1239 { 1240 char *cp; /* current position in file spec */ 1241 1242 /* Skip over whitespace. */ 1243 while (isspace(*file)) 1244 file++; 1245 if (*file == '\0') { 1246 Parse_Error(PARSE_FATAL, 1247 "Filename missing from \"include\""); 1248 return; 1249 } 1250 /* Skip to end of line or next whitespace. */ 1251 for (cp = file; *cp != '\0' && !isspace(*cp);) 1252 cp++; 1253 1254 ParseLookupIncludeFile(file, cp, true, false); 1255 } 1256 1257 /* Common part to lookup and read an include file. */ 1258 static void 1259 ParseLookupIncludeFile(spec, endSpec, isSystem, errIfNotFound) 1260 char *spec; 1261 char *endSpec; 1262 bool isSystem; 1263 bool errIfNotFound; 1264 { 1265 char *file; 1266 char *fullname; 1267 char endc; 1268 1269 /* Substitute for any variables in the file name before trying to 1270 * find the thing. */ 1271 endc = *endSpec; 1272 *endSpec = '\0'; 1273 file = Var_Subst(spec, NULL, false); 1274 *endSpec = endc; 1275 1276 /* Now that we know the file name and its search path, we attempt to 1277 * find the durn thing. NULL indicates the file still hasn't been 1278 * found. */ 1279 fullname = NULL; 1280 1281 /* Handle non-system non-absolute files... */ 1282 if (!isSystem && file[0] != '/') { 1283 /* ... by first searching relative to the including file's 1284 * location. We don't want to cd there, of course, so we 1285 * just tack on the old file's leading path components 1286 * and call Dir_FindFile to see if we can locate the beast. */ 1287 char *slash; 1288 const char *fname; 1289 1290 fname = Parse_Getfilename(); 1291 1292 slash = strrchr(fname, '/'); 1293 if (slash != NULL) { 1294 char *newName; 1295 1296 newName = Str_concati(fname, slash, file, strchr(file, '\0'), '/'); 1297 fullname = Dir_FindFile(newName, parseIncPath); 1298 if (fullname == NULL) 1299 fullname = Dir_FindFile(newName, dirSearchPath); 1300 free(newName); 1301 } 1302 } 1303 1304 /* Now look first on the -I search path, then on the .PATH 1305 * search path, if not found in a -I directory. 1306 * XXX: Suffix specific? */ 1307 if (fullname == NULL) 1308 fullname = Dir_FindFile(file, parseIncPath); 1309 if (fullname == NULL) 1310 fullname = Dir_FindFile(file, dirSearchPath); 1311 1312 /* Still haven't found the makefile. Look for it on the system 1313 * path as a last resort. */ 1314 if (fullname == NULL) 1315 fullname = Dir_FindFile(file, sysIncPath); 1316 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(copy, line) 1346 Buffer copy; 1347 const char *line; 1348 { 1349 const char *comment; 1350 const char *p; 1351 1352 comment = strchr(line, '#'); 1353 assert(comment != line); 1354 if (comment == NULL) 1355 return (char *)line; 1356 else { 1357 Buf_Reset(copy); 1358 1359 for (p = line; *p != '\0'; p++) { 1360 if (*p == '\\') { 1361 if (p[1] == '#') { 1362 Buf_Addi(copy, line, p); 1363 Buf_AddChar(copy, '#'); 1364 line = p+2; 1365 } 1366 if (p[1] != '\0') 1367 p++; 1368 } else if (*p == '#') 1369 break; 1370 } 1371 Buf_Addi(copy, line, p); 1372 Buf_KillTrailingSpaces(copy); 1373 return Buf_Retrieve(copy); 1374 } 1375 } 1376 1377 static bool 1378 ParseIsCond(linebuf, copy, line) 1379 Buffer linebuf; 1380 Buffer copy; 1381 char *line; 1382 { 1383 1384 char *stripped; 1385 1386 while (*line != '\0' && isspace(*line)) 1387 line++; 1388 1389 /* The line might be a conditional. Ask the conditional module 1390 * about it and act accordingly. */ 1391 switch (Cond_Eval(line)) { 1392 case COND_SKIP: 1393 /* Skip to next conditional that evaluates to COND_PARSE. */ 1394 do { 1395 line = Parse_ReadNextConditionalLine(linebuf); 1396 if (line != NULL) { 1397 while (*line != '\0' && isspace(*line)) 1398 line++; 1399 stripped = strip_comments(copy, line); 1400 } 1401 } while (line != NULL && Cond_Eval(stripped) != COND_PARSE); 1402 /* FALLTHROUGH */ 1403 case COND_PARSE: 1404 return true; 1405 case COND_ISFOR: { 1406 For *loop; 1407 1408 loop = For_Eval(line+3); 1409 if (loop != NULL) { 1410 bool ok; 1411 do { 1412 /* Find the matching endfor. */ 1413 line = ParseReadLoopLine(linebuf); 1414 if (line == NULL) { 1415 Parse_Error(PARSE_FATAL, 1416 "Unexpected end of file in for loop.\n"); 1417 return false; 1418 } 1419 ok = For_Accumulate(loop, line); 1420 } while (ok); 1421 For_Run(loop); 1422 return true; 1423 } 1424 break; 1425 } 1426 case COND_ISINCLUDE: 1427 ParseDoInclude(line + 7); 1428 return true; 1429 case COND_ISUNDEF: { 1430 char *cp; 1431 1432 line+=5; 1433 while (*line != '\0' && isspace(*line)) 1434 line++; 1435 for (cp = line; !isspace(*cp) && *cp != '\0';) 1436 cp++; 1437 *cp = '\0'; 1438 Var_Delete(line); 1439 return true; 1440 } 1441 default: 1442 break; 1443 } 1444 1445 return false; 1446 } 1447 1448 /*- 1449 *----------------------------------------------------------------------- 1450 * ParseFinishDependency -- 1451 * Handle the end of a dependency group. 1452 * 1453 * Side Effects: 1454 * 'targets' list destroyed. 1455 * 1456 *----------------------------------------------------------------------- 1457 */ 1458 static void 1459 ParseFinishDependency() 1460 { 1461 Array_Every(>argets, Suff_EndTransform); 1462 Array_Every(>argets, ParseHasCommands); 1463 Array_Reset(>argets); 1464 } 1465 1466 static void 1467 ParseDoCommands(line) 1468 const char *line; 1469 { 1470 /* add the command to the list of 1471 * commands of all targets in the dependency spec */ 1472 char *cmd = estrdup(line); 1473 1474 Array_ForEach(>argets, ParseAddCmd, cmd); 1475 #ifdef CLEANUP 1476 Lst_AtEnd(&targCmds, cmd); 1477 #endif 1478 } 1479 1480 void 1481 Parse_File(name, stream) 1482 const char *name; /* the name of the file being read */ 1483 FILE *stream; /* Stream open to makefile to parse */ 1484 { 1485 char *cp, /* pointer into the line */ 1486 *line; /* the line we're working on */ 1487 bool inDependency; /* true if currently in a dependency 1488 * line or its commands */ 1489 1490 BUFFER buf; 1491 BUFFER copy; 1492 1493 Buf_Init(&buf, MAKE_BSIZE); 1494 Buf_Init(©, MAKE_BSIZE); 1495 inDependency = false; 1496 Parse_FromFile(name, stream); 1497 1498 do { 1499 while ((line = Parse_ReadNormalLine(&buf)) != NULL) { 1500 if (*line == '\t') { 1501 if (inDependency) 1502 ParseDoCommands(line+1); 1503 else 1504 Parse_Error(PARSE_FATAL, 1505 "Unassociated shell command \"%s\"", 1506 line); 1507 } else { 1508 char *stripped; 1509 stripped = strip_comments(©, line); 1510 if (*stripped == '.' && ParseIsCond(&buf, ©, stripped+1)) 1511 ; 1512 else if (FEATURES(FEATURE_SYSVINCLUDE) && 1513 strncmp(stripped, "include", 7) == 0 && 1514 isspace(stripped[7]) && 1515 strchr(stripped, ':') == NULL) { 1516 /* It's an S3/S5-style "include". */ 1517 ParseTraditionalInclude(stripped + 7); 1518 } else if (FEATURES(FEATURE_CONDINCLUDE) && 1519 (*stripped == '-' || *stripped == 's') && 1520 strncmp(stripped+1, "include", 7) == 0 && 1521 isspace(stripped[8]) && 1522 strchr(stripped, ':') == NULL) { 1523 ParseConditionalInclude(stripped+8); 1524 } else { 1525 char *dep; 1526 1527 if (inDependency) 1528 ParseFinishDependency(); 1529 if (Parse_DoVar(stripped, VAR_GLOBAL)) 1530 inDependency = false; 1531 else { 1532 size_t pos; 1533 char *end; 1534 1535 /* Need a new list for the target nodes. */ 1536 Array_Reset(>argets); 1537 inDependency = true; 1538 1539 dep = NULL; 1540 /* First we need to find eventual dependencies */ 1541 pos = strcspn(stripped, ":!"); 1542 /* go over :!, and find ; */ 1543 if (stripped[pos] != '\0' && 1544 (end = strchr(stripped+pos+1, ';')) != NULL) { 1545 if (line != stripped) 1546 /* find matching ; in original... The 1547 * original might be slightly longer. */ 1548 dep = strchr(line+(end-stripped), ';'); 1549 else 1550 dep = end; 1551 /* kill end of line. */ 1552 *end = '\0'; 1553 } 1554 /* We now know it's a dependency line so it needs to 1555 * have all variables expanded before being parsed. 1556 * Tell the variable module to complain if some 1557 * variable is undefined... */ 1558 cp = Var_Subst(stripped, NULL, true); 1559 ParseDoDependency(cp); 1560 free(cp); 1561 1562 /* Parse dependency if it's not empty. */ 1563 if (dep != NULL) { 1564 do { 1565 dep++; 1566 } while (isspace(*dep)); 1567 if (*dep != '\0') 1568 ParseDoCommands(dep); 1569 } 1570 } 1571 } 1572 } 1573 } 1574 } while (Parse_NextFile()); 1575 1576 if (inDependency) 1577 ParseFinishDependency(); 1578 /* Make sure conditionals are clean. */ 1579 Cond_End(); 1580 1581 Parse_ReportErrors(); 1582 Buf_Destroy(&buf); 1583 Buf_Destroy(©); 1584 } 1585 1586 void 1587 Parse_Init() 1588 { 1589 mainNode = NULL; 1590 Static_Lst_Init(parseIncPath); 1591 Static_Lst_Init(sysIncPath); 1592 Array_Init(&gsources, SOURCES_SIZE); 1593 Array_Init(>argets, TARGETS_SIZE); 1594 1595 LowParse_Init(); 1596 #ifdef CLEANUP 1597 Static_Lst_Init(&targCmds); 1598 #endif 1599 } 1600 1601 #ifdef CLEANUP 1602 void 1603 Parse_End() 1604 { 1605 Lst_Destroy(&targCmds, (SimpleProc)free); 1606 Lst_Destroy(sysIncPath, Dir_Destroy); 1607 Lst_Destroy(parseIncPath, Dir_Destroy); 1608 LowParse_End(); 1609 } 1610 #endif 1611 1612 1613 void 1614 Parse_MainName(listmain) 1615 Lst listmain; /* result list */ 1616 { 1617 1618 if (mainNode == NULL) { 1619 Punt("no target to make."); 1620 /*NOTREACHED*/ 1621 } else if (mainNode->type & OP_DOUBLEDEP) { 1622 Lst_AtEnd(listmain, mainNode); 1623 Lst_Concat(listmain, &mainNode->cohorts); 1624 } 1625 else 1626 Lst_AtEnd(listmain, mainNode); 1627 } 1628 1629