Annotation of src/usr.bin/make/targ.c, Revision 1.28
1.28 ! espie 1: /* $OpenBSD: targ.c,v 1.27 2000/09/14 13:40:03 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 --
1.27 espie 44: * Target nodes are kept into a hash table.
1.1 deraadt 45: *
46: * Interface:
47: * Targ_Init Initialization procedure.
48: *
49: * Targ_End Cleanup the module
50: *
51: * Targ_NewGN Create a new GNode for the passed target
52: * (string). The node is *not* placed in the
53: * hash table, though all its fields are
54: * initialized.
55: *
56: * Targ_FindNode Find the node for a given target, creating
57: * and storing it if it doesn't exist and the
58: * flags are right (TARG_CREATE)
59: *
60: * Targ_FindList Given a list of names, find nodes for all
1.20 espie 61: * of them, creating nodes if needed.
1.1 deraadt 62: *
63: * Targ_Ignore Return TRUE if errors should be ignored when
64: * creating the given target.
65: *
66: * Targ_Silent Return TRUE if we should be silent when
67: * creating the given target.
68: *
69: * Targ_Precious Return TRUE if the target is precious and
70: * should not be removed if we are interrupted.
71: *
72: * Debugging:
73: * Targ_PrintGraph Print out the entire graphm all variables
74: * and statistics for the directory cache. Should
75: * print something for suffixes, too, but...
76: */
77:
1.27 espie 78: #include <stddef.h>
1.1 deraadt 79: #include <stdio.h>
80: #include <time.h>
81: #include "make.h"
1.27 espie 82: #include "ohash.h"
1.1 deraadt 83: #include "dir.h"
84:
1.26 espie 85: #ifndef lint
86: #if 0
87: static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94";
88: #else
89: UNUSED
1.28 ! espie 90: static char *rcsid = "$OpenBSD: targ.c,v 1.27 2000/09/14 13:40:03 espie Exp $";
1.26 espie 91: #endif
92: #endif /* not lint */
93:
1.10 espie 94: #ifdef CLEANUP
1.19 espie 95: static LIST allGNs; /* List of all the GNodes */
1.10 espie 96: #endif
1.27 espie 97: static struct hash targets; /* a hash table of same */
98: static struct hash_info gnode_info = {
99: offsetof(GNode, name),
100: NULL, hash_alloc, hash_free, element_alloc };
1.1 deraadt 101:
1.27 espie 102: static void TargPrintOnlySrc __P((GNode *));
1.18 espie 103: static void TargPrintName __P((void *));
1.27 espie 104: static void TargPrintNode __P((GNode *, int));
1.10 espie 105: #ifdef CLEANUP
1.18 espie 106: static void TargFreeGN __P((void *));
1.10 espie 107: #endif
1.1 deraadt 108:
109: /*-
110: *-----------------------------------------------------------------------
111: * Targ_Init --
112: * Initialize this module
113: *
1.26 espie 114: * Side Effects:
1.27 espie 115: * The targets hash table is initialized
1.1 deraadt 116: *-----------------------------------------------------------------------
117: */
118: void
1.19 espie 119: Targ_Init()
1.1 deraadt 120: {
1.19 espie 121: #ifdef CLEANUP
122: Lst_Init(&allGNs);
123: #endif
1.27 espie 124: /* A small make file already creates 200 targets. */
125: hash_init(&targets, 10, &gnode_info);
1.1 deraadt 126: }
127:
128: /*-
129: *-----------------------------------------------------------------------
130: * Targ_End --
131: * Finalize this module
132: *
133: * Side Effects:
134: * All lists and gnodes are cleared
135: *-----------------------------------------------------------------------
136: */
137: void
138: Targ_End ()
139: {
1.10 espie 140: #ifdef CLEANUP
1.19 espie 141: Lst_Destroy(&allGNs, TargFreeGN);
1.27 espie 142: hash_delete(&targets);
1.10 espie 143: #endif
1.1 deraadt 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:
1.27 espie 156: * The gnode is added to the set of all gnodes.
1.1 deraadt 157: *-----------------------------------------------------------------------
158: */
159: GNode *
1.27 espie 160: Targ_NewGN(name, end)
161: const char *name; /* the name to stick in the new node */
162: const char *end;
1.1 deraadt 163: {
1.27 espie 164: GNode *gn;
1.1 deraadt 165:
1.27 espie 166: gn = hash_create_entry(&gnode_info, name, &end);
167: gn->path = NULL;
1.1 deraadt 168: if (name[0] == '-' && name[1] == 'l') {
169: gn->type = OP_LIB;
170: } else {
171: gn->type = 0;
172: }
173: gn->unmade = 0;
174: gn->make = FALSE;
175: gn->made = UNMADE;
176: gn->childMade = FALSE;
1.2 deraadt 177: gn->order = 0;
1.14 espie 178: gn->mtime = gn->cmtime = OUT_OF_DATE;
1.19 espie 179: Lst_Init(&gn->iParents);
180: Lst_Init(&gn->cohorts);
181: Lst_Init(&gn->parents);
182: Lst_Init(&gn->children);
183: Lst_Init(&gn->successors);
184: Lst_Init(&gn->preds);
1.25 espie 185: SymTable_Init(&gn->context);
1.16 espie 186: gn->lineno = 0;
187: gn->fname = NULL;
1.19 espie 188: Lst_Init(&gn->commands);
1.1 deraadt 189: gn->suffix = NULL;
190:
1.10 espie 191: #ifdef CLEANUP
1.19 espie 192: Lst_AtEnd(&allGNs, gn);
1.10 espie 193: #endif
1.1 deraadt 194:
1.27 espie 195: return gn;
1.1 deraadt 196: }
197:
1.10 espie 198: #ifdef CLEANUP
1.1 deraadt 199: /*-
200: *-----------------------------------------------------------------------
201: * TargFreeGN --
202: * Destroy a GNode
203: *
204: * Results:
205: * None.
206: *
207: * Side Effects:
208: * None.
209: *-----------------------------------------------------------------------
210: */
211: static void
1.18 espie 212: TargFreeGN(gnp)
213: void *gnp;
1.1 deraadt 214: {
215: GNode *gn = (GNode *) gnp;
216:
1.9 espie 217: efree(gn->path);
1.24 espie 218: Lst_Destroy(&gn->iParents, NOFREE);
219: Lst_Destroy(&gn->cohorts, NOFREE);
220: Lst_Destroy(&gn->parents, NOFREE);
221: Lst_Destroy(&gn->children, NOFREE);
222: Lst_Destroy(&gn->successors, NOFREE);
223: Lst_Destroy(&gn->preds, NOFREE);
1.25 espie 224: SymTable_Destroy(&gn->context);
1.24 espie 225: Lst_Destroy(&gn->commands, NOFREE);
1.18 espie 226: free(gn);
1.1 deraadt 227: }
1.10 espie 228: #endif
1.1 deraadt 229:
230:
231: /*-
232: *-----------------------------------------------------------------------
233: * Targ_FindNode --
234: * Find a node in the list using the given name for matching
235: *
236: * Results:
1.12 espie 237: * The node in the list if it was. If it wasn't, return NULL of
1.1 deraadt 238: * flags was TARG_NOCREATE or the newly created and initialized node
239: * if it was TARG_CREATE
240: *
241: * Side Effects:
242: * Sometimes a node is created and added to the list
243: *-----------------------------------------------------------------------
244: */
245: GNode *
1.27 espie 246: Targ_FindNode(name, flags)
247: const char *name; /* the name to find */
248: int flags; /* flags governing events when target not
1.1 deraadt 249: * found */
250: {
1.27 espie 251: const char *end = NULL;
252: GNode *gn; /* node in that element */
253: unsigned int slot;
254:
255: slot = hash_qlookupi(&targets, name, &end);
256:
257: gn = hash_find(&targets, slot);
258:
259: if (gn == NULL && (flags & TARG_CREATE)) {
260: gn = Targ_NewGN(name, end);
261: hash_insert(&targets, slot, gn);
1.1 deraadt 262: }
263:
1.27 espie 264: return gn;
1.1 deraadt 265: }
266:
267: /*-
268: *-----------------------------------------------------------------------
269: * Targ_FindList --
1.5 millert 270: * Make a complete list of GNodes from the given list of names
1.1 deraadt 271: *
1.20 espie 272: * Side Effects:
273: * Nodes will be created for all names which do not yet have graph
274: * nodes.
1.1 deraadt 275: *
1.20 espie 276: * A complete list of graph nodes corresponding to all instances of
277: * all names is added to nodes.
1.1 deraadt 278: * -----------------------------------------------------------------------
279: */
1.20 espie 280: void
281: Targ_FindList(nodes, names)
282: Lst nodes; /* result list */
283: Lst names; /* list of names to find */
1.1 deraadt 284: {
1.20 espie 285: LstNode ln; /* name list element */
286: GNode *gn; /* node in tLn */
287: char *name;
1.1 deraadt 288:
1.22 espie 289: for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {
1.1 deraadt 290: name = (char *)Lst_Datum(ln);
1.20 espie 291: gn = Targ_FindNode(name, TARG_CREATE);
292: /*
293: * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
294: * are added to the list in the order in which they were
295: * encountered in the makefile.
296: */
297: Lst_AtEnd(nodes, gn);
298: if (gn->type & OP_DOUBLEDEP)
1.21 espie 299: Lst_Concat(nodes, &gn->cohorts);
1.1 deraadt 300: }
301: }
302:
303: /*-
304: *-----------------------------------------------------------------------
305: * Targ_Ignore --
306: * Return true if should ignore errors when creating gn
307: *-----------------------------------------------------------------------
308: */
309: Boolean
1.27 espie 310: Targ_Ignore(gn)
1.1 deraadt 311: GNode *gn; /* node to check for */
312: {
1.27 espie 313: if (ignoreErrors || gn->type & OP_IGNORE)
314: return TRUE;
315: else
316: return FALSE;
1.1 deraadt 317: }
318:
319: /*-
320: *-----------------------------------------------------------------------
321: * Targ_Silent --
322: * Return true if be silent when creating gn
323: *-----------------------------------------------------------------------
324: */
325: Boolean
1.27 espie 326: Targ_Silent(gn)
1.1 deraadt 327: GNode *gn; /* node to check for */
328: {
1.27 espie 329: if (beSilent || gn->type & OP_SILENT)
330: return TRUE;
331: else
332: return FALSE;
1.1 deraadt 333: }
334:
335: /*-
336: *-----------------------------------------------------------------------
337: * Targ_Precious --
338: * See if the given target is precious
339: *-----------------------------------------------------------------------
340: */
341: Boolean
342: Targ_Precious (gn)
343: GNode *gn; /* the node to check */
344: {
1.27 espie 345: if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP)))
346: return TRUE;
347: else
348: return FALSE;
1.1 deraadt 349: }
350:
351: /******************* DEBUG INFO PRINTING ****************/
352:
353: static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
1.5 millert 354: /*-
1.1 deraadt 355: *-----------------------------------------------------------------------
356: * Targ_SetMain --
357: * Set our idea of the main target we'll be creating. Used for
358: * debugging output.
359: *
360: * Side Effects:
361: * "mainTarg" is set to the main target's node.
362: *-----------------------------------------------------------------------
363: */
364: void
1.27 espie 365: Targ_SetMain(gn)
1.1 deraadt 366: GNode *gn; /* The main target we'll create */
367: {
368: mainTarg = gn;
369: }
370:
1.17 espie 371: static void
372: TargPrintName(gnp)
1.18 espie 373: void *gnp;
1.1 deraadt 374: {
1.17 espie 375: GNode *gn = (GNode *)gnp;
376:
377: printf("%s ", gn->name);
1.1 deraadt 378: }
379:
380:
1.17 espie 381: void
382: Targ_PrintCmd(cmd)
1.18 espie 383: void *cmd;
1.1 deraadt 384: {
1.17 espie 385: printf("\t%s\n", (char *)cmd);
1.1 deraadt 386: }
387:
388: /*-
389: *-----------------------------------------------------------------------
390: * Targ_FmtTime --
391: * Format a modification time in some reasonable way and return it.
392: *
393: * Results:
394: * The time reformatted.
395: *
396: * Side Effects:
397: * The time is placed in a static area, so it is overwritten
398: * with each call.
399: *
400: *-----------------------------------------------------------------------
401: */
402: char *
1.27 espie 403: Targ_FmtTime(time)
1.1 deraadt 404: time_t time;
405: {
406: struct tm *parts;
1.27 espie 407: static char buf[128];
1.1 deraadt 408:
409: parts = localtime(&time);
1.8 deraadt 410: strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
411: buf[sizeof(buf) - 1] = '\0';
1.1 deraadt 412: return(buf);
413: }
1.5 millert 414:
1.1 deraadt 415: /*-
416: *-----------------------------------------------------------------------
417: * Targ_PrintType --
418: * Print out a type field giving only those attributes the user can
419: * set.
420: *-----------------------------------------------------------------------
421: */
422: void
1.27 espie 423: Targ_PrintType(type)
424: int type;
1.1 deraadt 425: {
1.27 espie 426: int tbit;
1.5 millert 427:
1.1 deraadt 428: #ifdef __STDC__
429: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
430: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
431: #else
432: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf(".attr "); break
433: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
434: #endif /* __STDC__ */
435:
436: type &= ~OP_OPMASK;
437:
438: while (type) {
439: tbit = 1 << (ffs(type) - 1);
440: type &= ~tbit;
441:
442: switch(tbit) {
443: PRINTBIT(OPTIONAL);
444: PRINTBIT(USE);
445: PRINTBIT(EXEC);
446: PRINTBIT(IGNORE);
447: PRINTBIT(PRECIOUS);
448: PRINTBIT(SILENT);
449: PRINTBIT(MAKE);
450: PRINTBIT(JOIN);
451: PRINTBIT(INVISIBLE);
452: PRINTBIT(NOTMAIN);
453: PRINTDBIT(LIB);
454: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
455: case OP_MEMBER: if (DEBUG(TARG)) printf(".MEMBER "); break;
456: PRINTDBIT(ARCHV);
457: }
458: }
459: }
460:
461: /*-
462: *-----------------------------------------------------------------------
463: * TargPrintNode --
464: * print the contents of a node
465: *-----------------------------------------------------------------------
466: */
1.17 espie 467: static void
1.27 espie 468: TargPrintNode(gn, pass)
469: GNode *gn;
470: int pass;
1.1 deraadt 471: {
472: if (!OP_NOP(gn->type)) {
473: printf("#\n");
1.17 espie 474: if (gn == mainTarg)
1.1 deraadt 475: printf("# *** MAIN TARGET ***\n");
476: if (pass == 2) {
1.17 espie 477: if (gn->unmade)
1.1 deraadt 478: printf("# %d unmade children\n", gn->unmade);
1.17 espie 479: else
1.1 deraadt 480: printf("# No unmade children\n");
481: if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
1.17 espie 482: if (gn->mtime != OUT_OF_DATE)
1.1 deraadt 483: printf("# last modified %s: %s\n",
484: Targ_FmtTime(gn->mtime),
485: (gn->made == UNMADE ? "unmade" :
486: (gn->made == MADE ? "made" :
487: (gn->made == UPTODATE ? "up-to-date" :
488: "error when made"))));
1.17 espie 489: else if (gn->made != UNMADE)
1.1 deraadt 490: printf("# non-existent (maybe): %s\n",
491: (gn->made == MADE ? "made" :
492: (gn->made == UPTODATE ? "up-to-date" :
493: (gn->made == ERROR ? "error when made" :
494: "aborted"))));
1.17 espie 495: else
1.1 deraadt 496: printf("# unmade\n");
497: }
1.19 espie 498: if (!Lst_IsEmpty(&gn->iParents)) {
1.1 deraadt 499: printf("# implicit parents: ");
1.19 espie 500: Lst_Every(&gn->iParents, TargPrintName);
1.17 espie 501: fputc('\n', stdout);
1.1 deraadt 502: }
503: }
1.19 espie 504: if (!Lst_IsEmpty(&gn->parents)) {
1.1 deraadt 505: printf("# parents: ");
1.19 espie 506: Lst_Every(&gn->parents, TargPrintName);
1.1 deraadt 507: fputc ('\n', stdout);
508: }
1.5 millert 509:
1.1 deraadt 510: printf("%-16s", gn->name);
511: switch (gn->type & OP_OPMASK) {
512: case OP_DEPENDS:
513: printf(": "); break;
514: case OP_FORCE:
515: printf("! "); break;
516: case OP_DOUBLEDEP:
517: printf(":: "); break;
518: }
1.17 espie 519: Targ_PrintType(gn->type);
1.19 espie 520: Lst_Every(&gn->children, TargPrintName);
1.17 espie 521: fputc('\n', stdout);
1.19 espie 522: Lst_Every(&gn->commands, Targ_PrintCmd);
1.1 deraadt 523: printf("\n\n");
1.27 espie 524: if (gn->type & OP_DOUBLEDEP) {
525: LstNode ln;
526:
527: for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln))
528: TargPrintNode((GNode *)Lst_Datum(ln), pass);
529: }
1.1 deraadt 530: }
531: }
532:
533: /*-
534: *-----------------------------------------------------------------------
535: * TargPrintOnlySrc --
536: * Print only those targets that are just a source.
537: *-----------------------------------------------------------------------
538: */
1.17 espie 539: static void
1.27 espie 540: TargPrintOnlySrc(gn)
541: GNode *gn;
1.1 deraadt 542: {
543: if (OP_NOP(gn->type))
544: printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);
545: }
546:
547: /*-
548: *-----------------------------------------------------------------------
549: * Targ_PrintGraph --
1.27 espie 550: * print the entire graph.
1.1 deraadt 551: *-----------------------------------------------------------------------
552: */
553: void
1.27 espie 554: Targ_PrintGraph(pass)
555: int pass; /* Which pass this is. 1 => no processing
556: * 2 => processing done */
1.1 deraadt 557: {
1.27 espie 558: GNode *gn;
559: unsigned int i;
560:
1.1 deraadt 561: printf("#*** Input graph:\n");
1.27 espie 562: for (gn = hash_first(&targets, &i); gn != NULL;
563: gn = hash_next(&targets, &i))
564: TargPrintNode(gn, pass);
1.1 deraadt 565: printf("\n\n");
566: printf("#\n# Files that are only sources:\n");
1.27 espie 567: for (gn = hash_first(&targets, &i); gn != NULL;
568: gn = hash_next(&targets, &i))
569: TargPrintOnlySrc(gn);
1.1 deraadt 570: printf("#*** Global Variables:\n");
1.23 espie 571: Var_Dump(VAR_GLOBAL);
1.1 deraadt 572: printf("#*** Command-line Variables:\n");
1.23 espie 573: Var_Dump(VAR_CMD);
1.1 deraadt 574: printf("\n");
575: Dir_PrintDirectories();
576: printf("\n");
577: Suff_PrintAll();
578: }