targ.c revision 241146
1155408Srwatson/*	$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $	*/
2155408Srwatson
3155408Srwatson/*
4155408Srwatson * Copyright (c) 1988, 1989, 1990, 1993
5155408Srwatson *	The Regents of the University of California.  All rights reserved.
6155408Srwatson *
7155408Srwatson * This code is derived from software contributed to Berkeley by
8155408Srwatson * Adam de Boor.
9155408Srwatson *
10155408Srwatson * Redistribution and use in source and binary forms, with or without
11155408Srwatson * modification, are permitted provided that the following conditions
12155408Srwatson * are met:
13155408Srwatson * 1. Redistributions of source code must retain the above copyright
14155408Srwatson *    notice, this list of conditions and the following disclaimer.
15155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright
16155408Srwatson *    notice, this list of conditions and the following disclaimer in the
17155408Srwatson *    documentation and/or other materials provided with the distribution.
18155408Srwatson * 3. Neither the name of the University nor the names of its contributors
19155408Srwatson *    may be used to endorse or promote products derived from this software
20155408Srwatson *    without specific prior written permission.
21155408Srwatson *
22155408Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23155408Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25155408Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27155408Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32155408Srwatson * SUCH DAMAGE.
33155408Srwatson */
34155408Srwatson
35155408Srwatson/*
36155408Srwatson * Copyright (c) 1989 by Berkeley Softworks
37155408Srwatson * All rights reserved.
38155408Srwatson *
39155408Srwatson * This code is derived from software contributed to Berkeley by
40155408Srwatson * Adam de Boor.
41155408Srwatson *
42155408Srwatson * Redistribution and use in source and binary forms, with or without
43155408Srwatson * modification, are permitted provided that the following conditions
44155408Srwatson * are met:
45155408Srwatson * 1. Redistributions of source code must retain the above copyright
46155408Srwatson *    notice, this list of conditions and the following disclaimer.
47155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright
48155408Srwatson *    notice, this list of conditions and the following disclaimer in the
49155408Srwatson *    documentation and/or other materials provided with the distribution.
50155408Srwatson * 3. All advertising materials mentioning features or use of this software
51156880Srwatson *    must display the following acknowledgement:
52155408Srwatson *	This product includes software developed by the University of
53155408Srwatson *	California, Berkeley and its contributors.
54155408Srwatson * 4. Neither the name of the University nor the names of its contributors
55155408Srwatson *    may be used to endorse or promote products derived from this software
56155408Srwatson *    without specific prior written permission.
57155408Srwatson *
58159269Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59159269Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61155408Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63155408Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68159269Srwatson * SUCH DAMAGE.
69159269Srwatson */
70155408Srwatson
71155408Srwatson#ifndef MAKE_NATIVE
72155408Srwatsonstatic char rcsid[] = "$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $";
73155408Srwatson#else
74156883Srwatson#include <sys/cdefs.h>
75156880Srwatson#ifndef lint
76155408Srwatson#if 0
77155408Srwatsonstatic char sccsid[] = "@(#)targ.c	8.2 (Berkeley) 3/19/94";
78155408Srwatson#else
79155408Srwatson__RCSID("$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $");
80155408Srwatson#endif
81155408Srwatson#endif /* not lint */
82155408Srwatson#endif
83155408Srwatson
84155408Srwatson/*-
85155408Srwatson * targ.c --
86155408Srwatson *	Functions for maintaining the Lst allTargets. Target nodes are
87155408Srwatson * kept in two structures: a Lst, maintained by the list library, and a
88159269Srwatson * hash table, maintained by the hash library.
89159269Srwatson *
90159269Srwatson * Interface:
91159269Srwatson *	Targ_Init 	    	Initialization procedure.
92159269Srwatson *
93159269Srwatson *	Targ_End 	    	Cleanup the module
94159269Srwatson *
95159269Srwatson *	Targ_List 	    	Return the list of all targets so far.
96159269Srwatson *
97159269Srwatson *	Targ_NewGN	    	Create a new GNode for the passed target
98159269Srwatson *	    	  	    	(string). The node is *not* placed in the
99159269Srwatson *	    	  	    	hash table, though all its fields are
100159269Srwatson *	    	  	    	initialized.
101159269Srwatson *
102159269Srwatson *	Targ_FindNode	    	Find the node for a given target, creating
103159269Srwatson *	    	  	    	and storing it if it doesn't exist and the
104159269Srwatson *	    	  	    	flags are right (TARG_CREATE)
105155408Srwatson *
106155408Srwatson *	Targ_FindList	    	Given a list of names, find nodes for all
107155408Srwatson *	    	  	    	of them. If a name doesn't exist and the
108155408Srwatson *	    	  	    	TARG_NOCREATE flag was given, an error message
109155408Srwatson *	    	  	    	is printed. Else, if a name doesn't exist,
110155408Srwatson *	    	  	    	its node is created.
111155408Srwatson *
112155408Srwatson *	Targ_Ignore	    	Return TRUE if errors should be ignored when
113155408Srwatson *	    	  	    	creating the given target.
114155408Srwatson *
115155408Srwatson *	Targ_Silent	    	Return TRUE if we should be silent when
116155408Srwatson *	    	  	    	creating the given target.
117155408Srwatson *
118155408Srwatson *	Targ_Precious	    	Return TRUE if the target is precious and
119155408Srwatson *	    	  	    	should not be removed if we are interrupted.
120155408Srwatson *
121155408Srwatson *	Targ_Propagate		Propagate information between related
122155408Srwatson *				nodes.	Should be called after the
123155408Srwatson *				makefiles are parsed but before any
124155408Srwatson *				action is taken.
125159269Srwatson *
126159269Srwatson * Debugging:
127159269Srwatson *	Targ_PrintGraph	    	Print out the entire graphm all variables
128159269Srwatson *	    	  	    	and statistics for the directory cache. Should
129159269Srwatson *	    	  	    	print something for suffixes, too, but...
130159269Srwatson */
131159269Srwatson
132159269Srwatson#include	  <stdio.h>
133159269Srwatson#include	  <time.h>
134159269Srwatson
135159269Srwatson#include	  "make.h"
136159269Srwatson#include	  "hash.h"
137159269Srwatson#include	  "dir.h"
138155408Srwatson
139155408Srwatsonstatic Lst        allTargets;	/* the list of all targets found so far */
140159269Srwatson#ifdef CLEANUP
141159269Srwatsonstatic Lst	  allGNs;	/* List of all the GNodes */
142159269Srwatson#endif
143155408Srwatsonstatic Hash_Table targets;	/* a hash table of same */
144155408Srwatson
145155408Srwatson#define HTSIZE	191		/* initial size of hash table */
146155408Srwatson
147159269Srwatsonstatic int TargPrintOnlySrc(void *, void *);
148155408Srwatsonstatic int TargPrintName(void *, void *);
149155408Srwatson#ifdef CLEANUP
150155408Srwatsonstatic void TargFreeGN(void *);
151155408Srwatson#endif
152155408Srwatsonstatic int TargPropagateCohort(void *, void *);
153155408Srwatsonstatic int TargPropagateNode(void *, void *);
154159269Srwatson
155159269Srwatson/*-
156159269Srwatson *-----------------------------------------------------------------------
157155408Srwatson * Targ_Init --
158155408Srwatson *	Initialize this module
159155408Srwatson *
160155408Srwatson * Results:
161155408Srwatson *	None
162155408Srwatson *
163155408Srwatson * Side Effects:
164155408Srwatson *	The allTargets list and the targets hash table are initialized
165155408Srwatson *-----------------------------------------------------------------------
166155408Srwatson */
167155408Srwatsonvoid
168155408SrwatsonTarg_Init(void)
169155408Srwatson{
170155408Srwatson    allTargets = Lst_Init(FALSE);
171155408Srwatson    Hash_InitTable(&targets, HTSIZE);
172155408Srwatson}
173155408Srwatson
174155408Srwatson/*-
175161582Srwatson *-----------------------------------------------------------------------
176155408Srwatson * Targ_End --
177155408Srwatson *	Finalize this module
178155408Srwatson *
179159269Srwatson * Results:
180155408Srwatson *	None
181155408Srwatson *
182155408Srwatson * Side Effects:
183155408Srwatson *	All lists and gnodes are cleared
184155408Srwatson *-----------------------------------------------------------------------
185161582Srwatson */
186155408Srwatsonvoid
187155408SrwatsonTarg_End(void)
188155408Srwatson{
189161582Srwatson#ifdef CLEANUP
190161582Srwatson    Lst_Destroy(allTargets, NULL);
191161582Srwatson    if (allGNs)
192161582Srwatson	Lst_Destroy(allGNs, TargFreeGN);
193161582Srwatson    Hash_DeleteTable(&targets);
194161582Srwatson#endif
195161582Srwatson}
196161582Srwatson
197161582Srwatson/*-
198161582Srwatson *-----------------------------------------------------------------------
199155408Srwatson * Targ_List --
200155408Srwatson *	Return the list of all targets
201155408Srwatson *
202155408Srwatson * Results:
203155408Srwatson *	The list of all targets.
204155408Srwatson *
205155408Srwatson * Side Effects:
206155408Srwatson *	None
207155408Srwatson *-----------------------------------------------------------------------
208155408Srwatson */
209155408SrwatsonLst
210155408SrwatsonTarg_List(void)
211155408Srwatson{
212155408Srwatson    return allTargets;
213155408Srwatson}
214155408Srwatson
215155408Srwatson/*-
216155408Srwatson *-----------------------------------------------------------------------
217155408Srwatson * Targ_NewGN  --
218155408Srwatson *	Create and initialize a new graph node
219159269Srwatson *
220159269Srwatson * Input:
221159269Srwatson *	name		the name to stick in the new node
222159269Srwatson *
223159269Srwatson * Results:
224159269Srwatson *	An initialized graph node with the name field filled with a copy
225159269Srwatson *	of the passed name
226159269Srwatson *
227159269Srwatson * Side Effects:
228159269Srwatson *	The gnode is added to the list of all gnodes.
229159269Srwatson *-----------------------------------------------------------------------
230159269Srwatson */
231159269SrwatsonGNode *
232159269SrwatsonTarg_NewGN(const char *name)
233159269Srwatson{
234159269Srwatson    GNode *gn;
235159269Srwatson
236159269Srwatson    gn = bmake_malloc(sizeof(GNode));
237159269Srwatson    gn->name = bmake_strdup(name);
238159269Srwatson    gn->uname = NULL;
239159269Srwatson    gn->path = NULL;
240159269Srwatson    if (name[0] == '-' && name[1] == 'l') {
241159269Srwatson	gn->type = OP_LIB;
242159269Srwatson    } else {
243159269Srwatson	gn->type = 0;
244159269Srwatson    }
245159269Srwatson    gn->unmade =    	0;
246159269Srwatson    gn->unmade_cohorts = 0;
247159269Srwatson    gn->cohort_num[0] = 0;
248159269Srwatson    gn->centurion =    	NULL;
249159269Srwatson    gn->made = 	    	UNMADE;
250159269Srwatson    gn->flags = 	0;
251159269Srwatson    gn->checked =	0;
252159269Srwatson    gn->mtime =		0;
253159269Srwatson    gn->cmgn =		NULL;
254159269Srwatson    gn->iParents =  	Lst_Init(FALSE);
255159269Srwatson    gn->cohorts =   	Lst_Init(FALSE);
256159269Srwatson    gn->parents =   	Lst_Init(FALSE);
257159269Srwatson    gn->children =  	Lst_Init(FALSE);
258159269Srwatson    gn->order_pred =  	Lst_Init(FALSE);
259159269Srwatson    gn->order_succ =  	Lst_Init(FALSE);
260159269Srwatson    Hash_InitTable(&gn->context, 0);
261159269Srwatson    gn->commands =  	Lst_Init(FALSE);
262159269Srwatson    gn->suffix =	NULL;
263159269Srwatson    gn->lineno =	0;
264159269Srwatson    gn->fname = 	NULL;
265159269Srwatson
266159269Srwatson#ifdef CLEANUP
267159269Srwatson    if (allGNs == NULL)
268159269Srwatson	allGNs = Lst_Init(FALSE);
269159269Srwatson    Lst_AtEnd(allGNs, gn);
270159269Srwatson#endif
271159269Srwatson
272159269Srwatson    return (gn);
273159269Srwatson}
274159269Srwatson
275159269Srwatson#ifdef CLEANUP
276159269Srwatson/*-
277159269Srwatson *-----------------------------------------------------------------------
278159269Srwatson * TargFreeGN  --
279159269Srwatson *	Destroy a GNode
280159269Srwatson *
281159269Srwatson * Results:
282159269Srwatson *	None.
283159269Srwatson *
284159269Srwatson * Side Effects:
285159269Srwatson *	None.
286159269Srwatson *-----------------------------------------------------------------------
287159269Srwatson */
288159269Srwatsonstatic void
289159269SrwatsonTargFreeGN(void *gnp)
290159269Srwatson{
291159269Srwatson    GNode *gn = (GNode *)gnp;
292159269Srwatson
293159269Srwatson
294159269Srwatson    free(gn->name);
295159269Srwatson    if (gn->uname)
296159269Srwatson	free(gn->uname);
297159269Srwatson    if (gn->path)
298159269Srwatson	free(gn->path);
299159269Srwatson    /* gn->fname points to name allocated when file was opened, don't free */
300159269Srwatson
301159269Srwatson    Lst_Destroy(gn->iParents, NULL);
302159269Srwatson    Lst_Destroy(gn->cohorts, NULL);
303159269Srwatson    Lst_Destroy(gn->parents, NULL);
304159269Srwatson    Lst_Destroy(gn->children, NULL);
305159269Srwatson    Lst_Destroy(gn->order_succ, NULL);
306159269Srwatson    Lst_Destroy(gn->order_pred, NULL);
307159269Srwatson    Hash_DeleteTable(&gn->context);
308159269Srwatson    Lst_Destroy(gn->commands, NULL);
309159269Srwatson    free(gn);
310159269Srwatson}
311159269Srwatson#endif
312159269Srwatson
313159269Srwatson
314159269Srwatson/*-
315159269Srwatson *-----------------------------------------------------------------------
316159269Srwatson * Targ_FindNode  --
317159269Srwatson *	Find a node in the list using the given name for matching
318159269Srwatson *
319159269Srwatson * Input:
320159269Srwatson *	name		the name to find
321159269Srwatson *	flags		flags governing events when target not
322159269Srwatson *			found
323159269Srwatson *
324159269Srwatson * Results:
325159269Srwatson *	The node in the list if it was. If it wasn't, return NULL of
326159269Srwatson *	flags was TARG_NOCREATE or the newly created and initialized node
327159269Srwatson *	if it was TARG_CREATE
328159269Srwatson *
329159269Srwatson * Side Effects:
330159269Srwatson *	Sometimes a node is created and added to the list
331159269Srwatson *-----------------------------------------------------------------------
332159269Srwatson */
333159269SrwatsonGNode *
334159269SrwatsonTarg_FindNode(const char *name, int flags)
335159269Srwatson{
336159269Srwatson    GNode         *gn;	      /* node in that element */
337159269Srwatson    Hash_Entry	  *he = NULL; /* New or used hash entry for node */
338159269Srwatson    Boolean	  isNew;      /* Set TRUE if Hash_CreateEntry had to create */
339159269Srwatson			      /* an entry for the node */
340159269Srwatson
341159269Srwatson    if (!(flags & (TARG_CREATE | TARG_NOHASH))) {
342159269Srwatson	he = Hash_FindEntry(&targets, name);
343159269Srwatson	if (he == NULL)
344159269Srwatson	    return NULL;
345159269Srwatson	return (GNode *)Hash_GetValue(he);
346159269Srwatson    }
347159269Srwatson
348159269Srwatson    if (!(flags & TARG_NOHASH)) {
349159269Srwatson	he = Hash_CreateEntry(&targets, name, &isNew);
350159269Srwatson	if (!isNew)
351159269Srwatson	    return (GNode *)Hash_GetValue(he);
352159269Srwatson    }
353159269Srwatson
354159269Srwatson    gn = Targ_NewGN(name);
355159269Srwatson    if (!(flags & TARG_NOHASH))
356159269Srwatson	Hash_SetValue(he, gn);
357159269Srwatson    Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
358159269Srwatson    (void)Lst_AtEnd(allTargets, gn);
359159269Srwatson    if (doing_depend)
360159269Srwatson	gn->flags |= FROM_DEPEND;
361159269Srwatson    return gn;
362159269Srwatson}
363159269Srwatson
364159269Srwatson/*-
365159269Srwatson *-----------------------------------------------------------------------
366159269Srwatson * Targ_FindList --
367159269Srwatson *	Make a complete list of GNodes from the given list of names
368159269Srwatson *
369159269Srwatson * Input:
370159269Srwatson *	name		list of names to find
371159269Srwatson *	flags		flags used if no node is found for a given name
372159269Srwatson *
373159269Srwatson * Results:
374159269Srwatson *	A complete list of graph nodes corresponding to all instances of all
375159269Srwatson *	the names in names.
376159269Srwatson *
377159269Srwatson * Side Effects:
378159269Srwatson *	If flags is TARG_CREATE, nodes will be created for all names in
379159269Srwatson *	names which do not yet have graph nodes. If flags is TARG_NOCREATE,
380159269Srwatson *	an error message will be printed for each name which can't be found.
381159269Srwatson * -----------------------------------------------------------------------
382159269Srwatson */
383159269SrwatsonLst
384159269SrwatsonTarg_FindList(Lst names, int flags)
385159269Srwatson{
386159269Srwatson    Lst            nodes;	/* result list */
387159269Srwatson    LstNode	   ln;		/* name list element */
388159269Srwatson    GNode	   *gn;		/* node in tLn */
389159269Srwatson    char    	   *name;
390159269Srwatson
391159269Srwatson    nodes = Lst_Init(FALSE);
392159269Srwatson
393159269Srwatson    if (Lst_Open(names) == FAILURE) {
394159269Srwatson	return (nodes);
395159269Srwatson    }
396159269Srwatson    while ((ln = Lst_Next(names)) != NULL) {
397159269Srwatson	name = (char *)Lst_Datum(ln);
398155408Srwatson	gn = Targ_FindNode(name, flags);
399155408Srwatson	if (gn != NULL) {
400155408Srwatson	    /*
401155408Srwatson	     * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
402155408Srwatson	     * are added to the list in the order in which they were
403155408Srwatson	     * encountered in the makefile.
404155408Srwatson	     */
405155408Srwatson	    (void)Lst_AtEnd(nodes, gn);
406155408Srwatson	} else if (flags == TARG_NOCREATE) {
407155408Srwatson	    Error("\"%s\" -- target unknown.", name);
408155408Srwatson	}
409155408Srwatson    }
410155408Srwatson    Lst_Close(names);
411155408Srwatson    return (nodes);
412156292Srwatson}
413155408Srwatson
414155408Srwatson/*-
415155408Srwatson *-----------------------------------------------------------------------
416155408Srwatson * Targ_Ignore  --
417155408Srwatson *	Return true if should ignore errors when creating gn
418155408Srwatson *
419155408Srwatson * Input:
420155408Srwatson *	gn		node to check for
421155408Srwatson *
422155408Srwatson * Results:
423155408Srwatson *	TRUE if should ignore errors
424155408Srwatson *
425155408Srwatson * Side Effects:
426155408Srwatson *	None
427155408Srwatson *-----------------------------------------------------------------------
428155408Srwatson */
429155408SrwatsonBoolean
430155408SrwatsonTarg_Ignore(GNode *gn)
431155428Srwatson{
432155408Srwatson    if (ignoreErrors || gn->type & OP_IGNORE) {
433155408Srwatson	return (TRUE);
434155408Srwatson    } else {
435155408Srwatson	return (FALSE);
436155408Srwatson    }
437155408Srwatson}
438155408Srwatson
439155408Srwatson/*-
440161582Srwatson *-----------------------------------------------------------------------
441155408Srwatson * Targ_Silent  --
442155408Srwatson *	Return true if be silent when creating gn
443155408Srwatson *
444155408Srwatson * Input:
445155408Srwatson *	gn		node to check for
446155408Srwatson *
447155408Srwatson * Results:
448155408Srwatson *	TRUE if should be silent
449155408Srwatson *
450159269Srwatson * Side Effects:
451159269Srwatson *	None
452155408Srwatson *-----------------------------------------------------------------------
453155408Srwatson */
454155408SrwatsonBoolean
455155408SrwatsonTarg_Silent(GNode *gn)
456155408Srwatson{
457155408Srwatson    if (beSilent || gn->type & OP_SILENT) {
458155408Srwatson	return (TRUE);
459155408Srwatson    } else {
460155408Srwatson	return (FALSE);
461155408Srwatson    }
462159269Srwatson}
463159269Srwatson
464159269Srwatson/*-
465159269Srwatson *-----------------------------------------------------------------------
466159269Srwatson * Targ_Precious --
467159269Srwatson *	See if the given target is precious
468159269Srwatson *
469159269Srwatson * Input:
470159269Srwatson *	gn		the node to check
471159269Srwatson *
472159269Srwatson * Results:
473159269Srwatson *	TRUE if it is precious. FALSE otherwise
474159269Srwatson *
475159269Srwatson * Side Effects:
476159269Srwatson *	None
477159269Srwatson *-----------------------------------------------------------------------
478159269Srwatson */
479159269SrwatsonBoolean
480159269SrwatsonTarg_Precious(GNode *gn)
481159269Srwatson{
482159269Srwatson    if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
483159269Srwatson	return (TRUE);
484159269Srwatson    } else {
485159269Srwatson	return (FALSE);
486159269Srwatson    }
487159269Srwatson}
488159269Srwatson
489159269Srwatson/******************* DEBUG INFO PRINTING ****************/
490159269Srwatson
491159269Srwatsonstatic GNode	  *mainTarg;	/* the main target, as set by Targ_SetMain */
492155408Srwatson/*-
493155408Srwatson *-----------------------------------------------------------------------
494155408Srwatson * Targ_SetMain --
495155408Srwatson *	Set our idea of the main target we'll be creating. Used for
496155408Srwatson *	debugging output.
497155408Srwatson *
498155408Srwatson * Input:
499159269Srwatson *	gn		The main target we'll create
500155408Srwatson *
501159269Srwatson * Results:
502155408Srwatson *	None.
503155408Srwatson *
504155408Srwatson * Side Effects:
505155408Srwatson *	"mainTarg" is set to the main target's node.
506155408Srwatson *-----------------------------------------------------------------------
507155408Srwatson */
508155408Srwatsonvoid
509155408SrwatsonTarg_SetMain(GNode *gn)
510155408Srwatson{
511155408Srwatson    mainTarg = gn;
512155408Srwatson}
513155408Srwatson
514155408Srwatsonstatic int
515155408SrwatsonTargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED)
516155408Srwatson{
517155408Srwatson    GNode *gn = (GNode *)gnp;
518155408Srwatson
519155408Srwatson    fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num);
520155408Srwatson
521155408Srwatson    return 0;
522155408Srwatson}
523155408Srwatson
524155408Srwatson
525155408Srwatsonint
526155408SrwatsonTarg_PrintCmd(void *cmd, void *dummy)
527155408Srwatson{
528155408Srwatson    fprintf(debug_file, "\t%s\n", (char *)cmd);
529155408Srwatson    return (dummy ? 0 : 0);
530155408Srwatson}
531155408Srwatson
532155408Srwatson/*-
533155408Srwatson *-----------------------------------------------------------------------
534155408Srwatson * Targ_FmtTime --
535155408Srwatson *	Format a modification time in some reasonable way and return it.
536161582Srwatson *
537161582Srwatson * Results:
538159269Srwatson *	The time reformatted.
539159269Srwatson *
540159269Srwatson * Side Effects:
541159269Srwatson *	The time is placed in a static area, so it is overwritten
542159269Srwatson *	with each call.
543159269Srwatson *
544159269Srwatson *-----------------------------------------------------------------------
545159269Srwatson */
546159269Srwatsonchar *
547159269SrwatsonTarg_FmtTime(time_t tm)
548159269Srwatson{
549159269Srwatson    struct tm	  	*parts;
550159269Srwatson    static char	  	buf[128];
551161582Srwatson
552161582Srwatson    parts = localtime(&tm);
553161582Srwatson    (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
554155408Srwatson    return(buf);
555155408Srwatson}
556155408Srwatson
557159269Srwatson/*-
558155408Srwatson *-----------------------------------------------------------------------
559155408Srwatson * Targ_PrintType --
560155408Srwatson *	Print out a type field giving only those attributes the user can
561155408Srwatson *	set.
562159269Srwatson *
563155408Srwatson * Results:
564155408Srwatson *
565159269Srwatson * Side Effects:
566155408Srwatson *
567155408Srwatson *-----------------------------------------------------------------------
568155408Srwatson */
569155408Srwatsonvoid
570155408SrwatsonTarg_PrintType(int type)
571155408Srwatson{
572155408Srwatson    int    tbit;
573155408Srwatson
574155408Srwatson#define PRINTBIT(attr)	case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break
575155408Srwatson#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break
576155408Srwatson
577159269Srwatson    type &= ~OP_OPMASK;
578159269Srwatson
579159269Srwatson    while (type) {
580159269Srwatson	tbit = 1 << (ffs(type) - 1);
581159269Srwatson	type &= ~tbit;
582159269Srwatson
583159269Srwatson	switch(tbit) {
584159269Srwatson	    PRINTBIT(OPTIONAL);
585159269Srwatson	    PRINTBIT(USE);
586159269Srwatson	    PRINTBIT(EXEC);
587159269Srwatson	    PRINTBIT(IGNORE);
588159269Srwatson	    PRINTBIT(PRECIOUS);
589159269Srwatson	    PRINTBIT(SILENT);
590159269Srwatson	    PRINTBIT(MAKE);
591159269Srwatson	    PRINTBIT(JOIN);
592159269Srwatson	    PRINTBIT(INVISIBLE);
593161582Srwatson	    PRINTBIT(NOTMAIN);
594159269Srwatson	    PRINTDBIT(LIB);
595155408Srwatson	    /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
596155408Srwatson	    case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break;
597155408Srwatson	    PRINTDBIT(ARCHV);
598155408Srwatson	    PRINTDBIT(MADE);
599155408Srwatson	    PRINTDBIT(PHONY);
600155408Srwatson	}
601155408Srwatson    }
602155408Srwatson}
603155408Srwatson
604155408Srwatsonstatic const char *
605155408Srwatsonmade_name(enum enum_made made)
606155408Srwatson{
607155408Srwatson    switch (made) {
608155408Srwatson    case UNMADE:     return "unmade";
609155408Srwatson    case DEFERRED:   return "deferred";
610155408Srwatson    case REQUESTED:  return "requested";
611155408Srwatson    case BEINGMADE:  return "being made";
612155408Srwatson    case MADE:       return "made";
613155408Srwatson    case UPTODATE:   return "up-to-date";
614155408Srwatson    case ERROR:      return "error when made";
615155408Srwatson    case ABORTED:    return "aborted";
616155408Srwatson    default:         return "unknown enum_made value";
617155408Srwatson    }
618155408Srwatson}
619155408Srwatson
620155408Srwatson/*-
621155408Srwatson *-----------------------------------------------------------------------
622155408Srwatson * TargPrintNode --
623155408Srwatson *	print the contents of a node
624155408Srwatson *-----------------------------------------------------------------------
625155408Srwatson */
626155408Srwatsonint
627155408SrwatsonTarg_PrintNode(void *gnp, void *passp)
628155408Srwatson{
629155408Srwatson    GNode         *gn = (GNode *)gnp;
630155408Srwatson    int	    	  pass = passp ? *(int *)passp : 0;
631155408Srwatson
632155408Srwatson    fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n",
633155408Srwatson	    gn->name, gn->cohort_num, gn->flags, gn->type, gn->made);
634155408Srwatson    if (gn->flags == 0)
635155408Srwatson	return 0;
636155408Srwatson
637155408Srwatson    if (!OP_NOP(gn->type)) {
638155408Srwatson	fprintf(debug_file, "#\n");
639155408Srwatson	if (gn == mainTarg) {
640155408Srwatson	    fprintf(debug_file, "# *** MAIN TARGET ***\n");
641155408Srwatson	}
642155408Srwatson	if (pass >= 2) {
643155408Srwatson	    if (gn->unmade) {
644155408Srwatson		fprintf(debug_file, "# %d unmade children\n", gn->unmade);
645155408Srwatson	    } else {
646155408Srwatson		fprintf(debug_file, "# No unmade children\n");
647155408Srwatson	    }
648155408Srwatson	    if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
649155408Srwatson		if (gn->mtime != 0) {
650155408Srwatson		    fprintf(debug_file, "# last modified %s: %s\n",
651155408Srwatson			      Targ_FmtTime(gn->mtime),
652155408Srwatson			      made_name(gn->made));
653155408Srwatson		} else if (gn->made != UNMADE) {
654155408Srwatson		    fprintf(debug_file, "# non-existent (maybe): %s\n",
655155408Srwatson			      made_name(gn->made));
656155408Srwatson		} else {
657155408Srwatson		    fprintf(debug_file, "# unmade\n");
658155408Srwatson		}
659155408Srwatson	    }
660155408Srwatson	    if (!Lst_IsEmpty (gn->iParents)) {
661155408Srwatson		fprintf(debug_file, "# implicit parents: ");
662155408Srwatson		Lst_ForEach(gn->iParents, TargPrintName, NULL);
663155408Srwatson		fprintf(debug_file, "\n");
664155408Srwatson	    }
665155408Srwatson	} else {
666155408Srwatson	    if (gn->unmade)
667155408Srwatson		fprintf(debug_file, "# %d unmade children\n", gn->unmade);
668155408Srwatson	}
669155408Srwatson	if (!Lst_IsEmpty (gn->parents)) {
670155408Srwatson	    fprintf(debug_file, "# parents: ");
671155408Srwatson	    Lst_ForEach(gn->parents, TargPrintName, NULL);
672155408Srwatson	    fprintf(debug_file, "\n");
673155408Srwatson	}
674155408Srwatson	if (!Lst_IsEmpty (gn->order_pred)) {
675155408Srwatson	    fprintf(debug_file, "# order_pred: ");
676155408Srwatson	    Lst_ForEach(gn->order_pred, TargPrintName, NULL);
677155408Srwatson	    fprintf(debug_file, "\n");
678155408Srwatson	}
679156880Srwatson	if (!Lst_IsEmpty (gn->order_succ)) {
680156880Srwatson	    fprintf(debug_file, "# order_succ: ");
681155408Srwatson	    Lst_ForEach(gn->order_succ, TargPrintName, NULL);
682155408Srwatson	    fprintf(debug_file, "\n");
683155408Srwatson	}
684155408Srwatson
685155408Srwatson	fprintf(debug_file, "%-16s", gn->name);
686155408Srwatson	switch (gn->type & OP_OPMASK) {
687155408Srwatson	    case OP_DEPENDS:
688155408Srwatson		fprintf(debug_file, ": "); break;
689159269Srwatson	    case OP_FORCE:
690155408Srwatson		fprintf(debug_file, "! "); break;
691159269Srwatson	    case OP_DOUBLEDEP:
692159269Srwatson		fprintf(debug_file, ":: "); break;
693159269Srwatson	}
694155408Srwatson	Targ_PrintType(gn->type);
695155408Srwatson	Lst_ForEach(gn->children, TargPrintName, NULL);
696155408Srwatson	fprintf(debug_file, "\n");
697159269Srwatson	Lst_ForEach(gn->commands, Targ_PrintCmd, NULL);
698159269Srwatson	fprintf(debug_file, "\n\n");
699159269Srwatson	if (gn->type & OP_DOUBLEDEP) {
700159269Srwatson	    Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass);
701159269Srwatson	}
702159269Srwatson    }
703155408Srwatson    return (0);
704155408Srwatson}
705155408Srwatson
706155408Srwatson/*-
707155408Srwatson *-----------------------------------------------------------------------
708155408Srwatson * TargPrintOnlySrc --
709155408Srwatson *	Print only those targets that are just a source.
710155408Srwatson *
711155408Srwatson * Results:
712155408Srwatson *	0.
713155408Srwatson *
714155408Srwatson * Side Effects:
715155408Srwatson *	The name of each file is printed preceded by #\t
716155408Srwatson *
717155408Srwatson *-----------------------------------------------------------------------
718155408Srwatson */
719155408Srwatsonstatic int
720155408SrwatsonTargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED)
721155408Srwatson{
722155408Srwatson    GNode   	  *gn = (GNode *)gnp;
723155408Srwatson    if (!OP_NOP(gn->type))
724155408Srwatson	return 0;
725155408Srwatson
726155408Srwatson    fprintf(debug_file, "#\t%s [%s] ",
727155408Srwatson	    gn->name, gn->path ? gn->path : gn->name);
728155408Srwatson    Targ_PrintType(gn->type);
729155408Srwatson    fprintf(debug_file, "\n");
730155408Srwatson
731155408Srwatson    return 0;
732155408Srwatson}
733155408Srwatson
734155408Srwatson/*-
735155408Srwatson *-----------------------------------------------------------------------
736155408Srwatson * Targ_PrintGraph --
737155408Srwatson *	print the entire graph. heh heh
738155408Srwatson *
739155408Srwatson * Input:
740155408Srwatson *	pass		Which pass this is. 1 => no processing
741155408Srwatson *			2 => processing done
742156880Srwatson *
743155408Srwatson * Results:
744156880Srwatson *	none
745156880Srwatson *
746156880Srwatson * Side Effects:
747156880Srwatson *	lots o' output
748156880Srwatson *-----------------------------------------------------------------------
749156880Srwatson */
750156880Srwatsonvoid
751156880SrwatsonTarg_PrintGraph(int pass)
752156880Srwatson{
753156880Srwatson    fprintf(debug_file, "#*** Input graph:\n");
754156880Srwatson    Lst_ForEach(allTargets, Targ_PrintNode, &pass);
755156880Srwatson    fprintf(debug_file, "\n\n");
756156880Srwatson    fprintf(debug_file, "#\n#   Files that are only sources:\n");
757156880Srwatson    Lst_ForEach(allTargets, TargPrintOnlySrc, NULL);
758156880Srwatson    fprintf(debug_file, "#*** Global Variables:\n");
759156880Srwatson    Var_Dump(VAR_GLOBAL);
760156880Srwatson    fprintf(debug_file, "#*** Command-line Variables:\n");
761156880Srwatson    Var_Dump(VAR_CMD);
762156880Srwatson    fprintf(debug_file, "\n");
763156880Srwatson    Dir_PrintDirectories();
764156884Srwatson    fprintf(debug_file, "\n");
765156884Srwatson    Suff_PrintAll();
766156884Srwatson}
767156884Srwatson
768156884Srwatson/*-
769156884Srwatson *-----------------------------------------------------------------------
770156884Srwatson * TargPropagateNode --
771156884Srwatson *	Propagate information from a single node to related nodes if
772156884Srwatson *	appropriate.
773156884Srwatson *
774159269Srwatson * Input:
775159269Srwatson *	gnp		The node that we are processing.
776159269Srwatson *
777159269Srwatson * Results:
778159269Srwatson *	Always returns 0, for the benefit of Lst_ForEach().
779159269Srwatson *
780159269Srwatson * Side Effects:
781159269Srwatson *	Information is propagated from this node to cohort or child
782159269Srwatson *	nodes.
783159269Srwatson *
784159269Srwatson *	If the node was defined with "::", then TargPropagateCohort()
785159269Srwatson *	will be called for each cohort node.
786159269Srwatson *
787159269Srwatson *	If the node has recursive predecessors, then
788159269Srwatson *	TargPropagateRecpred() will be called for each recursive
789159269Srwatson *	predecessor.
790159269Srwatson *-----------------------------------------------------------------------
791159269Srwatson */
792159269Srwatsonstatic int
793159269SrwatsonTargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED)
794159269Srwatson{
795159269Srwatson    GNode	  *gn = (GNode *)gnp;
796159269Srwatson
797159269Srwatson    if (gn->type & OP_DOUBLEDEP)
798159269Srwatson	Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp);
799159269Srwatson    return (0);
800159269Srwatson}
801159269Srwatson
802159269Srwatson/*-
803159269Srwatson *-----------------------------------------------------------------------
804159269Srwatson * TargPropagateCohort --
805159269Srwatson *	Propagate some bits in the type mask from a node to
806159269Srwatson *	a related cohort node.
807159269Srwatson *
808159269Srwatson * Input:
809159269Srwatson *	cnp		The node that we are processing.
810159269Srwatson *	gnp		Another node that has cnp as a cohort.
811159269Srwatson *
812159269Srwatson * Results:
813159269Srwatson *	Always returns 0, for the benefit of Lst_ForEach().
814159269Srwatson *
815159269Srwatson * Side Effects:
816159269Srwatson *	cnp's type bitmask is modified to incorporate some of the
817159269Srwatson *	bits from gnp's type bitmask.  (XXX need a better explanation.)
818159269Srwatson *-----------------------------------------------------------------------
819159269Srwatson */
820159269Srwatsonstatic int
821159269SrwatsonTargPropagateCohort(void *cgnp, void *pgnp)
822159269Srwatson{
823159269Srwatson    GNode	  *cgn = (GNode *)cgnp;
824159269Srwatson    GNode	  *pgn = (GNode *)pgnp;
825159269Srwatson
826159269Srwatson    cgn->type |= pgn->type & ~OP_OPMASK;
827159269Srwatson    return (0);
828159269Srwatson}
829159269Srwatson
830159269Srwatson/*-
831159269Srwatson *-----------------------------------------------------------------------
832159269Srwatson * Targ_Propagate --
833159269Srwatson *	Propagate information between related nodes.  Should be called
834159269Srwatson *	after the makefiles are parsed but before any action is taken.
835159269Srwatson *
836159269Srwatson * Results:
837159269Srwatson *	none
838159269Srwatson *
839159269Srwatson * Side Effects:
840159269Srwatson *	Information is propagated between related nodes throughout the
841159269Srwatson *	graph.
842159269Srwatson *-----------------------------------------------------------------------
843159269Srwatson */
844159269Srwatsonvoid
845159269SrwatsonTarg_Propagate(void)
846159269Srwatson{
847159269Srwatson    Lst_ForEach(allTargets, TargPropagateNode, NULL);
848159269Srwatson}
849159269Srwatson