19093286bSSimon J. Gerraty /* $NetBSD: targ.c,v 1.181 2024/04/27 17:33:47 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
713955d011SMarcel Moolenaar /*
729093286bSSimon J. Gerraty * Maintaining the targets and sources, which are both implemented as GNode.
733955d011SMarcel Moolenaar *
743955d011SMarcel Moolenaar * Interface:
753955d011SMarcel Moolenaar * Targ_Init Initialize the module.
763955d011SMarcel Moolenaar *
773955d011SMarcel Moolenaar * Targ_End Clean up the module.
783955d011SMarcel Moolenaar *
799093286bSSimon J. Gerraty * Targ_List Return the list of all targets so far.
803955d011SMarcel Moolenaar *
813955d011SMarcel Moolenaar * GNode_New Create a new GNode with the given name, don't add it
823955d011SMarcel Moolenaar * to allNodes.
833955d011SMarcel Moolenaar *
843955d011SMarcel Moolenaar * Targ_FindNode Find the node, or return NULL.
853955d011SMarcel Moolenaar *
863955d011SMarcel Moolenaar * Targ_GetNode Find the node, or create it.
873955d011SMarcel Moolenaar *
883955d011SMarcel Moolenaar * Targ_NewInternalNode
893955d011SMarcel Moolenaar * Create an internal node.
903955d011SMarcel Moolenaar *
913955d011SMarcel Moolenaar * Targ_FindList Given a list of names, find nodes for all
923955d011SMarcel Moolenaar * of them, creating them as necessary.
933955d011SMarcel Moolenaar *
943955d011SMarcel Moolenaar * Targ_Propagate Propagate information between related nodes.
953955d011SMarcel Moolenaar * Should be called after the makefiles are parsed
963955d011SMarcel Moolenaar * but before any action is taken.
973955d011SMarcel Moolenaar *
983955d011SMarcel Moolenaar * Debugging:
993955d011SMarcel Moolenaar * Targ_PrintGraph
1003955d011SMarcel Moolenaar * Print out the entire graph, all variables and
1013955d011SMarcel Moolenaar * 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
1093955d011SMarcel Moolenaar /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
1103955d011SMarcel Moolenaar MAKE_RCSID("$NetBSD: targ.c,v 1.181 2024/04/27 17:33:47 rillig Exp $");
1113955d011SMarcel Moolenaar
1123955d011SMarcel Moolenaar /*
1133955d011SMarcel Moolenaar * All target nodes that appeared on the left-hand side of one of the
1143955d011SMarcel Moolenaar * dependency operators ':', '::', '!'.
1153955d011SMarcel Moolenaar */
1163955d011SMarcel Moolenaar static GNodeList allTargets = LST_INIT;
1173955d011SMarcel Moolenaar static HashTable allTargetsByName;
1183955d011SMarcel Moolenaar
1193955d011SMarcel Moolenaar #ifdef CLEANUP
1203955d011SMarcel Moolenaar static GNodeList allNodes = LST_INIT;
1213955d011SMarcel Moolenaar
1223955d011SMarcel Moolenaar static void GNode_Free(GNode *);
1233955d011SMarcel Moolenaar #endif
1243955d011SMarcel Moolenaar
1253955d011SMarcel Moolenaar void
Targ_Init(void)1263955d011SMarcel Moolenaar Targ_Init(void)
1273955d011SMarcel Moolenaar {
1283955d011SMarcel Moolenaar HashTable_Init(&allTargetsByName);
1293955d011SMarcel Moolenaar }
1303955d011SMarcel Moolenaar
1313955d011SMarcel Moolenaar void
Targ_End(void)1323955d011SMarcel Moolenaar Targ_End(void)
1333955d011SMarcel Moolenaar {
1343955d011SMarcel Moolenaar #ifdef CLEANUP
1353955d011SMarcel Moolenaar GNodeListNode *ln;
1363955d011SMarcel Moolenaar #endif
1373955d011SMarcel Moolenaar Targ_Stats();
1383955d011SMarcel Moolenaar #ifdef CLEANUP
1393955d011SMarcel Moolenaar Lst_Done(&allTargets);
1403955d011SMarcel Moolenaar HashTable_Done(&allTargetsByName);
1413955d011SMarcel Moolenaar for (ln = allNodes.first; ln != NULL; ln = ln->next)
1423955d011SMarcel Moolenaar GNode_Free(ln->datum);
1433955d011SMarcel Moolenaar Lst_Done(&allNodes);
1443955d011SMarcel Moolenaar #endif
1453955d011SMarcel Moolenaar }
1463955d011SMarcel Moolenaar
1473955d011SMarcel Moolenaar void
Targ_Stats(void)1483955d011SMarcel Moolenaar Targ_Stats(void)
1493955d011SMarcel Moolenaar {
1503955d011SMarcel Moolenaar HashTable_DebugStats(&allTargetsByName, "targets");
1513955d011SMarcel Moolenaar }
1523955d011SMarcel Moolenaar
1533955d011SMarcel Moolenaar /*
1543955d011SMarcel Moolenaar * Return the list of all targets, which are all nodes that appear on the
1553955d011SMarcel Moolenaar * left-hand side of a dependency declaration such as "target: source".
1563955d011SMarcel Moolenaar * The returned list does not contain pure sources.
1573955d011SMarcel Moolenaar */
1583955d011SMarcel Moolenaar GNodeList *
Targ_List(void)1593955d011SMarcel Moolenaar Targ_List(void)
1603955d011SMarcel Moolenaar {
1613955d011SMarcel Moolenaar return &allTargets;
1623955d011SMarcel Moolenaar }
1633955d011SMarcel Moolenaar
1643955d011SMarcel Moolenaar /*
1653955d011SMarcel Moolenaar * Create a new graph node, but don't register it anywhere.
1663955d011SMarcel Moolenaar *
1673955d011SMarcel Moolenaar * Graph nodes that occur on the left-hand side of a dependency line such
1683955d011SMarcel Moolenaar * as "target: source" are called targets. XXX: In some cases (like the
1693955d011SMarcel Moolenaar * .ALLTARGETS variable), other nodes are called targets as well, even if
1703955d011SMarcel Moolenaar * they never occur on the left-hand side of a dependency line.
1713955d011SMarcel Moolenaar *
1723955d011SMarcel Moolenaar * Typical names for graph nodes are:
1733955d011SMarcel Moolenaar * "src.c" an ordinary file
1743955d011SMarcel Moolenaar * "clean" a .PHONY target
1753955d011SMarcel Moolenaar * ".END" a special hook target
1763955d011SMarcel Moolenaar * "-lm" a library
1773955d011SMarcel Moolenaar * "libm.a(sin.o)" an archive member
1783955d011SMarcel Moolenaar */
1793955d011SMarcel Moolenaar GNode *
GNode_New(const char * name)1803955d011SMarcel Moolenaar GNode_New(const char *name)
1813955d011SMarcel Moolenaar {
1823955d011SMarcel Moolenaar GNode *gn;
1833955d011SMarcel Moolenaar
1843955d011SMarcel Moolenaar gn = bmake_malloc(sizeof *gn);
1853955d011SMarcel Moolenaar gn->name = bmake_strdup(name);
1863955d011SMarcel Moolenaar gn->uname = NULL;
1873955d011SMarcel Moolenaar gn->path = NULL;
1883955d011SMarcel Moolenaar gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : OP_NONE;
1893955d011SMarcel Moolenaar memset(&gn->flags, 0, sizeof(gn->flags));
1903955d011SMarcel Moolenaar gn->made = UNMADE;
1913955d011SMarcel Moolenaar gn->unmade = 0;
1923955d011SMarcel Moolenaar gn->mtime = 0;
1933955d011SMarcel Moolenaar gn->youngestChild = NULL;
1943955d011SMarcel Moolenaar Lst_Init(&gn->implicitParents);
1953955d011SMarcel Moolenaar Lst_Init(&gn->parents);
1963955d011SMarcel Moolenaar Lst_Init(&gn->children);
1973955d011SMarcel Moolenaar Lst_Init(&gn->order_pred);
1983955d011SMarcel Moolenaar Lst_Init(&gn->order_succ);
1993955d011SMarcel Moolenaar Lst_Init(&gn->cohorts);
2003955d011SMarcel Moolenaar gn->cohort_num[0] = '\0';
2013955d011SMarcel Moolenaar gn->unmade_cohorts = 0;
2023955d011SMarcel Moolenaar gn->centurion = NULL;
2033955d011SMarcel Moolenaar gn->checked_seqno = 0;
2043955d011SMarcel Moolenaar HashTable_Init(&gn->vars);
2053955d011SMarcel Moolenaar Lst_Init(&gn->commands);
2063955d011SMarcel Moolenaar gn->suffix = NULL;
2073955d011SMarcel Moolenaar gn->fname = NULL;
2083955d011SMarcel Moolenaar gn->lineno = 0;
2093955d011SMarcel Moolenaar gn->exit_status = 0;
2103955d011SMarcel Moolenaar
2113955d011SMarcel Moolenaar #ifdef CLEANUP
2123955d011SMarcel Moolenaar Lst_Append(&allNodes, gn);
2133955d011SMarcel Moolenaar #endif
2143955d011SMarcel Moolenaar
2153955d011SMarcel Moolenaar return gn;
2163955d011SMarcel Moolenaar }
2173955d011SMarcel Moolenaar
2183955d011SMarcel Moolenaar #ifdef CLEANUP
2193955d011SMarcel Moolenaar static void
GNode_Free(GNode * gn)2203955d011SMarcel Moolenaar GNode_Free(GNode *gn)
2213955d011SMarcel Moolenaar {
2223955d011SMarcel Moolenaar free(gn->name);
2233955d011SMarcel Moolenaar free(gn->uname);
2243955d011SMarcel Moolenaar free(gn->path);
2253955d011SMarcel Moolenaar
2263955d011SMarcel Moolenaar /* Don't free gn->youngestChild since it is not owned by this node. */
2273955d011SMarcel Moolenaar
2283955d011SMarcel Moolenaar /*
2293955d011SMarcel Moolenaar * In the following lists, only free the list nodes, but not the
2303955d011SMarcel Moolenaar * GNodes in them since these are not owned by this node.
2313955d011SMarcel Moolenaar */
2323955d011SMarcel Moolenaar Lst_Done(&gn->implicitParents);
2333955d011SMarcel Moolenaar Lst_Done(&gn->parents);
2343955d011SMarcel Moolenaar Lst_Done(&gn->children);
2353955d011SMarcel Moolenaar Lst_Done(&gn->order_pred);
2363955d011SMarcel Moolenaar Lst_Done(&gn->order_succ);
2373955d011SMarcel Moolenaar Lst_Done(&gn->cohorts);
2383955d011SMarcel Moolenaar
2393955d011SMarcel Moolenaar /*
2403955d011SMarcel Moolenaar * Do not free the variables themselves, even though they are owned
2413955d011SMarcel Moolenaar * by this node.
2423955d011SMarcel Moolenaar *
2433955d011SMarcel Moolenaar * XXX: For the nodes that represent targets or sources (and not
2443955d011SMarcel Moolenaar * SCOPE_GLOBAL), it should be safe to free the variables as well,
2453955d011SMarcel Moolenaar * since each node manages the memory for all its variables itself.
2463955d011SMarcel Moolenaar *
2473955d011SMarcel Moolenaar * XXX: The GNodes that are only used as variable scopes (SCOPE_CMD,
2483955d011SMarcel Moolenaar * SCOPE_GLOBAL, SCOPE_INTERNAL) are not freed at all (see Var_End,
2493955d011SMarcel Moolenaar * where they are not mentioned). These may be freed if their
2503955d011SMarcel Moolenaar * variable values are indeed not used anywhere else (see Trace_Init
2513955d011SMarcel Moolenaar * for the only suspicious use).
2523955d011SMarcel Moolenaar */
2533955d011SMarcel Moolenaar HashTable_Done(&gn->vars);
2543955d011SMarcel Moolenaar
2553955d011SMarcel Moolenaar /*
2563955d011SMarcel Moolenaar * Do not free the commands themselves, as they may be shared with
2573955d011SMarcel Moolenaar * other nodes.
2583955d011SMarcel Moolenaar */
2593955d011SMarcel Moolenaar Lst_Done(&gn->commands);
2603955d011SMarcel Moolenaar
2613955d011SMarcel Moolenaar /*
2623955d011SMarcel Moolenaar * gn->suffix is not owned by this node.
2633955d011SMarcel Moolenaar *
2643955d011SMarcel Moolenaar * XXX: gn->suffix should be unreferenced here. This requires a
2653955d011SMarcel Moolenaar * thorough check that the reference counting is done correctly in
2663955d011SMarcel Moolenaar * all places, otherwise a suffix might be freed too early.
2673955d011SMarcel Moolenaar */
2683955d011SMarcel Moolenaar
2693955d011SMarcel Moolenaar free(gn);
2703955d011SMarcel Moolenaar }
2713955d011SMarcel Moolenaar #endif
2729093286bSSimon J. Gerraty
2733955d011SMarcel Moolenaar /* Get the existing global node, or return NULL. */
2743955d011SMarcel Moolenaar GNode *
Targ_FindNode(const char * name)2753955d011SMarcel Moolenaar Targ_FindNode(const char *name)
2763955d011SMarcel Moolenaar {
2773955d011SMarcel Moolenaar return HashTable_FindValue(&allTargetsByName, name);
2783955d011SMarcel Moolenaar }
2793955d011SMarcel Moolenaar
2803955d011SMarcel Moolenaar /* Get the existing global node, or create it. */
2813955d011SMarcel Moolenaar GNode *
Targ_GetNode(const char * name)2823955d011SMarcel Moolenaar Targ_GetNode(const char *name)
2833955d011SMarcel Moolenaar {
2843955d011SMarcel Moolenaar bool isNew;
2853955d011SMarcel Moolenaar HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew);
2863955d011SMarcel Moolenaar if (!isNew)
2873955d011SMarcel Moolenaar return HashEntry_Get(he);
2883955d011SMarcel Moolenaar
2893955d011SMarcel Moolenaar {
2903955d011SMarcel Moolenaar GNode *gn = Targ_NewInternalNode(name);
2913955d011SMarcel Moolenaar HashEntry_Set(he, gn);
2923955d011SMarcel Moolenaar return gn;
2933955d011SMarcel Moolenaar }
2943955d011SMarcel Moolenaar }
2953955d011SMarcel Moolenaar
2963955d011SMarcel Moolenaar /*
2973955d011SMarcel Moolenaar * Create a node, register it in .ALLTARGETS but don't store it in the
2983955d011SMarcel Moolenaar * table of global nodes. This means it cannot be found by name.
2993955d011SMarcel Moolenaar *
3003955d011SMarcel Moolenaar * This is used for internal nodes, such as cohorts or .WAIT nodes.
3013955d011SMarcel Moolenaar */
3023955d011SMarcel Moolenaar GNode *
Targ_NewInternalNode(const char * name)3033955d011SMarcel Moolenaar Targ_NewInternalNode(const char *name)
3043955d011SMarcel Moolenaar {
3053955d011SMarcel Moolenaar GNode *gn = GNode_New(name);
3063955d011SMarcel Moolenaar Global_Append(".ALLTARGETS", name);
3073955d011SMarcel Moolenaar Lst_Append(&allTargets, gn);
3083955d011SMarcel Moolenaar DEBUG1(TARG, "Adding \"%s\" to all targets.\n", gn->name);
3093955d011SMarcel Moolenaar if (doing_depend)
3103955d011SMarcel Moolenaar gn->flags.fromDepend = true;
3113955d011SMarcel Moolenaar return gn;
3123955d011SMarcel Moolenaar }
3133955d011SMarcel Moolenaar
3143955d011SMarcel Moolenaar /*
3153955d011SMarcel Moolenaar * Return the .END node, which contains the commands to be run when
3163955d011SMarcel Moolenaar * everything else has been made.
3173955d011SMarcel Moolenaar */
3183955d011SMarcel Moolenaar GNode *
Targ_GetEndNode(void)3193955d011SMarcel Moolenaar Targ_GetEndNode(void)
3203955d011SMarcel Moolenaar {
3213955d011SMarcel Moolenaar /*
3223955d011SMarcel Moolenaar * Save the node locally to avoid having to search for it all
3233955d011SMarcel Moolenaar * the time.
3243955d011SMarcel Moolenaar */
3253955d011SMarcel Moolenaar static GNode *endNode = NULL;
3263955d011SMarcel Moolenaar
3273955d011SMarcel Moolenaar if (endNode == NULL) {
3283955d011SMarcel Moolenaar endNode = Targ_GetNode(".END");
3293955d011SMarcel Moolenaar endNode->type = OP_SPECIAL;
3303955d011SMarcel Moolenaar }
3313955d011SMarcel Moolenaar return endNode;
3323955d011SMarcel Moolenaar }
3333955d011SMarcel Moolenaar
3343955d011SMarcel Moolenaar /* Add the named nodes to the list, creating them as necessary. */
3353955d011SMarcel Moolenaar void
Targ_FindList(GNodeList * gns,StringList * names)3363955d011SMarcel Moolenaar Targ_FindList(GNodeList *gns, StringList *names)
3373955d011SMarcel Moolenaar {
3383955d011SMarcel Moolenaar StringListNode *ln;
3393955d011SMarcel Moolenaar
3403955d011SMarcel Moolenaar for (ln = names->first; ln != NULL; ln = ln->next) {
3413955d011SMarcel Moolenaar const char *name = ln->datum;
3423955d011SMarcel Moolenaar GNode *gn = Targ_GetNode(name);
3433955d011SMarcel Moolenaar Lst_Append(gns, gn);
3443955d011SMarcel Moolenaar }
3453955d011SMarcel Moolenaar }
3463955d011SMarcel Moolenaar
3473955d011SMarcel Moolenaar static void
PrintNodeNames(GNodeList * gnodes)3483955d011SMarcel Moolenaar PrintNodeNames(GNodeList *gnodes)
3493955d011SMarcel Moolenaar {
3503955d011SMarcel Moolenaar GNodeListNode *ln;
3513955d011SMarcel Moolenaar
3523955d011SMarcel Moolenaar for (ln = gnodes->first; ln != NULL; ln = ln->next) {
3533955d011SMarcel Moolenaar GNode *gn = ln->datum;
3543955d011SMarcel Moolenaar debug_printf(" %s%s", gn->name, gn->cohort_num);
3553955d011SMarcel Moolenaar }
3563955d011SMarcel Moolenaar }
3573955d011SMarcel Moolenaar
3583955d011SMarcel Moolenaar static void
PrintNodeNamesLine(const char * label,GNodeList * gnodes)3593955d011SMarcel Moolenaar PrintNodeNamesLine(const char *label, GNodeList *gnodes)
3603955d011SMarcel Moolenaar {
3613955d011SMarcel Moolenaar if (Lst_IsEmpty(gnodes))
3623955d011SMarcel Moolenaar return;
3633955d011SMarcel Moolenaar debug_printf("# %s:", label);
3643955d011SMarcel Moolenaar PrintNodeNames(gnodes);
3653955d011SMarcel Moolenaar debug_printf("\n");
3663955d011SMarcel Moolenaar }
3673955d011SMarcel Moolenaar
3683955d011SMarcel Moolenaar void
Targ_PrintCmds(GNode * gn)3693955d011SMarcel Moolenaar Targ_PrintCmds(GNode *gn)
3703955d011SMarcel Moolenaar {
3713955d011SMarcel Moolenaar StringListNode *ln;
3723955d011SMarcel Moolenaar
3733955d011SMarcel Moolenaar for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
3743955d011SMarcel Moolenaar const char *cmd = ln->datum;
3753955d011SMarcel Moolenaar debug_printf("\t%s\n", cmd);
3763955d011SMarcel Moolenaar }
3773955d011SMarcel Moolenaar }
3783955d011SMarcel Moolenaar
3793955d011SMarcel Moolenaar /*
3803955d011SMarcel Moolenaar * Format a modification time in some reasonable way and return it.
3813955d011SMarcel Moolenaar * The formatted time is placed in a static area, so it is overwritten
3823955d011SMarcel Moolenaar * with each call.
3833955d011SMarcel Moolenaar */
3843955d011SMarcel Moolenaar const char *
Targ_FmtTime(time_t tm)3853955d011SMarcel Moolenaar Targ_FmtTime(time_t tm)
3863955d011SMarcel Moolenaar {
3873955d011SMarcel Moolenaar static char buf[128];
3883955d011SMarcel Moolenaar
3893955d011SMarcel Moolenaar struct tm *parts = localtime(&tm);
3903955d011SMarcel Moolenaar (void)strftime(buf, sizeof buf, "%H:%M:%S %b %d, %Y", parts);
3913955d011SMarcel Moolenaar return buf;
3929093286bSSimon J. Gerraty }
3933955d011SMarcel Moolenaar
3943955d011SMarcel Moolenaar /* Print out a type field giving only those attributes the user can set. */
3953955d011SMarcel Moolenaar void
Targ_PrintType(GNodeType type)3963955d011SMarcel Moolenaar Targ_PrintType(GNodeType type)
3973955d011SMarcel Moolenaar {
3983955d011SMarcel Moolenaar static const struct {
3993955d011SMarcel Moolenaar GNodeType bit;
4003955d011SMarcel Moolenaar bool internal;
4013955d011SMarcel Moolenaar const char name[10];
4023955d011SMarcel Moolenaar } names[] = {
4033955d011SMarcel Moolenaar { OP_MEMBER, true, "MEMBER" },
4043955d011SMarcel Moolenaar { OP_LIB, true, "LIB" },
4053955d011SMarcel Moolenaar { OP_ARCHV, true, "ARCHV" },
4063955d011SMarcel Moolenaar { OP_PHONY, true, "PHONY" },
4073955d011SMarcel Moolenaar { OP_NOTMAIN, false, "NOTMAIN" },
4083955d011SMarcel Moolenaar { OP_INVISIBLE, false, "INVISIBLE" },
4099093286bSSimon J. Gerraty { OP_MADE, true, "MADE" },
4103955d011SMarcel Moolenaar { OP_JOIN, false, "JOIN" },
4113955d011SMarcel Moolenaar { OP_MAKE, false, "MAKE" },
4123955d011SMarcel Moolenaar { OP_SILENT, false, "SILENT" },
4133955d011SMarcel Moolenaar { OP_PRECIOUS, false, "PRECIOUS" },
4143955d011SMarcel Moolenaar { OP_IGNORE, false, "IGNORE" },
4153955d011SMarcel Moolenaar { OP_EXEC, false, "EXEC" },
4163955d011SMarcel Moolenaar { OP_USE, false, "USE" },
4173955d011SMarcel Moolenaar { OP_USEBEFORE, false, "USEBEFORE" },
4183955d011SMarcel Moolenaar { OP_OPTIONAL, false, "OPTIONAL" },
4193955d011SMarcel Moolenaar };
4203955d011SMarcel Moolenaar size_t i;
4213955d011SMarcel Moolenaar
4223955d011SMarcel Moolenaar for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
4233955d011SMarcel Moolenaar if (type & names[i].bit) {
4243955d011SMarcel Moolenaar if (names[i].internal)
4253955d011SMarcel Moolenaar DEBUG1(TARG, " .%s", names[i].name);
4263955d011SMarcel Moolenaar else
4273955d011SMarcel Moolenaar debug_printf(" .%s", names[i].name);
4283955d011SMarcel Moolenaar }
4293955d011SMarcel Moolenaar }
4303955d011SMarcel Moolenaar }
4319093286bSSimon J. Gerraty
4323955d011SMarcel Moolenaar const char *
GNodeMade_Name(GNodeMade made)4339093286bSSimon J. Gerraty GNodeMade_Name(GNodeMade made)
4343955d011SMarcel Moolenaar {
4353955d011SMarcel Moolenaar switch (made) {
4363955d011SMarcel Moolenaar case UNMADE: return "unmade";
4373955d011SMarcel Moolenaar case DEFERRED: return "deferred";
4383955d011SMarcel Moolenaar case REQUESTED: return "requested";
4393955d011SMarcel Moolenaar case BEINGMADE: return "being made";
4403955d011SMarcel Moolenaar case MADE: return "made";
4413955d011SMarcel Moolenaar case UPTODATE: return "up-to-date";
4423955d011SMarcel Moolenaar case ERROR: return "error when made";
4433955d011SMarcel Moolenaar case ABORTED: return "aborted";
4443955d011SMarcel Moolenaar default: return "unknown enum_made value";
4453955d011SMarcel Moolenaar }
4463955d011SMarcel Moolenaar }
4473955d011SMarcel Moolenaar
4483955d011SMarcel Moolenaar static const char *
GNode_OpName(const GNode * gn)4493955d011SMarcel Moolenaar GNode_OpName(const GNode *gn)
4503955d011SMarcel Moolenaar {
4513955d011SMarcel Moolenaar switch (gn->type & OP_OPMASK) {
4523955d011SMarcel Moolenaar case OP_DEPENDS:
4533955d011SMarcel Moolenaar return ":";
4543955d011SMarcel Moolenaar case OP_FORCE:
4553955d011SMarcel Moolenaar return "!";
4569093286bSSimon J. Gerraty case OP_DOUBLEDEP:
4573955d011SMarcel Moolenaar return "::";
4589093286bSSimon J. Gerraty }
4593955d011SMarcel Moolenaar return "";
4603955d011SMarcel Moolenaar }
4613955d011SMarcel Moolenaar
4623955d011SMarcel Moolenaar static bool
GNodeFlags_IsNone(GNodeFlags flags)4633955d011SMarcel Moolenaar GNodeFlags_IsNone(GNodeFlags flags)
4643955d011SMarcel Moolenaar {
4653955d011SMarcel Moolenaar return !flags.remake
4663955d011SMarcel Moolenaar && !flags.childMade
4673955d011SMarcel Moolenaar && !flags.force
4683955d011SMarcel Moolenaar && !flags.doneWait
4693955d011SMarcel Moolenaar && !flags.doneOrder
4703955d011SMarcel Moolenaar && !flags.fromDepend
4713955d011SMarcel Moolenaar && !flags.doneAllsrc
4723955d011SMarcel Moolenaar && !flags.cycle
4733955d011SMarcel Moolenaar && !flags.doneCycle;
4743955d011SMarcel Moolenaar }
4753955d011SMarcel Moolenaar
4763955d011SMarcel Moolenaar /* Print the contents of a node. */
4773955d011SMarcel Moolenaar void
Targ_PrintNode(GNode * gn,int pass)4783955d011SMarcel Moolenaar Targ_PrintNode(GNode *gn, int pass)
4793955d011SMarcel Moolenaar {
4803955d011SMarcel Moolenaar debug_printf("# %s%s", gn->name, gn->cohort_num);
4819093286bSSimon J. Gerraty GNode_FprintDetails(opts.debug_file, ", ", gn, "\n");
4823955d011SMarcel Moolenaar if (GNodeFlags_IsNone(gn->flags))
4839093286bSSimon J. Gerraty return;
4843955d011SMarcel Moolenaar
4853955d011SMarcel Moolenaar if (!GNode_IsTarget(gn))
4863955d011SMarcel Moolenaar return;
4873955d011SMarcel Moolenaar
4883955d011SMarcel Moolenaar debug_printf("#\n");
4893955d011SMarcel Moolenaar if (gn == mainNode)
4903955d011SMarcel Moolenaar debug_printf("# *** MAIN TARGET ***\n");
4913955d011SMarcel Moolenaar
4923955d011SMarcel Moolenaar if (pass >= 2) {
4933955d011SMarcel Moolenaar if (gn->unmade > 0)
4943955d011SMarcel Moolenaar debug_printf("# %d unmade children\n", gn->unmade);
4953955d011SMarcel Moolenaar else
4963955d011SMarcel Moolenaar debug_printf("# No unmade children\n");
4973955d011SMarcel Moolenaar if (!(gn->type & (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC))) {
4983955d011SMarcel Moolenaar if (gn->mtime != 0) {
4993955d011SMarcel Moolenaar debug_printf("# last modified %s: %s\n",
5003955d011SMarcel Moolenaar Targ_FmtTime(gn->mtime),
5013955d011SMarcel Moolenaar GNodeMade_Name(gn->made));
5023955d011SMarcel Moolenaar } else if (gn->made != UNMADE) {
5033955d011SMarcel Moolenaar debug_printf("# nonexistent (maybe): %s\n",
5043955d011SMarcel Moolenaar GNodeMade_Name(gn->made));
5053955d011SMarcel Moolenaar } else
5063955d011SMarcel Moolenaar debug_printf("# unmade\n");
5073955d011SMarcel Moolenaar }
5083955d011SMarcel Moolenaar PrintNodeNamesLine("implicit parents", &gn->implicitParents);
5093955d011SMarcel Moolenaar } else {
5103955d011SMarcel Moolenaar if (gn->unmade != 0)
5113955d011SMarcel Moolenaar debug_printf("# %d unmade children\n", gn->unmade);
5123955d011SMarcel Moolenaar }
5133955d011SMarcel Moolenaar
5143955d011SMarcel Moolenaar PrintNodeNamesLine("parents", &gn->parents);
5153955d011SMarcel Moolenaar PrintNodeNamesLine("order_pred", &gn->order_pred);
5163955d011SMarcel Moolenaar PrintNodeNamesLine("order_succ", &gn->order_succ);
5173955d011SMarcel Moolenaar
5183955d011SMarcel Moolenaar debug_printf("%-16s%s", gn->name, GNode_OpName(gn));
5193955d011SMarcel Moolenaar Targ_PrintType(gn->type);
5203955d011SMarcel Moolenaar PrintNodeNames(&gn->children);
5213955d011SMarcel Moolenaar debug_printf("\n");
5223955d011SMarcel Moolenaar Targ_PrintCmds(gn);
5233955d011SMarcel Moolenaar debug_printf("\n\n");
524e1cee40dSSimon J. Gerraty if (gn->type & OP_DOUBLEDEP)
5253955d011SMarcel Moolenaar Targ_PrintNodes(&gn->cohorts, pass);
5263955d011SMarcel Moolenaar }
527e1cee40dSSimon J. Gerraty
5283955d011SMarcel Moolenaar void
Targ_PrintNodes(GNodeList * gnodes,int pass)5293955d011SMarcel Moolenaar Targ_PrintNodes(GNodeList *gnodes, int pass)
5303955d011SMarcel Moolenaar {
5313955d011SMarcel Moolenaar GNodeListNode *ln;
5323955d011SMarcel Moolenaar
5333955d011SMarcel Moolenaar for (ln = gnodes->first; ln != NULL; ln = ln->next)
5343955d011SMarcel Moolenaar Targ_PrintNode(ln->datum, pass);
5353955d011SMarcel Moolenaar }
5363955d011SMarcel Moolenaar
5373955d011SMarcel Moolenaar static void
PrintOnlySources(void)5383955d011SMarcel Moolenaar PrintOnlySources(void)
5393955d011SMarcel Moolenaar {
5403955d011SMarcel Moolenaar GNodeListNode *ln;
5413955d011SMarcel Moolenaar
5423955d011SMarcel Moolenaar for (ln = allTargets.first; ln != NULL; ln = ln->next) {
5433955d011SMarcel Moolenaar GNode *gn = ln->datum;
5443955d011SMarcel Moolenaar if (GNode_IsTarget(gn))
5453955d011SMarcel Moolenaar continue;
5463955d011SMarcel Moolenaar
5473955d011SMarcel Moolenaar debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn));
5483955d011SMarcel Moolenaar Targ_PrintType(gn->type);
5493955d011SMarcel Moolenaar debug_printf("\n");
5503955d011SMarcel Moolenaar }
5513955d011SMarcel Moolenaar }
5529093286bSSimon J. Gerraty
5533955d011SMarcel Moolenaar /*
5543955d011SMarcel Moolenaar * Input:
5553955d011SMarcel Moolenaar * pass 1 => before processing
5563955d011SMarcel Moolenaar * 2 => after processing
5573955d011SMarcel Moolenaar * 3 => after processing, an error occurred
5583955d011SMarcel Moolenaar */
5593955d011SMarcel Moolenaar void
Targ_PrintGraph(int pass)5603955d011SMarcel Moolenaar Targ_PrintGraph(int pass)
5613955d011SMarcel Moolenaar {
5623955d011SMarcel Moolenaar debug_printf("#*** Input graph:\n");
5633955d011SMarcel Moolenaar Targ_PrintNodes(&allTargets, pass);
5643955d011SMarcel Moolenaar debug_printf("\n");
5653955d011SMarcel Moolenaar debug_printf("\n");
5663955d011SMarcel Moolenaar
5673955d011SMarcel Moolenaar debug_printf("#\n");
5683955d011SMarcel Moolenaar debug_printf("# Files that are only sources:\n");
5693955d011SMarcel Moolenaar PrintOnlySources();
5703955d011SMarcel Moolenaar
5713955d011SMarcel Moolenaar debug_printf("#*** Global Variables:\n");
5723955d011SMarcel Moolenaar Var_Dump(SCOPE_GLOBAL);
5733955d011SMarcel Moolenaar
5743955d011SMarcel Moolenaar debug_printf("#*** Command-line Variables:\n");
5753955d011SMarcel Moolenaar Var_Dump(SCOPE_CMDLINE);
5763955d011SMarcel Moolenaar
5773955d011SMarcel Moolenaar debug_printf("\n");
5783955d011SMarcel Moolenaar Dir_PrintDirectories();
5793955d011SMarcel Moolenaar debug_printf("\n");
5803955d011SMarcel Moolenaar
5813955d011SMarcel Moolenaar Suff_PrintAll();
5823955d011SMarcel Moolenaar }
5833955d011SMarcel Moolenaar
5843955d011SMarcel Moolenaar /*
5853955d011SMarcel Moolenaar * Propagate some type information to cohort nodes (those from the '::'
5863955d011SMarcel Moolenaar * dependency operator).
5873955d011SMarcel Moolenaar *
5883955d011SMarcel Moolenaar * Should be called after the makefiles are parsed but before any action is
5893955d011SMarcel Moolenaar * taken.
5903955d011SMarcel Moolenaar */
5913955d011SMarcel Moolenaar void
Targ_Propagate(void)5923955d011SMarcel Moolenaar Targ_Propagate(void)
5933955d011SMarcel Moolenaar {
5943955d011SMarcel Moolenaar GNodeListNode *ln, *cln;
5953955d011SMarcel Moolenaar
5963955d011SMarcel Moolenaar for (ln = allTargets.first; ln != NULL; ln = ln->next) {
5973955d011SMarcel Moolenaar GNode *gn = ln->datum;
5983955d011SMarcel Moolenaar GNodeType type = gn->type;
5993955d011SMarcel Moolenaar
6003955d011SMarcel Moolenaar if (!(type & OP_DOUBLEDEP))
6013955d011SMarcel Moolenaar continue;
6023955d011SMarcel Moolenaar
6033955d011SMarcel Moolenaar for (cln = gn->cohorts.first; cln != NULL; cln = cln->next) {
6043955d011SMarcel Moolenaar GNode *cohort = cln->datum;
6053955d011SMarcel Moolenaar
6063955d011SMarcel Moolenaar cohort->type |= type & (unsigned)~OP_OPMASK;
6073955d011SMarcel Moolenaar }
6083955d011SMarcel Moolenaar }
6093955d011SMarcel Moolenaar }
6103955d011SMarcel Moolenaar