1 /* $NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Adam de Boor. 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 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 /* 36 * Copyright (c) 1989 by Berkeley Softworks 37 * All rights reserved. 38 * 39 * This code is derived from software contributed to Berkeley by 40 * Adam de Boor. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 */ 70 71 #ifndef MAKE_NATIVE 72 static char rcsid[] = "$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $"; 73 #else 74 #include <sys/cdefs.h> 75 #ifndef lint 76 #if 0 77 static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94"; 78 #else 79 __RCSID("$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $"); 80 #endif 81 #endif /* not lint */ 82 #endif 83 84 /*- 85 * targ.c -- 86 * Functions for maintaining the Lst allTargets. Target nodes are 87 * kept in two structures: a Lst, maintained by the list library, and a 88 * hash table, maintained by the hash library. 89 * 90 * Interface: 91 * Targ_Init Initialization procedure. 92 * 93 * Targ_End Cleanup the module 94 * 95 * Targ_List Return the list of all targets so far. 96 * 97 * Targ_NewGN Create a new GNode for the passed target 98 * (string). The node is *not* placed in the 99 * hash table, though all its fields are 100 * initialized. 101 * 102 * Targ_FindNode Find the node for a given target, creating 103 * and storing it if it doesn't exist and the 104 * flags are right (TARG_CREATE) 105 * 106 * Targ_FindList Given a list of names, find nodes for all 107 * of them. If a name doesn't exist and the 108 * TARG_NOCREATE flag was given, an error message 109 * is printed. Else, if a name doesn't exist, 110 * its node is created. 111 * 112 * Targ_Ignore Return TRUE if errors should be ignored when 113 * creating the given target. 114 * 115 * Targ_Silent Return TRUE if we should be silent when 116 * creating the given target. 117 * 118 * Targ_Precious Return TRUE if the target is precious and 119 * should not be removed if we are interrupted. 120 * 121 * Targ_Propagate Propagate information between related 122 * nodes. Should be called after the 123 * makefiles are parsed but before any 124 * action is taken. 125 * 126 * Debugging: 127 * Targ_PrintGraph Print out the entire graphm all variables 128 * and statistics for the directory cache. Should 129 * print something for suffixes, too, but... 130 */ 131 132 #include <stdio.h> 133 #include <time.h> 134 135 #include "make.h" 136 #include "hash.h" 137 #include "dir.h" 138 139 static Lst allTargets; /* the list of all targets found so far */ 140 #ifdef CLEANUP 141 static Lst allGNs; /* List of all the GNodes */ 142 #endif 143 static Hash_Table targets; /* a hash table of same */ 144 145 #define HTSIZE 191 /* initial size of hash table */ 146 147 static int TargPrintOnlySrc(void *, void *); 148 static int TargPrintName(void *, void *); 149 #ifdef CLEANUP 150 static void TargFreeGN(void *); 151 #endif 152 static int TargPropagateCohort(void *, void *); 153 static int TargPropagateNode(void *, void *); 154 155 /*- 156 *----------------------------------------------------------------------- 157 * Targ_Init -- 158 * Initialize this module 159 * 160 * Results: 161 * None 162 * 163 * Side Effects: 164 * The allTargets list and the targets hash table are initialized 165 *----------------------------------------------------------------------- 166 */ 167 void 168 Targ_Init(void) 169 { 170 allTargets = Lst_Init(FALSE); 171 Hash_InitTable(&targets, HTSIZE); 172 } 173 174 /*- 175 *----------------------------------------------------------------------- 176 * Targ_End -- 177 * Finalize this module 178 * 179 * Results: 180 * None 181 * 182 * Side Effects: 183 * All lists and gnodes are cleared 184 *----------------------------------------------------------------------- 185 */ 186 void 187 Targ_End(void) 188 { 189 #ifdef CLEANUP 190 Lst_Destroy(allTargets, NULL); 191 if (allGNs) 192 Lst_Destroy(allGNs, TargFreeGN); 193 Hash_DeleteTable(&targets); 194 #endif 195 } 196 197 /*- 198 *----------------------------------------------------------------------- 199 * Targ_List -- 200 * Return the list of all targets 201 * 202 * Results: 203 * The list of all targets. 204 * 205 * Side Effects: 206 * None 207 *----------------------------------------------------------------------- 208 */ 209 Lst 210 Targ_List(void) 211 { 212 return allTargets; 213 } 214 215 /*- 216 *----------------------------------------------------------------------- 217 * Targ_NewGN -- 218 * Create and initialize a new graph node 219 * 220 * Input: 221 * name the name to stick in the new node 222 * 223 * Results: 224 * An initialized graph node with the name field filled with a copy 225 * of the passed name 226 * 227 * Side Effects: 228 * The gnode is added to the list of all gnodes. 229 *----------------------------------------------------------------------- 230 */ 231 GNode * 232 Targ_NewGN(const char *name) 233 { 234 GNode *gn; 235 236 gn = bmake_malloc(sizeof(GNode)); 237 gn->name = bmake_strdup(name); 238 gn->uname = NULL; 239 gn->path = NULL; 240 if (name[0] == '-' && name[1] == 'l') { 241 gn->type = OP_LIB; 242 } else { 243 gn->type = 0; 244 } 245 gn->unmade = 0; 246 gn->unmade_cohorts = 0; 247 gn->cohort_num[0] = 0; 248 gn->centurion = NULL; 249 gn->made = UNMADE; 250 gn->flags = 0; 251 gn->checked = 0; 252 gn->mtime = 0; 253 gn->cmgn = NULL; 254 gn->iParents = Lst_Init(FALSE); 255 gn->cohorts = Lst_Init(FALSE); 256 gn->parents = Lst_Init(FALSE); 257 gn->children = Lst_Init(FALSE); 258 gn->order_pred = Lst_Init(FALSE); 259 gn->order_succ = Lst_Init(FALSE); 260 Hash_InitTable(&gn->context, 0); 261 gn->commands = Lst_Init(FALSE); 262 gn->suffix = NULL; 263 gn->lineno = 0; 264 gn->fname = NULL; 265 266 #ifdef CLEANUP 267 if (allGNs == NULL) 268 allGNs = Lst_Init(FALSE); 269 Lst_AtEnd(allGNs, gn); 270 #endif 271 272 return (gn); 273 } 274 275 #ifdef CLEANUP 276 /*- 277 *----------------------------------------------------------------------- 278 * TargFreeGN -- 279 * Destroy a GNode 280 * 281 * Results: 282 * None. 283 * 284 * Side Effects: 285 * None. 286 *----------------------------------------------------------------------- 287 */ 288 static void 289 TargFreeGN(void *gnp) 290 { 291 GNode *gn = (GNode *)gnp; 292 293 294 free(gn->name); 295 if (gn->uname) 296 free(gn->uname); 297 if (gn->path) 298 free(gn->path); 299 /* gn->fname points to name allocated when file was opened, don't free */ 300 301 Lst_Destroy(gn->iParents, NULL); 302 Lst_Destroy(gn->cohorts, NULL); 303 Lst_Destroy(gn->parents, NULL); 304 Lst_Destroy(gn->children, NULL); 305 Lst_Destroy(gn->order_succ, NULL); 306 Lst_Destroy(gn->order_pred, NULL); 307 Hash_DeleteTable(&gn->context); 308 Lst_Destroy(gn->commands, NULL); 309 free(gn); 310 } 311 #endif 312 313 314 /*- 315 *----------------------------------------------------------------------- 316 * Targ_FindNode -- 317 * Find a node in the list using the given name for matching 318 * 319 * Input: 320 * name the name to find 321 * flags flags governing events when target not 322 * found 323 * 324 * Results: 325 * The node in the list if it was. If it wasn't, return NULL of 326 * flags was TARG_NOCREATE or the newly created and initialized node 327 * if it was TARG_CREATE 328 * 329 * Side Effects: 330 * Sometimes a node is created and added to the list 331 *----------------------------------------------------------------------- 332 */ 333 GNode * 334 Targ_FindNode(const char *name, int flags) 335 { 336 GNode *gn; /* node in that element */ 337 Hash_Entry *he; /* New or used hash entry for node */ 338 Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ 339 /* an entry for the node */ 340 341 #if defined(__minix) 342 /* triggers a 'may be used uninitialized', when compiled with gcc, 343 * asserts off, and -Os. */ 344 he = NULL; 345 #endif /* defined(__minix) */ 346 if (!(flags & (TARG_CREATE | TARG_NOHASH))) { 347 he = Hash_FindEntry(&targets, name); 348 if (he == NULL) 349 return NULL; 350 return (GNode *)Hash_GetValue(he); 351 } 352 353 if (!(flags & TARG_NOHASH)) { 354 he = Hash_CreateEntry(&targets, name, &isNew); 355 if (!isNew) 356 return (GNode *)Hash_GetValue(he); 357 } 358 359 gn = Targ_NewGN(name); 360 if (!(flags & TARG_NOHASH)) 361 Hash_SetValue(he, gn); 362 Var_Append(".ALLTARGETS", name, VAR_GLOBAL); 363 (void)Lst_AtEnd(allTargets, gn); 364 if (doing_depend) 365 gn->flags |= FROM_DEPEND; 366 return gn; 367 } 368 369 /*- 370 *----------------------------------------------------------------------- 371 * Targ_FindList -- 372 * Make a complete list of GNodes from the given list of names 373 * 374 * Input: 375 * name list of names to find 376 * flags flags used if no node is found for a given name 377 * 378 * Results: 379 * A complete list of graph nodes corresponding to all instances of all 380 * the names in names. 381 * 382 * Side Effects: 383 * If flags is TARG_CREATE, nodes will be created for all names in 384 * names which do not yet have graph nodes. If flags is TARG_NOCREATE, 385 * an error message will be printed for each name which can't be found. 386 * ----------------------------------------------------------------------- 387 */ 388 Lst 389 Targ_FindList(Lst names, int flags) 390 { 391 Lst nodes; /* result list */ 392 LstNode ln; /* name list element */ 393 GNode *gn; /* node in tLn */ 394 char *name; 395 396 nodes = Lst_Init(FALSE); 397 398 if (Lst_Open(names) == FAILURE) { 399 return (nodes); 400 } 401 while ((ln = Lst_Next(names)) != NULL) { 402 name = (char *)Lst_Datum(ln); 403 gn = Targ_FindNode(name, flags); 404 if (gn != NULL) { 405 /* 406 * Note: Lst_AtEnd must come before the Lst_Concat so the nodes 407 * are added to the list in the order in which they were 408 * encountered in the makefile. 409 */ 410 (void)Lst_AtEnd(nodes, gn); 411 } else if (flags == TARG_NOCREATE) { 412 Error("\"%s\" -- target unknown.", name); 413 } 414 } 415 Lst_Close(names); 416 return (nodes); 417 } 418 419 /*- 420 *----------------------------------------------------------------------- 421 * Targ_Ignore -- 422 * Return true if should ignore errors when creating gn 423 * 424 * Input: 425 * gn node to check for 426 * 427 * Results: 428 * TRUE if should ignore errors 429 * 430 * Side Effects: 431 * None 432 *----------------------------------------------------------------------- 433 */ 434 Boolean 435 Targ_Ignore(GNode *gn) 436 { 437 if (ignoreErrors || gn->type & OP_IGNORE) { 438 return (TRUE); 439 } else { 440 return (FALSE); 441 } 442 } 443 444 /*- 445 *----------------------------------------------------------------------- 446 * Targ_Silent -- 447 * Return true if be silent when creating gn 448 * 449 * Input: 450 * gn node to check for 451 * 452 * Results: 453 * TRUE if should be silent 454 * 455 * Side Effects: 456 * None 457 *----------------------------------------------------------------------- 458 */ 459 Boolean 460 Targ_Silent(GNode *gn) 461 { 462 if (beSilent || gn->type & OP_SILENT) { 463 return (TRUE); 464 } else { 465 return (FALSE); 466 } 467 } 468 469 /*- 470 *----------------------------------------------------------------------- 471 * Targ_Precious -- 472 * See if the given target is precious 473 * 474 * Input: 475 * gn the node to check 476 * 477 * Results: 478 * TRUE if it is precious. FALSE otherwise 479 * 480 * Side Effects: 481 * None 482 *----------------------------------------------------------------------- 483 */ 484 Boolean 485 Targ_Precious(GNode *gn) 486 { 487 if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) { 488 return (TRUE); 489 } else { 490 return (FALSE); 491 } 492 } 493 494 /******************* DEBUG INFO PRINTING ****************/ 495 496 static GNode *mainTarg; /* the main target, as set by Targ_SetMain */ 497 /*- 498 *----------------------------------------------------------------------- 499 * Targ_SetMain -- 500 * Set our idea of the main target we'll be creating. Used for 501 * debugging output. 502 * 503 * Input: 504 * gn The main target we'll create 505 * 506 * Results: 507 * None. 508 * 509 * Side Effects: 510 * "mainTarg" is set to the main target's node. 511 *----------------------------------------------------------------------- 512 */ 513 void 514 Targ_SetMain(GNode *gn) 515 { 516 mainTarg = gn; 517 } 518 519 static int 520 TargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED) 521 { 522 GNode *gn = (GNode *)gnp; 523 524 fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num); 525 526 return 0; 527 } 528 529 530 int 531 Targ_PrintCmd(void *cmd, void *dummy) 532 { 533 fprintf(debug_file, "\t%s\n", (char *)cmd); 534 return (dummy ? 0 : 0); 535 } 536 537 /*- 538 *----------------------------------------------------------------------- 539 * Targ_FmtTime -- 540 * Format a modification time in some reasonable way and return it. 541 * 542 * Results: 543 * The time reformatted. 544 * 545 * Side Effects: 546 * The time is placed in a static area, so it is overwritten 547 * with each call. 548 * 549 *----------------------------------------------------------------------- 550 */ 551 char * 552 Targ_FmtTime(time_t tm) 553 { 554 struct tm *parts; 555 static char buf[128]; 556 557 parts = localtime(&tm); 558 (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); 559 return(buf); 560 } 561 562 /*- 563 *----------------------------------------------------------------------- 564 * Targ_PrintType -- 565 * Print out a type field giving only those attributes the user can 566 * set. 567 * 568 * Results: 569 * 570 * Side Effects: 571 * 572 *----------------------------------------------------------------------- 573 */ 574 void 575 Targ_PrintType(int type) 576 { 577 int tbit; 578 579 #define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break 580 #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break 581 582 type &= ~OP_OPMASK; 583 584 while (type) { 585 tbit = 1 << (ffs(type) - 1); 586 type &= ~tbit; 587 588 switch(tbit) { 589 PRINTBIT(OPTIONAL); 590 PRINTBIT(USE); 591 PRINTBIT(EXEC); 592 PRINTBIT(IGNORE); 593 PRINTBIT(PRECIOUS); 594 PRINTBIT(SILENT); 595 PRINTBIT(MAKE); 596 PRINTBIT(JOIN); 597 PRINTBIT(INVISIBLE); 598 PRINTBIT(NOTMAIN); 599 PRINTDBIT(LIB); 600 /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ 601 case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break; 602 PRINTDBIT(ARCHV); 603 PRINTDBIT(MADE); 604 PRINTDBIT(PHONY); 605 } 606 } 607 } 608 609 static const char * 610 made_name(enum enum_made made) 611 { 612 switch (made) { 613 case UNMADE: return "unmade"; 614 case DEFERRED: return "deferred"; 615 case REQUESTED: return "requested"; 616 case BEINGMADE: return "being made"; 617 case MADE: return "made"; 618 case UPTODATE: return "up-to-date"; 619 case ERROR: return "error when made"; 620 case ABORTED: return "aborted"; 621 default: return "unknown enum_made value"; 622 } 623 } 624 625 /*- 626 *----------------------------------------------------------------------- 627 * TargPrintNode -- 628 * print the contents of a node 629 *----------------------------------------------------------------------- 630 */ 631 int 632 Targ_PrintNode(void *gnp, void *passp) 633 { 634 GNode *gn = (GNode *)gnp; 635 int pass = passp ? *(int *)passp : 0; 636 637 fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n", 638 gn->name, gn->cohort_num, gn->flags, gn->type, gn->made); 639 if (gn->flags == 0) 640 return 0; 641 642 if (!OP_NOP(gn->type)) { 643 fprintf(debug_file, "#\n"); 644 if (gn == mainTarg) { 645 fprintf(debug_file, "# *** MAIN TARGET ***\n"); 646 } 647 if (pass >= 2) { 648 if (gn->unmade) { 649 fprintf(debug_file, "# %d unmade children\n", gn->unmade); 650 } else { 651 fprintf(debug_file, "# No unmade children\n"); 652 } 653 if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) { 654 if (gn->mtime != 0) { 655 fprintf(debug_file, "# last modified %s: %s\n", 656 Targ_FmtTime(gn->mtime), 657 made_name(gn->made)); 658 } else if (gn->made != UNMADE) { 659 fprintf(debug_file, "# non-existent (maybe): %s\n", 660 made_name(gn->made)); 661 } else { 662 fprintf(debug_file, "# unmade\n"); 663 } 664 } 665 if (!Lst_IsEmpty (gn->iParents)) { 666 fprintf(debug_file, "# implicit parents: "); 667 Lst_ForEach(gn->iParents, TargPrintName, NULL); 668 fprintf(debug_file, "\n"); 669 } 670 } else { 671 if (gn->unmade) 672 fprintf(debug_file, "# %d unmade children\n", gn->unmade); 673 } 674 if (!Lst_IsEmpty (gn->parents)) { 675 fprintf(debug_file, "# parents: "); 676 Lst_ForEach(gn->parents, TargPrintName, NULL); 677 fprintf(debug_file, "\n"); 678 } 679 if (!Lst_IsEmpty (gn->order_pred)) { 680 fprintf(debug_file, "# order_pred: "); 681 Lst_ForEach(gn->order_pred, TargPrintName, NULL); 682 fprintf(debug_file, "\n"); 683 } 684 if (!Lst_IsEmpty (gn->order_succ)) { 685 fprintf(debug_file, "# order_succ: "); 686 Lst_ForEach(gn->order_succ, TargPrintName, NULL); 687 fprintf(debug_file, "\n"); 688 } 689 690 fprintf(debug_file, "%-16s", gn->name); 691 switch (gn->type & OP_OPMASK) { 692 case OP_DEPENDS: 693 fprintf(debug_file, ": "); break; 694 case OP_FORCE: 695 fprintf(debug_file, "! "); break; 696 case OP_DOUBLEDEP: 697 fprintf(debug_file, ":: "); break; 698 } 699 Targ_PrintType(gn->type); 700 Lst_ForEach(gn->children, TargPrintName, NULL); 701 fprintf(debug_file, "\n"); 702 Lst_ForEach(gn->commands, Targ_PrintCmd, NULL); 703 fprintf(debug_file, "\n\n"); 704 if (gn->type & OP_DOUBLEDEP) { 705 Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass); 706 } 707 } 708 return (0); 709 } 710 711 /*- 712 *----------------------------------------------------------------------- 713 * TargPrintOnlySrc -- 714 * Print only those targets that are just a source. 715 * 716 * Results: 717 * 0. 718 * 719 * Side Effects: 720 * The name of each file is printed preceded by #\t 721 * 722 *----------------------------------------------------------------------- 723 */ 724 static int 725 TargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED) 726 { 727 GNode *gn = (GNode *)gnp; 728 if (!OP_NOP(gn->type)) 729 return 0; 730 731 fprintf(debug_file, "#\t%s [%s] ", 732 gn->name, gn->path ? gn->path : gn->name); 733 Targ_PrintType(gn->type); 734 fprintf(debug_file, "\n"); 735 736 return 0; 737 } 738 739 /*- 740 *----------------------------------------------------------------------- 741 * Targ_PrintGraph -- 742 * print the entire graph. heh heh 743 * 744 * Input: 745 * pass Which pass this is. 1 => no processing 746 * 2 => processing done 747 * 748 * Results: 749 * none 750 * 751 * Side Effects: 752 * lots o' output 753 *----------------------------------------------------------------------- 754 */ 755 void 756 Targ_PrintGraph(int pass) 757 { 758 fprintf(debug_file, "#*** Input graph:\n"); 759 Lst_ForEach(allTargets, Targ_PrintNode, &pass); 760 fprintf(debug_file, "\n\n"); 761 fprintf(debug_file, "#\n# Files that are only sources:\n"); 762 Lst_ForEach(allTargets, TargPrintOnlySrc, NULL); 763 fprintf(debug_file, "#*** Global Variables:\n"); 764 Var_Dump(VAR_GLOBAL); 765 fprintf(debug_file, "#*** Command-line Variables:\n"); 766 Var_Dump(VAR_CMD); 767 fprintf(debug_file, "\n"); 768 Dir_PrintDirectories(); 769 fprintf(debug_file, "\n"); 770 Suff_PrintAll(); 771 } 772 773 /*- 774 *----------------------------------------------------------------------- 775 * TargPropagateNode -- 776 * Propagate information from a single node to related nodes if 777 * appropriate. 778 * 779 * Input: 780 * gnp The node that we are processing. 781 * 782 * Results: 783 * Always returns 0, for the benefit of Lst_ForEach(). 784 * 785 * Side Effects: 786 * Information is propagated from this node to cohort or child 787 * nodes. 788 * 789 * If the node was defined with "::", then TargPropagateCohort() 790 * will be called for each cohort node. 791 * 792 * If the node has recursive predecessors, then 793 * TargPropagateRecpred() will be called for each recursive 794 * predecessor. 795 *----------------------------------------------------------------------- 796 */ 797 static int 798 TargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED) 799 { 800 GNode *gn = (GNode *)gnp; 801 802 if (gn->type & OP_DOUBLEDEP) 803 Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp); 804 return (0); 805 } 806 807 /*- 808 *----------------------------------------------------------------------- 809 * TargPropagateCohort -- 810 * Propagate some bits in the type mask from a node to 811 * a related cohort node. 812 * 813 * Input: 814 * cnp The node that we are processing. 815 * gnp Another node that has cnp as a cohort. 816 * 817 * Results: 818 * Always returns 0, for the benefit of Lst_ForEach(). 819 * 820 * Side Effects: 821 * cnp's type bitmask is modified to incorporate some of the 822 * bits from gnp's type bitmask. (XXX need a better explanation.) 823 *----------------------------------------------------------------------- 824 */ 825 static int 826 TargPropagateCohort(void *cgnp, void *pgnp) 827 { 828 GNode *cgn = (GNode *)cgnp; 829 GNode *pgn = (GNode *)pgnp; 830 831 cgn->type |= pgn->type & ~OP_OPMASK; 832 return (0); 833 } 834 835 /*- 836 *----------------------------------------------------------------------- 837 * Targ_Propagate -- 838 * Propagate information between related nodes. Should be called 839 * after the makefiles are parsed but before any action is taken. 840 * 841 * Results: 842 * none 843 * 844 * Side Effects: 845 * Information is propagated between related nodes throughout the 846 * graph. 847 *----------------------------------------------------------------------- 848 */ 849 void 850 Targ_Propagate(void) 851 { 852 Lst_ForEach(allTargets, TargPropagateNode, NULL); 853 } 854