1*e2eeea75SSimon J. Gerraty /* $NetBSD: targ.c,v 1.135 2020/11/16 22:28:44 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 71*e2eeea75SSimon J. Gerraty /* 72*e2eeea75SSimon J. Gerraty * Maintaining the targets and sources, which are both implemented as GNode. 733955d011SMarcel Moolenaar * 743955d011SMarcel Moolenaar * Interface: 75*e2eeea75SSimon J. Gerraty * Targ_Init Initialize the module. 763955d011SMarcel Moolenaar * 77*e2eeea75SSimon 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*e2eeea75SSimon 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_Ignore Return TRUE if errors should be ignored when 973955d011SMarcel Moolenaar * creating the given target. 983955d011SMarcel Moolenaar * 993955d011SMarcel Moolenaar * Targ_Silent Return TRUE if we should be silent when 1003955d011SMarcel Moolenaar * creating the given target. 1013955d011SMarcel Moolenaar * 1023955d011SMarcel Moolenaar * Targ_Precious Return TRUE if the target is precious and 1033955d011SMarcel Moolenaar * should not be removed if we are interrupted. 1043955d011SMarcel Moolenaar * 105956e45f6SSimon J. Gerraty * Targ_Propagate Propagate information between related nodes. 106956e45f6SSimon J. Gerraty * Should be called after the makefiles are parsed 107956e45f6SSimon J. Gerraty * but before any action is taken. 1083955d011SMarcel Moolenaar * 1093955d011SMarcel Moolenaar * Debugging: 110956e45f6SSimon J. Gerraty * Targ_PrintGraph 111956e45f6SSimon J. Gerraty * Print out the entire graphm all variables and 112956e45f6SSimon J. Gerraty * statistics for the directory cache. Should print 113956e45f6SSimon J. Gerraty * something for suffixes, too, but... 1143955d011SMarcel Moolenaar */ 1153955d011SMarcel Moolenaar 1163955d011SMarcel Moolenaar #include <time.h> 1173955d011SMarcel Moolenaar 1183955d011SMarcel Moolenaar #include "make.h" 1193955d011SMarcel Moolenaar #include "dir.h" 1203955d011SMarcel Moolenaar 121956e45f6SSimon J. Gerraty /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */ 122*e2eeea75SSimon J. Gerraty MAKE_RCSID("$NetBSD: targ.c,v 1.135 2020/11/16 22:28:44 rillig Exp $"); 1233955d011SMarcel Moolenaar 124*e2eeea75SSimon J. Gerraty /* All target nodes found so far, but not the source nodes. */ 125*e2eeea75SSimon J. Gerraty static GNodeList *allTargets; 126*e2eeea75SSimon J. Gerraty static HashTable allTargetsByName; 127956e45f6SSimon J. Gerraty 1283955d011SMarcel Moolenaar #ifdef CLEANUP 129*e2eeea75SSimon J. Gerraty static GNodeList *allNodes; 130*e2eeea75SSimon J. Gerraty 131*e2eeea75SSimon J. Gerraty static void GNode_Free(void *); 1323955d011SMarcel Moolenaar #endif 1333955d011SMarcel Moolenaar 1343955d011SMarcel Moolenaar void 1353955d011SMarcel Moolenaar Targ_Init(void) 1363955d011SMarcel Moolenaar { 137956e45f6SSimon J. Gerraty allTargets = Lst_New(); 138*e2eeea75SSimon J. Gerraty HashTable_Init(&allTargetsByName); 139*e2eeea75SSimon J. Gerraty #ifdef CLEANUP 140*e2eeea75SSimon J. Gerraty allNodes = Lst_New(); 141*e2eeea75SSimon J. Gerraty #endif 1423955d011SMarcel Moolenaar } 1433955d011SMarcel Moolenaar 1443955d011SMarcel Moolenaar void 1453955d011SMarcel Moolenaar Targ_End(void) 1463955d011SMarcel Moolenaar { 1472c3632d1SSimon J. Gerraty Targ_Stats(); 1483955d011SMarcel Moolenaar #ifdef CLEANUP 1492c3632d1SSimon J. Gerraty Lst_Free(allTargets); 150*e2eeea75SSimon J. Gerraty HashTable_Done(&allTargetsByName); 151*e2eeea75SSimon J. Gerraty Lst_Destroy(allNodes, GNode_Free); 1523955d011SMarcel Moolenaar #endif 1533955d011SMarcel Moolenaar } 1543955d011SMarcel Moolenaar 1552c3632d1SSimon J. Gerraty void 1562c3632d1SSimon J. Gerraty Targ_Stats(void) 1572c3632d1SSimon J. Gerraty { 158*e2eeea75SSimon J. Gerraty HashTable_DebugStats(&allTargetsByName, "targets"); 1592c3632d1SSimon J. Gerraty } 1602c3632d1SSimon J. Gerraty 161*e2eeea75SSimon J. Gerraty /* 162*e2eeea75SSimon J. Gerraty * Return the list of all targets, which are all nodes that appear on the 163*e2eeea75SSimon J. Gerraty * left-hand side of a dependency declaration such as "target: source". 164*e2eeea75SSimon J. Gerraty * The returned list does not contain pure sources. 165*e2eeea75SSimon J. Gerraty */ 166956e45f6SSimon J. Gerraty GNodeList * 1673955d011SMarcel Moolenaar Targ_List(void) 1683955d011SMarcel Moolenaar { 1693955d011SMarcel Moolenaar return allTargets; 1703955d011SMarcel Moolenaar } 1713955d011SMarcel Moolenaar 172*e2eeea75SSimon J. Gerraty /* Create a new graph node, but don't register it anywhere. 1733955d011SMarcel Moolenaar * 174*e2eeea75SSimon J. Gerraty * Graph nodes that appear on the left-hand side of a dependency line such 175*e2eeea75SSimon J. Gerraty * as "target: source" are called targets. XXX: In some cases (like the 176*e2eeea75SSimon J. Gerraty * .ALLTARGETS variable), all nodes are called targets as well, even if they 177*e2eeea75SSimon J. Gerraty * never appear on the left-hand side. This is a mistake. 178*e2eeea75SSimon J. Gerraty * 179*e2eeea75SSimon J. Gerraty * Typical names for graph nodes are: 180*e2eeea75SSimon J. Gerraty * "src.c" (an ordinary file) 181*e2eeea75SSimon J. Gerraty * "clean" (a .PHONY target) 182*e2eeea75SSimon J. Gerraty * ".END" (a special hook target) 183*e2eeea75SSimon J. Gerraty * "-lm" (a library) 184*e2eeea75SSimon J. Gerraty * "libc.a(isspace.o)" (an archive member) 1853955d011SMarcel Moolenaar */ 1863955d011SMarcel Moolenaar GNode * 187*e2eeea75SSimon J. Gerraty GNode_New(const char *name) 1883955d011SMarcel Moolenaar { 1893955d011SMarcel Moolenaar GNode *gn; 1903955d011SMarcel Moolenaar 191*e2eeea75SSimon J. Gerraty gn = bmake_malloc(sizeof *gn); 1923955d011SMarcel Moolenaar gn->name = bmake_strdup(name); 1933955d011SMarcel Moolenaar gn->uname = NULL; 1943955d011SMarcel Moolenaar gn->path = NULL; 1952c3632d1SSimon J. Gerraty gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : 0; 1963955d011SMarcel Moolenaar gn->flags = 0; 197*e2eeea75SSimon J. Gerraty gn->made = UNMADE; 198*e2eeea75SSimon J. Gerraty gn->unmade = 0; 1993955d011SMarcel Moolenaar gn->mtime = 0; 200956e45f6SSimon J. Gerraty gn->youngestChild = NULL; 201956e45f6SSimon J. Gerraty gn->implicitParents = Lst_New(); 202956e45f6SSimon J. Gerraty gn->parents = Lst_New(); 203956e45f6SSimon J. Gerraty gn->children = Lst_New(); 204956e45f6SSimon J. Gerraty gn->order_pred = Lst_New(); 205956e45f6SSimon J. Gerraty gn->order_succ = Lst_New(); 206*e2eeea75SSimon J. Gerraty gn->cohorts = Lst_New(); 207*e2eeea75SSimon J. Gerraty gn->cohort_num[0] = '\0'; 208*e2eeea75SSimon J. Gerraty gn->unmade_cohorts = 0; 209*e2eeea75SSimon J. Gerraty gn->centurion = NULL; 210*e2eeea75SSimon J. Gerraty gn->checked_seqno = 0; 211956e45f6SSimon J. Gerraty HashTable_Init(&gn->context); 212956e45f6SSimon J. Gerraty gn->commands = Lst_New(); 2133955d011SMarcel Moolenaar gn->suffix = NULL; 2143955d011SMarcel Moolenaar gn->fname = NULL; 2152c3632d1SSimon J. Gerraty gn->lineno = 0; 2163955d011SMarcel Moolenaar 2173955d011SMarcel Moolenaar #ifdef CLEANUP 218*e2eeea75SSimon J. Gerraty Lst_Append(allNodes, gn); 2193955d011SMarcel Moolenaar #endif 2203955d011SMarcel Moolenaar 2213841c287SSimon J. Gerraty return gn; 2223955d011SMarcel Moolenaar } 2233955d011SMarcel Moolenaar 2243955d011SMarcel Moolenaar #ifdef CLEANUP 2253955d011SMarcel Moolenaar static void 226*e2eeea75SSimon J. Gerraty GNode_Free(void *gnp) 2273955d011SMarcel Moolenaar { 228956e45f6SSimon J. Gerraty GNode *gn = gnp; 2293955d011SMarcel Moolenaar 2303955d011SMarcel Moolenaar free(gn->name); 2313955d011SMarcel Moolenaar free(gn->uname); 2323955d011SMarcel Moolenaar free(gn->path); 233*e2eeea75SSimon J. Gerraty /* gn->youngestChild is not owned by this node. */ 234*e2eeea75SSimon J. Gerraty Lst_Free(gn->implicitParents); /* ... but not the nodes themselves, */ 235*e2eeea75SSimon J. Gerraty Lst_Free(gn->parents); /* as they are not owned by this node. */ 236*e2eeea75SSimon J. Gerraty Lst_Free(gn->children); /* likewise */ 237*e2eeea75SSimon J. Gerraty Lst_Free(gn->order_pred); /* likewise */ 238*e2eeea75SSimon J. Gerraty Lst_Free(gn->order_succ); /* likewise */ 239*e2eeea75SSimon J. Gerraty Lst_Free(gn->cohorts); /* likewise */ 240*e2eeea75SSimon J. Gerraty HashTable_Done(&gn->context); /* ... but not the variables themselves, 241*e2eeea75SSimon J. Gerraty * even though they are owned by this node. 242*e2eeea75SSimon J. Gerraty * XXX: they should probably be freed. */ 243*e2eeea75SSimon J. Gerraty Lst_Free(gn->commands); /* ... but not the commands themselves, 244*e2eeea75SSimon J. Gerraty * as they may be shared with other nodes. */ 245*e2eeea75SSimon J. Gerraty /* gn->suffix is not owned by this node. */ 246*e2eeea75SSimon J. Gerraty /* XXX: gn->suffix should be unreferenced here. This requires a thorough 247*e2eeea75SSimon J. Gerraty * check that the reference counting is done correctly in all places, 248*e2eeea75SSimon J. Gerraty * otherwise a suffix might be freed too early. */ 2493955d011SMarcel Moolenaar 2503955d011SMarcel Moolenaar free(gn); 2513955d011SMarcel Moolenaar } 2523955d011SMarcel Moolenaar #endif 2533955d011SMarcel Moolenaar 254956e45f6SSimon J. Gerraty /* Get the existing global node, or return NULL. */ 2553955d011SMarcel Moolenaar GNode * 256956e45f6SSimon J. Gerraty Targ_FindNode(const char *name) 2573955d011SMarcel Moolenaar { 258*e2eeea75SSimon J. Gerraty return HashTable_FindValue(&allTargetsByName, name); 2593955d011SMarcel Moolenaar } 2603955d011SMarcel Moolenaar 261956e45f6SSimon J. Gerraty /* Get the existing global node, or create it. */ 262956e45f6SSimon J. Gerraty GNode * 263956e45f6SSimon J. Gerraty Targ_GetNode(const char *name) 264956e45f6SSimon J. Gerraty { 265956e45f6SSimon J. Gerraty Boolean isNew; 266*e2eeea75SSimon J. Gerraty HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew); 2673955d011SMarcel Moolenaar if (!isNew) 268956e45f6SSimon J. Gerraty return HashEntry_Get(he); 269956e45f6SSimon J. Gerraty 270956e45f6SSimon J. Gerraty { 271956e45f6SSimon J. Gerraty GNode *gn = Targ_NewInternalNode(name); 272956e45f6SSimon J. Gerraty HashEntry_Set(he, gn); 273956e45f6SSimon J. Gerraty return gn; 274956e45f6SSimon J. Gerraty } 2753955d011SMarcel Moolenaar } 2763955d011SMarcel Moolenaar 277*e2eeea75SSimon J. Gerraty /* 278*e2eeea75SSimon J. Gerraty * Create a node, register it in .ALLTARGETS but don't store it in the 279956e45f6SSimon J. Gerraty * table of global nodes. This means it cannot be found by name. 280956e45f6SSimon J. Gerraty * 281*e2eeea75SSimon J. Gerraty * This is used for internal nodes, such as cohorts or .WAIT nodes. 282*e2eeea75SSimon J. Gerraty */ 283956e45f6SSimon J. Gerraty GNode * 284956e45f6SSimon J. Gerraty Targ_NewInternalNode(const char *name) 285956e45f6SSimon J. Gerraty { 286*e2eeea75SSimon J. Gerraty GNode *gn = GNode_New(name); 2873955d011SMarcel Moolenaar Var_Append(".ALLTARGETS", name, VAR_GLOBAL); 2882c3632d1SSimon J. Gerraty Lst_Append(allTargets, gn); 2893955d011SMarcel Moolenaar if (doing_depend) 2903955d011SMarcel Moolenaar gn->flags |= FROM_DEPEND; 2913955d011SMarcel Moolenaar return gn; 2923955d011SMarcel Moolenaar } 2933955d011SMarcel Moolenaar 294*e2eeea75SSimon J. Gerraty /* 295*e2eeea75SSimon J. Gerraty * Return the .END node, which contains the commands to be run when 296*e2eeea75SSimon J. Gerraty * everything else has been made. 297*e2eeea75SSimon J. Gerraty */ 298956e45f6SSimon J. Gerraty GNode *Targ_GetEndNode(void) 2993955d011SMarcel Moolenaar { 300956e45f6SSimon J. Gerraty /* Save the node locally to avoid having to search for it all the time. */ 301956e45f6SSimon J. Gerraty static GNode *endNode = NULL; 302956e45f6SSimon J. Gerraty if (endNode == NULL) { 303956e45f6SSimon J. Gerraty endNode = Targ_GetNode(".END"); 304956e45f6SSimon J. Gerraty endNode->type = OP_SPECIAL; 305956e45f6SSimon J. Gerraty } 306956e45f6SSimon J. Gerraty return endNode; 307956e45f6SSimon J. Gerraty } 3083955d011SMarcel Moolenaar 309956e45f6SSimon J. Gerraty /* Return the named nodes, creating them as necessary. */ 310956e45f6SSimon J. Gerraty GNodeList * 311956e45f6SSimon J. Gerraty Targ_FindList(StringList *names) 312956e45f6SSimon J. Gerraty { 313956e45f6SSimon J. Gerraty StringListNode *ln; 314956e45f6SSimon J. Gerraty GNodeList *nodes = Lst_New(); 315956e45f6SSimon J. Gerraty for (ln = names->first; ln != NULL; ln = ln->next) { 316956e45f6SSimon J. Gerraty const char *name = ln->datum; 317956e45f6SSimon J. Gerraty GNode *gn = Targ_GetNode(name); 3182c3632d1SSimon J. Gerraty Lst_Append(nodes, gn); 3193955d011SMarcel Moolenaar } 3203841c287SSimon J. Gerraty return nodes; 3213955d011SMarcel Moolenaar } 3223955d011SMarcel Moolenaar 3232c3632d1SSimon J. Gerraty /* Return true if should ignore errors when creating gn. */ 3243955d011SMarcel Moolenaar Boolean 325*e2eeea75SSimon J. Gerraty Targ_Ignore(const GNode *gn) 3263955d011SMarcel Moolenaar { 327956e45f6SSimon J. Gerraty return opts.ignoreErrors || gn->type & OP_IGNORE; 3283955d011SMarcel Moolenaar } 3293955d011SMarcel Moolenaar 3302c3632d1SSimon J. Gerraty /* Return true if be silent when creating gn. */ 3313955d011SMarcel Moolenaar Boolean 332*e2eeea75SSimon J. Gerraty Targ_Silent(const GNode *gn) 3333955d011SMarcel Moolenaar { 334956e45f6SSimon J. Gerraty return opts.beSilent || gn->type & OP_SILENT; 3353955d011SMarcel Moolenaar } 3363955d011SMarcel Moolenaar 3372c3632d1SSimon J. Gerraty /* See if the given target is precious. */ 3383955d011SMarcel Moolenaar Boolean 339*e2eeea75SSimon J. Gerraty Targ_Precious(const GNode *gn) 3403955d011SMarcel Moolenaar { 341*e2eeea75SSimon J. Gerraty /* XXX: Why are '::' targets precious? */ 3422c3632d1SSimon J. Gerraty return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP); 3433955d011SMarcel Moolenaar } 3443955d011SMarcel Moolenaar 345*e2eeea75SSimon J. Gerraty /* 346*e2eeea75SSimon J. Gerraty * The main target to be made; only for debugging output. 347*e2eeea75SSimon J. Gerraty * See mainNode in parse.c for the definitive source. 348*e2eeea75SSimon J. Gerraty */ 349*e2eeea75SSimon J. Gerraty static GNode *mainTarg; 3503955d011SMarcel Moolenaar 351*e2eeea75SSimon J. Gerraty /* Remember the main target to make; only used for debugging. */ 3523955d011SMarcel Moolenaar void 3533955d011SMarcel Moolenaar Targ_SetMain(GNode *gn) 3543955d011SMarcel Moolenaar { 3553955d011SMarcel Moolenaar mainTarg = gn; 3563955d011SMarcel Moolenaar } 3573955d011SMarcel Moolenaar 358956e45f6SSimon J. Gerraty static void 359956e45f6SSimon J. Gerraty PrintNodeNames(GNodeList *gnodes) 3603955d011SMarcel Moolenaar { 361956e45f6SSimon J. Gerraty GNodeListNode *node; 3623955d011SMarcel Moolenaar 363956e45f6SSimon J. Gerraty for (node = gnodes->first; node != NULL; node = node->next) { 364956e45f6SSimon J. Gerraty GNode *gn = node->datum; 365956e45f6SSimon J. Gerraty debug_printf(" %s%s", gn->name, gn->cohort_num); 366956e45f6SSimon J. Gerraty } 3673955d011SMarcel Moolenaar } 3683955d011SMarcel Moolenaar 369956e45f6SSimon J. Gerraty static void 370956e45f6SSimon J. Gerraty PrintNodeNamesLine(const char *label, GNodeList *gnodes) 3713955d011SMarcel Moolenaar { 372956e45f6SSimon J. Gerraty if (Lst_IsEmpty(gnodes)) 373956e45f6SSimon J. Gerraty return; 374956e45f6SSimon J. Gerraty debug_printf("# %s:", label); 375956e45f6SSimon J. Gerraty PrintNodeNames(gnodes); 376956e45f6SSimon J. Gerraty debug_printf("\n"); 377956e45f6SSimon J. Gerraty } 378956e45f6SSimon J. Gerraty 379956e45f6SSimon J. Gerraty void 380956e45f6SSimon J. Gerraty Targ_PrintCmds(GNode *gn) 381956e45f6SSimon J. Gerraty { 382956e45f6SSimon J. Gerraty StringListNode *ln; 383956e45f6SSimon J. Gerraty for (ln = gn->commands->first; ln != NULL; ln = ln->next) { 384956e45f6SSimon J. Gerraty const char *cmd = ln->datum; 385956e45f6SSimon J. Gerraty debug_printf("\t%s\n", cmd); 386956e45f6SSimon J. Gerraty } 3873955d011SMarcel Moolenaar } 3883955d011SMarcel Moolenaar 3892c3632d1SSimon J. Gerraty /* Format a modification time in some reasonable way and return it. 3902c3632d1SSimon J. Gerraty * The time is placed in a static area, so it is overwritten with each call. */ 3913955d011SMarcel Moolenaar char * 3923955d011SMarcel Moolenaar Targ_FmtTime(time_t tm) 3933955d011SMarcel Moolenaar { 3943955d011SMarcel Moolenaar struct tm *parts; 3953955d011SMarcel Moolenaar static char buf[128]; 3963955d011SMarcel Moolenaar 3973955d011SMarcel Moolenaar parts = localtime(&tm); 3983955d011SMarcel Moolenaar (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); 3993841c287SSimon J. Gerraty return buf; 4003955d011SMarcel Moolenaar } 4013955d011SMarcel Moolenaar 4022c3632d1SSimon J. Gerraty /* Print out a type field giving only those attributes the user can set. */ 4033955d011SMarcel Moolenaar void 4043955d011SMarcel Moolenaar Targ_PrintType(int type) 4053955d011SMarcel Moolenaar { 4063955d011SMarcel Moolenaar int tbit; 4073955d011SMarcel Moolenaar 408956e45f6SSimon J. Gerraty #define PRINTBIT(attr) case CONCAT(OP_,attr): debug_printf(" ." #attr); break 409956e45f6SSimon J. Gerraty #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))debug_printf(" ." #attr); break 4103955d011SMarcel Moolenaar 4113955d011SMarcel Moolenaar type &= ~OP_OPMASK; 4123955d011SMarcel Moolenaar 4133955d011SMarcel Moolenaar while (type) { 4143955d011SMarcel Moolenaar tbit = 1 << (ffs(type) - 1); 4153955d011SMarcel Moolenaar type &= ~tbit; 4163955d011SMarcel Moolenaar 4173955d011SMarcel Moolenaar switch(tbit) { 4183955d011SMarcel Moolenaar PRINTBIT(OPTIONAL); 4193955d011SMarcel Moolenaar PRINTBIT(USE); 4203955d011SMarcel Moolenaar PRINTBIT(EXEC); 4213955d011SMarcel Moolenaar PRINTBIT(IGNORE); 4223955d011SMarcel Moolenaar PRINTBIT(PRECIOUS); 4233955d011SMarcel Moolenaar PRINTBIT(SILENT); 4243955d011SMarcel Moolenaar PRINTBIT(MAKE); 4253955d011SMarcel Moolenaar PRINTBIT(JOIN); 4263955d011SMarcel Moolenaar PRINTBIT(INVISIBLE); 4273955d011SMarcel Moolenaar PRINTBIT(NOTMAIN); 4283955d011SMarcel Moolenaar PRINTDBIT(LIB); 4293955d011SMarcel Moolenaar /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ 430956e45f6SSimon J. Gerraty case OP_MEMBER: if (DEBUG(TARG))debug_printf(" .MEMBER"); break; 4313955d011SMarcel Moolenaar PRINTDBIT(ARCHV); 4323955d011SMarcel Moolenaar PRINTDBIT(MADE); 4333955d011SMarcel Moolenaar PRINTDBIT(PHONY); 4343955d011SMarcel Moolenaar } 4353955d011SMarcel Moolenaar } 4363955d011SMarcel Moolenaar } 4373955d011SMarcel Moolenaar 4383955d011SMarcel Moolenaar static const char * 4392c3632d1SSimon J. Gerraty made_name(GNodeMade made) 4403955d011SMarcel Moolenaar { 4413955d011SMarcel Moolenaar switch (made) { 4423955d011SMarcel Moolenaar case UNMADE: return "unmade"; 4433955d011SMarcel Moolenaar case DEFERRED: return "deferred"; 4443955d011SMarcel Moolenaar case REQUESTED: return "requested"; 4453955d011SMarcel Moolenaar case BEINGMADE: return "being made"; 4463955d011SMarcel Moolenaar case MADE: return "made"; 4473955d011SMarcel Moolenaar case UPTODATE: return "up-to-date"; 4483955d011SMarcel Moolenaar case ERROR: return "error when made"; 4493955d011SMarcel Moolenaar case ABORTED: return "aborted"; 4503955d011SMarcel Moolenaar default: return "unknown enum_made value"; 4513955d011SMarcel Moolenaar } 4523955d011SMarcel Moolenaar } 4533955d011SMarcel Moolenaar 454956e45f6SSimon J. Gerraty static const char * 455956e45f6SSimon J. Gerraty GNode_OpName(const GNode *gn) 4563955d011SMarcel Moolenaar { 457956e45f6SSimon J. Gerraty switch (gn->type & OP_OPMASK) { 458956e45f6SSimon J. Gerraty case OP_DEPENDS: 459956e45f6SSimon J. Gerraty return ":"; 460956e45f6SSimon J. Gerraty case OP_FORCE: 461956e45f6SSimon J. Gerraty return "!"; 462956e45f6SSimon J. Gerraty case OP_DOUBLEDEP: 463956e45f6SSimon J. Gerraty return "::"; 464956e45f6SSimon J. Gerraty } 465956e45f6SSimon J. Gerraty return ""; 466956e45f6SSimon J. Gerraty } 4673955d011SMarcel Moolenaar 468956e45f6SSimon J. Gerraty /* Print the contents of a node. */ 469956e45f6SSimon J. Gerraty void 470956e45f6SSimon J. Gerraty Targ_PrintNode(GNode *gn, int pass) 471956e45f6SSimon J. Gerraty { 472956e45f6SSimon J. Gerraty debug_printf("# %s%s", gn->name, gn->cohort_num); 473956e45f6SSimon J. Gerraty GNode_FprintDetails(opts.debug_file, ", ", gn, "\n"); 4743955d011SMarcel Moolenaar if (gn->flags == 0) 475956e45f6SSimon J. Gerraty return; 4763955d011SMarcel Moolenaar 477956e45f6SSimon J. Gerraty if (GNode_IsTarget(gn)) { 478956e45f6SSimon J. Gerraty debug_printf("#\n"); 4793955d011SMarcel Moolenaar if (gn == mainTarg) { 480956e45f6SSimon J. Gerraty debug_printf("# *** MAIN TARGET ***\n"); 4813955d011SMarcel Moolenaar } 4823955d011SMarcel Moolenaar if (pass >= 2) { 483*e2eeea75SSimon J. Gerraty if (gn->unmade > 0) { 484956e45f6SSimon J. Gerraty debug_printf("# %d unmade children\n", gn->unmade); 4853955d011SMarcel Moolenaar } else { 486956e45f6SSimon J. Gerraty debug_printf("# No unmade children\n"); 4873955d011SMarcel Moolenaar } 4883955d011SMarcel Moolenaar if (!(gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) { 4893955d011SMarcel Moolenaar if (gn->mtime != 0) { 490956e45f6SSimon J. Gerraty debug_printf("# last modified %s: %s\n", 4913955d011SMarcel Moolenaar Targ_FmtTime(gn->mtime), 4923955d011SMarcel Moolenaar made_name(gn->made)); 4933955d011SMarcel Moolenaar } else if (gn->made != UNMADE) { 494956e45f6SSimon J. Gerraty debug_printf("# non-existent (maybe): %s\n", 4953955d011SMarcel Moolenaar made_name(gn->made)); 4963955d011SMarcel Moolenaar } else { 497956e45f6SSimon J. Gerraty debug_printf("# unmade\n"); 4983955d011SMarcel Moolenaar } 4993955d011SMarcel Moolenaar } 500956e45f6SSimon J. Gerraty PrintNodeNamesLine("implicit parents", gn->implicitParents); 5013955d011SMarcel Moolenaar } else { 5023955d011SMarcel Moolenaar if (gn->unmade) 503956e45f6SSimon J. Gerraty debug_printf("# %d unmade children\n", gn->unmade); 5043955d011SMarcel Moolenaar } 505956e45f6SSimon J. Gerraty PrintNodeNamesLine("parents", gn->parents); 506956e45f6SSimon J. Gerraty PrintNodeNamesLine("order_pred", gn->order_pred); 507956e45f6SSimon J. Gerraty PrintNodeNamesLine("order_succ", gn->order_succ); 5083955d011SMarcel Moolenaar 509956e45f6SSimon J. Gerraty debug_printf("%-16s%s", gn->name, GNode_OpName(gn)); 5103955d011SMarcel Moolenaar Targ_PrintType(gn->type); 511956e45f6SSimon J. Gerraty PrintNodeNames(gn->children); 512956e45f6SSimon J. Gerraty debug_printf("\n"); 513956e45f6SSimon J. Gerraty Targ_PrintCmds(gn); 514956e45f6SSimon J. Gerraty debug_printf("\n\n"); 5153955d011SMarcel Moolenaar if (gn->type & OP_DOUBLEDEP) { 516956e45f6SSimon J. Gerraty Targ_PrintNodes(gn->cohorts, pass); 5173955d011SMarcel Moolenaar } 5183955d011SMarcel Moolenaar } 5193955d011SMarcel Moolenaar } 5203955d011SMarcel Moolenaar 521956e45f6SSimon J. Gerraty void 522956e45f6SSimon J. Gerraty Targ_PrintNodes(GNodeList *gnodes, int pass) 5233955d011SMarcel Moolenaar { 524956e45f6SSimon J. Gerraty GNodeListNode *ln; 525956e45f6SSimon J. Gerraty for (ln = gnodes->first; ln != NULL; ln = ln->next) 526956e45f6SSimon J. Gerraty Targ_PrintNode(ln->datum, pass); 527956e45f6SSimon J. Gerraty } 5283955d011SMarcel Moolenaar 529956e45f6SSimon J. Gerraty /* Print only those targets that are just a source. */ 530956e45f6SSimon J. Gerraty static void 531956e45f6SSimon J. Gerraty PrintOnlySources(void) 532956e45f6SSimon J. Gerraty { 533956e45f6SSimon J. Gerraty GNodeListNode *ln; 534956e45f6SSimon J. Gerraty 535956e45f6SSimon J. Gerraty for (ln = allTargets->first; ln != NULL; ln = ln->next) { 536956e45f6SSimon J. Gerraty GNode *gn = ln->datum; 537956e45f6SSimon J. Gerraty if (GNode_IsTarget(gn)) 538956e45f6SSimon J. Gerraty continue; 539956e45f6SSimon J. Gerraty 540956e45f6SSimon J. Gerraty debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn)); 5413955d011SMarcel Moolenaar Targ_PrintType(gn->type); 542956e45f6SSimon J. Gerraty debug_printf("\n"); 543956e45f6SSimon J. Gerraty } 5443955d011SMarcel Moolenaar } 5453955d011SMarcel Moolenaar 5462c3632d1SSimon J. Gerraty /* Input: 5472c3632d1SSimon J. Gerraty * pass 1 => before processing 5482c3632d1SSimon J. Gerraty * 2 => after processing 5492c3632d1SSimon J. Gerraty * 3 => after processing, an error occurred 5503955d011SMarcel Moolenaar */ 5513955d011SMarcel Moolenaar void 5523955d011SMarcel Moolenaar Targ_PrintGraph(int pass) 5533955d011SMarcel Moolenaar { 554956e45f6SSimon J. Gerraty debug_printf("#*** Input graph:\n"); 555956e45f6SSimon J. Gerraty Targ_PrintNodes(allTargets, pass); 556*e2eeea75SSimon J. Gerraty debug_printf("\n"); 557*e2eeea75SSimon J. Gerraty debug_printf("\n"); 558*e2eeea75SSimon J. Gerraty 559*e2eeea75SSimon J. Gerraty debug_printf("#\n"); 560*e2eeea75SSimon J. Gerraty debug_printf("# Files that are only sources:\n"); 561956e45f6SSimon J. Gerraty PrintOnlySources(); 562*e2eeea75SSimon J. Gerraty 563956e45f6SSimon J. Gerraty debug_printf("#*** Global Variables:\n"); 5643955d011SMarcel Moolenaar Var_Dump(VAR_GLOBAL); 565*e2eeea75SSimon J. Gerraty 566956e45f6SSimon J. Gerraty debug_printf("#*** Command-line Variables:\n"); 567956e45f6SSimon J. Gerraty Var_Dump(VAR_CMDLINE); 568*e2eeea75SSimon J. Gerraty 569956e45f6SSimon J. Gerraty debug_printf("\n"); 5703955d011SMarcel Moolenaar Dir_PrintDirectories(); 571956e45f6SSimon J. Gerraty debug_printf("\n"); 572*e2eeea75SSimon J. Gerraty 5733955d011SMarcel Moolenaar Suff_PrintAll(); 5743955d011SMarcel Moolenaar } 5753955d011SMarcel Moolenaar 576*e2eeea75SSimon J. Gerraty /* Propagate some type information to cohort nodes (those from the '::' 5772c3632d1SSimon J. Gerraty * dependency operator). 5783955d011SMarcel Moolenaar * 5792c3632d1SSimon J. Gerraty * Should be called after the makefiles are parsed but before any action is 5802c3632d1SSimon J. Gerraty * taken. */ 5813955d011SMarcel Moolenaar void 5823955d011SMarcel Moolenaar Targ_Propagate(void) 5833955d011SMarcel Moolenaar { 584956e45f6SSimon J. Gerraty GNodeListNode *ln, *cln; 5852c3632d1SSimon J. Gerraty 586956e45f6SSimon J. Gerraty for (ln = allTargets->first; ln != NULL; ln = ln->next) { 587956e45f6SSimon J. Gerraty GNode *gn = ln->datum; 588956e45f6SSimon J. Gerraty GNodeType type = gn->type; 5892c3632d1SSimon J. Gerraty 590956e45f6SSimon J. Gerraty if (!(type & OP_DOUBLEDEP)) 5912c3632d1SSimon J. Gerraty continue; 5922c3632d1SSimon J. Gerraty 593956e45f6SSimon J. Gerraty for (cln = gn->cohorts->first; cln != NULL; cln = cln->next) { 594956e45f6SSimon J. Gerraty GNode *cohort = cln->datum; 5952c3632d1SSimon J. Gerraty 596956e45f6SSimon J. Gerraty cohort->type |= type & ~OP_OPMASK; 5972c3632d1SSimon J. Gerraty } 5982c3632d1SSimon J. Gerraty } 5993955d011SMarcel Moolenaar } 600