xref: /freebsd/contrib/bmake/targ.c (revision e2eeea75eb8b6dd50c1298067a0655880d186734)
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