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