1*9f45a3c8SSimon J. Gerraty /* $NetBSD: targ.c,v 1.176 2022/01/07 20:50:35 rillig Exp $ */ 23955d011SMarcel Moolenaar 33955d011SMarcel Moolenaar /* 43955d011SMarcel Moolenaar * Copyright (c) 1988, 1989, 1990, 1993 53955d011SMarcel Moolenaar * The Regents of the University of California. All rights reserved. 63955d011SMarcel Moolenaar * 73955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 83955d011SMarcel Moolenaar * Adam de Boor. 93955d011SMarcel Moolenaar * 103955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 113955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 123955d011SMarcel Moolenaar * are met: 133955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 143955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 153955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 163955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 173955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 183955d011SMarcel Moolenaar * 3. Neither the name of the University nor the names of its contributors 193955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 203955d011SMarcel Moolenaar * without specific prior written permission. 213955d011SMarcel Moolenaar * 223955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 233955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 243955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 253955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 263955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 273955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 283955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 293955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 303955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 313955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 323955d011SMarcel Moolenaar * SUCH DAMAGE. 333955d011SMarcel Moolenaar */ 343955d011SMarcel Moolenaar 353955d011SMarcel Moolenaar /* 363955d011SMarcel Moolenaar * Copyright (c) 1989 by Berkeley Softworks 373955d011SMarcel Moolenaar * All rights reserved. 383955d011SMarcel Moolenaar * 393955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 403955d011SMarcel Moolenaar * Adam de Boor. 413955d011SMarcel Moolenaar * 423955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 433955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 443955d011SMarcel Moolenaar * are met: 453955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 463955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 473955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 483955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 493955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 503955d011SMarcel Moolenaar * 3. All advertising materials mentioning features or use of this software 513955d011SMarcel Moolenaar * must display the following acknowledgement: 523955d011SMarcel Moolenaar * This product includes software developed by the University of 533955d011SMarcel Moolenaar * California, Berkeley and its contributors. 543955d011SMarcel Moolenaar * 4. Neither the name of the University nor the names of its contributors 553955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 563955d011SMarcel Moolenaar * without specific prior written permission. 573955d011SMarcel Moolenaar * 583955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 593955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 603955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 613955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 623955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 633955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 643955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 653955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 663955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 673955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 683955d011SMarcel Moolenaar * SUCH DAMAGE. 693955d011SMarcel Moolenaar */ 703955d011SMarcel Moolenaar 71e2eeea75SSimon J. Gerraty /* 72e2eeea75SSimon J. Gerraty * Maintaining the targets and sources, which are both implemented as GNode. 733955d011SMarcel Moolenaar * 743955d011SMarcel Moolenaar * Interface: 75e2eeea75SSimon J. Gerraty * Targ_Init Initialize the module. 763955d011SMarcel Moolenaar * 77e2eeea75SSimon J. Gerraty * Targ_End Clean up the module. 783955d011SMarcel Moolenaar * 793955d011SMarcel Moolenaar * Targ_List Return the list of all targets so far. 803955d011SMarcel Moolenaar * 81*9f45a3c8SSimon J. Gerraty * GNode_New Create a new GNode with the given name, don't add it 82*9f45a3c8SSimon J. Gerraty * to allNodes. 833955d011SMarcel Moolenaar * 84956e45f6SSimon J. Gerraty * Targ_FindNode Find the node, or return NULL. 85956e45f6SSimon J. Gerraty * 86956e45f6SSimon J. Gerraty * Targ_GetNode Find the node, or create it. 87956e45f6SSimon J. Gerraty * 88956e45f6SSimon J. Gerraty * Targ_NewInternalNode 89956e45f6SSimon J. Gerraty * Create an internal node. 903955d011SMarcel Moolenaar * 913955d011SMarcel Moolenaar * Targ_FindList Given a list of names, find nodes for all 92956e45f6SSimon J. Gerraty * of them, creating them as necessary. 933955d011SMarcel Moolenaar * 94956e45f6SSimon J. Gerraty * Targ_Propagate Propagate information between related nodes. 95956e45f6SSimon J. Gerraty * Should be called after the makefiles are parsed 96956e45f6SSimon J. Gerraty * but before any action is taken. 973955d011SMarcel Moolenaar * 983955d011SMarcel Moolenaar * Debugging: 99956e45f6SSimon J. Gerraty * Targ_PrintGraph 10006b9b3e0SSimon J. Gerraty * Print out the entire graph, all variables and 101*9f45a3c8SSimon J. Gerraty * statistics for the directory cache. 1023955d011SMarcel Moolenaar */ 1033955d011SMarcel Moolenaar 1043955d011SMarcel Moolenaar #include <time.h> 1053955d011SMarcel Moolenaar 1063955d011SMarcel Moolenaar #include "make.h" 1073955d011SMarcel Moolenaar #include "dir.h" 1083955d011SMarcel Moolenaar 109956e45f6SSimon J. Gerraty /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */ 110*9f45a3c8SSimon J. Gerraty MAKE_RCSID("$NetBSD: targ.c,v 1.176 2022/01/07 20:50:35 rillig Exp $"); 1113955d011SMarcel Moolenaar 11206b9b3e0SSimon J. Gerraty /* 11306b9b3e0SSimon J. Gerraty * All target nodes that appeared on the left-hand side of one of the 11406b9b3e0SSimon J. Gerraty * dependency operators ':', '::', '!'. 11506b9b3e0SSimon J. Gerraty */ 11606b9b3e0SSimon J. Gerraty static GNodeList allTargets = LST_INIT; 117e2eeea75SSimon J. Gerraty static HashTable allTargetsByName; 118956e45f6SSimon J. Gerraty 1193955d011SMarcel Moolenaar #ifdef CLEANUP 12006b9b3e0SSimon J. Gerraty static GNodeList allNodes = LST_INIT; 121e2eeea75SSimon J. Gerraty 122e2eeea75SSimon J. Gerraty static void GNode_Free(void *); 1233955d011SMarcel Moolenaar #endif 1243955d011SMarcel Moolenaar 1253955d011SMarcel Moolenaar void 1263955d011SMarcel Moolenaar Targ_Init(void) 1273955d011SMarcel Moolenaar { 128e2eeea75SSimon J. Gerraty HashTable_Init(&allTargetsByName); 1293955d011SMarcel Moolenaar } 1303955d011SMarcel Moolenaar 1313955d011SMarcel Moolenaar void 1323955d011SMarcel Moolenaar Targ_End(void) 1333955d011SMarcel Moolenaar { 1342c3632d1SSimon J. Gerraty Targ_Stats(); 1353955d011SMarcel Moolenaar #ifdef CLEANUP 13606b9b3e0SSimon J. Gerraty Lst_Done(&allTargets); 137e2eeea75SSimon J. Gerraty HashTable_Done(&allTargetsByName); 13806b9b3e0SSimon J. Gerraty Lst_DoneCall(&allNodes, GNode_Free); 1393955d011SMarcel Moolenaar #endif 1403955d011SMarcel Moolenaar } 1413955d011SMarcel Moolenaar 1422c3632d1SSimon J. Gerraty void 1432c3632d1SSimon J. Gerraty Targ_Stats(void) 1442c3632d1SSimon J. Gerraty { 145e2eeea75SSimon J. Gerraty HashTable_DebugStats(&allTargetsByName, "targets"); 1462c3632d1SSimon J. Gerraty } 1472c3632d1SSimon J. Gerraty 148e2eeea75SSimon J. Gerraty /* 149e2eeea75SSimon J. Gerraty * Return the list of all targets, which are all nodes that appear on the 150e2eeea75SSimon J. Gerraty * left-hand side of a dependency declaration such as "target: source". 151e2eeea75SSimon J. Gerraty * The returned list does not contain pure sources. 152e2eeea75SSimon J. Gerraty */ 153956e45f6SSimon J. Gerraty GNodeList * 1543955d011SMarcel Moolenaar Targ_List(void) 1553955d011SMarcel Moolenaar { 15606b9b3e0SSimon J. Gerraty return &allTargets; 1573955d011SMarcel Moolenaar } 1583955d011SMarcel Moolenaar 15906b9b3e0SSimon J. Gerraty /* 16006b9b3e0SSimon J. Gerraty * Create a new graph node, but don't register it anywhere. 1613955d011SMarcel Moolenaar * 162e2eeea75SSimon J. Gerraty * Graph nodes that appear on the left-hand side of a dependency line such 163e2eeea75SSimon J. Gerraty * as "target: source" are called targets. XXX: In some cases (like the 164e2eeea75SSimon J. Gerraty * .ALLTARGETS variable), all nodes are called targets as well, even if they 165e2eeea75SSimon J. Gerraty * never appear on the left-hand side. This is a mistake. 166e2eeea75SSimon J. Gerraty * 167e2eeea75SSimon J. Gerraty * Typical names for graph nodes are: 168e2eeea75SSimon J. Gerraty * "src.c" (an ordinary file) 169e2eeea75SSimon J. Gerraty * "clean" (a .PHONY target) 170e2eeea75SSimon J. Gerraty * ".END" (a special hook target) 171e2eeea75SSimon J. Gerraty * "-lm" (a library) 172e2eeea75SSimon J. Gerraty * "libc.a(isspace.o)" (an archive member) 1733955d011SMarcel Moolenaar */ 1743955d011SMarcel Moolenaar GNode * 175e2eeea75SSimon J. Gerraty GNode_New(const char *name) 1763955d011SMarcel Moolenaar { 1773955d011SMarcel Moolenaar GNode *gn; 1783955d011SMarcel Moolenaar 179e2eeea75SSimon J. Gerraty gn = bmake_malloc(sizeof *gn); 1803955d011SMarcel Moolenaar gn->name = bmake_strdup(name); 1813955d011SMarcel Moolenaar gn->uname = NULL; 1823955d011SMarcel Moolenaar gn->path = NULL; 18306b9b3e0SSimon J. Gerraty gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : OP_NONE; 18412904384SSimon J. Gerraty memset(&gn->flags, 0, sizeof(gn->flags)); 185e2eeea75SSimon J. Gerraty gn->made = UNMADE; 186e2eeea75SSimon J. Gerraty gn->unmade = 0; 1873955d011SMarcel Moolenaar gn->mtime = 0; 188956e45f6SSimon J. Gerraty gn->youngestChild = NULL; 18906b9b3e0SSimon J. Gerraty Lst_Init(&gn->implicitParents); 19006b9b3e0SSimon J. Gerraty Lst_Init(&gn->parents); 19106b9b3e0SSimon J. Gerraty Lst_Init(&gn->children); 19206b9b3e0SSimon J. Gerraty Lst_Init(&gn->order_pred); 19306b9b3e0SSimon J. Gerraty Lst_Init(&gn->order_succ); 19406b9b3e0SSimon J. Gerraty Lst_Init(&gn->cohorts); 195e2eeea75SSimon J. Gerraty gn->cohort_num[0] = '\0'; 196e2eeea75SSimon J. Gerraty gn->unmade_cohorts = 0; 197e2eeea75SSimon J. Gerraty gn->centurion = NULL; 198e2eeea75SSimon J. Gerraty gn->checked_seqno = 0; 19906b9b3e0SSimon J. Gerraty HashTable_Init(&gn->vars); 20006b9b3e0SSimon J. Gerraty Lst_Init(&gn->commands); 2013955d011SMarcel Moolenaar gn->suffix = NULL; 2023955d011SMarcel Moolenaar gn->fname = NULL; 2032c3632d1SSimon J. Gerraty gn->lineno = 0; 2043955d011SMarcel Moolenaar 2053955d011SMarcel Moolenaar #ifdef CLEANUP 20606b9b3e0SSimon J. Gerraty Lst_Append(&allNodes, gn); 2073955d011SMarcel Moolenaar #endif 2083955d011SMarcel Moolenaar 2093841c287SSimon J. Gerraty return gn; 2103955d011SMarcel Moolenaar } 2113955d011SMarcel Moolenaar 2123955d011SMarcel Moolenaar #ifdef CLEANUP 2133955d011SMarcel Moolenaar static void 214e2eeea75SSimon J. Gerraty GNode_Free(void *gnp) 2153955d011SMarcel Moolenaar { 216956e45f6SSimon J. Gerraty GNode *gn = gnp; 2173955d011SMarcel Moolenaar 2183955d011SMarcel Moolenaar free(gn->name); 2193955d011SMarcel Moolenaar free(gn->uname); 2203955d011SMarcel Moolenaar free(gn->path); 22106b9b3e0SSimon J. Gerraty 22206b9b3e0SSimon J. Gerraty /* Don't free gn->youngestChild since it is not owned by this node. */ 22306b9b3e0SSimon J. Gerraty 22406b9b3e0SSimon J. Gerraty /* 22506b9b3e0SSimon J. Gerraty * In the following lists, only free the list nodes, but not the 22606b9b3e0SSimon J. Gerraty * GNodes in them since these are not owned by this node. 22706b9b3e0SSimon J. Gerraty */ 22806b9b3e0SSimon J. Gerraty Lst_Done(&gn->implicitParents); 22906b9b3e0SSimon J. Gerraty Lst_Done(&gn->parents); 23006b9b3e0SSimon J. Gerraty Lst_Done(&gn->children); 23106b9b3e0SSimon J. Gerraty Lst_Done(&gn->order_pred); 23206b9b3e0SSimon J. Gerraty Lst_Done(&gn->order_succ); 23306b9b3e0SSimon J. Gerraty Lst_Done(&gn->cohorts); 23406b9b3e0SSimon J. Gerraty 23506b9b3e0SSimon J. Gerraty /* 23606b9b3e0SSimon J. Gerraty * Do not free the variables themselves, even though they are owned 23706b9b3e0SSimon J. Gerraty * by this node. 23806b9b3e0SSimon J. Gerraty * 23906b9b3e0SSimon J. Gerraty * XXX: For the nodes that represent targets or sources (and not 240dba7b0efSSimon J. Gerraty * SCOPE_GLOBAL), it should be safe to free the variables as well, 24106b9b3e0SSimon J. Gerraty * since each node manages the memory for all its variables itself. 24206b9b3e0SSimon J. Gerraty * 243b0c40a00SSimon J. Gerraty * XXX: The GNodes that are only used as variable scopes (SCOPE_CMD, 244dba7b0efSSimon J. Gerraty * SCOPE_GLOBAL, SCOPE_INTERNAL) are not freed at all (see Var_End, 245dba7b0efSSimon J. Gerraty * where they are not mentioned). These might be freed at all, if 246dba7b0efSSimon J. Gerraty * their variable values are indeed not used anywhere else (see 247dba7b0efSSimon J. Gerraty * Trace_Init for the only suspicious use). 24806b9b3e0SSimon J. Gerraty */ 24906b9b3e0SSimon J. Gerraty HashTable_Done(&gn->vars); 25006b9b3e0SSimon J. Gerraty 25106b9b3e0SSimon J. Gerraty /* 25206b9b3e0SSimon J. Gerraty * Do not free the commands themselves, as they may be shared with 25306b9b3e0SSimon J. Gerraty * other nodes. 25406b9b3e0SSimon J. Gerraty */ 25506b9b3e0SSimon J. Gerraty Lst_Done(&gn->commands); 25606b9b3e0SSimon J. Gerraty 25706b9b3e0SSimon J. Gerraty /* 25806b9b3e0SSimon J. Gerraty * gn->suffix is not owned by this node. 25906b9b3e0SSimon J. Gerraty * 26006b9b3e0SSimon J. Gerraty * XXX: gn->suffix should be unreferenced here. This requires a 26106b9b3e0SSimon J. Gerraty * thorough check that the reference counting is done correctly in 26206b9b3e0SSimon J. Gerraty * all places, otherwise a suffix might be freed too early. 26306b9b3e0SSimon J. Gerraty */ 2643955d011SMarcel Moolenaar 2653955d011SMarcel Moolenaar free(gn); 2663955d011SMarcel Moolenaar } 2673955d011SMarcel Moolenaar #endif 2683955d011SMarcel Moolenaar 269956e45f6SSimon J. Gerraty /* Get the existing global node, or return NULL. */ 2703955d011SMarcel Moolenaar GNode * 271956e45f6SSimon J. Gerraty Targ_FindNode(const char *name) 2723955d011SMarcel Moolenaar { 273e2eeea75SSimon J. Gerraty return HashTable_FindValue(&allTargetsByName, name); 2743955d011SMarcel Moolenaar } 2753955d011SMarcel Moolenaar 276956e45f6SSimon J. Gerraty /* Get the existing global node, or create it. */ 277956e45f6SSimon J. Gerraty GNode * 278956e45f6SSimon J. Gerraty Targ_GetNode(const char *name) 279956e45f6SSimon J. Gerraty { 280b0c40a00SSimon J. Gerraty bool isNew; 281e2eeea75SSimon J. Gerraty HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew); 2823955d011SMarcel Moolenaar if (!isNew) 283956e45f6SSimon J. Gerraty return HashEntry_Get(he); 284956e45f6SSimon J. Gerraty 285956e45f6SSimon J. Gerraty { 286956e45f6SSimon J. Gerraty GNode *gn = Targ_NewInternalNode(name); 287956e45f6SSimon J. Gerraty HashEntry_Set(he, gn); 288956e45f6SSimon J. Gerraty return gn; 289956e45f6SSimon J. Gerraty } 2903955d011SMarcel Moolenaar } 2913955d011SMarcel Moolenaar 292e2eeea75SSimon J. Gerraty /* 293e2eeea75SSimon J. Gerraty * Create a node, register it in .ALLTARGETS but don't store it in the 294956e45f6SSimon J. Gerraty * table of global nodes. This means it cannot be found by name. 295956e45f6SSimon J. Gerraty * 296e2eeea75SSimon J. Gerraty * This is used for internal nodes, such as cohorts or .WAIT nodes. 297e2eeea75SSimon J. Gerraty */ 298956e45f6SSimon J. Gerraty GNode * 299956e45f6SSimon J. Gerraty Targ_NewInternalNode(const char *name) 300956e45f6SSimon J. Gerraty { 301e2eeea75SSimon J. Gerraty GNode *gn = GNode_New(name); 302dba7b0efSSimon J. Gerraty Global_Append(".ALLTARGETS", name); 30306b9b3e0SSimon J. Gerraty Lst_Append(&allTargets, gn); 30406b9b3e0SSimon J. Gerraty DEBUG1(TARG, "Adding \"%s\" to all targets.\n", gn->name); 3053955d011SMarcel Moolenaar if (doing_depend) 30612904384SSimon J. Gerraty gn->flags.fromDepend = true; 3073955d011SMarcel Moolenaar return gn; 3083955d011SMarcel Moolenaar } 3093955d011SMarcel Moolenaar 310e2eeea75SSimon J. Gerraty /* 311e2eeea75SSimon J. Gerraty * Return the .END node, which contains the commands to be run when 312e2eeea75SSimon J. Gerraty * everything else has been made. 313e2eeea75SSimon J. Gerraty */ 31406b9b3e0SSimon J. Gerraty GNode * 31506b9b3e0SSimon J. Gerraty Targ_GetEndNode(void) 3163955d011SMarcel Moolenaar { 31706b9b3e0SSimon J. Gerraty /* 31806b9b3e0SSimon J. Gerraty * Save the node locally to avoid having to search for it all 31906b9b3e0SSimon J. Gerraty * the time. 32006b9b3e0SSimon J. Gerraty */ 321956e45f6SSimon J. Gerraty static GNode *endNode = NULL; 32206b9b3e0SSimon J. Gerraty 323956e45f6SSimon J. Gerraty if (endNode == NULL) { 324956e45f6SSimon J. Gerraty endNode = Targ_GetNode(".END"); 325956e45f6SSimon J. Gerraty endNode->type = OP_SPECIAL; 326956e45f6SSimon J. Gerraty } 327956e45f6SSimon J. Gerraty return endNode; 328956e45f6SSimon J. Gerraty } 3293955d011SMarcel Moolenaar 33006b9b3e0SSimon J. Gerraty /* Add the named nodes to the list, creating them as necessary. */ 33106b9b3e0SSimon J. Gerraty void 33206b9b3e0SSimon J. Gerraty Targ_FindList(GNodeList *gns, StringList *names) 333956e45f6SSimon J. Gerraty { 334956e45f6SSimon J. Gerraty StringListNode *ln; 33506b9b3e0SSimon J. Gerraty 336956e45f6SSimon J. Gerraty for (ln = names->first; ln != NULL; ln = ln->next) { 337956e45f6SSimon J. Gerraty const char *name = ln->datum; 338956e45f6SSimon J. Gerraty GNode *gn = Targ_GetNode(name); 33906b9b3e0SSimon J. Gerraty Lst_Append(gns, gn); 3403955d011SMarcel Moolenaar } 3413955d011SMarcel Moolenaar } 3423955d011SMarcel Moolenaar 343956e45f6SSimon J. Gerraty static void 344956e45f6SSimon J. Gerraty PrintNodeNames(GNodeList *gnodes) 3453955d011SMarcel Moolenaar { 34606b9b3e0SSimon J. Gerraty GNodeListNode *ln; 3473955d011SMarcel Moolenaar 34806b9b3e0SSimon J. Gerraty for (ln = gnodes->first; ln != NULL; ln = ln->next) { 34906b9b3e0SSimon J. Gerraty GNode *gn = ln->datum; 350956e45f6SSimon J. Gerraty debug_printf(" %s%s", gn->name, gn->cohort_num); 351956e45f6SSimon J. Gerraty } 3523955d011SMarcel Moolenaar } 3533955d011SMarcel Moolenaar 354956e45f6SSimon J. Gerraty static void 355956e45f6SSimon J. Gerraty PrintNodeNamesLine(const char *label, GNodeList *gnodes) 3563955d011SMarcel Moolenaar { 357956e45f6SSimon J. Gerraty if (Lst_IsEmpty(gnodes)) 358956e45f6SSimon J. Gerraty return; 359956e45f6SSimon J. Gerraty debug_printf("# %s:", label); 360956e45f6SSimon J. Gerraty PrintNodeNames(gnodes); 361956e45f6SSimon J. Gerraty debug_printf("\n"); 362956e45f6SSimon J. Gerraty } 363956e45f6SSimon J. Gerraty 364956e45f6SSimon J. Gerraty void 365956e45f6SSimon J. Gerraty Targ_PrintCmds(GNode *gn) 366956e45f6SSimon J. Gerraty { 367956e45f6SSimon J. Gerraty StringListNode *ln; 36806b9b3e0SSimon J. Gerraty 36906b9b3e0SSimon J. Gerraty for (ln = gn->commands.first; ln != NULL; ln = ln->next) { 370956e45f6SSimon J. Gerraty const char *cmd = ln->datum; 371956e45f6SSimon J. Gerraty debug_printf("\t%s\n", cmd); 372956e45f6SSimon J. Gerraty } 3733955d011SMarcel Moolenaar } 3743955d011SMarcel Moolenaar 37506b9b3e0SSimon J. Gerraty /* 37606b9b3e0SSimon J. Gerraty * Format a modification time in some reasonable way and return it. 37706b9b3e0SSimon J. Gerraty * The formatted time is placed in a static area, so it is overwritten 37806b9b3e0SSimon J. Gerraty * with each call. 37906b9b3e0SSimon J. Gerraty */ 38006b9b3e0SSimon J. Gerraty const char * 3813955d011SMarcel Moolenaar Targ_FmtTime(time_t tm) 3823955d011SMarcel Moolenaar { 3833955d011SMarcel Moolenaar static char buf[128]; 3843955d011SMarcel Moolenaar 38506b9b3e0SSimon J. Gerraty struct tm *parts = localtime(&tm); 386b0c40a00SSimon J. Gerraty (void)strftime(buf, sizeof buf, "%H:%M:%S %b %d, %Y", parts); 3873841c287SSimon J. Gerraty return buf; 3883955d011SMarcel Moolenaar } 3893955d011SMarcel Moolenaar 3902c3632d1SSimon J. Gerraty /* Print out a type field giving only those attributes the user can set. */ 3913955d011SMarcel Moolenaar void 39212904384SSimon J. Gerraty Targ_PrintType(GNodeType type) 3933955d011SMarcel Moolenaar { 39412904384SSimon J. Gerraty static const struct { 39512904384SSimon J. Gerraty GNodeType bit; 39612904384SSimon J. Gerraty bool internal; 39712904384SSimon J. Gerraty const char name[10]; 39812904384SSimon J. Gerraty } names[] = { 39912904384SSimon J. Gerraty { OP_MEMBER, true, "MEMBER" }, 40012904384SSimon J. Gerraty { OP_LIB, true, "LIB" }, 40112904384SSimon J. Gerraty { OP_ARCHV, true, "ARCHV" }, 40212904384SSimon J. Gerraty { OP_PHONY, true, "PHONY" }, 40312904384SSimon J. Gerraty { OP_NOTMAIN, false, "NOTMAIN" }, 40412904384SSimon J. Gerraty { OP_INVISIBLE, false, "INVISIBLE" }, 40512904384SSimon J. Gerraty { OP_MADE, true, "MADE" }, 40612904384SSimon J. Gerraty { OP_JOIN, false, "JOIN" }, 40712904384SSimon J. Gerraty { OP_MAKE, false, "MAKE" }, 40812904384SSimon J. Gerraty { OP_SILENT, false, "SILENT" }, 40912904384SSimon J. Gerraty { OP_PRECIOUS, false, "PRECIOUS" }, 41012904384SSimon J. Gerraty { OP_IGNORE, false, "IGNORE" }, 41112904384SSimon J. Gerraty { OP_EXEC, false, "EXEC" }, 41212904384SSimon J. Gerraty { OP_USE, false, "USE" }, 41312904384SSimon J. Gerraty { OP_OPTIONAL, false, "OPTIONAL" }, 41412904384SSimon J. Gerraty }; 41512904384SSimon J. Gerraty size_t i; 4163955d011SMarcel Moolenaar 41712904384SSimon J. Gerraty for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) { 41812904384SSimon J. Gerraty if (type & names[i].bit) { 41912904384SSimon J. Gerraty if (names[i].internal) 42012904384SSimon J. Gerraty DEBUG1(TARG, " .%s", names[i].name); 42112904384SSimon J. Gerraty else 42212904384SSimon J. Gerraty debug_printf(" .%s", names[i].name); 4233955d011SMarcel Moolenaar } 4243955d011SMarcel Moolenaar } 4253955d011SMarcel Moolenaar } 4263955d011SMarcel Moolenaar 427dba7b0efSSimon J. Gerraty const char * 428dba7b0efSSimon J. Gerraty GNodeMade_Name(GNodeMade made) 4293955d011SMarcel Moolenaar { 4303955d011SMarcel Moolenaar switch (made) { 4313955d011SMarcel Moolenaar case UNMADE: return "unmade"; 4323955d011SMarcel Moolenaar case DEFERRED: return "deferred"; 4333955d011SMarcel Moolenaar case REQUESTED: return "requested"; 4343955d011SMarcel Moolenaar case BEINGMADE: return "being made"; 4353955d011SMarcel Moolenaar case MADE: return "made"; 4363955d011SMarcel Moolenaar case UPTODATE: return "up-to-date"; 4373955d011SMarcel Moolenaar case ERROR: return "error when made"; 4383955d011SMarcel Moolenaar case ABORTED: return "aborted"; 4393955d011SMarcel Moolenaar default: return "unknown enum_made value"; 4403955d011SMarcel Moolenaar } 4413955d011SMarcel Moolenaar } 4423955d011SMarcel Moolenaar 443956e45f6SSimon J. Gerraty static const char * 444956e45f6SSimon J. Gerraty GNode_OpName(const GNode *gn) 4453955d011SMarcel Moolenaar { 446956e45f6SSimon J. Gerraty switch (gn->type & OP_OPMASK) { 447956e45f6SSimon J. Gerraty case OP_DEPENDS: 448956e45f6SSimon J. Gerraty return ":"; 449956e45f6SSimon J. Gerraty case OP_FORCE: 450956e45f6SSimon J. Gerraty return "!"; 451956e45f6SSimon J. Gerraty case OP_DOUBLEDEP: 452956e45f6SSimon J. Gerraty return "::"; 453956e45f6SSimon J. Gerraty } 454956e45f6SSimon J. Gerraty return ""; 455956e45f6SSimon J. Gerraty } 4563955d011SMarcel Moolenaar 45712904384SSimon J. Gerraty static bool 45812904384SSimon J. Gerraty GNodeFlags_IsNone(GNodeFlags flags) 45912904384SSimon J. Gerraty { 46012904384SSimon J. Gerraty return !flags.remake 46112904384SSimon J. Gerraty && !flags.childMade 46212904384SSimon J. Gerraty && !flags.force 46312904384SSimon J. Gerraty && !flags.doneWait 46412904384SSimon J. Gerraty && !flags.doneOrder 46512904384SSimon J. Gerraty && !flags.fromDepend 46612904384SSimon J. Gerraty && !flags.doneAllsrc 46712904384SSimon J. Gerraty && !flags.cycle 46812904384SSimon J. Gerraty && !flags.doneCycle; 46912904384SSimon J. Gerraty } 47012904384SSimon J. Gerraty 471956e45f6SSimon J. Gerraty /* Print the contents of a node. */ 472956e45f6SSimon J. Gerraty void 473956e45f6SSimon J. Gerraty Targ_PrintNode(GNode *gn, int pass) 474956e45f6SSimon J. Gerraty { 475956e45f6SSimon J. Gerraty debug_printf("# %s%s", gn->name, gn->cohort_num); 476956e45f6SSimon J. Gerraty GNode_FprintDetails(opts.debug_file, ", ", gn, "\n"); 47712904384SSimon J. Gerraty if (GNodeFlags_IsNone(gn->flags)) 478956e45f6SSimon J. Gerraty return; 4793955d011SMarcel Moolenaar 48006b9b3e0SSimon J. Gerraty if (!GNode_IsTarget(gn)) 48106b9b3e0SSimon J. Gerraty return; 48206b9b3e0SSimon J. Gerraty 483956e45f6SSimon J. Gerraty debug_printf("#\n"); 484*9f45a3c8SSimon J. Gerraty if (gn == mainNode) 485956e45f6SSimon J. Gerraty debug_printf("# *** MAIN TARGET ***\n"); 48606b9b3e0SSimon J. Gerraty 4873955d011SMarcel Moolenaar if (pass >= 2) { 48806b9b3e0SSimon J. Gerraty if (gn->unmade > 0) 489956e45f6SSimon J. Gerraty debug_printf("# %d unmade children\n", gn->unmade); 49006b9b3e0SSimon J. Gerraty else 491956e45f6SSimon J. Gerraty debug_printf("# No unmade children\n"); 4923955d011SMarcel Moolenaar if (!(gn->type & (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC))) { 4933955d011SMarcel Moolenaar if (gn->mtime != 0) { 494956e45f6SSimon J. Gerraty debug_printf("# last modified %s: %s\n", 4953955d011SMarcel Moolenaar Targ_FmtTime(gn->mtime), 496dba7b0efSSimon J. Gerraty GNodeMade_Name(gn->made)); 4973955d011SMarcel Moolenaar } else if (gn->made != UNMADE) { 49806b9b3e0SSimon J. Gerraty debug_printf("# nonexistent (maybe): %s\n", 499dba7b0efSSimon J. Gerraty GNodeMade_Name(gn->made)); 50006b9b3e0SSimon J. Gerraty } else 501956e45f6SSimon J. Gerraty debug_printf("# unmade\n"); 5023955d011SMarcel Moolenaar } 50306b9b3e0SSimon J. Gerraty PrintNodeNamesLine("implicit parents", &gn->implicitParents); 5043955d011SMarcel Moolenaar } else { 50506b9b3e0SSimon J. Gerraty if (gn->unmade != 0) 506956e45f6SSimon J. Gerraty debug_printf("# %d unmade children\n", gn->unmade); 5073955d011SMarcel Moolenaar } 50806b9b3e0SSimon J. Gerraty 50906b9b3e0SSimon J. Gerraty PrintNodeNamesLine("parents", &gn->parents); 51006b9b3e0SSimon J. Gerraty PrintNodeNamesLine("order_pred", &gn->order_pred); 51106b9b3e0SSimon J. Gerraty PrintNodeNamesLine("order_succ", &gn->order_succ); 5123955d011SMarcel Moolenaar 513956e45f6SSimon J. Gerraty debug_printf("%-16s%s", gn->name, GNode_OpName(gn)); 5143955d011SMarcel Moolenaar Targ_PrintType(gn->type); 51506b9b3e0SSimon J. Gerraty PrintNodeNames(&gn->children); 516956e45f6SSimon J. Gerraty debug_printf("\n"); 517956e45f6SSimon J. Gerraty Targ_PrintCmds(gn); 518956e45f6SSimon J. Gerraty debug_printf("\n\n"); 51906b9b3e0SSimon J. Gerraty if (gn->type & OP_DOUBLEDEP) 52006b9b3e0SSimon J. Gerraty Targ_PrintNodes(&gn->cohorts, pass); 5213955d011SMarcel Moolenaar } 5223955d011SMarcel Moolenaar 523956e45f6SSimon J. Gerraty void 524956e45f6SSimon J. Gerraty Targ_PrintNodes(GNodeList *gnodes, int pass) 5253955d011SMarcel Moolenaar { 526956e45f6SSimon J. Gerraty GNodeListNode *ln; 52706b9b3e0SSimon J. Gerraty 528956e45f6SSimon J. Gerraty for (ln = gnodes->first; ln != NULL; ln = ln->next) 529956e45f6SSimon J. Gerraty Targ_PrintNode(ln->datum, pass); 530956e45f6SSimon J. Gerraty } 5313955d011SMarcel Moolenaar 532956e45f6SSimon J. Gerraty static void 533956e45f6SSimon J. Gerraty PrintOnlySources(void) 534956e45f6SSimon J. Gerraty { 535956e45f6SSimon J. Gerraty GNodeListNode *ln; 536956e45f6SSimon J. Gerraty 53706b9b3e0SSimon J. Gerraty for (ln = allTargets.first; ln != NULL; ln = ln->next) { 538956e45f6SSimon J. Gerraty GNode *gn = ln->datum; 539956e45f6SSimon J. Gerraty if (GNode_IsTarget(gn)) 540956e45f6SSimon J. Gerraty continue; 541956e45f6SSimon J. Gerraty 542956e45f6SSimon J. Gerraty debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn)); 5433955d011SMarcel Moolenaar Targ_PrintType(gn->type); 544956e45f6SSimon J. Gerraty debug_printf("\n"); 545956e45f6SSimon J. Gerraty } 5463955d011SMarcel Moolenaar } 5473955d011SMarcel Moolenaar 54806b9b3e0SSimon J. Gerraty /* 54906b9b3e0SSimon J. Gerraty * Input: 5502c3632d1SSimon J. Gerraty * pass 1 => before processing 5512c3632d1SSimon J. Gerraty * 2 => after processing 5522c3632d1SSimon J. Gerraty * 3 => after processing, an error occurred 5533955d011SMarcel Moolenaar */ 5543955d011SMarcel Moolenaar void 5553955d011SMarcel Moolenaar Targ_PrintGraph(int pass) 5563955d011SMarcel Moolenaar { 557956e45f6SSimon J. Gerraty debug_printf("#*** Input graph:\n"); 55806b9b3e0SSimon J. Gerraty Targ_PrintNodes(&allTargets, pass); 559e2eeea75SSimon J. Gerraty debug_printf("\n"); 560e2eeea75SSimon J. Gerraty debug_printf("\n"); 561e2eeea75SSimon J. Gerraty 562e2eeea75SSimon J. Gerraty debug_printf("#\n"); 563e2eeea75SSimon J. Gerraty debug_printf("# Files that are only sources:\n"); 564956e45f6SSimon J. Gerraty PrintOnlySources(); 565e2eeea75SSimon J. Gerraty 566956e45f6SSimon J. Gerraty debug_printf("#*** Global Variables:\n"); 567dba7b0efSSimon J. Gerraty Var_Dump(SCOPE_GLOBAL); 568e2eeea75SSimon J. Gerraty 569956e45f6SSimon J. Gerraty debug_printf("#*** Command-line Variables:\n"); 570dba7b0efSSimon J. Gerraty Var_Dump(SCOPE_CMDLINE); 571e2eeea75SSimon J. Gerraty 572956e45f6SSimon J. Gerraty debug_printf("\n"); 5733955d011SMarcel Moolenaar Dir_PrintDirectories(); 574956e45f6SSimon J. Gerraty debug_printf("\n"); 575e2eeea75SSimon J. Gerraty 5763955d011SMarcel Moolenaar Suff_PrintAll(); 5773955d011SMarcel Moolenaar } 5783955d011SMarcel Moolenaar 57906b9b3e0SSimon J. Gerraty /* 58006b9b3e0SSimon J. Gerraty * Propagate some type information to cohort nodes (those from the '::' 5812c3632d1SSimon J. Gerraty * dependency operator). 5823955d011SMarcel Moolenaar * 5832c3632d1SSimon J. Gerraty * Should be called after the makefiles are parsed but before any action is 58406b9b3e0SSimon J. Gerraty * taken. 58506b9b3e0SSimon J. Gerraty */ 5863955d011SMarcel Moolenaar void 5873955d011SMarcel Moolenaar Targ_Propagate(void) 5883955d011SMarcel Moolenaar { 589956e45f6SSimon J. Gerraty GNodeListNode *ln, *cln; 5902c3632d1SSimon J. Gerraty 59106b9b3e0SSimon J. Gerraty for (ln = allTargets.first; ln != NULL; ln = ln->next) { 592956e45f6SSimon J. Gerraty GNode *gn = ln->datum; 593956e45f6SSimon J. Gerraty GNodeType type = gn->type; 5942c3632d1SSimon J. Gerraty 595956e45f6SSimon J. Gerraty if (!(type & OP_DOUBLEDEP)) 5962c3632d1SSimon J. Gerraty continue; 5972c3632d1SSimon J. Gerraty 59806b9b3e0SSimon J. Gerraty for (cln = gn->cohorts.first; cln != NULL; cln = cln->next) { 599956e45f6SSimon J. Gerraty GNode *cohort = cln->datum; 6002c3632d1SSimon J. Gerraty 601956e45f6SSimon J. Gerraty cohort->type |= type & ~OP_OPMASK; 6022c3632d1SSimon J. Gerraty } 6032c3632d1SSimon J. Gerraty } 6043955d011SMarcel Moolenaar } 605