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