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