1*dba7b0efSSimon J. Gerraty /* $NetBSD: targ.c,v 1.165 2021/02/04 21:42:46 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 * 81e2eeea75SSimon J. Gerraty * GNode_New Create a new GNode for the passed target 823955d011SMarcel Moolenaar * (string). The node is *not* placed in the 833955d011SMarcel Moolenaar * hash table, though all its fields are 843955d011SMarcel Moolenaar * initialized. 853955d011SMarcel Moolenaar * 86956e45f6SSimon J. Gerraty * Targ_FindNode Find the node, or return NULL. 87956e45f6SSimon J. Gerraty * 88956e45f6SSimon J. Gerraty * Targ_GetNode Find the node, or create it. 89956e45f6SSimon J. Gerraty * 90956e45f6SSimon J. Gerraty * Targ_NewInternalNode 91956e45f6SSimon J. Gerraty * Create an internal node. 923955d011SMarcel Moolenaar * 933955d011SMarcel Moolenaar * Targ_FindList Given a list of names, find nodes for all 94956e45f6SSimon J. Gerraty * of them, creating them as necessary. 953955d011SMarcel Moolenaar * 963955d011SMarcel Moolenaar * Targ_Precious Return TRUE if the target is precious and 973955d011SMarcel Moolenaar * should not be removed if we are interrupted. 983955d011SMarcel Moolenaar * 99956e45f6SSimon J. Gerraty * Targ_Propagate Propagate information between related nodes. 100956e45f6SSimon J. Gerraty * Should be called after the makefiles are parsed 101956e45f6SSimon J. Gerraty * but before any action is taken. 1023955d011SMarcel Moolenaar * 1033955d011SMarcel Moolenaar * Debugging: 104956e45f6SSimon J. Gerraty * Targ_PrintGraph 10506b9b3e0SSimon J. Gerraty * Print out the entire graph, all variables and 106956e45f6SSimon J. Gerraty * statistics for the directory cache. Should print 107956e45f6SSimon J. Gerraty * something for suffixes, too, but... 1083955d011SMarcel Moolenaar */ 1093955d011SMarcel Moolenaar 1103955d011SMarcel Moolenaar #include <time.h> 1113955d011SMarcel Moolenaar 1123955d011SMarcel Moolenaar #include "make.h" 1133955d011SMarcel Moolenaar #include "dir.h" 1143955d011SMarcel Moolenaar 115956e45f6SSimon J. Gerraty /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */ 116*dba7b0efSSimon J. Gerraty MAKE_RCSID("$NetBSD: targ.c,v 1.165 2021/02/04 21:42:46 rillig Exp $"); 1173955d011SMarcel Moolenaar 11806b9b3e0SSimon J. Gerraty /* 11906b9b3e0SSimon J. Gerraty * All target nodes that appeared on the left-hand side of one of the 12006b9b3e0SSimon J. Gerraty * dependency operators ':', '::', '!'. 12106b9b3e0SSimon J. Gerraty */ 12206b9b3e0SSimon J. Gerraty static GNodeList allTargets = LST_INIT; 123e2eeea75SSimon J. Gerraty static HashTable allTargetsByName; 124956e45f6SSimon J. Gerraty 1253955d011SMarcel Moolenaar #ifdef CLEANUP 12606b9b3e0SSimon J. Gerraty static GNodeList allNodes = LST_INIT; 127e2eeea75SSimon J. Gerraty 128e2eeea75SSimon J. Gerraty static void GNode_Free(void *); 1293955d011SMarcel Moolenaar #endif 1303955d011SMarcel Moolenaar 1313955d011SMarcel Moolenaar void 1323955d011SMarcel Moolenaar Targ_Init(void) 1333955d011SMarcel Moolenaar { 134e2eeea75SSimon J. Gerraty HashTable_Init(&allTargetsByName); 1353955d011SMarcel Moolenaar } 1363955d011SMarcel Moolenaar 1373955d011SMarcel Moolenaar void 1383955d011SMarcel Moolenaar Targ_End(void) 1393955d011SMarcel Moolenaar { 1402c3632d1SSimon J. Gerraty Targ_Stats(); 1413955d011SMarcel Moolenaar #ifdef CLEANUP 14206b9b3e0SSimon J. Gerraty Lst_Done(&allTargets); 143e2eeea75SSimon J. Gerraty HashTable_Done(&allTargetsByName); 14406b9b3e0SSimon J. Gerraty Lst_DoneCall(&allNodes, GNode_Free); 1453955d011SMarcel Moolenaar #endif 1463955d011SMarcel Moolenaar } 1473955d011SMarcel Moolenaar 1482c3632d1SSimon J. Gerraty void 1492c3632d1SSimon J. Gerraty Targ_Stats(void) 1502c3632d1SSimon J. Gerraty { 151e2eeea75SSimon J. Gerraty HashTable_DebugStats(&allTargetsByName, "targets"); 1522c3632d1SSimon J. Gerraty } 1532c3632d1SSimon J. Gerraty 154e2eeea75SSimon J. Gerraty /* 155e2eeea75SSimon J. Gerraty * Return the list of all targets, which are all nodes that appear on the 156e2eeea75SSimon J. Gerraty * left-hand side of a dependency declaration such as "target: source". 157e2eeea75SSimon J. Gerraty * The returned list does not contain pure sources. 158e2eeea75SSimon J. Gerraty */ 159956e45f6SSimon J. Gerraty GNodeList * 1603955d011SMarcel Moolenaar Targ_List(void) 1613955d011SMarcel Moolenaar { 16206b9b3e0SSimon J. Gerraty return &allTargets; 1633955d011SMarcel Moolenaar } 1643955d011SMarcel Moolenaar 16506b9b3e0SSimon J. Gerraty /* 16606b9b3e0SSimon J. Gerraty * Create a new graph node, but don't register it anywhere. 1673955d011SMarcel Moolenaar * 168e2eeea75SSimon J. Gerraty * Graph nodes that appear on the left-hand side of a dependency line such 169e2eeea75SSimon J. Gerraty * as "target: source" are called targets. XXX: In some cases (like the 170e2eeea75SSimon J. Gerraty * .ALLTARGETS variable), all nodes are called targets as well, even if they 171e2eeea75SSimon J. Gerraty * never appear on the left-hand side. This is a mistake. 172e2eeea75SSimon J. Gerraty * 173e2eeea75SSimon J. Gerraty * Typical names for graph nodes are: 174e2eeea75SSimon J. Gerraty * "src.c" (an ordinary file) 175e2eeea75SSimon J. Gerraty * "clean" (a .PHONY target) 176e2eeea75SSimon J. Gerraty * ".END" (a special hook target) 177e2eeea75SSimon J. Gerraty * "-lm" (a library) 178e2eeea75SSimon J. Gerraty * "libc.a(isspace.o)" (an archive member) 1793955d011SMarcel Moolenaar */ 1803955d011SMarcel Moolenaar GNode * 181e2eeea75SSimon J. Gerraty GNode_New(const char *name) 1823955d011SMarcel Moolenaar { 1833955d011SMarcel Moolenaar GNode *gn; 1843955d011SMarcel Moolenaar 185e2eeea75SSimon J. Gerraty gn = bmake_malloc(sizeof *gn); 1863955d011SMarcel Moolenaar gn->name = bmake_strdup(name); 1873955d011SMarcel Moolenaar gn->uname = NULL; 1883955d011SMarcel Moolenaar gn->path = NULL; 18906b9b3e0SSimon J. Gerraty gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : OP_NONE; 19006b9b3e0SSimon J. Gerraty gn->flags = GNF_NONE; 191e2eeea75SSimon J. Gerraty gn->made = UNMADE; 192e2eeea75SSimon J. Gerraty gn->unmade = 0; 1933955d011SMarcel Moolenaar gn->mtime = 0; 194956e45f6SSimon J. Gerraty gn->youngestChild = NULL; 19506b9b3e0SSimon J. Gerraty Lst_Init(&gn->implicitParents); 19606b9b3e0SSimon J. Gerraty Lst_Init(&gn->parents); 19706b9b3e0SSimon J. Gerraty Lst_Init(&gn->children); 19806b9b3e0SSimon J. Gerraty Lst_Init(&gn->order_pred); 19906b9b3e0SSimon J. Gerraty Lst_Init(&gn->order_succ); 20006b9b3e0SSimon J. Gerraty Lst_Init(&gn->cohorts); 201e2eeea75SSimon J. Gerraty gn->cohort_num[0] = '\0'; 202e2eeea75SSimon J. Gerraty gn->unmade_cohorts = 0; 203e2eeea75SSimon J. Gerraty gn->centurion = NULL; 204e2eeea75SSimon J. Gerraty gn->checked_seqno = 0; 20506b9b3e0SSimon J. Gerraty HashTable_Init(&gn->vars); 20606b9b3e0SSimon J. Gerraty Lst_Init(&gn->commands); 2073955d011SMarcel Moolenaar gn->suffix = NULL; 2083955d011SMarcel Moolenaar gn->fname = NULL; 2092c3632d1SSimon J. Gerraty gn->lineno = 0; 2103955d011SMarcel Moolenaar 2113955d011SMarcel Moolenaar #ifdef CLEANUP 21206b9b3e0SSimon J. Gerraty Lst_Append(&allNodes, gn); 2133955d011SMarcel Moolenaar #endif 2143955d011SMarcel Moolenaar 2153841c287SSimon J. Gerraty return gn; 2163955d011SMarcel Moolenaar } 2173955d011SMarcel Moolenaar 2183955d011SMarcel Moolenaar #ifdef CLEANUP 2193955d011SMarcel Moolenaar static void 220e2eeea75SSimon J. Gerraty GNode_Free(void *gnp) 2213955d011SMarcel Moolenaar { 222956e45f6SSimon J. Gerraty GNode *gn = gnp; 2233955d011SMarcel Moolenaar 2243955d011SMarcel Moolenaar free(gn->name); 2253955d011SMarcel Moolenaar free(gn->uname); 2263955d011SMarcel Moolenaar free(gn->path); 22706b9b3e0SSimon J. Gerraty 22806b9b3e0SSimon J. Gerraty /* Don't free gn->youngestChild since it is not owned by this node. */ 22906b9b3e0SSimon J. Gerraty 23006b9b3e0SSimon J. Gerraty /* 23106b9b3e0SSimon J. Gerraty * In the following lists, only free the list nodes, but not the 23206b9b3e0SSimon J. Gerraty * GNodes in them since these are not owned by this node. 23306b9b3e0SSimon J. Gerraty */ 23406b9b3e0SSimon J. Gerraty Lst_Done(&gn->implicitParents); 23506b9b3e0SSimon J. Gerraty Lst_Done(&gn->parents); 23606b9b3e0SSimon J. Gerraty Lst_Done(&gn->children); 23706b9b3e0SSimon J. Gerraty Lst_Done(&gn->order_pred); 23806b9b3e0SSimon J. Gerraty Lst_Done(&gn->order_succ); 23906b9b3e0SSimon J. Gerraty Lst_Done(&gn->cohorts); 24006b9b3e0SSimon J. Gerraty 24106b9b3e0SSimon J. Gerraty /* 24206b9b3e0SSimon J. Gerraty * Do not free the variables themselves, even though they are owned 24306b9b3e0SSimon J. Gerraty * by this node. 24406b9b3e0SSimon J. Gerraty * 24506b9b3e0SSimon J. Gerraty * XXX: For the nodes that represent targets or sources (and not 246*dba7b0efSSimon J. Gerraty * SCOPE_GLOBAL), it should be safe to free the variables as well, 24706b9b3e0SSimon J. Gerraty * since each node manages the memory for all its variables itself. 24806b9b3e0SSimon J. Gerraty * 249*dba7b0efSSimon J. Gerraty * XXX: The GNodes that are only used as variable scopes (VAR_CMD, 250*dba7b0efSSimon J. Gerraty * SCOPE_GLOBAL, SCOPE_INTERNAL) are not freed at all (see Var_End, 251*dba7b0efSSimon J. Gerraty * where they are not mentioned). These might be freed at all, if 252*dba7b0efSSimon J. Gerraty * their variable values are indeed not used anywhere else (see 253*dba7b0efSSimon J. Gerraty * Trace_Init for the only suspicious use). 25406b9b3e0SSimon J. Gerraty */ 25506b9b3e0SSimon J. Gerraty HashTable_Done(&gn->vars); 25606b9b3e0SSimon J. Gerraty 25706b9b3e0SSimon J. Gerraty /* 25806b9b3e0SSimon J. Gerraty * Do not free the commands themselves, as they may be shared with 25906b9b3e0SSimon J. Gerraty * other nodes. 26006b9b3e0SSimon J. Gerraty */ 26106b9b3e0SSimon J. Gerraty Lst_Done(&gn->commands); 26206b9b3e0SSimon J. Gerraty 26306b9b3e0SSimon J. Gerraty /* 26406b9b3e0SSimon J. Gerraty * gn->suffix is not owned by this node. 26506b9b3e0SSimon J. Gerraty * 26606b9b3e0SSimon J. Gerraty * XXX: gn->suffix should be unreferenced here. This requires a 26706b9b3e0SSimon J. Gerraty * thorough check that the reference counting is done correctly in 26806b9b3e0SSimon J. Gerraty * all places, otherwise a suffix might be freed too early. 26906b9b3e0SSimon J. Gerraty */ 2703955d011SMarcel Moolenaar 2713955d011SMarcel Moolenaar free(gn); 2723955d011SMarcel Moolenaar } 2733955d011SMarcel Moolenaar #endif 2743955d011SMarcel Moolenaar 275956e45f6SSimon J. Gerraty /* Get the existing global node, or return NULL. */ 2763955d011SMarcel Moolenaar GNode * 277956e45f6SSimon J. Gerraty Targ_FindNode(const char *name) 2783955d011SMarcel Moolenaar { 279e2eeea75SSimon J. Gerraty return HashTable_FindValue(&allTargetsByName, name); 2803955d011SMarcel Moolenaar } 2813955d011SMarcel Moolenaar 282956e45f6SSimon J. Gerraty /* Get the existing global node, or create it. */ 283956e45f6SSimon J. Gerraty GNode * 284956e45f6SSimon J. Gerraty Targ_GetNode(const char *name) 285956e45f6SSimon J. Gerraty { 286956e45f6SSimon J. Gerraty Boolean isNew; 287e2eeea75SSimon J. Gerraty HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew); 2883955d011SMarcel Moolenaar if (!isNew) 289956e45f6SSimon J. Gerraty return HashEntry_Get(he); 290956e45f6SSimon J. Gerraty 291956e45f6SSimon J. Gerraty { 292956e45f6SSimon J. Gerraty GNode *gn = Targ_NewInternalNode(name); 293956e45f6SSimon J. Gerraty HashEntry_Set(he, gn); 294956e45f6SSimon J. Gerraty return gn; 295956e45f6SSimon J. Gerraty } 2963955d011SMarcel Moolenaar } 2973955d011SMarcel Moolenaar 298e2eeea75SSimon J. Gerraty /* 299e2eeea75SSimon J. Gerraty * Create a node, register it in .ALLTARGETS but don't store it in the 300956e45f6SSimon J. Gerraty * table of global nodes. This means it cannot be found by name. 301956e45f6SSimon J. Gerraty * 302e2eeea75SSimon J. Gerraty * This is used for internal nodes, such as cohorts or .WAIT nodes. 303e2eeea75SSimon J. Gerraty */ 304956e45f6SSimon J. Gerraty GNode * 305956e45f6SSimon J. Gerraty Targ_NewInternalNode(const char *name) 306956e45f6SSimon J. Gerraty { 307e2eeea75SSimon J. Gerraty GNode *gn = GNode_New(name); 308*dba7b0efSSimon J. Gerraty Global_Append(".ALLTARGETS", name); 30906b9b3e0SSimon J. Gerraty Lst_Append(&allTargets, gn); 31006b9b3e0SSimon J. Gerraty DEBUG1(TARG, "Adding \"%s\" to all targets.\n", gn->name); 3113955d011SMarcel Moolenaar if (doing_depend) 3123955d011SMarcel Moolenaar gn->flags |= FROM_DEPEND; 3133955d011SMarcel Moolenaar return gn; 3143955d011SMarcel Moolenaar } 3153955d011SMarcel Moolenaar 316e2eeea75SSimon J. Gerraty /* 317e2eeea75SSimon J. Gerraty * Return the .END node, which contains the commands to be run when 318e2eeea75SSimon J. Gerraty * everything else has been made. 319e2eeea75SSimon J. Gerraty */ 32006b9b3e0SSimon J. Gerraty GNode * 32106b9b3e0SSimon J. Gerraty Targ_GetEndNode(void) 3223955d011SMarcel Moolenaar { 32306b9b3e0SSimon J. Gerraty /* 32406b9b3e0SSimon J. Gerraty * Save the node locally to avoid having to search for it all 32506b9b3e0SSimon J. Gerraty * the time. 32606b9b3e0SSimon J. Gerraty */ 327956e45f6SSimon J. Gerraty static GNode *endNode = NULL; 32806b9b3e0SSimon J. Gerraty 329956e45f6SSimon J. Gerraty if (endNode == NULL) { 330956e45f6SSimon J. Gerraty endNode = Targ_GetNode(".END"); 331956e45f6SSimon J. Gerraty endNode->type = OP_SPECIAL; 332956e45f6SSimon J. Gerraty } 333956e45f6SSimon J. Gerraty return endNode; 334956e45f6SSimon J. Gerraty } 3353955d011SMarcel Moolenaar 33606b9b3e0SSimon J. Gerraty /* Add the named nodes to the list, creating them as necessary. */ 33706b9b3e0SSimon J. Gerraty void 33806b9b3e0SSimon J. Gerraty Targ_FindList(GNodeList *gns, StringList *names) 339956e45f6SSimon J. Gerraty { 340956e45f6SSimon J. Gerraty StringListNode *ln; 34106b9b3e0SSimon J. Gerraty 342956e45f6SSimon J. Gerraty for (ln = names->first; ln != NULL; ln = ln->next) { 343956e45f6SSimon J. Gerraty const char *name = ln->datum; 344956e45f6SSimon J. Gerraty GNode *gn = Targ_GetNode(name); 34506b9b3e0SSimon J. Gerraty Lst_Append(gns, gn); 3463955d011SMarcel Moolenaar } 3473955d011SMarcel Moolenaar } 3483955d011SMarcel Moolenaar 3492c3632d1SSimon J. Gerraty /* See if the given target is precious. */ 3503955d011SMarcel Moolenaar Boolean 351e2eeea75SSimon J. Gerraty Targ_Precious(const GNode *gn) 3523955d011SMarcel Moolenaar { 353e2eeea75SSimon J. Gerraty /* XXX: Why are '::' targets precious? */ 3542c3632d1SSimon J. Gerraty return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP); 3553955d011SMarcel Moolenaar } 3563955d011SMarcel Moolenaar 357e2eeea75SSimon J. Gerraty /* 358e2eeea75SSimon J. Gerraty * The main target to be made; only for debugging output. 359e2eeea75SSimon J. Gerraty * See mainNode in parse.c for the definitive source. 360e2eeea75SSimon J. Gerraty */ 361e2eeea75SSimon J. Gerraty static GNode *mainTarg; 3623955d011SMarcel Moolenaar 363e2eeea75SSimon J. Gerraty /* Remember the main target to make; only used for debugging. */ 3643955d011SMarcel Moolenaar void 3653955d011SMarcel Moolenaar Targ_SetMain(GNode *gn) 3663955d011SMarcel Moolenaar { 3673955d011SMarcel Moolenaar mainTarg = gn; 3683955d011SMarcel Moolenaar } 3693955d011SMarcel Moolenaar 370956e45f6SSimon J. Gerraty static void 371956e45f6SSimon J. Gerraty PrintNodeNames(GNodeList *gnodes) 3723955d011SMarcel Moolenaar { 37306b9b3e0SSimon J. Gerraty GNodeListNode *ln; 3743955d011SMarcel Moolenaar 37506b9b3e0SSimon J. Gerraty for (ln = gnodes->first; ln != NULL; ln = ln->next) { 37606b9b3e0SSimon J. Gerraty GNode *gn = ln->datum; 377956e45f6SSimon J. Gerraty debug_printf(" %s%s", gn->name, gn->cohort_num); 378956e45f6SSimon J. Gerraty } 3793955d011SMarcel Moolenaar } 3803955d011SMarcel Moolenaar 381956e45f6SSimon J. Gerraty static void 382956e45f6SSimon J. Gerraty PrintNodeNamesLine(const char *label, GNodeList *gnodes) 3833955d011SMarcel Moolenaar { 384956e45f6SSimon J. Gerraty if (Lst_IsEmpty(gnodes)) 385956e45f6SSimon J. Gerraty return; 386956e45f6SSimon J. Gerraty debug_printf("# %s:", label); 387956e45f6SSimon J. Gerraty PrintNodeNames(gnodes); 388956e45f6SSimon J. Gerraty debug_printf("\n"); 389956e45f6SSimon J. Gerraty } 390956e45f6SSimon J. Gerraty 391956e45f6SSimon J. Gerraty void 392956e45f6SSimon J. Gerraty Targ_PrintCmds(GNode *gn) 393956e45f6SSimon J. Gerraty { 394956e45f6SSimon J. Gerraty StringListNode *ln; 39506b9b3e0SSimon J. Gerraty 39606b9b3e0SSimon J. Gerraty for (ln = gn->commands.first; ln != NULL; ln = ln->next) { 397956e45f6SSimon J. Gerraty const char *cmd = ln->datum; 398956e45f6SSimon J. Gerraty debug_printf("\t%s\n", cmd); 399956e45f6SSimon J. Gerraty } 4003955d011SMarcel Moolenaar } 4013955d011SMarcel Moolenaar 40206b9b3e0SSimon J. Gerraty /* 40306b9b3e0SSimon J. Gerraty * Format a modification time in some reasonable way and return it. 40406b9b3e0SSimon J. Gerraty * The formatted time is placed in a static area, so it is overwritten 40506b9b3e0SSimon J. Gerraty * with each call. 40606b9b3e0SSimon J. Gerraty */ 40706b9b3e0SSimon J. Gerraty const char * 4083955d011SMarcel Moolenaar Targ_FmtTime(time_t tm) 4093955d011SMarcel Moolenaar { 4103955d011SMarcel Moolenaar static char buf[128]; 4113955d011SMarcel Moolenaar 41206b9b3e0SSimon J. Gerraty struct tm *parts = localtime(&tm); 4133955d011SMarcel Moolenaar (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); 4143841c287SSimon J. Gerraty return buf; 4153955d011SMarcel Moolenaar } 4163955d011SMarcel Moolenaar 4172c3632d1SSimon J. Gerraty /* Print out a type field giving only those attributes the user can set. */ 4183955d011SMarcel Moolenaar void 4193955d011SMarcel Moolenaar Targ_PrintType(int type) 4203955d011SMarcel Moolenaar { 4213955d011SMarcel Moolenaar int tbit; 4223955d011SMarcel Moolenaar 4233955d011SMarcel Moolenaar type &= ~OP_OPMASK; 4243955d011SMarcel Moolenaar 42506b9b3e0SSimon J. Gerraty while (type != 0) { 4263955d011SMarcel Moolenaar tbit = 1 << (ffs(type) - 1); 4273955d011SMarcel Moolenaar type &= ~tbit; 4283955d011SMarcel Moolenaar 4293955d011SMarcel Moolenaar switch (tbit) { 43006b9b3e0SSimon J. Gerraty #define PRINTBIT(bit, attr) case bit: debug_printf(" " attr); break 43106b9b3e0SSimon J. Gerraty #define PRINTDBIT(bit, attr) case bit: DEBUG0(TARG, " " attr); break 43206b9b3e0SSimon J. Gerraty PRINTBIT(OP_OPTIONAL, ".OPTIONAL"); 43306b9b3e0SSimon J. Gerraty PRINTBIT(OP_USE, ".USE"); 43406b9b3e0SSimon J. Gerraty PRINTBIT(OP_EXEC, ".EXEC"); 43506b9b3e0SSimon J. Gerraty PRINTBIT(OP_IGNORE, ".IGNORE"); 43606b9b3e0SSimon J. Gerraty PRINTBIT(OP_PRECIOUS, ".PRECIOUS"); 43706b9b3e0SSimon J. Gerraty PRINTBIT(OP_SILENT, ".SILENT"); 43806b9b3e0SSimon J. Gerraty PRINTBIT(OP_MAKE, ".MAKE"); 43906b9b3e0SSimon J. Gerraty PRINTBIT(OP_JOIN, ".JOIN"); 44006b9b3e0SSimon J. Gerraty PRINTBIT(OP_INVISIBLE, ".INVISIBLE"); 44106b9b3e0SSimon J. Gerraty PRINTBIT(OP_NOTMAIN, ".NOTMAIN"); 44206b9b3e0SSimon J. Gerraty PRINTDBIT(OP_LIB, ".LIB"); 44306b9b3e0SSimon J. Gerraty PRINTDBIT(OP_MEMBER, ".MEMBER"); 44406b9b3e0SSimon J. Gerraty PRINTDBIT(OP_ARCHV, ".ARCHV"); 44506b9b3e0SSimon J. Gerraty PRINTDBIT(OP_MADE, ".MADE"); 44606b9b3e0SSimon J. Gerraty PRINTDBIT(OP_PHONY, ".PHONY"); 44706b9b3e0SSimon J. Gerraty #undef PRINTBIT 44806b9b3e0SSimon J. Gerraty #undef PRINTDBIT 4493955d011SMarcel Moolenaar } 4503955d011SMarcel Moolenaar } 4513955d011SMarcel Moolenaar } 4523955d011SMarcel Moolenaar 453*dba7b0efSSimon J. Gerraty const char * 454*dba7b0efSSimon J. Gerraty GNodeMade_Name(GNodeMade made) 4553955d011SMarcel Moolenaar { 4563955d011SMarcel Moolenaar switch (made) { 4573955d011SMarcel Moolenaar case UNMADE: return "unmade"; 4583955d011SMarcel Moolenaar case DEFERRED: return "deferred"; 4593955d011SMarcel Moolenaar case REQUESTED: return "requested"; 4603955d011SMarcel Moolenaar case BEINGMADE: return "being made"; 4613955d011SMarcel Moolenaar case MADE: return "made"; 4623955d011SMarcel Moolenaar case UPTODATE: return "up-to-date"; 4633955d011SMarcel Moolenaar case ERROR: return "error when made"; 4643955d011SMarcel Moolenaar case ABORTED: return "aborted"; 4653955d011SMarcel Moolenaar default: return "unknown enum_made value"; 4663955d011SMarcel Moolenaar } 4673955d011SMarcel Moolenaar } 4683955d011SMarcel Moolenaar 469956e45f6SSimon J. Gerraty static const char * 470956e45f6SSimon J. Gerraty GNode_OpName(const GNode *gn) 4713955d011SMarcel Moolenaar { 472956e45f6SSimon J. Gerraty switch (gn->type & OP_OPMASK) { 473956e45f6SSimon J. Gerraty case OP_DEPENDS: 474956e45f6SSimon J. Gerraty return ":"; 475956e45f6SSimon J. Gerraty case OP_FORCE: 476956e45f6SSimon J. Gerraty return "!"; 477956e45f6SSimon J. Gerraty case OP_DOUBLEDEP: 478956e45f6SSimon J. Gerraty return "::"; 479956e45f6SSimon J. Gerraty } 480956e45f6SSimon J. Gerraty return ""; 481956e45f6SSimon J. Gerraty } 4823955d011SMarcel Moolenaar 483956e45f6SSimon J. Gerraty /* Print the contents of a node. */ 484956e45f6SSimon J. Gerraty void 485956e45f6SSimon J. Gerraty Targ_PrintNode(GNode *gn, int pass) 486956e45f6SSimon J. Gerraty { 487956e45f6SSimon J. Gerraty debug_printf("# %s%s", gn->name, gn->cohort_num); 488956e45f6SSimon J. Gerraty GNode_FprintDetails(opts.debug_file, ", ", gn, "\n"); 4893955d011SMarcel Moolenaar if (gn->flags == 0) 490956e45f6SSimon J. Gerraty return; 4913955d011SMarcel Moolenaar 49206b9b3e0SSimon J. Gerraty if (!GNode_IsTarget(gn)) 49306b9b3e0SSimon J. Gerraty return; 49406b9b3e0SSimon J. Gerraty 495956e45f6SSimon J. Gerraty debug_printf("#\n"); 49606b9b3e0SSimon J. Gerraty if (gn == mainTarg) 497956e45f6SSimon J. Gerraty debug_printf("# *** MAIN TARGET ***\n"); 49806b9b3e0SSimon J. Gerraty 4993955d011SMarcel Moolenaar if (pass >= 2) { 50006b9b3e0SSimon J. Gerraty if (gn->unmade > 0) 501956e45f6SSimon J. Gerraty debug_printf("# %d unmade children\n", gn->unmade); 50206b9b3e0SSimon J. Gerraty else 503956e45f6SSimon J. Gerraty debug_printf("# No unmade children\n"); 5043955d011SMarcel Moolenaar if (!(gn->type & (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC))) { 5053955d011SMarcel Moolenaar if (gn->mtime != 0) { 506956e45f6SSimon J. Gerraty debug_printf("# last modified %s: %s\n", 5073955d011SMarcel Moolenaar Targ_FmtTime(gn->mtime), 508*dba7b0efSSimon J. Gerraty GNodeMade_Name(gn->made)); 5093955d011SMarcel Moolenaar } else if (gn->made != UNMADE) { 51006b9b3e0SSimon J. Gerraty debug_printf("# nonexistent (maybe): %s\n", 511*dba7b0efSSimon J. Gerraty GNodeMade_Name(gn->made)); 51206b9b3e0SSimon J. Gerraty } else 513956e45f6SSimon J. Gerraty debug_printf("# unmade\n"); 5143955d011SMarcel Moolenaar } 51506b9b3e0SSimon J. Gerraty PrintNodeNamesLine("implicit parents", &gn->implicitParents); 5163955d011SMarcel Moolenaar } else { 51706b9b3e0SSimon J. Gerraty if (gn->unmade != 0) 518956e45f6SSimon J. Gerraty debug_printf("# %d unmade children\n", gn->unmade); 5193955d011SMarcel Moolenaar } 52006b9b3e0SSimon J. Gerraty 52106b9b3e0SSimon J. Gerraty PrintNodeNamesLine("parents", &gn->parents); 52206b9b3e0SSimon J. Gerraty PrintNodeNamesLine("order_pred", &gn->order_pred); 52306b9b3e0SSimon J. Gerraty PrintNodeNamesLine("order_succ", &gn->order_succ); 5243955d011SMarcel Moolenaar 525956e45f6SSimon J. Gerraty debug_printf("%-16s%s", gn->name, GNode_OpName(gn)); 5263955d011SMarcel Moolenaar Targ_PrintType(gn->type); 52706b9b3e0SSimon J. Gerraty PrintNodeNames(&gn->children); 528956e45f6SSimon J. Gerraty debug_printf("\n"); 529956e45f6SSimon J. Gerraty Targ_PrintCmds(gn); 530956e45f6SSimon J. Gerraty debug_printf("\n\n"); 53106b9b3e0SSimon J. Gerraty if (gn->type & OP_DOUBLEDEP) 53206b9b3e0SSimon J. Gerraty Targ_PrintNodes(&gn->cohorts, pass); 5333955d011SMarcel Moolenaar } 5343955d011SMarcel Moolenaar 535956e45f6SSimon J. Gerraty void 536956e45f6SSimon J. Gerraty Targ_PrintNodes(GNodeList *gnodes, int pass) 5373955d011SMarcel Moolenaar { 538956e45f6SSimon J. Gerraty GNodeListNode *ln; 53906b9b3e0SSimon J. Gerraty 540956e45f6SSimon J. Gerraty for (ln = gnodes->first; ln != NULL; ln = ln->next) 541956e45f6SSimon J. Gerraty Targ_PrintNode(ln->datum, pass); 542956e45f6SSimon J. Gerraty } 5433955d011SMarcel Moolenaar 544956e45f6SSimon J. Gerraty /* Print only those targets that are just a source. */ 545956e45f6SSimon J. Gerraty static void 546956e45f6SSimon J. Gerraty PrintOnlySources(void) 547956e45f6SSimon J. Gerraty { 548956e45f6SSimon J. Gerraty GNodeListNode *ln; 549956e45f6SSimon J. Gerraty 55006b9b3e0SSimon J. Gerraty for (ln = allTargets.first; ln != NULL; ln = ln->next) { 551956e45f6SSimon J. Gerraty GNode *gn = ln->datum; 552956e45f6SSimon J. Gerraty if (GNode_IsTarget(gn)) 553956e45f6SSimon J. Gerraty continue; 554956e45f6SSimon J. Gerraty 555956e45f6SSimon J. Gerraty debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn)); 5563955d011SMarcel Moolenaar Targ_PrintType(gn->type); 557956e45f6SSimon J. Gerraty debug_printf("\n"); 558956e45f6SSimon J. Gerraty } 5593955d011SMarcel Moolenaar } 5603955d011SMarcel Moolenaar 56106b9b3e0SSimon J. Gerraty /* 56206b9b3e0SSimon J. Gerraty * Input: 5632c3632d1SSimon J. Gerraty * pass 1 => before processing 5642c3632d1SSimon J. Gerraty * 2 => after processing 5652c3632d1SSimon J. Gerraty * 3 => after processing, an error occurred 5663955d011SMarcel Moolenaar */ 5673955d011SMarcel Moolenaar void 5683955d011SMarcel Moolenaar Targ_PrintGraph(int pass) 5693955d011SMarcel Moolenaar { 570956e45f6SSimon J. Gerraty debug_printf("#*** Input graph:\n"); 57106b9b3e0SSimon J. Gerraty Targ_PrintNodes(&allTargets, pass); 572e2eeea75SSimon J. Gerraty debug_printf("\n"); 573e2eeea75SSimon J. Gerraty debug_printf("\n"); 574e2eeea75SSimon J. Gerraty 575e2eeea75SSimon J. Gerraty debug_printf("#\n"); 576e2eeea75SSimon J. Gerraty debug_printf("# Files that are only sources:\n"); 577956e45f6SSimon J. Gerraty PrintOnlySources(); 578e2eeea75SSimon J. Gerraty 579956e45f6SSimon J. Gerraty debug_printf("#*** Global Variables:\n"); 580*dba7b0efSSimon J. Gerraty Var_Dump(SCOPE_GLOBAL); 581e2eeea75SSimon J. Gerraty 582956e45f6SSimon J. Gerraty debug_printf("#*** Command-line Variables:\n"); 583*dba7b0efSSimon J. Gerraty Var_Dump(SCOPE_CMDLINE); 584e2eeea75SSimon J. Gerraty 585956e45f6SSimon J. Gerraty debug_printf("\n"); 5863955d011SMarcel Moolenaar Dir_PrintDirectories(); 587956e45f6SSimon J. Gerraty debug_printf("\n"); 588e2eeea75SSimon J. Gerraty 5893955d011SMarcel Moolenaar Suff_PrintAll(); 5903955d011SMarcel Moolenaar } 5913955d011SMarcel Moolenaar 59206b9b3e0SSimon J. Gerraty /* 59306b9b3e0SSimon J. Gerraty * Propagate some type information to cohort nodes (those from the '::' 5942c3632d1SSimon J. Gerraty * dependency operator). 5953955d011SMarcel Moolenaar * 5962c3632d1SSimon J. Gerraty * Should be called after the makefiles are parsed but before any action is 59706b9b3e0SSimon J. Gerraty * taken. 59806b9b3e0SSimon J. Gerraty */ 5993955d011SMarcel Moolenaar void 6003955d011SMarcel Moolenaar Targ_Propagate(void) 6013955d011SMarcel Moolenaar { 602956e45f6SSimon J. Gerraty GNodeListNode *ln, *cln; 6032c3632d1SSimon J. Gerraty 60406b9b3e0SSimon J. Gerraty for (ln = allTargets.first; ln != NULL; ln = ln->next) { 605956e45f6SSimon J. Gerraty GNode *gn = ln->datum; 606956e45f6SSimon J. Gerraty GNodeType type = gn->type; 6072c3632d1SSimon J. Gerraty 608956e45f6SSimon J. Gerraty if (!(type & OP_DOUBLEDEP)) 6092c3632d1SSimon J. Gerraty continue; 6102c3632d1SSimon J. Gerraty 61106b9b3e0SSimon J. Gerraty for (cln = gn->cohorts.first; cln != NULL; cln = cln->next) { 612956e45f6SSimon J. Gerraty GNode *cohort = cln->datum; 6132c3632d1SSimon J. Gerraty 614956e45f6SSimon J. Gerraty cohort->type |= type & ~OP_OPMASK; 6152c3632d1SSimon J. Gerraty } 6162c3632d1SSimon J. Gerraty } 6173955d011SMarcel Moolenaar } 618