1 1.185 rillig /* $NetBSD: targ.c,v 1.185 2025/05/07 19:49:00 rillig Exp $ */ 2 1.5 christos 3 1.1 cgd /* 4 1.10 christos * Copyright (c) 1988, 1989, 1990, 1993 5 1.10 christos * The Regents of the University of California. All rights reserved. 6 1.30 agc * 7 1.30 agc * This code is derived from software contributed to Berkeley by 8 1.30 agc * Adam de Boor. 9 1.30 agc * 10 1.30 agc * Redistribution and use in source and binary forms, with or without 11 1.30 agc * modification, are permitted provided that the following conditions 12 1.30 agc * are met: 13 1.30 agc * 1. Redistributions of source code must retain the above copyright 14 1.30 agc * notice, this list of conditions and the following disclaimer. 15 1.30 agc * 2. Redistributions in binary form must reproduce the above copyright 16 1.30 agc * notice, this list of conditions and the following disclaimer in the 17 1.30 agc * documentation and/or other materials provided with the distribution. 18 1.30 agc * 3. Neither the name of the University nor the names of its contributors 19 1.30 agc * may be used to endorse or promote products derived from this software 20 1.30 agc * without specific prior written permission. 21 1.30 agc * 22 1.30 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.30 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.30 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.30 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.30 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.30 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.30 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.30 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.30 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.30 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.30 agc * SUCH DAMAGE. 33 1.30 agc */ 34 1.30 agc 35 1.30 agc /* 36 1.1 cgd * Copyright (c) 1989 by Berkeley Softworks 37 1.1 cgd * All rights reserved. 38 1.1 cgd * 39 1.1 cgd * This code is derived from software contributed to Berkeley by 40 1.1 cgd * Adam de Boor. 41 1.1 cgd * 42 1.1 cgd * Redistribution and use in source and binary forms, with or without 43 1.1 cgd * modification, are permitted provided that the following conditions 44 1.1 cgd * are met: 45 1.1 cgd * 1. Redistributions of source code must retain the above copyright 46 1.1 cgd * notice, this list of conditions and the following disclaimer. 47 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 48 1.1 cgd * notice, this list of conditions and the following disclaimer in the 49 1.1 cgd * documentation and/or other materials provided with the distribution. 50 1.1 cgd * 3. All advertising materials mentioning features or use of this software 51 1.1 cgd * must display the following acknowledgement: 52 1.1 cgd * This product includes software developed by the University of 53 1.1 cgd * California, Berkeley and its contributors. 54 1.1 cgd * 4. Neither the name of the University nor the names of its contributors 55 1.1 cgd * may be used to endorse or promote products derived from this software 56 1.1 cgd * without specific prior written permission. 57 1.1 cgd * 58 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 1.1 cgd * SUCH DAMAGE. 69 1.1 cgd */ 70 1.1 cgd 71 1.132 rillig /* 72 1.132 rillig * Maintaining the targets and sources, which are both implemented as GNode. 73 1.1 cgd * 74 1.1 cgd * Interface: 75 1.132 rillig * Targ_Init Initialize the module. 76 1.1 cgd * 77 1.132 rillig * Targ_End Clean up the module. 78 1.4 jtc * 79 1.106 rillig * Targ_List Return the list of all targets so far. 80 1.12 christos * 81 1.175 rillig * GNode_New Create a new GNode with the given name, don't add it 82 1.175 rillig * to allNodes. 83 1.1 cgd * 84 1.106 rillig * Targ_FindNode Find the node, or return NULL. 85 1.98 rillig * 86 1.106 rillig * Targ_GetNode Find the node, or create it. 87 1.98 rillig * 88 1.106 rillig * Targ_NewInternalNode 89 1.106 rillig * Create an internal node. 90 1.1 cgd * 91 1.106 rillig * Targ_FindList Given a list of names, find nodes for all 92 1.106 rillig * of them, creating them as necessary. 93 1.1 cgd * 94 1.106 rillig * Targ_Propagate Propagate information between related nodes. 95 1.106 rillig * Should be called after the makefiles are parsed 96 1.106 rillig * but before any action is taken. 97 1.42 apb * 98 1.1 cgd * Debugging: 99 1.106 rillig * Targ_PrintGraph 100 1.148 rillig * Print out the entire graph, all variables and 101 1.175 rillig * statistics for the directory cache. 102 1.1 cgd */ 103 1.1 cgd 104 1.111 rillig #include <time.h> 105 1.28 wiz 106 1.111 rillig #include "make.h" 107 1.111 rillig #include "dir.h" 108 1.1 cgd 109 1.88 rillig /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */ 110 1.185 rillig MAKE_RCSID("$NetBSD: targ.c,v 1.185 2025/05/07 19:49:00 rillig Exp $"); 111 1.88 rillig 112 1.136 rillig /* 113 1.136 rillig * All target nodes that appeared on the left-hand side of one of the 114 1.136 rillig * dependency operators ':', '::', '!'. 115 1.136 rillig */ 116 1.148 rillig static GNodeList allTargets = LST_INIT; 117 1.133 rillig static HashTable allTargetsByName; 118 1.130 rillig 119 1.18 mycroft #ifdef CLEANUP 120 1.148 rillig static GNodeList allNodes = LST_INIT; 121 1.1 cgd 122 1.181 rillig static void GNode_Free(GNode *); 123 1.18 mycroft #endif 124 1.4 jtc 125 1.1 cgd void 126 1.28 wiz Targ_Init(void) 127 1.1 cgd { 128 1.150 rillig HashTable_Init(&allTargetsByName); 129 1.184 rillig SCOPE_INTERNAL = GNode_New("Internal"); 130 1.184 rillig SCOPE_GLOBAL = GNode_New("Global"); 131 1.184 rillig SCOPE_CMDLINE = GNode_New("Command"); 132 1.1 cgd } 133 1.1 cgd 134 1.184 rillig #ifdef CLEANUP 135 1.4 jtc void 136 1.28 wiz Targ_End(void) 137 1.4 jtc { 138 1.181 rillig GNodeListNode *ln; 139 1.184 rillig 140 1.150 rillig Lst_Done(&allTargets); 141 1.150 rillig HashTable_Done(&allTargetsByName); 142 1.181 rillig for (ln = allNodes.first; ln != NULL; ln = ln->next) 143 1.181 rillig GNode_Free(ln->datum); 144 1.181 rillig Lst_Done(&allNodes); 145 1.184 rillig } 146 1.18 mycroft #endif 147 1.12 christos 148 1.64 sjg void 149 1.64 sjg Targ_Stats(void) 150 1.64 sjg { 151 1.150 rillig HashTable_DebugStats(&allTargetsByName, "targets"); 152 1.64 sjg } 153 1.64 sjg 154 1.132 rillig /* 155 1.132 rillig * Return the list of all targets, which are all nodes that appear on the 156 1.132 rillig * left-hand side of a dependency declaration such as "target: source". 157 1.132 rillig * The returned list does not contain pure sources. 158 1.132 rillig */ 159 1.89 rillig GNodeList * 160 1.28 wiz Targ_List(void) 161 1.12 christos { 162 1.150 rillig return &allTargets; 163 1.4 jtc } 164 1.4 jtc 165 1.150 rillig /* 166 1.150 rillig * Create a new graph node, but don't register it anywhere. 167 1.1 cgd * 168 1.179 rillig * Graph nodes that occur on the left-hand side of a dependency line such 169 1.132 rillig * as "target: source" are called targets. XXX: In some cases (like the 170 1.179 rillig * .ALLTARGETS variable), other nodes are called targets as well, even if 171 1.179 rillig * they never occur on the left-hand side of a dependency line. 172 1.132 rillig * 173 1.132 rillig * Typical names for graph nodes are: 174 1.179 rillig * "src.c" an ordinary file 175 1.179 rillig * "clean" a .PHONY target 176 1.179 rillig * ".END" a special hook target 177 1.179 rillig * "-lm" a library 178 1.179 rillig * "libm.a(sin.o)" an archive member 179 1.1 cgd */ 180 1.1 cgd GNode * 181 1.128 rillig GNode_New(const char *name) 182 1.1 cgd { 183 1.150 rillig GNode *gn; 184 1.1 cgd 185 1.150 rillig gn = bmake_malloc(sizeof *gn); 186 1.150 rillig gn->name = bmake_strdup(name); 187 1.150 rillig gn->uname = NULL; 188 1.150 rillig gn->path = NULL; 189 1.152 rillig gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : OP_NONE; 190 1.173 rillig memset(&gn->flags, 0, sizeof(gn->flags)); 191 1.150 rillig gn->made = UNMADE; 192 1.150 rillig gn->unmade = 0; 193 1.150 rillig gn->mtime = 0; 194 1.150 rillig gn->youngestChild = NULL; 195 1.150 rillig Lst_Init(&gn->implicitParents); 196 1.150 rillig Lst_Init(&gn->parents); 197 1.150 rillig Lst_Init(&gn->children); 198 1.150 rillig Lst_Init(&gn->order_pred); 199 1.150 rillig Lst_Init(&gn->order_succ); 200 1.150 rillig Lst_Init(&gn->cohorts); 201 1.150 rillig gn->cohort_num[0] = '\0'; 202 1.150 rillig gn->unmade_cohorts = 0; 203 1.150 rillig gn->centurion = NULL; 204 1.150 rillig gn->checked_seqno = 0; 205 1.150 rillig HashTable_Init(&gn->vars); 206 1.150 rillig Lst_Init(&gn->commands); 207 1.150 rillig gn->suffix = NULL; 208 1.150 rillig gn->fname = NULL; 209 1.150 rillig gn->lineno = 0; 210 1.180 sjg gn->exit_status = 0; 211 1.1 cgd 212 1.18 mycroft #ifdef CLEANUP 213 1.150 rillig Lst_Append(&allNodes, gn); 214 1.18 mycroft #endif 215 1.4 jtc 216 1.150 rillig return gn; 217 1.1 cgd } 218 1.1 cgd 219 1.18 mycroft #ifdef CLEANUP 220 1.4 jtc static void 221 1.181 rillig GNode_Free(GNode *gn) 222 1.4 jtc { 223 1.182 rillig Var_DeleteAll(gn); 224 1.182 rillig 225 1.150 rillig free(gn->name); 226 1.150 rillig free(gn->uname); 227 1.150 rillig free(gn->path); 228 1.150 rillig 229 1.150 rillig /* Don't free gn->youngestChild since it is not owned by this node. */ 230 1.150 rillig 231 1.150 rillig /* 232 1.150 rillig * In the following lists, only free the list nodes, but not the 233 1.150 rillig * GNodes in them since these are not owned by this node. 234 1.150 rillig */ 235 1.150 rillig Lst_Done(&gn->implicitParents); 236 1.150 rillig Lst_Done(&gn->parents); 237 1.150 rillig Lst_Done(&gn->children); 238 1.150 rillig Lst_Done(&gn->order_pred); 239 1.150 rillig Lst_Done(&gn->order_succ); 240 1.150 rillig Lst_Done(&gn->cohorts); 241 1.150 rillig 242 1.150 rillig HashTable_Done(&gn->vars); 243 1.150 rillig 244 1.150 rillig /* 245 1.150 rillig * Do not free the commands themselves, as they may be shared with 246 1.150 rillig * other nodes. 247 1.150 rillig */ 248 1.150 rillig Lst_Done(&gn->commands); 249 1.150 rillig 250 1.150 rillig /* 251 1.150 rillig * gn->suffix is not owned by this node. 252 1.150 rillig * 253 1.150 rillig * XXX: gn->suffix should be unreferenced here. This requires a 254 1.150 rillig * thorough check that the reference counting is done correctly in 255 1.150 rillig * all places, otherwise a suffix might be freed too early. 256 1.150 rillig */ 257 1.77 rillig 258 1.150 rillig free(gn); 259 1.4 jtc } 260 1.18 mycroft #endif 261 1.4 jtc 262 1.95 rillig /* Get the existing global node, or return NULL. */ 263 1.95 rillig GNode * 264 1.95 rillig Targ_FindNode(const char *name) 265 1.95 rillig { 266 1.150 rillig return HashTable_FindValue(&allTargetsByName, name); 267 1.95 rillig } 268 1.95 rillig 269 1.95 rillig /* Get the existing global node, or create it. */ 270 1.95 rillig GNode * 271 1.95 rillig Targ_GetNode(const char *name) 272 1.95 rillig { 273 1.167 rillig bool isNew; 274 1.150 rillig HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew); 275 1.150 rillig if (!isNew) 276 1.150 rillig return HashEntry_Get(he); 277 1.150 rillig 278 1.150 rillig { 279 1.150 rillig GNode *gn = Targ_NewInternalNode(name); 280 1.150 rillig HashEntry_Set(he, gn); 281 1.150 rillig return gn; 282 1.150 rillig } 283 1.95 rillig } 284 1.95 rillig 285 1.132 rillig /* 286 1.132 rillig * Create a node, register it in .ALLTARGETS but don't store it in the 287 1.95 rillig * table of global nodes. This means it cannot be found by name. 288 1.95 rillig * 289 1.132 rillig * This is used for internal nodes, such as cohorts or .WAIT nodes. 290 1.132 rillig */ 291 1.95 rillig GNode * 292 1.95 rillig Targ_NewInternalNode(const char *name) 293 1.95 rillig { 294 1.150 rillig GNode *gn = GNode_New(name); 295 1.163 rillig Global_Append(".ALLTARGETS", name); 296 1.150 rillig Lst_Append(&allTargets, gn); 297 1.150 rillig DEBUG1(TARG, "Adding \"%s\" to all targets.\n", gn->name); 298 1.150 rillig if (doing_depend) 299 1.173 rillig gn->flags.fromDepend = true; 300 1.150 rillig return gn; 301 1.95 rillig } 302 1.95 rillig 303 1.132 rillig /* 304 1.132 rillig * Return the .END node, which contains the commands to be run when 305 1.132 rillig * everything else has been made. 306 1.132 rillig */ 307 1.156 rillig GNode * 308 1.156 rillig Targ_GetEndNode(void) 309 1.90 rillig { 310 1.150 rillig /* 311 1.150 rillig * Save the node locally to avoid having to search for it all 312 1.150 rillig * the time. 313 1.150 rillig */ 314 1.150 rillig static GNode *endNode = NULL; 315 1.150 rillig 316 1.150 rillig if (endNode == NULL) { 317 1.150 rillig endNode = Targ_GetNode(".END"); 318 1.150 rillig endNode->type = OP_SPECIAL; 319 1.150 rillig } 320 1.150 rillig return endNode; 321 1.90 rillig } 322 1.90 rillig 323 1.149 rillig /* Add the named nodes to the list, creating them as necessary. */ 324 1.147 rillig void 325 1.149 rillig Targ_FindList(GNodeList *gns, StringList *names) 326 1.1 cgd { 327 1.150 rillig StringListNode *ln; 328 1.149 rillig 329 1.150 rillig for (ln = names->first; ln != NULL; ln = ln->next) { 330 1.150 rillig const char *name = ln->datum; 331 1.150 rillig GNode *gn = Targ_GetNode(name); 332 1.150 rillig Lst_Append(gns, gn); 333 1.150 rillig } 334 1.1 cgd } 335 1.1 cgd 336 1.86 rillig static void 337 1.89 rillig PrintNodeNames(GNodeList *gnodes) 338 1.1 cgd { 339 1.150 rillig GNodeListNode *ln; 340 1.38 dsl 341 1.150 rillig for (ln = gnodes->first; ln != NULL; ln = ln->next) { 342 1.150 rillig GNode *gn = ln->datum; 343 1.150 rillig debug_printf(" %s%s", gn->name, gn->cohort_num); 344 1.150 rillig } 345 1.85 rillig } 346 1.38 dsl 347 1.85 rillig static void 348 1.89 rillig PrintNodeNamesLine(const char *label, GNodeList *gnodes) 349 1.85 rillig { 350 1.150 rillig if (Lst_IsEmpty(gnodes)) 351 1.150 rillig return; 352 1.150 rillig debug_printf("# %s:", label); 353 1.150 rillig PrintNodeNames(gnodes); 354 1.150 rillig debug_printf("\n"); 355 1.1 cgd } 356 1.1 cgd 357 1.84 rillig void 358 1.84 rillig Targ_PrintCmds(GNode *gn) 359 1.84 rillig { 360 1.150 rillig StringListNode *ln; 361 1.150 rillig 362 1.150 rillig for (ln = gn->commands.first; ln != NULL; ln = ln->next) { 363 1.150 rillig const char *cmd = ln->datum; 364 1.150 rillig debug_printf("\t%s\n", cmd); 365 1.150 rillig } 366 1.84 rillig } 367 1.84 rillig 368 1.150 rillig /* 369 1.150 rillig * Format a modification time in some reasonable way and return it. 370 1.158 rillig * The formatted time is placed in a static area, so it is overwritten 371 1.158 rillig * with each call. 372 1.150 rillig */ 373 1.157 rillig const char * 374 1.28 wiz Targ_FmtTime(time_t tm) 375 1.1 cgd { 376 1.150 rillig static char buf[128]; 377 1.1 cgd 378 1.158 rillig struct tm *parts = localtime(&tm); 379 1.168 rillig (void)strftime(buf, sizeof buf, "%H:%M:%S %b %d, %Y", parts); 380 1.150 rillig return buf; 381 1.1 cgd } 382 1.10 christos 383 1.77 rillig /* Print out a type field giving only those attributes the user can set. */ 384 1.1 cgd void 385 1.171 rillig Targ_PrintType(GNodeType type) 386 1.1 cgd { 387 1.169 rillig static const struct { 388 1.169 rillig GNodeType bit; 389 1.169 rillig bool internal; 390 1.172 rillig const char name[10]; 391 1.169 rillig } names[] = { 392 1.169 rillig { OP_MEMBER, true, "MEMBER" }, 393 1.169 rillig { OP_LIB, true, "LIB" }, 394 1.169 rillig { OP_ARCHV, true, "ARCHV" }, 395 1.169 rillig { OP_PHONY, true, "PHONY" }, 396 1.169 rillig { OP_NOTMAIN, false, "NOTMAIN" }, 397 1.169 rillig { OP_INVISIBLE, false, "INVISIBLE" }, 398 1.169 rillig { OP_MADE, true, "MADE" }, 399 1.169 rillig { OP_JOIN, false, "JOIN" }, 400 1.169 rillig { OP_MAKE, false, "MAKE" }, 401 1.169 rillig { OP_SILENT, false, "SILENT" }, 402 1.169 rillig { OP_PRECIOUS, false, "PRECIOUS" }, 403 1.169 rillig { OP_IGNORE, false, "IGNORE" }, 404 1.169 rillig { OP_EXEC, false, "EXEC" }, 405 1.169 rillig { OP_USE, false, "USE" }, 406 1.177 rillig { OP_USEBEFORE, false, "USEBEFORE" }, 407 1.169 rillig { OP_OPTIONAL, false, "OPTIONAL" }, 408 1.169 rillig }; 409 1.170 rillig size_t i; 410 1.169 rillig 411 1.170 rillig for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) { 412 1.169 rillig if (type & names[i].bit) { 413 1.169 rillig if (names[i].internal) 414 1.169 rillig DEBUG1(TARG, " .%s", names[i].name); 415 1.169 rillig else 416 1.169 rillig debug_printf(" .%s", names[i].name); 417 1.150 rillig } 418 1.1 cgd } 419 1.1 cgd } 420 1.1 cgd 421 1.161 rillig const char * 422 1.161 rillig GNodeMade_Name(GNodeMade made) 423 1.45 dsl { 424 1.150 rillig switch (made) { 425 1.150 rillig case UNMADE: return "unmade"; 426 1.150 rillig case DEFERRED: return "deferred"; 427 1.150 rillig case REQUESTED: return "requested"; 428 1.150 rillig case BEINGMADE: return "being made"; 429 1.150 rillig case MADE: return "made"; 430 1.150 rillig case UPTODATE: return "up-to-date"; 431 1.150 rillig case ERROR: return "error when made"; 432 1.150 rillig case ABORTED: return "aborted"; 433 1.150 rillig default: return "unknown enum_made value"; 434 1.150 rillig } 435 1.45 dsl } 436 1.45 dsl 437 1.114 rillig static const char * 438 1.114 rillig GNode_OpName(const GNode *gn) 439 1.114 rillig { 440 1.150 rillig switch (gn->type & OP_OPMASK) { 441 1.150 rillig case OP_DEPENDS: 442 1.150 rillig return ":"; 443 1.150 rillig case OP_FORCE: 444 1.150 rillig return "!"; 445 1.150 rillig case OP_DOUBLEDEP: 446 1.150 rillig return "::"; 447 1.150 rillig } 448 1.150 rillig return ""; 449 1.114 rillig } 450 1.114 rillig 451 1.173 rillig static bool 452 1.173 rillig GNodeFlags_IsNone(GNodeFlags flags) 453 1.173 rillig { 454 1.173 rillig return !flags.remake 455 1.173 rillig && !flags.childMade 456 1.173 rillig && !flags.force 457 1.173 rillig && !flags.doneWait 458 1.173 rillig && !flags.doneOrder 459 1.173 rillig && !flags.fromDepend 460 1.173 rillig && !flags.doneAllsrc 461 1.173 rillig && !flags.cycle 462 1.173 rillig && !flags.doneCycle; 463 1.173 rillig } 464 1.173 rillig 465 1.105 rillig /* Print the contents of a node. */ 466 1.105 rillig void 467 1.105 rillig Targ_PrintNode(GNode *gn, int pass) 468 1.1 cgd { 469 1.150 rillig debug_printf("# %s%s", gn->name, gn->cohort_num); 470 1.150 rillig GNode_FprintDetails(opts.debug_file, ", ", gn, "\n"); 471 1.173 rillig if (GNodeFlags_IsNone(gn->flags)) 472 1.150 rillig return; 473 1.150 rillig 474 1.150 rillig if (!GNode_IsTarget(gn)) 475 1.150 rillig return; 476 1.45 dsl 477 1.107 rillig debug_printf("#\n"); 478 1.176 rillig if (gn == mainNode) 479 1.150 rillig debug_printf("# *** MAIN TARGET ***\n"); 480 1.150 rillig 481 1.45 dsl if (pass >= 2) { 482 1.150 rillig if (gn->unmade > 0) 483 1.150 rillig debug_printf("# %d unmade children\n", gn->unmade); 484 1.150 rillig else 485 1.150 rillig debug_printf("# No unmade children\n"); 486 1.150 rillig if (!(gn->type & (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC))) { 487 1.150 rillig if (gn->mtime != 0) { 488 1.150 rillig debug_printf("# last modified %s: %s\n", 489 1.150 rillig Targ_FmtTime(gn->mtime), 490 1.161 rillig GNodeMade_Name(gn->made)); 491 1.150 rillig } else if (gn->made != UNMADE) { 492 1.159 rillig debug_printf("# nonexistent (maybe): %s\n", 493 1.161 rillig GNodeMade_Name(gn->made)); 494 1.150 rillig } else 495 1.150 rillig debug_printf("# unmade\n"); 496 1.1 cgd } 497 1.150 rillig PrintNodeNamesLine("implicit parents", &gn->implicitParents); 498 1.41 dsl } else { 499 1.160 rillig if (gn->unmade != 0) 500 1.150 rillig debug_printf("# %d unmade children\n", gn->unmade); 501 1.1 cgd } 502 1.150 rillig 503 1.143 rillig PrintNodeNamesLine("parents", &gn->parents); 504 1.144 rillig PrintNodeNamesLine("order_pred", &gn->order_pred); 505 1.144 rillig PrintNodeNamesLine("order_succ", &gn->order_succ); 506 1.10 christos 507 1.114 rillig debug_printf("%-16s%s", gn->name, GNode_OpName(gn)); 508 1.34 christos Targ_PrintType(gn->type); 509 1.143 rillig PrintNodeNames(&gn->children); 510 1.107 rillig debug_printf("\n"); 511 1.84 rillig Targ_PrintCmds(gn); 512 1.107 rillig debug_printf("\n\n"); 513 1.150 rillig if (gn->type & OP_DOUBLEDEP) 514 1.150 rillig Targ_PrintNodes(&gn->cohorts, pass); 515 1.1 cgd } 516 1.1 cgd 517 1.87 rillig void 518 1.89 rillig Targ_PrintNodes(GNodeList *gnodes, int pass) 519 1.87 rillig { 520 1.150 rillig GNodeListNode *ln; 521 1.150 rillig 522 1.150 rillig for (ln = gnodes->first; ln != NULL; ln = ln->next) 523 1.150 rillig Targ_PrintNode(ln->datum, pass); 524 1.87 rillig } 525 1.87 rillig 526 1.103 mrg static void 527 1.100 rillig PrintOnlySources(void) 528 1.4 jtc { 529 1.150 rillig GNodeListNode *ln; 530 1.100 rillig 531 1.150 rillig for (ln = allTargets.first; ln != NULL; ln = ln->next) { 532 1.150 rillig GNode *gn = ln->datum; 533 1.150 rillig if (GNode_IsTarget(gn)) 534 1.150 rillig continue; 535 1.150 rillig 536 1.150 rillig debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn)); 537 1.150 rillig Targ_PrintType(gn->type); 538 1.150 rillig debug_printf("\n"); 539 1.150 rillig } 540 1.1 cgd } 541 1.1 cgd 542 1.150 rillig /* 543 1.150 rillig * Input: 544 1.77 rillig * pass 1 => before processing 545 1.77 rillig * 2 => after processing 546 1.77 rillig * 3 => after processing, an error occurred 547 1.1 cgd */ 548 1.3 cgd void 549 1.28 wiz Targ_PrintGraph(int pass) 550 1.1 cgd { 551 1.185 rillig debug_printf("#*** Begin input graph for pass %d in %s:\n", 552 1.185 rillig pass, curdir); 553 1.150 rillig Targ_PrintNodes(&allTargets, pass); 554 1.150 rillig debug_printf("\n"); 555 1.150 rillig debug_printf("\n"); 556 1.135 rillig 557 1.150 rillig debug_printf("#\n"); 558 1.150 rillig debug_printf("# Files that are only sources:\n"); 559 1.150 rillig PrintOnlySources(); 560 1.135 rillig 561 1.150 rillig debug_printf("#*** Global Variables:\n"); 562 1.164 rillig Var_Dump(SCOPE_GLOBAL); 563 1.135 rillig 564 1.150 rillig debug_printf("#*** Command-line Variables:\n"); 565 1.164 rillig Var_Dump(SCOPE_CMDLINE); 566 1.135 rillig 567 1.150 rillig debug_printf("\n"); 568 1.150 rillig Dir_PrintDirectories(); 569 1.150 rillig debug_printf("\n"); 570 1.135 rillig 571 1.150 rillig Suff_PrintAll(); 572 1.185 rillig debug_printf("#*** End input graph for pass %d in %s:\n", 573 1.185 rillig pass, curdir); 574 1.19 mycroft } 575 1.19 mycroft 576 1.150 rillig /* 577 1.150 rillig * Propagate some type information to cohort nodes (those from the '::' 578 1.78 rillig * dependency operator). 579 1.77 rillig * 580 1.78 rillig * Should be called after the makefiles are parsed but before any action is 581 1.150 rillig * taken. 582 1.150 rillig */ 583 1.78 rillig void 584 1.78 rillig Targ_Propagate(void) 585 1.19 mycroft { 586 1.150 rillig GNodeListNode *ln, *cln; 587 1.45 dsl 588 1.150 rillig for (ln = allTargets.first; ln != NULL; ln = ln->next) { 589 1.150 rillig GNode *gn = ln->datum; 590 1.150 rillig GNodeType type = gn->type; 591 1.19 mycroft 592 1.150 rillig if (!(type & OP_DOUBLEDEP)) 593 1.150 rillig continue; 594 1.42 apb 595 1.150 rillig for (cln = gn->cohorts.first; cln != NULL; cln = cln->next) { 596 1.150 rillig GNode *cohort = cln->datum; 597 1.42 apb 598 1.178 rillig cohort->type |= type & (unsigned)~OP_OPMASK; 599 1.150 rillig } 600 1.78 rillig } 601 1.1 cgd } 602