Deleted Added
full compact
targ.c (103508) targ.c (103545)
1/*
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)targ.c 8.2 (Berkeley) 3/19/94
39 */
40
41#include <sys/cdefs.h>
1/*
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)targ.c 8.2 (Berkeley) 3/19/94
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/usr.bin/make/targ.c 103508 2002-09-17 22:31:26Z jmallett $");
42__FBSDID("$FreeBSD: head/usr.bin/make/targ.c 103545 2002-09-18 16:13:03Z jmallett $");
43
44/*-
45 * targ.c --
46 * Functions for maintaining the Lst allTargets. Target nodes are
47 * kept in two structures: a Lst, maintained by the list library, and a
48 * hash table, maintained by the hash library.
49 *
50 * Interface:
51 * Targ_Init Initialization procedure.
52 *
53 * Targ_End Cleanup the module
54 *
55 * Targ_NewGN Create a new GNode for the passed target
56 * (string). The node is *not* placed in the
57 * hash table, though all its fields are
58 * initialized.
59 *
60 * Targ_FindNode Find the node for a given target, creating
61 * and storing it if it doesn't exist and the
62 * flags are right (TARG_CREATE)
63 *
64 * Targ_FindList Given a list of names, find nodes for all
65 * of them. If a name doesn't exist and the
66 * TARG_NOCREATE flag was given, an error message
67 * is printed. Else, if a name doesn't exist,
68 * its node is created.
69 *
70 * Targ_Ignore Return TRUE if errors should be ignored when
71 * creating the given target.
72 *
73 * Targ_Silent Return TRUE if we should be silent when
74 * creating the given target.
75 *
76 * Targ_Precious Return TRUE if the target is precious and
77 * should not be removed if we are interrupted.
78 *
79 * Debugging:
80 * Targ_PrintGraph Print out the entire graphm all variables
81 * and statistics for the directory cache. Should
82 * print something for suffixes, too, but...
83 */
84
85#include <stdio.h>
86#include <time.h>
87#include "make.h"
88#include "hash.h"
89#include "dir.h"
90
91static Lst allTargets; /* the list of all targets found so far */
92static Lst allGNs; /* List of all the GNodes */
93static Hash_Table targets; /* a hash table of same */
94
95#define HTSIZE 191 /* initial size of hash table */
96
97static int TargPrintOnlySrc(void *, void *);
98static int TargPrintName(void *, void *);
99static int TargPrintNode(void *, void *);
100static void TargFreeGN(void *);
101
102/*-
103 *-----------------------------------------------------------------------
104 * Targ_Init --
105 * Initialize this module
106 *
107 * Results:
108 * None
109 *
110 * Side Effects:
111 * The allTargets list and the targets hash table are initialized
112 *-----------------------------------------------------------------------
113 */
114void
115Targ_Init ()
116{
117 allTargets = Lst_Init (FALSE);
118 Hash_InitTable (&targets, HTSIZE);
119}
120
121/*-
122 *-----------------------------------------------------------------------
123 * Targ_End --
124 * Finalize this module
125 *
126 * Results:
127 * None
128 *
129 * Side Effects:
130 * All lists and gnodes are cleared
131 *-----------------------------------------------------------------------
132 */
133void
134Targ_End ()
135{
136 Lst_Destroy(allTargets, NOFREE);
137 if (allGNs)
138 Lst_Destroy(allGNs, TargFreeGN);
139 Hash_DeleteTable(&targets);
140}
141
142/*-
143 *-----------------------------------------------------------------------
144 * Targ_NewGN --
145 * Create and initialize a new graph node
146 *
147 * Results:
148 * An initialized graph node with the name field filled with a copy
149 * of the passed name
150 *
151 * Side Effects:
152 * The gnode is added to the list of all gnodes.
153 *-----------------------------------------------------------------------
154 */
155GNode *
156Targ_NewGN (name)
157 char *name; /* the name to stick in the new node */
158{
159 GNode *gn;
160
161 gn = (GNode *) emalloc (sizeof (GNode));
162 gn->name = estrdup (name);
163 gn->path = (char *) 0;
164 if (name[0] == '-' && name[1] == 'l') {
165 gn->type = OP_LIB;
166 } else {
167 gn->type = 0;
168 }
169 gn->unmade = 0;
170 gn->make = FALSE;
171 gn->made = UNMADE;
172 gn->childMade = FALSE;
173 gn->order = 0;
174 gn->mtime = gn->cmtime = 0;
175 gn->iParents = Lst_Init (FALSE);
176 gn->cohorts = Lst_Init (FALSE);
177 gn->parents = Lst_Init (FALSE);
178 gn->children = Lst_Init (FALSE);
179 gn->successors = Lst_Init (FALSE);
180 gn->preds = Lst_Init (FALSE);
181 gn->context = Lst_Init (FALSE);
182 gn->commands = Lst_Init (FALSE);
183 gn->suffix = NULL;
184
185 if (allGNs == NULL)
186 allGNs = Lst_Init(FALSE);
187 Lst_AtEnd(allGNs, (void *) gn);
188
189 return (gn);
190}
191
192/*-
193 *-----------------------------------------------------------------------
194 * TargFreeGN --
195 * Destroy a GNode
196 *
197 * Results:
198 * None.
199 *
200 * Side Effects:
201 * None.
202 *-----------------------------------------------------------------------
203 */
204static void
205TargFreeGN (gnp)
206 void * gnp;
207{
208 GNode *gn = (GNode *) gnp;
209
210
211 free(gn->name);
212 efree(gn->path);
213
214 Lst_Destroy(gn->iParents, NOFREE);
215 Lst_Destroy(gn->cohorts, NOFREE);
216 Lst_Destroy(gn->parents, NOFREE);
217 Lst_Destroy(gn->children, NOFREE);
218 Lst_Destroy(gn->successors, NOFREE);
219 Lst_Destroy(gn->preds, NOFREE);
220 Lst_Destroy(gn->context, NOFREE);
221 Lst_Destroy(gn->commands, NOFREE);
222 free(gn);
223}
224
225
226/*-
227 *-----------------------------------------------------------------------
228 * Targ_FindNode --
229 * Find a node in the list using the given name for matching
230 *
231 * Results:
232 * The node in the list if it was. If it wasn't, return NULL of
233 * flags was TARG_NOCREATE or the newly created and initialized node
234 * if it was TARG_CREATE
235 *
236 * Side Effects:
237 * Sometimes a node is created and added to the list
238 *-----------------------------------------------------------------------
239 */
240GNode *
241Targ_FindNode (name, flags)
242 char *name; /* the name to find */
243 int flags; /* flags governing events when target not
244 * found */
245{
246 GNode *gn; /* node in that element */
247 Hash_Entry *he; /* New or used hash entry for node */
248 Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */
249 /* an entry for the node */
250
251
252 if (flags & TARG_CREATE) {
253 he = Hash_CreateEntry (&targets, name, &isNew);
254 if (isNew) {
255 gn = Targ_NewGN (name);
256 Hash_SetValue (he, gn);
257 (void) Lst_AtEnd (allTargets, (void *)gn);
258 }
259 } else {
260 he = Hash_FindEntry (&targets, name);
261 }
262
263 if (he == (Hash_Entry *) NULL) {
264 return (NULL);
265 } else {
266 return ((GNode *) Hash_GetValue (he));
267 }
268}
269
270/*-
271 *-----------------------------------------------------------------------
272 * Targ_FindList --
273 * Make a complete list of GNodes from the given list of names
274 *
275 * Results:
276 * A complete list of graph nodes corresponding to all instances of all
277 * the names in names.
278 *
279 * Side Effects:
280 * If flags is TARG_CREATE, nodes will be created for all names in
281 * names which do not yet have graph nodes. If flags is TARG_NOCREATE,
282 * an error message will be printed for each name which can't be found.
283 * -----------------------------------------------------------------------
284 */
285Lst
286Targ_FindList (names, flags)
287 Lst names; /* list of names to find */
288 int flags; /* flags used if no node is found for a given
289 * name */
290{
291 Lst nodes; /* result list */
292 LstNode ln; /* name list element */
293 GNode *gn; /* node in tLn */
294 char *name;
295
296 nodes = Lst_Init (FALSE);
297
298 if (Lst_Open (names) == FAILURE) {
299 return (nodes);
300 }
301 while ((ln = Lst_Next (names)) != NULL) {
302 name = (char *)Lst_Datum(ln);
303 gn = Targ_FindNode (name, flags);
304 if (gn != NULL) {
305 /*
306 * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
307 * are added to the list in the order in which they were
308 * encountered in the makefile.
309 */
310 (void) Lst_AtEnd (nodes, (void *)gn);
311 if (gn->type & OP_DOUBLEDEP) {
312 (void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
313 }
314 } else if (flags == TARG_NOCREATE) {
315 Error ("\"%s\" -- target unknown.", name);
316 }
317 }
318 Lst_Close (names);
319 return (nodes);
320}
321
322/*-
323 *-----------------------------------------------------------------------
324 * Targ_Ignore --
325 * Return true if should ignore errors when creating gn
326 *
327 * Results:
328 * TRUE if should ignore errors
329 *
330 * Side Effects:
331 * None
332 *-----------------------------------------------------------------------
333 */
334Boolean
335Targ_Ignore (gn)
336 GNode *gn; /* node to check for */
337{
338 if (ignoreErrors || gn->type & OP_IGNORE) {
339 return (TRUE);
340 } else {
341 return (FALSE);
342 }
343}
344
345/*-
346 *-----------------------------------------------------------------------
347 * Targ_Silent --
348 * Return true if be silent when creating gn
349 *
350 * Results:
351 * TRUE if should be silent
352 *
353 * Side Effects:
354 * None
355 *-----------------------------------------------------------------------
356 */
357Boolean
358Targ_Silent (gn)
359 GNode *gn; /* node to check for */
360{
361 if (beSilent || gn->type & OP_SILENT) {
362 return (TRUE);
363 } else {
364 return (FALSE);
365 }
366}
367
368/*-
369 *-----------------------------------------------------------------------
370 * Targ_Precious --
371 * See if the given target is precious
372 *
373 * Results:
374 * TRUE if it is precious. FALSE otherwise
375 *
376 * Side Effects:
377 * None
378 *-----------------------------------------------------------------------
379 */
380Boolean
381Targ_Precious (gn)
382 GNode *gn; /* the node to check */
383{
384 if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
385 return (TRUE);
386 } else {
387 return (FALSE);
388 }
389}
390
391/******************* DEBUG INFO PRINTING ****************/
392
393static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
394/*-
395 *-----------------------------------------------------------------------
396 * Targ_SetMain --
397 * Set our idea of the main target we'll be creating. Used for
398 * debugging output.
399 *
400 * Results:
401 * None.
402 *
403 * Side Effects:
404 * "mainTarg" is set to the main target's node.
405 *-----------------------------------------------------------------------
406 */
407void
408Targ_SetMain (gn)
409 GNode *gn; /* The main target we'll create */
410{
411 mainTarg = gn;
412}
413
414static int
415TargPrintName (gnp, ppath)
416 void * gnp;
417 void * ppath;
418{
419 GNode *gn = (GNode *) gnp;
420 printf ("%s ", gn->name);
421#ifdef notdef
422 if (ppath) {
423 if (gn->path) {
424 printf ("[%s] ", gn->path);
425 }
426 if (gn == mainTarg) {
427 printf ("(MAIN NAME) ");
428 }
429 }
430#endif /* notdef */
431 return (ppath ? 0 : 0);
432}
433
434
435int
436Targ_PrintCmd (cmd, dummy)
437 void * cmd;
438 void * dummy;
439{
440 printf ("\t%s\n", (char *) cmd);
441 return (dummy ? 0 : 0);
442}
443
444/*-
445 *-----------------------------------------------------------------------
446 * Targ_FmtTime --
447 * Format a modification time in some reasonable way and return it.
448 *
449 * Results:
450 * The time reformatted.
451 *
452 * Side Effects:
453 * The time is placed in a static area, so it is overwritten
454 * with each call.
455 *
456 *-----------------------------------------------------------------------
457 */
458char *
459Targ_FmtTime (time)
460 time_t time;
461{
462 struct tm *parts;
463 static char buf[128];
464
465 parts = localtime(&time);
466
467 strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
468 buf[sizeof(buf) - 1] = '\0';
469 return(buf);
470}
471
472/*-
473 *-----------------------------------------------------------------------
474 * Targ_PrintType --
475 * Print out a type field giving only those attributes the user can
476 * set.
477 *
478 * Results:
479 *
480 * Side Effects:
481 *
482 *-----------------------------------------------------------------------
483 */
484void
485Targ_PrintType (type)
486 int type;
487{
488 int tbit;
489
490#define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
43
44/*-
45 * targ.c --
46 * Functions for maintaining the Lst allTargets. Target nodes are
47 * kept in two structures: a Lst, maintained by the list library, and a
48 * hash table, maintained by the hash library.
49 *
50 * Interface:
51 * Targ_Init Initialization procedure.
52 *
53 * Targ_End Cleanup the module
54 *
55 * Targ_NewGN Create a new GNode for the passed target
56 * (string). The node is *not* placed in the
57 * hash table, though all its fields are
58 * initialized.
59 *
60 * Targ_FindNode Find the node for a given target, creating
61 * and storing it if it doesn't exist and the
62 * flags are right (TARG_CREATE)
63 *
64 * Targ_FindList Given a list of names, find nodes for all
65 * of them. If a name doesn't exist and the
66 * TARG_NOCREATE flag was given, an error message
67 * is printed. Else, if a name doesn't exist,
68 * its node is created.
69 *
70 * Targ_Ignore Return TRUE if errors should be ignored when
71 * creating the given target.
72 *
73 * Targ_Silent Return TRUE if we should be silent when
74 * creating the given target.
75 *
76 * Targ_Precious Return TRUE if the target is precious and
77 * should not be removed if we are interrupted.
78 *
79 * Debugging:
80 * Targ_PrintGraph Print out the entire graphm all variables
81 * and statistics for the directory cache. Should
82 * print something for suffixes, too, but...
83 */
84
85#include <stdio.h>
86#include <time.h>
87#include "make.h"
88#include "hash.h"
89#include "dir.h"
90
91static Lst allTargets; /* the list of all targets found so far */
92static Lst allGNs; /* List of all the GNodes */
93static Hash_Table targets; /* a hash table of same */
94
95#define HTSIZE 191 /* initial size of hash table */
96
97static int TargPrintOnlySrc(void *, void *);
98static int TargPrintName(void *, void *);
99static int TargPrintNode(void *, void *);
100static void TargFreeGN(void *);
101
102/*-
103 *-----------------------------------------------------------------------
104 * Targ_Init --
105 * Initialize this module
106 *
107 * Results:
108 * None
109 *
110 * Side Effects:
111 * The allTargets list and the targets hash table are initialized
112 *-----------------------------------------------------------------------
113 */
114void
115Targ_Init ()
116{
117 allTargets = Lst_Init (FALSE);
118 Hash_InitTable (&targets, HTSIZE);
119}
120
121/*-
122 *-----------------------------------------------------------------------
123 * Targ_End --
124 * Finalize this module
125 *
126 * Results:
127 * None
128 *
129 * Side Effects:
130 * All lists and gnodes are cleared
131 *-----------------------------------------------------------------------
132 */
133void
134Targ_End ()
135{
136 Lst_Destroy(allTargets, NOFREE);
137 if (allGNs)
138 Lst_Destroy(allGNs, TargFreeGN);
139 Hash_DeleteTable(&targets);
140}
141
142/*-
143 *-----------------------------------------------------------------------
144 * Targ_NewGN --
145 * Create and initialize a new graph node
146 *
147 * Results:
148 * An initialized graph node with the name field filled with a copy
149 * of the passed name
150 *
151 * Side Effects:
152 * The gnode is added to the list of all gnodes.
153 *-----------------------------------------------------------------------
154 */
155GNode *
156Targ_NewGN (name)
157 char *name; /* the name to stick in the new node */
158{
159 GNode *gn;
160
161 gn = (GNode *) emalloc (sizeof (GNode));
162 gn->name = estrdup (name);
163 gn->path = (char *) 0;
164 if (name[0] == '-' && name[1] == 'l') {
165 gn->type = OP_LIB;
166 } else {
167 gn->type = 0;
168 }
169 gn->unmade = 0;
170 gn->make = FALSE;
171 gn->made = UNMADE;
172 gn->childMade = FALSE;
173 gn->order = 0;
174 gn->mtime = gn->cmtime = 0;
175 gn->iParents = Lst_Init (FALSE);
176 gn->cohorts = Lst_Init (FALSE);
177 gn->parents = Lst_Init (FALSE);
178 gn->children = Lst_Init (FALSE);
179 gn->successors = Lst_Init (FALSE);
180 gn->preds = Lst_Init (FALSE);
181 gn->context = Lst_Init (FALSE);
182 gn->commands = Lst_Init (FALSE);
183 gn->suffix = NULL;
184
185 if (allGNs == NULL)
186 allGNs = Lst_Init(FALSE);
187 Lst_AtEnd(allGNs, (void *) gn);
188
189 return (gn);
190}
191
192/*-
193 *-----------------------------------------------------------------------
194 * TargFreeGN --
195 * Destroy a GNode
196 *
197 * Results:
198 * None.
199 *
200 * Side Effects:
201 * None.
202 *-----------------------------------------------------------------------
203 */
204static void
205TargFreeGN (gnp)
206 void * gnp;
207{
208 GNode *gn = (GNode *) gnp;
209
210
211 free(gn->name);
212 efree(gn->path);
213
214 Lst_Destroy(gn->iParents, NOFREE);
215 Lst_Destroy(gn->cohorts, NOFREE);
216 Lst_Destroy(gn->parents, NOFREE);
217 Lst_Destroy(gn->children, NOFREE);
218 Lst_Destroy(gn->successors, NOFREE);
219 Lst_Destroy(gn->preds, NOFREE);
220 Lst_Destroy(gn->context, NOFREE);
221 Lst_Destroy(gn->commands, NOFREE);
222 free(gn);
223}
224
225
226/*-
227 *-----------------------------------------------------------------------
228 * Targ_FindNode --
229 * Find a node in the list using the given name for matching
230 *
231 * Results:
232 * The node in the list if it was. If it wasn't, return NULL of
233 * flags was TARG_NOCREATE or the newly created and initialized node
234 * if it was TARG_CREATE
235 *
236 * Side Effects:
237 * Sometimes a node is created and added to the list
238 *-----------------------------------------------------------------------
239 */
240GNode *
241Targ_FindNode (name, flags)
242 char *name; /* the name to find */
243 int flags; /* flags governing events when target not
244 * found */
245{
246 GNode *gn; /* node in that element */
247 Hash_Entry *he; /* New or used hash entry for node */
248 Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */
249 /* an entry for the node */
250
251
252 if (flags & TARG_CREATE) {
253 he = Hash_CreateEntry (&targets, name, &isNew);
254 if (isNew) {
255 gn = Targ_NewGN (name);
256 Hash_SetValue (he, gn);
257 (void) Lst_AtEnd (allTargets, (void *)gn);
258 }
259 } else {
260 he = Hash_FindEntry (&targets, name);
261 }
262
263 if (he == (Hash_Entry *) NULL) {
264 return (NULL);
265 } else {
266 return ((GNode *) Hash_GetValue (he));
267 }
268}
269
270/*-
271 *-----------------------------------------------------------------------
272 * Targ_FindList --
273 * Make a complete list of GNodes from the given list of names
274 *
275 * Results:
276 * A complete list of graph nodes corresponding to all instances of all
277 * the names in names.
278 *
279 * Side Effects:
280 * If flags is TARG_CREATE, nodes will be created for all names in
281 * names which do not yet have graph nodes. If flags is TARG_NOCREATE,
282 * an error message will be printed for each name which can't be found.
283 * -----------------------------------------------------------------------
284 */
285Lst
286Targ_FindList (names, flags)
287 Lst names; /* list of names to find */
288 int flags; /* flags used if no node is found for a given
289 * name */
290{
291 Lst nodes; /* result list */
292 LstNode ln; /* name list element */
293 GNode *gn; /* node in tLn */
294 char *name;
295
296 nodes = Lst_Init (FALSE);
297
298 if (Lst_Open (names) == FAILURE) {
299 return (nodes);
300 }
301 while ((ln = Lst_Next (names)) != NULL) {
302 name = (char *)Lst_Datum(ln);
303 gn = Targ_FindNode (name, flags);
304 if (gn != NULL) {
305 /*
306 * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
307 * are added to the list in the order in which they were
308 * encountered in the makefile.
309 */
310 (void) Lst_AtEnd (nodes, (void *)gn);
311 if (gn->type & OP_DOUBLEDEP) {
312 (void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
313 }
314 } else if (flags == TARG_NOCREATE) {
315 Error ("\"%s\" -- target unknown.", name);
316 }
317 }
318 Lst_Close (names);
319 return (nodes);
320}
321
322/*-
323 *-----------------------------------------------------------------------
324 * Targ_Ignore --
325 * Return true if should ignore errors when creating gn
326 *
327 * Results:
328 * TRUE if should ignore errors
329 *
330 * Side Effects:
331 * None
332 *-----------------------------------------------------------------------
333 */
334Boolean
335Targ_Ignore (gn)
336 GNode *gn; /* node to check for */
337{
338 if (ignoreErrors || gn->type & OP_IGNORE) {
339 return (TRUE);
340 } else {
341 return (FALSE);
342 }
343}
344
345/*-
346 *-----------------------------------------------------------------------
347 * Targ_Silent --
348 * Return true if be silent when creating gn
349 *
350 * Results:
351 * TRUE if should be silent
352 *
353 * Side Effects:
354 * None
355 *-----------------------------------------------------------------------
356 */
357Boolean
358Targ_Silent (gn)
359 GNode *gn; /* node to check for */
360{
361 if (beSilent || gn->type & OP_SILENT) {
362 return (TRUE);
363 } else {
364 return (FALSE);
365 }
366}
367
368/*-
369 *-----------------------------------------------------------------------
370 * Targ_Precious --
371 * See if the given target is precious
372 *
373 * Results:
374 * TRUE if it is precious. FALSE otherwise
375 *
376 * Side Effects:
377 * None
378 *-----------------------------------------------------------------------
379 */
380Boolean
381Targ_Precious (gn)
382 GNode *gn; /* the node to check */
383{
384 if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
385 return (TRUE);
386 } else {
387 return (FALSE);
388 }
389}
390
391/******************* DEBUG INFO PRINTING ****************/
392
393static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
394/*-
395 *-----------------------------------------------------------------------
396 * Targ_SetMain --
397 * Set our idea of the main target we'll be creating. Used for
398 * debugging output.
399 *
400 * Results:
401 * None.
402 *
403 * Side Effects:
404 * "mainTarg" is set to the main target's node.
405 *-----------------------------------------------------------------------
406 */
407void
408Targ_SetMain (gn)
409 GNode *gn; /* The main target we'll create */
410{
411 mainTarg = gn;
412}
413
414static int
415TargPrintName (gnp, ppath)
416 void * gnp;
417 void * ppath;
418{
419 GNode *gn = (GNode *) gnp;
420 printf ("%s ", gn->name);
421#ifdef notdef
422 if (ppath) {
423 if (gn->path) {
424 printf ("[%s] ", gn->path);
425 }
426 if (gn == mainTarg) {
427 printf ("(MAIN NAME) ");
428 }
429 }
430#endif /* notdef */
431 return (ppath ? 0 : 0);
432}
433
434
435int
436Targ_PrintCmd (cmd, dummy)
437 void * cmd;
438 void * dummy;
439{
440 printf ("\t%s\n", (char *) cmd);
441 return (dummy ? 0 : 0);
442}
443
444/*-
445 *-----------------------------------------------------------------------
446 * Targ_FmtTime --
447 * Format a modification time in some reasonable way and return it.
448 *
449 * Results:
450 * The time reformatted.
451 *
452 * Side Effects:
453 * The time is placed in a static area, so it is overwritten
454 * with each call.
455 *
456 *-----------------------------------------------------------------------
457 */
458char *
459Targ_FmtTime (time)
460 time_t time;
461{
462 struct tm *parts;
463 static char buf[128];
464
465 parts = localtime(&time);
466
467 strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
468 buf[sizeof(buf) - 1] = '\0';
469 return(buf);
470}
471
472/*-
473 *-----------------------------------------------------------------------
474 * Targ_PrintType --
475 * Print out a type field giving only those attributes the user can
476 * set.
477 *
478 * Results:
479 *
480 * Side Effects:
481 *
482 *-----------------------------------------------------------------------
483 */
484void
485Targ_PrintType (type)
486 int type;
487{
488 int tbit;
489
490#define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
491#define PRINTDBIT(attr) case CONCAT(OP_,attr): DEBUGF(TARG, "." #attr " "); break
491#define PRINTDBIT(attr) case CONCAT(OP_,attr): DEBUGF(TARG, ("." #attr " ")); break
492
493 type &= ~OP_OPMASK;
494
495 while (type) {
496 tbit = 1 << (ffs(type) - 1);
497 type &= ~tbit;
498
499 switch(tbit) {
500 PRINTBIT(OPTIONAL);
501 PRINTBIT(USE);
502 PRINTBIT(EXEC);
503 PRINTBIT(IGNORE);
504 PRINTBIT(PRECIOUS);
505 PRINTBIT(SILENT);
506 PRINTBIT(MAKE);
507 PRINTBIT(JOIN);
508 PRINTBIT(INVISIBLE);
509 PRINTBIT(NOTMAIN);
510 PRINTDBIT(LIB);
511 /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
492
493 type &= ~OP_OPMASK;
494
495 while (type) {
496 tbit = 1 << (ffs(type) - 1);
497 type &= ~tbit;
498
499 switch(tbit) {
500 PRINTBIT(OPTIONAL);
501 PRINTBIT(USE);
502 PRINTBIT(EXEC);
503 PRINTBIT(IGNORE);
504 PRINTBIT(PRECIOUS);
505 PRINTBIT(SILENT);
506 PRINTBIT(MAKE);
507 PRINTBIT(JOIN);
508 PRINTBIT(INVISIBLE);
509 PRINTBIT(NOTMAIN);
510 PRINTDBIT(LIB);
511 /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
512 case OP_MEMBER: DEBUGF(TARG, ".MEMBER "); break;
512 case OP_MEMBER: DEBUGF(TARG, (".MEMBER ")); break;
513 PRINTDBIT(ARCHV);
514 }
515 }
516}
517
518/*-
519 *-----------------------------------------------------------------------
520 * TargPrintNode --
521 * print the contents of a node
522 *-----------------------------------------------------------------------
523 */
524static int
525TargPrintNode (gnp, passp)
526 void * gnp;
527 void * passp;
528{
529 GNode *gn = (GNode *) gnp;
530 int pass = *(int *) passp;
531 if (!OP_NOP(gn->type)) {
532 printf("#\n");
533 if (gn == mainTarg) {
534 printf("# *** MAIN TARGET ***\n");
535 }
536 if (pass == 2) {
537 if (gn->unmade) {
538 printf("# %d unmade children\n", gn->unmade);
539 } else {
540 printf("# No unmade children\n");
541 }
542 if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
543 if (gn->mtime != 0) {
544 printf("# last modified %s: %s\n",
545 Targ_FmtTime(gn->mtime),
546 (gn->made == UNMADE ? "unmade" :
547 (gn->made == MADE ? "made" :
548 (gn->made == UPTODATE ? "up-to-date" :
549 "error when made"))));
550 } else if (gn->made != UNMADE) {
551 printf("# non-existent (maybe): %s\n",
552 (gn->made == MADE ? "made" :
553 (gn->made == UPTODATE ? "up-to-date" :
554 (gn->made == ERROR ? "error when made" :
555 "aborted"))));
556 } else {
557 printf("# unmade\n");
558 }
559 }
560 if (!Lst_IsEmpty (gn->iParents)) {
561 printf("# implicit parents: ");
562 Lst_ForEach (gn->iParents, TargPrintName, (void *)0);
563 fputc ('\n', stdout);
564 }
565 }
566 if (!Lst_IsEmpty (gn->parents)) {
567 printf("# parents: ");
568 Lst_ForEach (gn->parents, TargPrintName, (void *)0);
569 fputc ('\n', stdout);
570 }
571
572 printf("%-16s", gn->name);
573 switch (gn->type & OP_OPMASK) {
574 case OP_DEPENDS:
575 printf(": "); break;
576 case OP_FORCE:
577 printf("! "); break;
578 case OP_DOUBLEDEP:
579 printf(":: "); break;
580 }
581 Targ_PrintType (gn->type);
582 Lst_ForEach (gn->children, TargPrintName, (void *)0);
583 fputc ('\n', stdout);
584 Lst_ForEach (gn->commands, Targ_PrintCmd, (void *)0);
585 printf("\n\n");
586 if (gn->type & OP_DOUBLEDEP) {
587 Lst_ForEach (gn->cohorts, TargPrintNode, (void *)&pass);
588 }
589 }
590 return (0);
591}
592
593/*-
594 *-----------------------------------------------------------------------
595 * TargPrintOnlySrc --
596 * Print only those targets that are just a source.
597 *
598 * Results:
599 * 0.
600 *
601 * Side Effects:
602 * The name of each file is printed preceded by #\t
603 *
604 *-----------------------------------------------------------------------
605 */
606static int
607TargPrintOnlySrc(gnp, dummy)
608 void * gnp;
609 void * dummy;
610{
611 GNode *gn = (GNode *) gnp;
612 if (OP_NOP(gn->type))
613 printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);
614
615 return (dummy ? 0 : 0);
616}
617
618/*-
619 *-----------------------------------------------------------------------
620 * Targ_PrintGraph --
621 * print the entire graph. heh heh
622 *
623 * Results:
624 * none
625 *
626 * Side Effects:
627 * lots o' output
628 *-----------------------------------------------------------------------
629 */
630void
631Targ_PrintGraph (pass)
632 int pass; /* Which pass this is. 1 => no processing
633 * 2 => processing done */
634{
635 printf("#*** Input graph:\n");
636 Lst_ForEach (allTargets, TargPrintNode, (void *)&pass);
637 printf("\n\n");
638 printf("#\n# Files that are only sources:\n");
639 Lst_ForEach (allTargets, TargPrintOnlySrc, (void *) 0);
640 printf("#*** Global Variables:\n");
641 Var_Dump (VAR_GLOBAL);
642 printf("#*** Command-line Variables:\n");
643 Var_Dump (VAR_CMD);
644 printf("\n");
645 Dir_PrintDirectories();
646 printf("\n");
647 Suff_PrintAll();
648}
513 PRINTDBIT(ARCHV);
514 }
515 }
516}
517
518/*-
519 *-----------------------------------------------------------------------
520 * TargPrintNode --
521 * print the contents of a node
522 *-----------------------------------------------------------------------
523 */
524static int
525TargPrintNode (gnp, passp)
526 void * gnp;
527 void * passp;
528{
529 GNode *gn = (GNode *) gnp;
530 int pass = *(int *) passp;
531 if (!OP_NOP(gn->type)) {
532 printf("#\n");
533 if (gn == mainTarg) {
534 printf("# *** MAIN TARGET ***\n");
535 }
536 if (pass == 2) {
537 if (gn->unmade) {
538 printf("# %d unmade children\n", gn->unmade);
539 } else {
540 printf("# No unmade children\n");
541 }
542 if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
543 if (gn->mtime != 0) {
544 printf("# last modified %s: %s\n",
545 Targ_FmtTime(gn->mtime),
546 (gn->made == UNMADE ? "unmade" :
547 (gn->made == MADE ? "made" :
548 (gn->made == UPTODATE ? "up-to-date" :
549 "error when made"))));
550 } else if (gn->made != UNMADE) {
551 printf("# non-existent (maybe): %s\n",
552 (gn->made == MADE ? "made" :
553 (gn->made == UPTODATE ? "up-to-date" :
554 (gn->made == ERROR ? "error when made" :
555 "aborted"))));
556 } else {
557 printf("# unmade\n");
558 }
559 }
560 if (!Lst_IsEmpty (gn->iParents)) {
561 printf("# implicit parents: ");
562 Lst_ForEach (gn->iParents, TargPrintName, (void *)0);
563 fputc ('\n', stdout);
564 }
565 }
566 if (!Lst_IsEmpty (gn->parents)) {
567 printf("# parents: ");
568 Lst_ForEach (gn->parents, TargPrintName, (void *)0);
569 fputc ('\n', stdout);
570 }
571
572 printf("%-16s", gn->name);
573 switch (gn->type & OP_OPMASK) {
574 case OP_DEPENDS:
575 printf(": "); break;
576 case OP_FORCE:
577 printf("! "); break;
578 case OP_DOUBLEDEP:
579 printf(":: "); break;
580 }
581 Targ_PrintType (gn->type);
582 Lst_ForEach (gn->children, TargPrintName, (void *)0);
583 fputc ('\n', stdout);
584 Lst_ForEach (gn->commands, Targ_PrintCmd, (void *)0);
585 printf("\n\n");
586 if (gn->type & OP_DOUBLEDEP) {
587 Lst_ForEach (gn->cohorts, TargPrintNode, (void *)&pass);
588 }
589 }
590 return (0);
591}
592
593/*-
594 *-----------------------------------------------------------------------
595 * TargPrintOnlySrc --
596 * Print only those targets that are just a source.
597 *
598 * Results:
599 * 0.
600 *
601 * Side Effects:
602 * The name of each file is printed preceded by #\t
603 *
604 *-----------------------------------------------------------------------
605 */
606static int
607TargPrintOnlySrc(gnp, dummy)
608 void * gnp;
609 void * dummy;
610{
611 GNode *gn = (GNode *) gnp;
612 if (OP_NOP(gn->type))
613 printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);
614
615 return (dummy ? 0 : 0);
616}
617
618/*-
619 *-----------------------------------------------------------------------
620 * Targ_PrintGraph --
621 * print the entire graph. heh heh
622 *
623 * Results:
624 * none
625 *
626 * Side Effects:
627 * lots o' output
628 *-----------------------------------------------------------------------
629 */
630void
631Targ_PrintGraph (pass)
632 int pass; /* Which pass this is. 1 => no processing
633 * 2 => processing done */
634{
635 printf("#*** Input graph:\n");
636 Lst_ForEach (allTargets, TargPrintNode, (void *)&pass);
637 printf("\n\n");
638 printf("#\n# Files that are only sources:\n");
639 Lst_ForEach (allTargets, TargPrintOnlySrc, (void *) 0);
640 printf("#*** Global Variables:\n");
641 Var_Dump (VAR_GLOBAL);
642 printf("#*** Command-line Variables:\n");
643 Var_Dump (VAR_CMD);
644 printf("\n");
645 Dir_PrintDirectories();
646 printf("\n");
647 Suff_PrintAll();
648}