VirtualBox

source: kBuild/trunk/src/kmk/targ.c@ 47

Last change on this file since 47 was 47, checked in by bird, 22 years ago

ISO Date/Time.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette