1/* $OpenBSD: parse.c,v 1.136 2023/09/04 11:35:11 espie Exp $ */ 2/* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ 3 4/* 5 * Copyright (c) 1999 Marc Espie. 6 * 7 * Extensive code changes for the OpenBSD project. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 22 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30/* 31 * Copyright (c) 1988, 1989, 1990, 1993 32 * The Regents of the University of California. All rights reserved. 33 * Copyright (c) 1989 by Berkeley Softworks 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Adam de Boor. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 64#include <assert.h> 65#include <ctype.h> 66#include <stddef.h> 67#include <stdio.h> 68#include <stdlib.h> 69#include <string.h> 70#include <ohash.h> 71#include "defines.h" 72#include "dir.h" 73#include "direxpand.h" 74#include "job.h" 75#include "buf.h" 76#include "for.h" 77#include "lowparse.h" 78#include "arch.h" 79#include "cond.h" 80#include "suff.h" 81#include "parse.h" 82#include "var.h" 83#include "targ.h" 84#include "error.h" 85#include "str.h" 86#include "main.h" 87#include "gnode.h" 88#include "memory.h" 89#include "extern.h" 90#include "lst.h" 91#include "parsevar.h" 92#include "stats.h" 93#include "garray.h" 94#include "node_int.h" 95#include "nodehashconsts.h" 96 97 98/* gsources and gtargets should be local to some functions, but they're 99 * set as persistent arrays for performance reasons. 100 */ 101static struct growableArray gsources, gtargets; 102static struct ohash htargets; 103static bool htargets_setup = false; 104#define SOURCES_SIZE 128 105#define TARGETS_SIZE 32 106 107static LIST theUserIncPath;/* list of directories for "..." includes */ 108static LIST theSysIncPath; /* list of directories for <...> includes */ 109Lst systemIncludePath = &theSysIncPath; 110Lst userIncludePath = &theUserIncPath; 111 112static GNode *mainNode; /* The main target to create. This is the 113 * first target on the first dependency 114 * line in the first makefile */ 115/*- 116 * specType contains the special TYPE of the current target. It is 117 * SPECIAL_NONE if the target is unspecial. If it *is* special, however, 118 * the children are linked as children of the parent but not vice versa. 119 * This variable is set in ParseDoDependency 120 */ 121 122static unsigned int specType; 123static int waiting; 124 125/* 126 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 127 * seen, then set to each successive source on the line. 128 */ 129static GNode *predecessor; 130 131static void ParseLinkSrc(GNode *, GNode *); 132static int ParseDoOp(GNode **, unsigned int); 133static void ParseDoSpecial(GNode *, unsigned int); 134static int ParseAddDep(GNode *, GNode *); 135static void ParseDoSrc(struct growableArray *, struct growableArray *, int, 136 const char *, const char *); 137static int ParseFindMain(void *, void *); 138static void ParseClearPath(void *); 139 140static void add_target_node(const char *, const char *); 141static void add_target_nodes(const char *, const char *); 142static void apply_op(struct growableArray *, unsigned int, GNode *); 143static void ParseDoDependency(const char *); 144static void ParseAddCmd(void *, void *); 145static void ParseHasCommands(void *); 146static bool handle_poison(const char *); 147static bool handle_for_loop(Buffer, const char *); 148static bool handle_undef(const char *); 149#define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop") 150static bool handle_bsd_command(Buffer, Buffer, const char *); 151static bool register_target(GNode *, struct ohash *); 152static char *strip_comments(Buffer, const char *); 153static char *resolve_include_filename(const char *, const char *, bool); 154static void handle_include_file(const char *, const char *, bool, bool); 155static bool lookup_bsd_include(const char *); 156static void lookup_sysv_style_include(const char *, const char *, bool); 157static void lookup_sysv_include(const char *, const char *); 158static void lookup_conditional_include(const char *, const char *); 159static bool parse_as_special_line(Buffer, Buffer, const char *); 160static unsigned int parse_operator(const char **); 161 162static const char *parse_do_targets(Lst, unsigned int *, const char *); 163static void parse_target_line(struct growableArray *, const char *, 164 const char *, bool *); 165 166static void finish_commands(struct growableArray *); 167static void parse_commands(struct growableArray *, const char *); 168static void create_special_nodes(void); 169static bool found_delimiter(const char *); 170static unsigned int handle_special_targets(Lst); 171static void dump_targets(void); 172static void dedup_targets(struct growableArray *); 173static void build_target_group(struct growableArray *, struct ohash *t); 174static void reset_target_hash(void); 175 176 177#define P(k) k, sizeof(k), K_##k 178 179static struct { 180 const char *keyword; 181 size_t sz; 182 uint32_t hv; 183 unsigned int special; 184 unsigned int special_op; 185} specials[] = { 186 { P(NODE_EXEC), SPECIAL_DEPRECATED, 0 }, 187 { P(NODE_IGNORE), SPECIAL_IGNORE, OP_IGNORE }, 188 { P(NODE_INCLUDES), SPECIAL_DEPRECATED, 0 }, 189 { P(NODE_INVISIBLE), SPECIAL_DEPRECATED, 0 }, 190 { P(NODE_JOIN), SPECIAL_DEPRECATED, 0 }, 191 { P(NODE_LIBS), SPECIAL_DEPRECATED, 0 }, 192 { P(NODE_MADE), SPECIAL_DEPRECATED, 0 }, 193 { P(NODE_MAIN), SPECIAL_MAIN, 0 }, 194 { P(NODE_MAKE), SPECIAL_MAKE, OP_MAKE }, 195 { P(NODE_MAKEFLAGS), SPECIAL_MFLAGS, 0 }, 196 { P(NODE_MFLAGS), SPECIAL_MFLAGS, 0 }, 197 { P(NODE_NOTMAIN), SPECIAL_NOTMAIN, OP_NOTMAIN }, 198 { P(NODE_NOTPARALLEL), SPECIAL_NOTPARALLEL, 0 }, 199 { P(NODE_NO_PARALLEL), SPECIAL_NOTPARALLEL, 0 }, 200 { P(NODE_NULL), SPECIAL_DEPRECATED, 0 }, 201 { P(NODE_OPTIONAL), SPECIAL_OPTIONAL, OP_OPTIONAL }, 202 { P(NODE_ORDER), SPECIAL_ORDER, 0 }, 203 { P(NODE_PARALLEL), SPECIAL_PARALLEL, 0 }, 204 { P(NODE_PATH), SPECIAL_PATH, 0 }, 205 { P(NODE_PHONY), SPECIAL_PHONY, OP_PHONY }, 206 { P(NODE_PRECIOUS), SPECIAL_PRECIOUS, OP_PRECIOUS }, 207 { P(NODE_RECURSIVE), SPECIAL_MAKE, OP_MAKE }, 208 { P(NODE_SILENT), SPECIAL_SILENT, OP_SILENT }, 209 { P(NODE_SINGLESHELL), SPECIAL_NOTHING, 0 }, 210 { P(NODE_SUFFIXES), SPECIAL_SUFFIXES, 0 }, 211 { P(NODE_USE), SPECIAL_USE, OP_USE }, 212 { P(NODE_WAIT), SPECIAL_WAIT, 0 }, 213 { P(NODE_CHEAP), SPECIAL_CHEAP, OP_CHEAP }, 214 { P(NODE_EXPENSIVE), SPECIAL_EXPENSIVE, OP_EXPENSIVE }, 215 { P(NODE_POSIX), SPECIAL_NOTHING, 0 }, 216 { P(NODE_SCCS_GET), SPECIAL_NOTHING, 0 }, 217}; 218 219#undef P 220 221static void 222create_special_nodes() 223{ 224 unsigned int i; 225 226 for (i = 0; i < sizeof(specials)/sizeof(specials[0]); i++) { 227 (void)Targ_mk_special_node(specials[i].keyword, 228 specials[i].sz, specials[i].hv, 229 OP_ZERO, specials[i].special, specials[i].special_op); 230 } 231} 232 233/*- 234 *--------------------------------------------------------------------- 235 * ParseLinkSrc -- 236 * Link the parent node to its new child. Used by 237 * ParseDoDependency. If the specType isn't 'Not', the parent 238 * isn't linked as a parent of the child. 239 * 240 * Side Effects: 241 * New elements are added to the parents list of cgn and the 242 * children list of cgn. the children_left field of pgn is updated 243 * to reflect the additional child. 244 *--------------------------------------------------------------------- 245 */ 246static void 247ParseLinkSrc(GNode *pgn, GNode *cgn) 248{ 249 if (Lst_AddNew(&pgn->children, cgn)) { 250 if (specType == SPECIAL_NONE) 251 Lst_AtEnd(&cgn->parents, pgn); 252 pgn->children_left++; 253 } 254} 255 256static char * 257operator_string(int op) 258{ 259 /* XXX we don't bother freeing this, it's used for a fatal error 260 * anyways 261 */ 262 char *result = emalloc(5); 263 char *t = result; 264 if (op & OP_DEPENDS) { 265 *t++ = ':'; 266 } 267 if (op & OP_FORCE) { 268 *t++ = '!'; 269 } 270 if (op & OP_DOUBLEDEP) { 271 *t++ = ':'; 272 *t++ = ':'; 273 } 274 *t = 0; 275 return result; 276} 277 278/*- 279 *--------------------------------------------------------------------- 280 * ParseDoOp -- 281 * Apply the parsed operator to the given target node. Used in a 282 * Array_Find call by ParseDoDependency once all targets have 283 * been found and their operator parsed. If the previous and new 284 * operators are incompatible, a major error is taken, and the find 285 * stops early 286 * 287 * Side Effects: 288 * The node gets the right dependency operator. 289 * Cohorts may be created for double dep. 290 *--------------------------------------------------------------------- 291 */ 292static int 293ParseDoOp(GNode **gnp, unsigned int op) 294{ 295 GNode *gn = *gnp; 296 297 assert(op == (op & OP_OPMASK)); 298 299 /* if the node didn't already appear on the left hand side (no known 300 * dependency operator), we don't need to do much. */ 301 if (!OP_NOP(gn->type)) { 302 /* 303 * If the dependency mask of the operator and the node don't 304 * match and the node has actually had an operator applied to 305 * it before, and the operator actually has some dependency 306 * information in it, complain. */ 307 if (op != (gn->type & OP_OPMASK)) { 308 Parse_Error(PARSE_FATAL, 309 "Inconsistent dependency operator for target %s\n" 310 "\t(was %s%s, now %s%s)", 311 gn->name, gn->name, operator_string(gn->type), 312 gn->name, operator_string(op)); 313 return 0; 314 } 315 316 if (op == OP_DOUBLEDEP) { 317 /* If the node was the object of a :: operator, we need 318 * to create a new instance of it for the children and 319 * commands on this dependency line. The new instance 320 * is placed on the 'cohorts' list of the initial one 321 * (note the initial one is not on its own cohorts 322 * list) and the new instance is linked to all parents 323 * of the initial instance. */ 324 GNode *cohort; 325 LstNode ln; 326 327 cohort = Targ_NewGN(gn->name); 328 /* Duplicate links to parents so graph traversal is 329 * simple. Perhaps some type bits should be 330 * duplicated? 331 * 332 * Make the cohort invisible as well to avoid 333 * duplicating it into other variables. True, parents 334 * of this target won't tend to do anything with their 335 * local variables, but better safe than sorry. */ 336 for (ln = Lst_First(&gn->parents); ln != NULL; 337 ln = Lst_Adv(ln)) 338 ParseLinkSrc(Lst_Datum(ln), cohort); 339 cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; 340 Lst_AtEnd(&gn->cohorts, cohort); 341 342 /* Replace the node in the targets list with the new 343 * copy */ 344 *gnp = cohort; 345 gn = cohort; 346 } 347 } 348 /* Preserve possible special flags already applied to the operator */ 349 gn->type |= op; 350 return 1; 351} 352 353static void 354ParseDoSpecial(GNode *gn, unsigned int special_op) 355{ 356 gn->type |= special_op; 357} 358 359/*- 360 *--------------------------------------------------------------------- 361 * ParseAddDep -- 362 * Check if the pair of GNodes given needs to be synchronized. 363 * This has to be when two nodes are on different sides of a 364 * .WAIT directive. 365 * 366 * Results: 367 * Returns 0 if the two targets need to be ordered, 1 otherwise. 368 * If it returns 0, the search can stop. 369 * 370 * Side Effects: 371 * A dependency can be added between the two nodes. 372 * 373 *--------------------------------------------------------------------- 374 */ 375static int 376ParseAddDep(GNode *p, GNode *s) 377{ 378 if (p->order < s->order) { 379 /* XXX: This can cause cycles but finding them is hard 380 * and debugging output will show the problem. */ 381 Lst_AtEnd(&s->predecessors, p); 382 Lst_AtEnd(&p->successors, s); 383 return 1; 384 } else 385 return 0; 386} 387 388static void 389apply_op(struct growableArray *targets, unsigned int op, GNode *gn) 390{ 391 if (op) 392 gn->type |= op; 393 else 394 Array_ForEach(targets, ParseLinkSrc, gn); 395} 396 397/*- 398 *--------------------------------------------------------------------- 399 * ParseDoSrc -- 400 * Given the name of a source, figure out if it is an attribute 401 * and apply it to the targets if it is. Else decide if there is 402 * some attribute which should be applied *to* the source because 403 * of some special target and apply it if so. Otherwise, make the 404 * source be a child of the targets in the list 'targets' 405 * 406 * Side Effects: 407 * Operator bits may be added to the list of targets or to the source. 408 * The targets may have a new source added to their lists of children. 409 *--------------------------------------------------------------------- 410 */ 411static void 412ParseDoSrc( 413 struct growableArray *targets, 414 struct growableArray *sources, 415 int tOp, /* operator (if any) from special targets */ 416 const char *src, /* name of the source to handle */ 417 const char *esrc) 418{ 419 GNode *gn = Targ_FindNodei(src, esrc, TARG_CREATE); 420 if (gn->special == SPECIAL_DEPRECATED) { 421 Parse_Error(PARSE_FATAL, "Deprecated keyword found %s\n", 422 gn->name); 423 return; 424 } 425 if (gn->special_op) { 426 Array_ForEach(targets, ParseDoSpecial, gn->special_op); 427 return; 428 } 429 if (gn->special == SPECIAL_WAIT) { 430 waiting++; 431 return; 432 } 433 434 switch (specType) { 435 case SPECIAL_MAIN: 436 /* 437 * If we have noted the existence of a .MAIN, it means we need 438 * to add the sources of said target to the list of things 439 * to create. Note that this will only be invoked if the user 440 * didn't specify a target on the command line. This is to 441 * allow #ifmake's to succeed, or something... 442 */ 443 Lst_AtEnd(create, gn->name); 444 /* 445 * Add the name to the .TARGETS variable as well, so the user 446 * can employ that, if desired. 447 */ 448 Var_Append(".TARGETS", gn->name); 449 return; 450 451 case SPECIAL_ORDER: 452 /* 453 * Create proper predecessor/successor links between the 454 * previous source and the current one. 455 */ 456 if (predecessor != NULL) { 457 Lst_AtEnd(&predecessor->successors, gn); 458 Lst_AtEnd(&gn->predecessors, predecessor); 459 } 460 predecessor = gn; 461 break; 462 463 default: 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 apply_op(targets, tOp, gn); 471 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 472 LstNode ln; 473 474 for (ln=Lst_First(&gn->cohorts); ln != NULL; 475 ln = Lst_Adv(ln)){ 476 apply_op(targets, tOp, Lst_Datum(ln)); 477 } 478 } 479 break; 480 } 481 482 gn->order = waiting; 483 Array_AtEnd(sources, gn); 484 if (waiting) 485 Array_Find(sources, ParseAddDep, gn); 486} 487 488/*- 489 *----------------------------------------------------------------------- 490 * ParseFindMain -- 491 * Find a real target in the list and set it to be the main one. 492 * Called by ParseDoDependency when a main target hasn't been found 493 * yet. 494 * 495 * Results: 496 * 1 if main not found yet, 0 if it is. 497 * 498 * Side Effects: 499 * mainNode is changed and. 500 *----------------------------------------------------------------------- 501 */ 502static int 503ParseFindMain(void *gnp, void *dummy UNUSED) 504{ 505 GNode *gn = gnp; 506 507 if ((gn->type & OP_NOTARGET) == 0 && gn->special == SPECIAL_NONE) { 508 mainNode = gn; 509 return 0; 510 } else { 511 return 1; 512 } 513} 514 515/*- 516 *----------------------------------------------------------------------- 517 * ParseClearPath -- 518 * Reinit path to an empty path 519 *----------------------------------------------------------------------- 520 */ 521static void 522ParseClearPath(void *p) 523{ 524 Lst path = p; 525 526 Lst_Destroy(path, Dir_Destroy); 527 Lst_Init(path); 528} 529 530static void 531add_target_node(const char *line, const char *end) 532{ 533 GNode *gn; 534 535 gn = Suff_ParseAsTransform(line, end); 536 537 if (gn == NULL) { 538 gn = Targ_FindNodei(line, end, TARG_CREATE); 539 gn->type &= ~OP_DUMMY; 540 } 541 542 Array_AtEnd(>argets, gn); 543} 544 545static void 546add_target_nodes(const char *line, const char *end) 547{ 548 549 if (Dir_HasWildcardsi(line, end)) { 550 /* 551 * Targets are to be sought only in the current directory, 552 * so create an empty path for the thing. Note we need to 553 * use Dir_Destroy in the destruction of the path as the 554 * Dir module could have added a directory to the path... 555 */ 556 char *targName; 557 LIST emptyPath; 558 LIST curTargs; 559 560 Lst_Init(&emptyPath); 561 Lst_Init(&curTargs); 562 Dir_Expandi(line, end, &emptyPath, &curTargs); 563 Lst_Destroy(&emptyPath, Dir_Destroy); 564 while ((targName = Lst_DeQueue(&curTargs)) != NULL) { 565 add_target_node(targName, targName + strlen(targName)); 566 } 567 Lst_Destroy(&curTargs, NOFREE); 568 } else { 569 add_target_node(line, end); 570 } 571} 572 573/* special target line check: a proper delimiter is a ':' or '!', but 574 * we don't want to end a target on such a character if there is a better 575 * match later on. 576 * By "better" I mean one that is followed by whitespace. This allows the 577 * user to have targets like: 578 * fie::fi:fo: fum 579 * where "fie::fi:fo" is the target. In real life this is used for perl5 580 * library man pages where "::" separates an object from its class. Ie: 581 * "File::Spec::Unix". 582 * This behaviour is also consistent with other versions of make. 583 */ 584static bool 585found_delimiter(const char *s) 586{ 587 if (*s == '!' || *s == ':') { 588 const char *p = s + 1; 589 590 if (*s == ':' && *p == ':') 591 p++; 592 593 /* Found the best match already. */ 594 if (ISSPACE(*p) || *p == '\0') 595 return true; 596 597 do { 598 p += strcspn(p, "!:"); 599 if (*p == '\0') 600 break; 601 /* always prefer : to ! if not space separated */ 602 if (*p == ':' && *s == '!') 603 return false; 604 p++; 605 } while (*p != '\0' && !ISSPACE(*p)); 606 607 /* No better match later on... */ 608 if (*p == '\0') 609 return true; 610 } 611 return false; 612} 613 614static const char * 615parse_do_targets(Lst paths, unsigned int *op, const char *line) 616{ 617 const char *cp; 618 619 do { 620 for (cp = line; *cp && !ISSPACE(*cp) && *cp != '(';) { 621 if (*cp == '$') 622 /* Must be a dynamic source (would have been 623 * expanded otherwise), so call the Var module 624 * to parse the puppy so we can safely advance 625 * beyond it...There should be no errors in 626 * this, as they would have been discovered in 627 * the initial Var_Subst and we wouldn't be 628 * here. */ 629 Var_ParseSkip(&cp, NULL); 630 else { 631 if (found_delimiter(cp)) 632 break; 633 cp++; 634 } 635 } 636 637 if (*cp == '(') { 638 LIST temp; 639 Lst_Init(&temp); 640 /* Archives must be handled specially to make sure the 641 * OP_ARCHV flag is set in their 'type' field, for one 642 * thing, and because things like "archive(file1.o 643 * file2.o file3.o)" are permissible. 644 * Arch_ParseArchive will set 'line' to be the first 645 * non-blank after the archive-spec. It creates/finds 646 * nodes for the members and places them on the given 647 * list, returning true if all went well and false if 648 * there was an error in the specification. On error, 649 * line should remain untouched. */ 650 if (!Arch_ParseArchive(&line, &temp, NULL)) { 651 Parse_Error(PARSE_FATAL, 652 "Error in archive specification: \"%s\"", 653 line); 654 return NULL; 655 } else { 656 AppendList2Array(&temp, >argets); 657 Lst_Destroy(&temp, NOFREE); 658 cp = line; 659 continue; 660 } 661 } 662 if (*cp == '\0') { 663 /* Ending a dependency line without an operator is a 664 * Bozo no-no */ 665 /* Deeper check for cvs conflicts */ 666 if (gtargets.n > 0 && 667 (strcmp(gtargets.a[0]->name, "<<<<<<<") == 0 || 668 strcmp(gtargets.a[0]->name, ">>>>>>>") == 0)) { 669 Parse_Error(PARSE_FATAL, 670 "Need an operator (likely from a cvs update conflict)"); 671 } else { 672 Parse_Error(PARSE_FATAL, 673 "Need an operator in '%s'", line); 674 } 675 return NULL; 676 } 677 /* 678 * Have word in line. Get or create its nodes and stick it at 679 * the end of the targets list 680 */ 681 if (*line != '\0') 682 add_target_nodes(line, cp); 683 684 while (ISSPACE(*cp)) 685 cp++; 686 line = cp; 687 } while (*line != '!' && *line != ':' && *line); 688 *op = handle_special_targets(paths); 689 return cp; 690} 691 692static void 693dump_targets() 694{ 695 size_t i; 696 for (i = 0; i < gtargets.n; i++) 697 fprintf(stderr, "%s", gtargets.a[i]->name); 698 fprintf(stderr, "\n"); 699} 700 701static unsigned int 702handle_special_targets(Lst paths) 703{ 704 size_t i; 705 int seen_path = 0; 706 int seen_special = 0; 707 int seen_normal = 0; 708 int type; 709 710 for (i = 0; i < gtargets.n; i++) { 711 type = gtargets.a[i]->special; 712 if (type == SPECIAL_DEPRECATED) { 713 Parse_Error(PARSE_FATAL, 714 "Deprecated keyword found %s\n", 715 gtargets.a[i]->name); 716 specType = SPECIAL_ERROR; 717 return 0; 718 } 719 if (type == SPECIAL_PATH) { 720 seen_path++; 721 Lst_AtEnd(paths, find_suffix_path(gtargets.a[i])); 722 } else if (type != 0) 723 seen_special++; 724 else 725 seen_normal++; 726 } 727 if ((seen_path != 0) + (seen_special != 0) + (seen_normal != 0) > 1) { 728 Parse_Error(PARSE_FATAL, "Wrong mix of special targets"); 729 dump_targets(); 730 specType = SPECIAL_ERROR; 731 return 0; 732 } 733 if (seen_normal != 0) { 734 specType = SPECIAL_NONE; 735 return 0; 736 } else if (seen_path != 0) { 737 specType = SPECIAL_PATH; 738 return 0; 739 } else if (seen_special == 0) { 740 specType = SPECIAL_NONE; 741 return 0; 742 } else if (seen_special != 1) { 743 Parse_Error(PARSE_FATAL, 744 "Mixing special targets is not allowed"); 745 dump_targets(); 746 return 0; 747 } else if (seen_special == 1) { 748 specType = gtargets.a[0]->special; 749 switch (specType) { 750 case SPECIAL_MAIN: 751 if (!Lst_IsEmpty(create)) { 752 specType = SPECIAL_NONE; 753 } 754 break; 755 case SPECIAL_NOTPARALLEL: 756 set_notparallel(); 757 break; 758 case SPECIAL_ORDER: 759 predecessor = NULL; 760 break; 761 default: 762 break; 763 } 764 return gtargets.a[0]->special_op; 765 } else { 766 /* we're allowed to have 0 target */ 767 specType = SPECIAL_NONE; 768 return 0; 769 } 770} 771 772static unsigned int 773parse_operator(const char **pos) 774{ 775 const char *cp = *pos; 776 unsigned int op = OP_ERROR; 777 778 if (*cp == '!') { 779 op = OP_FORCE; 780 } else if (*cp == ':') { 781 if (cp[1] == ':') { 782 op = OP_DOUBLEDEP; 783 cp++; 784 } else { 785 op = OP_DEPENDS; 786 } 787 } else { 788 Parse_Error(PARSE_FATAL, "Missing dependency operator"); 789 return OP_ERROR; 790 } 791 792 cp++; /* Advance beyond operator */ 793 794 /* Get to the first source */ 795 while (ISSPACE(*cp)) 796 cp++; 797 *pos = cp; 798 return op; 799} 800 801/*- 802 *--------------------------------------------------------------------- 803 * ParseDoDependency -- 804 * Parse the dependency line in line. 805 * 806 * Side Effects: 807 * The nodes of the sources are linked as children to the nodes of the 808 * targets. Some nodes may be created. 809 * 810 * We parse a dependency line by first extracting words from the line and 811 * finding nodes in the list of all targets with that name. This is done 812 * until a character is encountered which is an operator character. Currently 813 * these are only ! and :. At this point the operator is parsed and the 814 * pointer into the line advanced until the first source is encountered. 815 * The parsed operator is applied to each node in the 'targets' list, 816 * which is where the nodes found for the targets are kept, by means of 817 * the ParseDoOp function. 818 * The sources are read in much the same way as the targets were except 819 * that now they are expanded using the wildcarding scheme of the C-Shell 820 * and all instances of the resulting words in the list of all targets 821 * are found. Each of the resulting nodes is then linked to each of the 822 * targets as one of its children. 823 * Certain targets are handled specially. These are the ones detailed 824 * by the specType variable. 825 * The storing of transformation rules is also taken care of here. 826 * A target is recognized as a transformation rule by calling 827 * Suff_IsTransform. If it is a transformation rule, its node is gotten 828 * from the suffix module via Suff_AddTransform rather than the standard 829 * Targ_FindNode in the target module. 830 *--------------------------------------------------------------------- 831 */ 832static void 833ParseDoDependency(const char *line) /* the line to parse */ 834{ 835 const char *cp; /* our current position */ 836 unsigned int op; /* the operator on the line */ 837 LIST paths; /* List of search paths to alter when parsing 838 * a list of .PATH targets */ 839 unsigned int tOp; /* operator from special target */ 840 841 waiting = 0; 842 Lst_Init(&paths); 843 844 Array_Reset(&gsources); 845 846 cp = parse_do_targets(&paths, &tOp, line); 847 assert(specType == SPECIAL_PATH || Lst_IsEmpty(&paths)); 848 if (cp == NULL || specType == SPECIAL_ERROR) { 849 /* invalidate targets for further processing */ 850 Array_Reset(>argets); 851 return; 852 } 853 854 op = parse_operator(&cp); 855 if (op == OP_ERROR) { 856 /* invalidate targets for further processing */ 857 Array_Reset(>argets); 858 return; 859 } 860 861 Array_FindP(>argets, ParseDoOp, op); 862 dedup_targets(>argets); 863 864 line = cp; 865 866 /* Several special targets have specific semantics with no source: 867 * .SUFFIXES clears out all old suffixes 868 * .PRECIOUS/.IGNORE/.SILENT 869 * apply to all target 870 * .PATH clears out all search paths. */ 871 if (!*line) { 872 switch (specType) { 873 case SPECIAL_SUFFIXES: 874 Suff_DisableAllSuffixes(); 875 break; 876 case SPECIAL_PRECIOUS: 877 allPrecious = true; 878 break; 879 case SPECIAL_IGNORE: 880 ignoreErrors = true; 881 break; 882 case SPECIAL_SILENT: 883 beSilent = true; 884 break; 885 case SPECIAL_PATH: 886 Lst_Every(&paths, ParseClearPath); 887 break; 888 default: 889 break; 890 } 891 } else if (specType == SPECIAL_MFLAGS) { 892 Main_ParseArgLine(line); 893 return; 894 } else if (specType == SPECIAL_NOTPARALLEL) { 895 return; 896 } 897 898 /* NOW GO FOR THE SOURCES */ 899 if (specType == SPECIAL_SUFFIXES || specType == SPECIAL_PATH || 900 specType == SPECIAL_NOTHING) { 901 while (*line) { 902 /* Some special targets take a list of space-separated 903 * words. For each word, 904 * 905 * if .SUFFIXES, add it to the list of suffixes maintained 906 * by suff.c. 907 * 908 * if .PATHS, add it as a directory on the main search path. 909 * 910 * if .LIBS/.INCLUDE/.NULL... this has been deprecated, 911 * ignore 912 */ 913 while (*cp && !ISSPACE(*cp)) 914 cp++; 915 switch (specType) { 916 case SPECIAL_SUFFIXES: 917 Suff_AddSuffixi(line, cp); 918 break; 919 case SPECIAL_PATH: 920 { 921 LstNode ln; 922 923 for (ln = Lst_First(&paths); ln != NULL; 924 ln = Lst_Adv(ln)) 925 Dir_AddDiri(Lst_Datum(ln), line, cp); 926 break; 927 } 928 default: 929 break; 930 } 931 if (*cp != '\0') 932 cp++; 933 while (ISSPACE(*cp)) 934 cp++; 935 line = cp; 936 } 937 } else { 938 while (*line) { 939 /* 940 * The targets take real sources, so we must beware of 941 * archive specifications (i.e. things with left 942 * parentheses in them) and handle them accordingly. 943 */ 944 while (*cp && !ISSPACE(*cp)) { 945 if (*cp == '(' && cp > line && cp[-1] != '$') { 946 /* 947 * Only stop for a left parenthesis if 948 * it isn't at the start of a word 949 * (that'll be for variable changes 950 * later) and isn't preceded by a 951 * dollar sign (a dynamic source). 952 */ 953 break; 954 } else { 955 cp++; 956 } 957 } 958 959 if (*cp == '(') { 960 GNode *gn; 961 LIST sources; /* list of archive source 962 * names after expansion */ 963 964 Lst_Init(&sources); 965 if (!Arch_ParseArchive(&line, &sources, NULL)) { 966 Parse_Error(PARSE_FATAL, 967 "Error in source archive spec \"%s\"", 968 line); 969 return; 970 } 971 972 while ((gn = Lst_DeQueue(&sources)) != NULL) 973 ParseDoSrc(>argets, &gsources, tOp, 974 gn->name, NULL); 975 cp = line; 976 } else { 977 const char *endSrc = cp; 978 979 ParseDoSrc(>argets, &gsources, tOp, line, 980 endSrc); 981 if (*cp) 982 cp++; 983 } 984 while (ISSPACE(*cp)) 985 cp++; 986 line = cp; 987 } 988 } 989 990 /* If we're not in the SPEC_PATH case the list is empty, but who 991 * cares ? This is cheap. 992 */ 993 Lst_Destroy(&paths, NOFREE); 994 995 if (mainNode == NULL) { 996 /* If we have yet to decide on a main target to make, in the 997 * absence of any user input, we want the first target on 998 * the first dependency line that is actually a real target 999 * (i.e. isn't a .USE or .EXEC rule) to be made. */ 1000 Array_Find(>argets, ParseFindMain, NULL); 1001 } 1002} 1003 1004/*- 1005 * ParseAddCmd -- 1006 * Lst_ForEach function to add a command line to all targets 1007 * 1008 * The new command may be added to the commands list of the node. 1009 * 1010 * If the target already had commands, we ignore the new ones, but 1011 * we note that we got double commands (in case we actually get to run 1012 * that ambiguous target). 1013 * 1014 * Note this does not apply to :: dependency lines, since those 1015 * will generate fresh cloned nodes and add them to the cohorts 1016 * field of the main node. 1017 */ 1018static void 1019ParseAddCmd(void *gnp, void *cmd) 1020{ 1021 GNode *gn = gnp; 1022 1023 if (!(gn->type & OP_HAS_COMMANDS)) 1024 Lst_AtEnd(&gn->commands, cmd); 1025 else 1026 gn->type |= OP_DOUBLE; 1027} 1028 1029/*- 1030 *----------------------------------------------------------------------- 1031 * ParseHasCommands -- 1032 * Record that the target gained commands through OP_HAS_COMMANDS, 1033 * so that double command lists may be ignored. 1034 *----------------------------------------------------------------------- 1035 */ 1036static void 1037ParseHasCommands(void *gnp) 1038{ 1039 GNode *gn = gnp; 1040 gn->type |= OP_HAS_COMMANDS; 1041 1042} 1043 1044 1045/* Strip comments from line. Build a copy in buffer if necessary, */ 1046static char * 1047strip_comments(Buffer copy, const char *line) 1048{ 1049 const char *comment; 1050 const char *p; 1051 1052 comment = strchr(line, '#'); 1053 if (comment == NULL) 1054 return (char *)line; 1055 else { 1056 Buf_Reset(copy); 1057 1058 for (p = line; *p != '\0'; p++) { 1059 if (*p == '\\') { 1060 if (p[1] == '#') { 1061 Buf_Addi(copy, line, p); 1062 Buf_AddChar(copy, '#'); 1063 line = p+2; 1064 } 1065 if (p[1] != '\0') 1066 p++; 1067 } else if (*p == '#') 1068 break; 1069 } 1070 Buf_Addi(copy, line, p); 1071 return Buf_Retrieve(copy); 1072 } 1073} 1074 1075 1076 1077/*** 1078 *** Support for various include constructs 1079 ***/ 1080 1081 1082void 1083Parse_AddIncludeDir(const char *dir) 1084{ 1085 Dir_AddDir(userIncludePath, dir); 1086} 1087 1088static char * 1089resolve_include_filename(const char *file, const char *efile, bool isSystem) 1090{ 1091 char *fullname; 1092 1093 /* Look up system files on the system path first */ 1094 if (isSystem) { 1095 fullname = Dir_FindFileNoDoti(file, efile, systemIncludePath); 1096 if (fullname) 1097 return fullname; 1098 } 1099 1100 /* Handle non-system non-absolute files... */ 1101 if (!isSystem && file[0] != '/') { 1102 /* ... by looking first under the same directory as the 1103 * current file */ 1104 char *slash = NULL; 1105 const char *fname; 1106 1107 fname = Parse_Getfilename(); 1108 1109 if (fname != NULL) 1110 slash = strrchr(fname, '/'); 1111 1112 if (slash != NULL) { 1113 char *newName; 1114 1115 newName = Str_concati(fname, slash, file, efile, '/'); 1116 fullname = Dir_FindFile(newName, userIncludePath); 1117 if (fullname == NULL) 1118 fullname = Dir_FindFile(newName, defaultPath); 1119 free(newName); 1120 if (fullname) 1121 return fullname; 1122 } 1123 } 1124 1125 /* Now look first on the -I search path, then on the .PATH 1126 * search path, if not found in a -I directory. 1127 * XXX: Suffix specific? */ 1128 fullname = Dir_FindFilei(file, efile, userIncludePath); 1129 if (fullname) 1130 return fullname; 1131 fullname = Dir_FindFilei(file, efile, defaultPath); 1132 if (fullname) 1133 return fullname; 1134 1135 /* Still haven't found the makefile. Look for it on the system 1136 * path as a last resort (if we haven't already). */ 1137 if (isSystem) 1138 return NULL; 1139 else 1140 return Dir_FindFilei(file, efile, systemIncludePath); 1141} 1142 1143static void 1144handle_include_file(const char *file, const char *efile, bool isSystem, 1145 bool errIfNotFound) 1146{ 1147 char *fullname; 1148 1149 fullname = resolve_include_filename(file, efile, isSystem); 1150 if (fullname == NULL && errIfNotFound) 1151 Parse_Error(PARSE_FATAL, "Could not find %.*s", 1152 (int)(efile - file), file); 1153 1154 if (fullname != NULL) { 1155 FILE *f; 1156 1157 f = fopen(fullname, "r"); 1158 if (f == NULL && errIfNotFound) 1159 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 1160 else 1161 Parse_FromFile(fullname, f); 1162 } 1163} 1164 1165/* .include <file> (system) or .include "file" (normal) */ 1166static bool 1167lookup_bsd_include(const char *file) 1168{ 1169 char endc; 1170 const char *efile; 1171 char *file2; 1172 bool isSystem; 1173 1174 /* find starting delimiter */ 1175 while (ISSPACE(*file)) 1176 file++; 1177 1178 /* determine type of file */ 1179 if (*file == '<') { 1180 isSystem = true; 1181 endc = '>'; 1182 } else if (*file == '"') { 1183 isSystem = false; 1184 endc = '"'; 1185 } else { 1186 Parse_Error(PARSE_WARNING, 1187 ".include filename must be delimited by '\"' or '<'"); 1188 return false; 1189 } 1190 1191 /* delimit file name between file and efile */ 1192 for (efile = ++file; *efile != endc; efile++) { 1193 if (*efile == '\0') { 1194 Parse_Error(PARSE_WARNING, 1195 "Unclosed .include filename. '%c' expected", endc); 1196 return false; 1197 } 1198 } 1199 /* Substitute for any variables in the file name before trying to 1200 * find the thing. */ 1201 file2 = Var_Substi(file, efile, NULL, false); 1202 handle_include_file(file2, strchr(file2, '\0'), isSystem, true); 1203 free(file2); 1204 return true; 1205} 1206 1207 1208static void 1209lookup_sysv_style_include(const char *line, const char *directive, 1210 bool errIfMissing) 1211{ 1212 char *file; 1213 char *name; 1214 char *ename; 1215 bool okay = false; 1216 1217 /* Substitute for any variables in the file name before trying to 1218 * find the thing. */ 1219 file = Var_Subst(line, NULL, false); 1220 1221 /* sys5 allows for list of files separated by spaces */ 1222 name = file; 1223 while (1) { 1224 /* find beginning of name */ 1225 while (ISSPACE(*name)) 1226 name++; 1227 if (*name == '\0') 1228 break; 1229 for (ename = name; *ename != '\0' && !ISSPACE(*ename);) 1230 ename++; 1231 handle_include_file(name, ename, true, errIfMissing); 1232 okay = true; 1233 name = ename; 1234 } 1235 1236 free(file); 1237 if (!okay) { 1238 Parse_Error(PARSE_FATAL, "Filename missing from \"%s\"", 1239 directive); 1240 } 1241} 1242 1243 1244/* system V construct: include file */ 1245static void 1246lookup_sysv_include(const char *file, const char *directive) 1247{ 1248 lookup_sysv_style_include(file, directive, true); 1249} 1250 1251 1252/* sinclude file and -include file */ 1253static void 1254lookup_conditional_include(const char *file, const char *directive) 1255{ 1256 lookup_sysv_style_include(file, directive, false); 1257} 1258 1259 1260/*** 1261 *** BSD-specific . constructs 1262 *** They all follow the same pattern: 1263 *** if the syntax matches BSD stuff, then we're committed to handle 1264 *** them and report fatal errors (like, include file not existing) 1265 *** otherwise, we return false, and hope somebody else will handle it. 1266 ***/ 1267 1268static bool 1269handle_poison(const char *line) 1270{ 1271 const char *p = line; 1272 int type = POISON_NORMAL; 1273 bool not = false; 1274 bool paren_to_match = false; 1275 const char *name, *ename; 1276 1277 while (ISSPACE(*p)) 1278 p++; 1279 if (*p == '!') { 1280 not = true; 1281 p++; 1282 } 1283 while (ISSPACE(*p)) 1284 p++; 1285 if (strncmp(p, "defined", 7) == 0) { 1286 type = POISON_DEFINED; 1287 p += 7; 1288 } else if (strncmp(p, "empty", 5) == 0) { 1289 type = POISON_EMPTY; 1290 p += 5; 1291 } 1292 while (ISSPACE(*p)) 1293 p++; 1294 if (*p == '(') { 1295 paren_to_match = true; 1296 p++; 1297 } 1298 while (ISSPACE(*p)) 1299 p++; 1300 name = ename = p; 1301 while (*p != '\0' && !ISSPACE(*p)) { 1302 if (*p == ')' && paren_to_match) { 1303 paren_to_match = false; 1304 p++; 1305 break; 1306 } 1307 p++; 1308 ename = p; 1309 } 1310 while (ISSPACE(*p)) 1311 p++; 1312 switch(type) { 1313 case POISON_NORMAL: 1314 case POISON_EMPTY: 1315 if (not) 1316 type = POISON_INVALID; 1317 break; 1318 case POISON_DEFINED: 1319 if (not) 1320 type = POISON_NOT_DEFINED; 1321 else 1322 type = POISON_INVALID; 1323 break; 1324 } 1325 if ((*p != '\0' && *p != '#') || type == POISON_INVALID) { 1326 Parse_Error(PARSE_WARNING, "Invalid syntax for .poison: %s", 1327 line); 1328 return false; 1329 } else { 1330 Var_Mark(name, ename, type); 1331 return true; 1332 } 1333} 1334 1335 1336static bool 1337handle_for_loop(Buffer linebuf, const char *line) 1338{ 1339 For *loop; 1340 1341 loop = For_Eval(line); 1342 if (loop != NULL) { 1343 bool ok; 1344 do { 1345 /* Find the matching endfor. */ 1346 line = ParseReadLoopLine(linebuf); 1347 if (line == NULL) { 1348 Parse_Error(PARSE_FATAL, 1349 "Unexpected end of file in for loop.\n"); 1350 return false; 1351 } 1352 ok = For_Accumulate(loop, line); 1353 } while (ok); 1354 For_Run(loop); 1355 return true; 1356 } else 1357 return false; 1358} 1359 1360static bool 1361handle_undef(const char *line) 1362{ 1363 const char *eline; 1364 1365 while (ISSPACE(*line)) 1366 line++; 1367 for (eline = line; !ISSPACE(*eline) && *eline != '\0';) 1368 eline++; 1369 Var_Deletei(line, eline); 1370 return true; 1371} 1372 1373/* global hub for the construct */ 1374static bool 1375handle_bsd_command(Buffer linebuf, Buffer copy, const char *line) 1376{ 1377 char *stripped; 1378 1379 while (ISSPACE(*line)) 1380 line++; 1381 1382 /* delegate basic classification to the conditional module */ 1383 switch (Cond_Eval(line)) { 1384 case COND_SKIP: 1385 /* Skip to next conditional that evaluates to COND_PARSE. */ 1386 do { 1387 line = Parse_ReadNextConditionalLine(linebuf); 1388 if (line != NULL) { 1389 while (ISSPACE(*line)) 1390 line++; 1391 stripped = strip_comments(copy, line); 1392 } 1393 } while (line != NULL && Cond_Eval(stripped) != COND_PARSE); 1394 /* FALLTHROUGH */ 1395 case COND_PARSE: 1396 return true; 1397 case COND_ISFOR: 1398 return handle_for_loop(linebuf, line + 3); 1399 case COND_ISINCLUDE: 1400 return lookup_bsd_include(line + 7); 1401 case COND_ISPOISON: 1402 return handle_poison(line + 6); 1403 case COND_ISUNDEF: 1404 return handle_undef(line + 5); 1405 default: 1406 break; 1407 } 1408 1409 return false; 1410} 1411 1412/* postprocess group of targets prior to linking stuff with them */ 1413static bool 1414register_target(GNode *gn, struct ohash *t) 1415{ 1416 unsigned int slot; 1417 uint32_t hv; 1418 const char *ename = NULL; 1419 GNode *gn2; 1420 1421 hv = ohash_interval(gn->name, &ename); 1422 1423 slot = ohash_lookup_interval(t, gn->name, ename, hv); 1424 gn2 = ohash_find(t, slot); 1425 1426 if (gn2 == NULL) { 1427 ohash_insert(t, slot, gn); 1428 return true; 1429 } else 1430 return false; 1431} 1432 1433static void 1434build_target_group(struct growableArray *targets, struct ohash *t) 1435{ 1436 LstNode ln; 1437 bool seen_target = false; 1438 unsigned int i; 1439 1440 /* may be 0 if wildcard expansion resulted in zero match */ 1441 if (targets->n <= 1) 1442 return; 1443 1444 /* Perform checks to see if we must tie targets together */ 1445 /* XXX */ 1446 if (targets->a[0]->type & OP_TRANSFORM) 1447 return; 1448 1449 for (ln = Lst_First(&targets->a[0]->commands); ln != NULL; 1450 ln = Lst_Adv(ln)) { 1451 struct command *cmd = Lst_Datum(ln); 1452 if (Var_Check_for_target(cmd->string)) { 1453 seen_target = true; 1454 break; 1455 } 1456 } 1457 if (DEBUG(TARGGROUP)) { 1458 fprintf(stderr, 1459 seen_target ? "No target group at %lu: ": 1460 "Target group at %lu:", Parse_Getlineno()); 1461 for (i = 0; i < targets->n; i++) 1462 fprintf(stderr, " %s", targets->a[i]->name); 1463 fprintf(stderr, "\n"); 1464 } 1465 if (seen_target) 1466 return; 1467 1468 GNode *gn, *gn2; 1469 /* targets may already participate in groupling lists, 1470 * so rebuild the circular list "from scratch" 1471 */ 1472 1473 for (i = 0; i < targets->n; i++) { 1474 gn = targets->a[i]; 1475 for (gn2 = gn->groupling; gn2 != gn; gn2 = gn2->groupling) { 1476 if (!gn2) 1477 break; 1478 register_target(gn2, t); 1479 } 1480 } 1481 1482 for (gn = ohash_first(t, &i); gn != NULL; gn = ohash_next(t, &i)) { 1483 gn->groupling = gn2; 1484 gn2 = gn; 1485 } 1486 gn = ohash_first(t, &i); 1487 gn->groupling = gn2; 1488} 1489 1490static void 1491reset_target_hash() 1492{ 1493 if (htargets_setup) 1494 ohash_delete(&htargets); 1495 ohash_init(&htargets, 5, &gnode_info); 1496 htargets_setup = true; 1497} 1498 1499void 1500Parse_End() 1501{ 1502 if (htargets_setup) 1503 ohash_delete(&htargets); 1504} 1505 1506static void 1507dedup_targets(struct growableArray *targets) 1508{ 1509 unsigned int i, j; 1510 1511 if (targets->n <= 1) 1512 return; 1513 1514 reset_target_hash(); 1515 /* first let's de-dup the list */ 1516 for (i = 0, j = 0; i < targets->n; i++) { 1517 GNode *gn = targets->a[i]; 1518 if (register_target(gn, &htargets)) 1519 targets->a[j++] = targets->a[i]; 1520 } 1521 targets->n = j; 1522} 1523 1524 1525/*** 1526 *** handle a group of commands 1527 ***/ 1528 1529static void 1530finish_commands(struct growableArray *targets) 1531{ 1532 build_target_group(targets, &htargets); 1533 Array_Every(targets, ParseHasCommands); 1534} 1535 1536static void 1537parse_commands(struct growableArray *targets, const char *line) 1538{ 1539 /* add the command to the list of 1540 * commands of all targets in the dependency spec */ 1541 1542 struct command *cmd; 1543 size_t len = strlen(line); 1544 1545 cmd = emalloc(sizeof(struct command) + len); 1546 memcpy(&cmd->string, line, len+1); 1547 Parse_FillLocation(&cmd->location); 1548 1549 Array_ForEach(targets, ParseAddCmd, cmd); 1550} 1551 1552static bool 1553parse_as_special_line(Buffer buf, Buffer copy, const char *line) 1554{ 1555 if (*line == '.' && handle_bsd_command(buf, copy, line+1)) 1556 return true; 1557 if (strncmp(line, "include", 7) == 0 && 1558 ISSPACE(line[7]) && 1559 strchr(line, ':') == NULL) { 1560 /* It's an S3/S5-style "include". */ 1561 lookup_sysv_include(line + 7, "include"); 1562 return true; 1563 } 1564 if (strncmp(line, "sinclude", 8) == 0 && 1565 ISSPACE(line[8]) && 1566 strchr(line, ':') == NULL) { 1567 lookup_conditional_include(line+8, "sinclude"); 1568 return true; 1569 } 1570 if (strncmp(line, "-include", 8) == 0 && 1571 ISSPACE(line[8]) && 1572 strchr(line, ':') == NULL) { 1573 lookup_conditional_include(line+8, "-include"); 1574 return true; 1575 } 1576 return false; 1577} 1578 1579static void 1580parse_target_line(struct growableArray *targets, const char *line, 1581 const char *stripped, bool *pcommands_seen) 1582{ 1583 size_t pos; 1584 char *end; 1585 char *cp; 1586 char *cmd; 1587 1588 /* let's start a new set of commands */ 1589 Array_Reset(targets); 1590 1591 /* XXX this is a dirty heuristic to handle target: dep ; commands */ 1592 cmd = NULL; 1593 /* First we need to find eventual dependencies */ 1594 pos = strcspn(stripped, ":!"); 1595 /* go over :!, and find ; */ 1596 if (stripped[pos] != '\0' && 1597 (end = strchr(stripped+pos+1, ';')) != NULL) { 1598 if (line != stripped) 1599 /* find matching ; in original... The 1600 * original might be slightly longer. */ 1601 cmd = strchr(line+(end-stripped), ';'); 1602 else 1603 cmd = end; 1604 /* kill end of line. */ 1605 *end = '\0'; 1606 } 1607 /* We now know it's a dependency line so it needs to 1608 * have all variables expanded before being parsed. 1609 */ 1610 cp = Var_Subst(stripped, NULL, false); 1611 ParseDoDependency(cp); 1612 free(cp); 1613 1614 /* Parse command if it's not empty. */ 1615 if (cmd != NULL) { 1616 do { 1617 cmd++; 1618 } while (ISSPACE(*cmd)); 1619 if (*cmd != '\0') { 1620 parse_commands(targets, cmd); 1621 *pcommands_seen = true; 1622 } 1623 } 1624} 1625 1626void 1627Parse_File(const char *filename, FILE *stream) 1628{ 1629 char *line; 1630 bool expectingCommands = false; 1631 bool commands_seen = false; 1632 1633 /* permanent spaces to shave time */ 1634 static BUFFER buf; 1635 static BUFFER copy; 1636 1637 Buf_Reinit(&buf, MAKE_BSIZE); 1638 Buf_Reinit(©, MAKE_BSIZE); 1639 1640 Parse_FromFile(filename, stream); 1641 do { 1642 while ((line = Parse_ReadNormalLine(&buf)) != NULL) { 1643 if (*line == '\t') { 1644 if (expectingCommands) { 1645 commands_seen = true; 1646 parse_commands(>argets, line+1); 1647 } else 1648 Parse_Error(PARSE_FATAL, 1649 "Unassociated shell command \"%s\"", 1650 line); 1651 } else { 1652 const char *stripped = strip_comments(©, 1653 line); 1654 if (!parse_as_special_line(&buf, ©, 1655 stripped)) { 1656 if (commands_seen) 1657 finish_commands(>argets); 1658 commands_seen = false; 1659 if (Parse_As_Var_Assignment(stripped)) 1660 expectingCommands = false; 1661 else { 1662 parse_target_line(>argets, 1663 line, stripped, 1664 &commands_seen); 1665 expectingCommands = true; 1666 } 1667 } 1668 } 1669 } 1670 } while (Parse_NextFile()); 1671 1672 if (commands_seen) 1673 finish_commands(>argets); 1674 /* Make sure conditionals are clean. */ 1675 Cond_End(); 1676 1677 Parse_ReportErrors(); 1678} 1679 1680void 1681Parse_Init(void) 1682{ 1683 mainNode = NULL; 1684 Static_Lst_Init(userIncludePath); 1685 Static_Lst_Init(systemIncludePath); 1686 Array_Init(>argets, TARGETS_SIZE); 1687 Array_Init(&gsources, SOURCES_SIZE); 1688 create_special_nodes(); 1689} 1690 1691void 1692Parse_MainName(Lst listmain) /* result list */ 1693{ 1694 if (mainNode == NULL) { 1695 dump_unreadable(); 1696 Punt("no target to make."); 1697 /*NOTREACHED*/ 1698 } else if (mainNode->type & OP_DOUBLEDEP) { 1699 Lst_AtEnd(listmain, mainNode); 1700 Lst_Concat(listmain, &mainNode->cohorts); 1701 } 1702 else 1703 Lst_AtEnd(listmain, mainNode); 1704} 1705