|
|
1.1 root 1: /*
2: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
3: * Copyright (c) 1988, 1989 by Adam de Boor
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 are permitted
11: * provided that: (1) source distributions retain this entire copyright
12: * notice and comment, and (2) distributions including binaries display
13: * the following acknowledgement: ``This product includes software
14: * developed by the University of California, Berkeley and its contributors''
15: * in the documentation or other materials provided with the distribution
16: * and in all advertising materials mentioning features or use of this
17: * software. Neither the name of the University nor the names of its
18: * contributors may be used to endorse or promote products derived
19: * from this software without specific prior written permission.
20: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
22: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23: */
24:
25: #ifndef lint
26: static char sccsid[] = "@(#)targ.c 5.7 (Berkeley) 6/1/90";
27: #endif /* not lint */
28:
29: /*-
30: * targ.c --
31: * Functions for maintaining the Lst allTargets. Target nodes are
32: * kept in two structures: a Lst, maintained by the list library, and a
33: * hash table, maintained by the hash library.
34: *
35: * Interface:
36: * Targ_Init Initialization procedure.
37: *
38: * Targ_NewGN Create a new GNode for the passed target
39: * (string). The node is *not* placed in the
40: * hash table, though all its fields are
41: * initialized.
42: *
43: * Targ_FindNode Find the node for a given target, creating
44: * and storing it if it doesn't exist and the
45: * flags are right (TARG_CREATE)
46: *
47: * Targ_FindList Given a list of names, find nodes for all
48: * of them. If a name doesn't exist and the
49: * TARG_NOCREATE flag was given, an error message
50: * is printed. Else, if a name doesn't exist,
51: * its node is created.
52: *
53: * Targ_Ignore Return TRUE if errors should be ignored when
54: * creating the given target.
55: *
56: * Targ_Silent Return TRUE if we should be silent when
57: * creating the given target.
58: *
59: * Targ_Precious Return TRUE if the target is precious and
60: * should not be removed if we are interrupted.
61: *
62: * Debugging:
63: * Targ_PrintGraph Print out the entire graphm all variables
64: * and statistics for the directory cache. Should
65: * print something for suffixes, too, but...
66: */
67:
68: #include <stdio.h>
69: #include <time.h>
70: #include "make.h"
71: #include "hash.h"
72:
73: static Lst allTargets; /* the list of all targets found so far */
74: static Hash_Table targets; /* a hash table of same */
75:
76: #define HTSIZE 191 /* initial size of hash table */
77:
78: /*-
79: *-----------------------------------------------------------------------
80: * Targ_Init --
81: * Initialize this module
82: *
83: * Results:
84: * None
85: *
86: * Side Effects:
87: * The allTargets list and the targets hash table are initialized
88: *-----------------------------------------------------------------------
89: */
90: void
91: Targ_Init ()
92: {
93: allTargets = Lst_Init (FALSE);
94: Hash_InitTable (&targets, HTSIZE, HASH_STRING_KEYS);
95: }
96:
97: /*-
98: *-----------------------------------------------------------------------
99: * Targ_NewGN --
100: * Create and initialize a new graph node
101: *
102: * Results:
103: * An initialized graph node with the name field filled with a copy
104: * of the passed name
105: *
106: * Side Effects:
107: * None.
108: *-----------------------------------------------------------------------
109: */
110: GNode *
111: Targ_NewGN (name)
112: char *name; /* the name to stick in the new node */
113: {
114: register GNode *gn;
115:
116: gn = (GNode *) emalloc (sizeof (GNode));
117: gn->name = strdup (name);
118: gn->path = (char *) 0;
119: if (name[0] == '-' && name[1] == 'l') {
120: gn->type = OP_LIB;
121: } else {
122: gn->type = 0;
123: }
124: gn->unmade = 0;
125: gn->make = FALSE;
126: gn->made = UNMADE;
127: gn->childMade = FALSE;
128: gn->mtime = gn->cmtime = 0;
129: gn->iParents = Lst_Init (FALSE);
130: gn->cohorts = Lst_Init (FALSE);
131: gn->parents = Lst_Init (FALSE);
132: gn->children = Lst_Init (FALSE);
133: gn->successors = Lst_Init(FALSE);
134: gn->preds = Lst_Init(FALSE);
135: gn->context = Lst_Init (FALSE);
136: gn->commands = Lst_Init (FALSE);
137:
138: return (gn);
139: }
140:
141: /*-
142: *-----------------------------------------------------------------------
143: * Targ_FindNode --
144: * Find a node in the list using the given name for matching
145: *
146: * Results:
147: * The node in the list if it was. If it wasn't, return NILGNODE of
148: * flags was TARG_NOCREATE or the newly created and initialized node
149: * if it was TARG_CREATE
150: *
151: * Side Effects:
152: * Sometimes a node is created and added to the list
153: *-----------------------------------------------------------------------
154: */
155: GNode *
156: Targ_FindNode (name, flags)
157: char *name; /* the name to find */
158: int flags; /* flags governing events when target not
159: * found */
160: {
161: GNode *gn; /* node in that element */
162: Hash_Entry *he; /* New or used hash entry for node */
163: Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */
164: /* an entry for the node */
165:
166:
167: if (flags & TARG_CREATE) {
168: he = Hash_CreateEntry (&targets, name, &isNew);
169: if (isNew) {
170: gn = Targ_NewGN (name);
171: Hash_SetValue (he, gn);
172: (void) Lst_AtEnd (allTargets, (ClientData)gn);
173: }
174: } else {
175: he = Hash_FindEntry (&targets, name);
176: }
177:
178: if (he == (Hash_Entry *) NULL) {
179: return (NILGNODE);
180: } else {
181: return ((GNode *) Hash_GetValue (he));
182: }
183: }
184:
185: /*-
186: *-----------------------------------------------------------------------
187: * Targ_FindList --
188: * Make a complete list of GNodes from the given list of names
189: *
190: * Results:
191: * A complete list of graph nodes corresponding to all instances of all
192: * the names in names.
193: *
194: * Side Effects:
195: * If flags is TARG_CREATE, nodes will be created for all names in
196: * names which do not yet have graph nodes. If flags is TARG_NOCREATE,
197: * an error message will be printed for each name which can't be found.
198: * -----------------------------------------------------------------------
199: */
200: Lst
201: Targ_FindList (names, flags)
202: Lst names; /* list of names to find */
203: int flags; /* flags used if no node is found for a given
204: * name */
205: {
206: Lst nodes; /* result list */
207: register LstNode ln; /* name list element */
208: register GNode *gn; /* node in tLn */
209: char *name;
210:
211: nodes = Lst_Init (FALSE);
212:
213: if (Lst_Open (names) == FAILURE) {
214: return (nodes);
215: }
216: while ((ln = Lst_Next (names)) != NILLNODE) {
217: name = (char *)Lst_Datum(ln);
218: gn = Targ_FindNode (name, flags);
219: if (gn != NILGNODE) {
220: /*
221: * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
222: * are added to the list in the order in which they were
223: * encountered in the makefile.
224: */
225: (void) Lst_AtEnd (nodes, (ClientData)gn);
226: if (gn->type & OP_DOUBLEDEP) {
227: (void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
228: }
229: } else if (flags == TARG_NOCREATE) {
230: Error ("\"%s\" -- target unknown.", name);
231: }
232: }
233: Lst_Close (names);
234: return (nodes);
235: }
236:
237: /*-
238: *-----------------------------------------------------------------------
239: * Targ_Ignore --
240: * Return true if should ignore errors when creating gn
241: *
242: * Results:
243: * TRUE if should ignore errors
244: *
245: * Side Effects:
246: * None
247: *-----------------------------------------------------------------------
248: */
249: Boolean
250: Targ_Ignore (gn)
251: GNode *gn; /* node to check for */
252: {
253: if (ignoreErrors || gn->type & OP_IGNORE) {
254: return (TRUE);
255: } else {
256: return (FALSE);
257: }
258: }
259:
260: /*-
261: *-----------------------------------------------------------------------
262: * Targ_Silent --
263: * Return true if be silent when creating gn
264: *
265: * Results:
266: * TRUE if should be silent
267: *
268: * Side Effects:
269: * None
270: *-----------------------------------------------------------------------
271: */
272: Boolean
273: Targ_Silent (gn)
274: GNode *gn; /* node to check for */
275: {
276: if (beSilent || gn->type & OP_SILENT) {
277: return (TRUE);
278: } else {
279: return (FALSE);
280: }
281: }
282:
283: /*-
284: *-----------------------------------------------------------------------
285: * Targ_Precious --
286: * See if the given target is precious
287: *
288: * Results:
289: * TRUE if it is precious. FALSE otherwise
290: *
291: * Side Effects:
292: * None
293: *-----------------------------------------------------------------------
294: */
295: Boolean
296: Targ_Precious (gn)
297: GNode *gn; /* the node to check */
298: {
299: if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
300: return (TRUE);
301: } else {
302: return (FALSE);
303: }
304: }
305:
306: /******************* DEBUG INFO PRINTING ****************/
307:
308: static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
309: /*-
310: *-----------------------------------------------------------------------
311: * Targ_SetMain --
312: * Set our idea of the main target we'll be creating. Used for
313: * debugging output.
314: *
315: * Results:
316: * None.
317: *
318: * Side Effects:
319: * "mainTarg" is set to the main target's node.
320: *-----------------------------------------------------------------------
321: */
322: void
323: Targ_SetMain (gn)
324: GNode *gn; /* The main target we'll create */
325: {
326: mainTarg = gn;
327: }
328:
329: static int
330: TargPrintName (gn, ppath)
331: GNode *gn;
332: int ppath;
333: {
334: printf ("%s ", gn->name);
335: #ifdef notdef
336: if (ppath) {
337: if (gn->path) {
338: printf ("[%s] ", gn->path);
339: }
340: if (gn == mainTarg) {
341: printf ("(MAIN NAME) ");
342: }
343: }
344: #endif notdef
345: return (0);
346: }
347:
348:
349: int
350: Targ_PrintCmd (cmd)
351: char *cmd;
352: {
353: printf ("\t%s\n", cmd);
354: return (0);
355: }
356:
357: /*-
358: *-----------------------------------------------------------------------
359: * Targ_FmtTime --
360: * Format a modification time in some reasonable way and return it.
361: *
362: * Results:
363: * The time reformatted.
364: *
365: * Side Effects:
366: * The time is placed in a static area, so it is overwritten
367: * with each call.
368: *
369: *-----------------------------------------------------------------------
370: */
371: char *
372: Targ_FmtTime (time)
373: int time;
374: {
375: struct tm *parts;
376: static char buf[40];
377: static char *months[] = {
378: "Jan", "Feb", "Mar", "Apr", "May", "Jun",
379: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
380: };
381:
382: parts = localtime(&time);
383:
384: sprintf (buf, "%d:%02d:%02d %s %d, 19%d",
385: parts->tm_hour, parts->tm_min, parts->tm_sec,
386: months[parts->tm_mon], parts->tm_mday, parts->tm_year);
387: return(buf);
388: }
389:
390: /*-
391: *-----------------------------------------------------------------------
392: * Targ_PrintType --
393: * Print out a type field giving only those attributes the user can
394: * set.
395: *
396: * Results:
397: *
398: * Side Effects:
399: *
400: *-----------------------------------------------------------------------
401: */
402: void
403: Targ_PrintType (type)
404: register int type;
405: {
406: register int tbit;
407:
408: #ifdef __STDC__
409: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
410: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
411: #else
412: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf(".attr "); break
413: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
414: #endif /* __STDC__ */
415:
416: type &= ~OP_OPMASK;
417:
418: while (type) {
419: tbit = 1 << (ffs(type) - 1);
420: type &= ~tbit;
421:
422: switch(tbit) {
423: PRINTBIT(OPTIONAL);
424: PRINTBIT(USE);
425: PRINTBIT(EXEC);
426: PRINTBIT(IGNORE);
427: PRINTBIT(PRECIOUS);
428: PRINTBIT(SILENT);
429: PRINTBIT(MAKE);
430: PRINTBIT(JOIN);
431: PRINTBIT(INVISIBLE);
432: PRINTBIT(NOTMAIN);
433: PRINTDBIT(LIB);
434: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
435: case OP_MEMBER: if (DEBUG(TARG)) printf(".MEMBER "); break;
436: PRINTDBIT(ARCHV);
437: }
438: }
439: }
440:
441: /*-
442: *-----------------------------------------------------------------------
443: * TargPrintNode --
444: * print the contents of a node
445: *-----------------------------------------------------------------------
446: */
447: static int
448: TargPrintNode (gn, pass)
449: GNode *gn;
450: int pass;
451: {
452: if (!OP_NOP(gn->type)) {
453: printf("#\n");
454: if (gn == mainTarg) {
455: printf("# *** MAIN TARGET ***\n");
456: }
457: if (pass == 2) {
458: if (gn->unmade) {
459: printf("# %d unmade children\n", gn->unmade);
460: } else {
461: printf("# No unmade children\n");
462: }
463: if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
464: if (gn->mtime != 0) {
465: printf("# last modified %s: %s\n",
466: Targ_FmtTime(gn->mtime),
467: (gn->made == UNMADE ? "unmade" :
468: (gn->made == MADE ? "made" :
469: (gn->made == UPTODATE ? "up-to-date" :
470: "error when made"))));
471: } else if (gn->made != UNMADE) {
472: printf("# non-existent (maybe): %s\n",
473: (gn->made == MADE ? "made" :
474: (gn->made == UPTODATE ? "up-to-date" :
475: (gn->made == ERROR ? "error when made" :
476: "aborted"))));
477: } else {
478: printf("# unmade\n");
479: }
480: }
481: if (!Lst_IsEmpty (gn->iParents)) {
482: printf("# implicit parents: ");
483: Lst_ForEach (gn->iParents, TargPrintName, (ClientData)0);
484: putc ('\n', stdout);
485: }
486: }
487: if (!Lst_IsEmpty (gn->parents)) {
488: printf("# parents: ");
489: Lst_ForEach (gn->parents, TargPrintName, (ClientData)0);
490: putc ('\n', stdout);
491: }
492:
493: printf("%-16s", gn->name);
494: switch (gn->type & OP_OPMASK) {
495: case OP_DEPENDS:
496: printf(": "); break;
497: case OP_FORCE:
498: printf("! "); break;
499: case OP_DOUBLEDEP:
500: printf(":: "); break;
501: }
502: Targ_PrintType (gn->type);
503: Lst_ForEach (gn->children, TargPrintName, (ClientData)0);
504: putc ('\n', stdout);
505: Lst_ForEach (gn->commands, Targ_PrintCmd, (ClientData)0);
506: printf("\n\n");
507: if (gn->type & OP_DOUBLEDEP) {
508: Lst_ForEach (gn->cohorts, TargPrintNode, (ClientData)pass);
509: }
510: }
511: return (0);
512: }
513:
514: /*-
515: *-----------------------------------------------------------------------
516: * TargPrintOnlySrc --
517: * Print only those targets that are just a source.
518: *
519: * Results:
520: * 0.
521: *
522: * Side Effects:
523: * The name of each file is printed preceeded by #\t
524: *
525: *-----------------------------------------------------------------------
526: */
527: static int
528: TargPrintOnlySrc(gn)
529: GNode *gn;
530: {
531: if (OP_NOP(gn->type)) {
532: printf("#\t%s [%s]\n", gn->name,
533: gn->path ? gn->path : gn->name);
534: }
535: return (0);
536: }
537:
538: /*-
539: *-----------------------------------------------------------------------
540: * Targ_PrintGraph --
541: * print the entire graph. heh heh
542: *
543: * Results:
544: * none
545: *
546: * Side Effects:
547: * lots o' output
548: *-----------------------------------------------------------------------
549: */
550: Targ_PrintGraph (pass)
551: int pass; /* Which pass this is. 1 => no processing
552: * 2 => processing done */
553: {
554: printf("#*** Input graph:\n");
555: Lst_ForEach (allTargets, TargPrintNode, (ClientData)pass);
556: printf("\n\n");
557: printf("#\n# Files that are only sources:\n");
558: Lst_ForEach (allTargets, TargPrintOnlySrc);
559: printf("#*** Global Variables:\n");
560: Var_Dump (VAR_GLOBAL);
561: printf("#*** Command-line Variables:\n");
562: Var_Dump (VAR_CMD);
563: printf("\n");
564: Dir_PrintDirectories();
565: printf("\n");
566: Suff_PrintAll();
567: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.