Annotation of src/usr.bin/make/targ.c, Revision 1.68
1.68 ! rillig 1: /* $NetBSD: targ.c,v 1.67 2020/08/21 04:42:02 rillig Exp $ */
1.5 christos 2:
1.1 cgd 3: /*
1.10 christos 4: * Copyright (c) 1988, 1989, 1990, 1993
5: * The Regents of the University of California. All rights reserved.
1.30 agc 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, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: /*
1.1 cgd 36: * Copyright (c) 1989 by Berkeley Softworks
37: * All rights reserved.
38: *
39: * This code is derived from software contributed to Berkeley by
40: * Adam de Boor.
41: *
42: * Redistribution and use in source and binary forms, with or without
43: * modification, are permitted provided that the following conditions
44: * are met:
45: * 1. Redistributions of source code must retain the above copyright
46: * notice, this list of conditions and the following disclaimer.
47: * 2. Redistributions in binary form must reproduce the above copyright
48: * notice, this list of conditions and the following disclaimer in the
49: * documentation and/or other materials provided with the distribution.
50: * 3. All advertising materials mentioning features or use of this software
51: * must display the following acknowledgement:
52: * This product includes software developed by the University of
53: * California, Berkeley and its contributors.
54: * 4. Neither the name of the University nor the names of its contributors
55: * may be used to endorse or promote products derived from this software
56: * without specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68: * SUCH DAMAGE.
69: */
70:
1.31 ross 71: #ifndef MAKE_NATIVE
1.68 ! rillig 72: static char rcsid[] = "$NetBSD: targ.c,v 1.67 2020/08/21 04:42:02 rillig Exp $";
1.14 lukem 73: #else
1.13 christos 74: #include <sys/cdefs.h>
1.1 cgd 75: #ifndef lint
1.9 thorpej 76: #if 0
1.10 christos 77: static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94";
1.9 thorpej 78: #else
1.68 ! rillig 79: __RCSID("$NetBSD: targ.c,v 1.67 2020/08/21 04:42:02 rillig Exp $");
1.9 thorpej 80: #endif
1.1 cgd 81: #endif /* not lint */
1.14 lukem 82: #endif
1.1 cgd 83:
84: /*-
85: * targ.c --
86: * Functions for maintaining the Lst allTargets. Target nodes are
87: * kept in two structures: a Lst, maintained by the list library, and a
88: * hash table, maintained by the hash library.
89: *
90: * Interface:
91: * Targ_Init Initialization procedure.
92: *
1.4 jtc 93: * Targ_End Cleanup the module
94: *
1.12 christos 95: * Targ_List Return the list of all targets so far.
96: *
1.1 cgd 97: * Targ_NewGN Create a new GNode for the passed target
98: * (string). The node is *not* placed in the
99: * hash table, though all its fields are
100: * initialized.
101: *
102: * Targ_FindNode Find the node for a given target, creating
103: * and storing it if it doesn't exist and the
104: * flags are right (TARG_CREATE)
105: *
106: * Targ_FindList Given a list of names, find nodes for all
107: * of them. If a name doesn't exist and the
108: * TARG_NOCREATE flag was given, an error message
109: * is printed. Else, if a name doesn't exist,
110: * its node is created.
111: *
112: * Targ_Ignore Return TRUE if errors should be ignored when
113: * creating the given target.
114: *
115: * Targ_Silent Return TRUE if we should be silent when
116: * creating the given target.
117: *
118: * Targ_Precious Return TRUE if the target is precious and
119: * should not be removed if we are interrupted.
120: *
1.42 apb 121: * Targ_Propagate Propagate information between related
122: * nodes. Should be called after the
123: * makefiles are parsed but before any
124: * action is taken.
125: *
1.1 cgd 126: * Debugging:
127: * Targ_PrintGraph Print out the entire graphm all variables
128: * and statistics for the directory cache. Should
129: * print something for suffixes, too, but...
130: */
131:
132: #include <stdio.h>
133: #include <time.h>
1.28 wiz 134:
1.1 cgd 135: #include "make.h"
136: #include "hash.h"
1.3 cgd 137: #include "dir.h"
1.1 cgd 138:
139: static Lst allTargets; /* the list of all targets found so far */
1.18 mycroft 140: #ifdef CLEANUP
1.4 jtc 141: static Lst allGNs; /* List of all the GNodes */
1.18 mycroft 142: #endif
1.1 cgd 143: static Hash_Table targets; /* a hash table of same */
144:
145: #define HTSIZE 191 /* initial size of hash table */
146:
1.55 dsl 147: static int TargPrintOnlySrc(void *, void *);
148: static int TargPrintName(void *, void *);
1.18 mycroft 149: #ifdef CLEANUP
1.55 dsl 150: static void TargFreeGN(void *);
1.18 mycroft 151: #endif
1.55 dsl 152: static int TargPropagateCohort(void *, void *);
153: static int TargPropagateNode(void *, void *);
1.4 jtc 154:
1.1 cgd 155: /*-
156: *-----------------------------------------------------------------------
157: * Targ_Init --
158: * Initialize this module
159: *
160: * Results:
161: * None
162: *
163: * Side Effects:
164: * The allTargets list and the targets hash table are initialized
165: *-----------------------------------------------------------------------
166: */
167: void
1.28 wiz 168: Targ_Init(void)
1.1 cgd 169: {
1.65 rillig 170: allTargets = Lst_Init();
1.34 christos 171: Hash_InitTable(&targets, HTSIZE);
1.1 cgd 172: }
173:
174: /*-
175: *-----------------------------------------------------------------------
1.4 jtc 176: * Targ_End --
177: * Finalize this module
178: *
179: * Results:
180: * None
181: *
182: * Side Effects:
183: * All lists and gnodes are cleared
184: *-----------------------------------------------------------------------
185: */
186: void
1.28 wiz 187: Targ_End(void)
1.4 jtc 188: {
1.64 sjg 189: Targ_Stats();
1.18 mycroft 190: #ifdef CLEANUP
1.54 dsl 191: Lst_Destroy(allTargets, NULL);
1.4 jtc 192: if (allGNs)
193: Lst_Destroy(allGNs, TargFreeGN);
194: Hash_DeleteTable(&targets);
1.18 mycroft 195: #endif
1.12 christos 196: }
197:
1.64 sjg 198: void
199: Targ_Stats(void)
200: {
201: Hash_DebugStats(&targets, "targets");
202: }
203:
1.12 christos 204: /*-
205: *-----------------------------------------------------------------------
206: * Targ_List --
207: * Return the list of all targets
208: *
209: * Results:
210: * The list of all targets.
211: *
212: * Side Effects:
213: * None
214: *-----------------------------------------------------------------------
215: */
216: Lst
1.28 wiz 217: Targ_List(void)
1.12 christos 218: {
219: return allTargets;
1.4 jtc 220: }
221:
222: /*-
223: *-----------------------------------------------------------------------
1.1 cgd 224: * Targ_NewGN --
225: * Create and initialize a new graph node
226: *
1.28 wiz 227: * Input:
228: * name the name to stick in the new node
229: *
1.1 cgd 230: * Results:
231: * An initialized graph node with the name field filled with a copy
232: * of the passed name
233: *
234: * Side Effects:
1.4 jtc 235: * The gnode is added to the list of all gnodes.
1.1 cgd 236: *-----------------------------------------------------------------------
237: */
238: GNode *
1.29 christos 239: Targ_NewGN(const char *name)
1.1 cgd 240: {
1.28 wiz 241: GNode *gn;
1.1 cgd 242:
1.53 joerg 243: gn = bmake_malloc(sizeof(GNode));
244: gn->name = bmake_strdup(name);
1.11 christos 245: gn->uname = NULL;
1.29 christos 246: gn->path = NULL;
1.1 cgd 247: if (name[0] == '-' && name[1] == 'l') {
248: gn->type = OP_LIB;
249: } else {
250: gn->type = 0;
251: }
252: gn->unmade = 0;
1.27 pk 253: gn->unmade_cohorts = 0;
1.45 dsl 254: gn->cohort_num[0] = 0;
1.27 pk 255: gn->centurion = NULL;
1.1 cgd 256: gn->made = UNMADE;
1.16 christos 257: gn->flags = 0;
1.56 christos 258: gn->checked = 0;
259: gn->mtime = 0;
260: gn->cmgn = NULL;
1.65 rillig 261: gn->iParents = Lst_Init();
262: gn->cohorts = Lst_Init();
263: gn->parents = Lst_Init();
264: gn->children = Lst_Init();
265: gn->order_pred = Lst_Init();
266: gn->order_succ = Lst_Init();
1.17 mycroft 267: Hash_InitTable(&gn->context, 0);
1.65 rillig 268: gn->commands = Lst_Init();
1.3 cgd 269: gn->suffix = NULL;
1.21 christos 270: gn->lineno = 0;
271: gn->fname = NULL;
1.1 cgd 272:
1.18 mycroft 273: #ifdef CLEANUP
1.4 jtc 274: if (allGNs == NULL)
1.65 rillig 275: allGNs = Lst_Init();
1.44 dsl 276: Lst_AtEnd(allGNs, gn);
1.18 mycroft 277: #endif
1.4 jtc 278:
1.63 rillig 279: return gn;
1.1 cgd 280: }
281:
1.18 mycroft 282: #ifdef CLEANUP
1.1 cgd 283: /*-
284: *-----------------------------------------------------------------------
1.4 jtc 285: * TargFreeGN --
286: * Destroy a GNode
287: *
288: * Results:
289: * None.
290: *
291: * Side Effects:
292: * None.
293: *-----------------------------------------------------------------------
294: */
295: static void
1.55 dsl 296: TargFreeGN(void *gnp)
1.4 jtc 297: {
1.37 christos 298: GNode *gn = (GNode *)gnp;
1.4 jtc 299:
300:
301: free(gn->name);
1.61 christos 302: free(gn->uname);
303: free(gn->path);
1.46 dsl 304: /* gn->fname points to name allocated when file was opened, don't free */
1.4 jtc 305:
1.54 dsl 306: Lst_Destroy(gn->iParents, NULL);
307: Lst_Destroy(gn->cohorts, NULL);
308: Lst_Destroy(gn->parents, NULL);
309: Lst_Destroy(gn->children, NULL);
310: Lst_Destroy(gn->order_succ, NULL);
311: Lst_Destroy(gn->order_pred, NULL);
1.17 mycroft 312: Hash_DeleteTable(&gn->context);
1.54 dsl 313: Lst_Destroy(gn->commands, NULL);
1.36 christos 314: free(gn);
1.4 jtc 315: }
1.18 mycroft 316: #endif
1.4 jtc 317:
318:
319: /*-
320: *-----------------------------------------------------------------------
1.1 cgd 321: * Targ_FindNode --
322: * Find a node in the list using the given name for matching
323: *
1.28 wiz 324: * Input:
325: * name the name to find
326: * flags flags governing events when target not
327: * found
328: *
1.1 cgd 329: * Results:
1.54 dsl 330: * The node in the list if it was. If it wasn't, return NULL of
1.1 cgd 331: * flags was TARG_NOCREATE or the newly created and initialized node
332: * if it was TARG_CREATE
333: *
334: * Side Effects:
335: * Sometimes a node is created and added to the list
336: *-----------------------------------------------------------------------
337: */
338: GNode *
1.29 christos 339: Targ_FindNode(const char *name, int flags)
1.1 cgd 340: {
341: GNode *gn; /* node in that element */
1.60 manu 342: Hash_Entry *he = NULL; /* New or used hash entry for node */
1.1 cgd 343: Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */
344: /* an entry for the node */
345:
1.45 dsl 346: if (!(flags & (TARG_CREATE | TARG_NOHASH))) {
347: he = Hash_FindEntry(&targets, name);
348: if (he == NULL)
1.54 dsl 349: return NULL;
1.45 dsl 350: return (GNode *)Hash_GetValue(he);
351: }
1.1 cgd 352:
1.45 dsl 353: if (!(flags & TARG_NOHASH)) {
1.34 christos 354: he = Hash_CreateEntry(&targets, name, &isNew);
1.45 dsl 355: if (!isNew)
356: return (GNode *)Hash_GetValue(he);
1.1 cgd 357: }
358:
1.45 dsl 359: gn = Targ_NewGN(name);
360: if (!(flags & TARG_NOHASH))
361: Hash_SetValue(he, gn);
362: Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
1.68 ! rillig 363: Lst_AppendS(allTargets, gn);
1.50 dsl 364: if (doing_depend)
365: gn->flags |= FROM_DEPEND;
1.45 dsl 366: return gn;
1.1 cgd 367: }
368:
369: /*-
370: *-----------------------------------------------------------------------
371: * Targ_FindList --
1.10 christos 372: * Make a complete list of GNodes from the given list of names
1.1 cgd 373: *
1.28 wiz 374: * Input:
375: * name list of names to find
376: * flags flags used if no node is found for a given name
377: *
1.1 cgd 378: * Results:
379: * A complete list of graph nodes corresponding to all instances of all
1.10 christos 380: * the names in names.
1.1 cgd 381: *
382: * Side Effects:
383: * If flags is TARG_CREATE, nodes will be created for all names in
384: * names which do not yet have graph nodes. If flags is TARG_NOCREATE,
385: * an error message will be printed for each name which can't be found.
386: * -----------------------------------------------------------------------
387: */
388: Lst
1.28 wiz 389: Targ_FindList(Lst names, int flags)
1.1 cgd 390: {
391: Lst nodes; /* result list */
1.28 wiz 392: LstNode ln; /* name list element */
393: GNode *gn; /* node in tLn */
394: char *name;
1.1 cgd 395:
1.65 rillig 396: nodes = Lst_Init();
1.1 cgd 397:
1.67 rillig 398: Lst_OpenS(names);
1.66 rillig 399: while ((ln = Lst_NextS(names)) != NULL) {
1.1 cgd 400: name = (char *)Lst_Datum(ln);
1.34 christos 401: gn = Targ_FindNode(name, flags);
1.54 dsl 402: if (gn != NULL) {
1.1 cgd 403: /*
404: * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
405: * are added to the list in the order in which they were
406: * encountered in the makefile.
407: */
1.68 ! rillig 408: Lst_AppendS(nodes, gn);
1.1 cgd 409: } else if (flags == TARG_NOCREATE) {
1.34 christos 410: Error("\"%s\" -- target unknown.", name);
1.1 cgd 411: }
412: }
1.67 rillig 413: Lst_CloseS(names);
1.63 rillig 414: return nodes;
1.1 cgd 415: }
416:
417: /*-
418: *-----------------------------------------------------------------------
419: * Targ_Ignore --
420: * Return true if should ignore errors when creating gn
421: *
1.28 wiz 422: * Input:
423: * gn node to check for
424: *
1.1 cgd 425: * Results:
426: * TRUE if should ignore errors
427: *
428: * Side Effects:
429: * None
430: *-----------------------------------------------------------------------
431: */
432: Boolean
1.28 wiz 433: Targ_Ignore(GNode *gn)
1.1 cgd 434: {
435: if (ignoreErrors || gn->type & OP_IGNORE) {
1.63 rillig 436: return TRUE;
1.1 cgd 437: } else {
1.63 rillig 438: return FALSE;
1.1 cgd 439: }
440: }
441:
442: /*-
443: *-----------------------------------------------------------------------
444: * Targ_Silent --
445: * Return true if be silent when creating gn
446: *
1.28 wiz 447: * Input:
448: * gn node to check for
449: *
1.1 cgd 450: * Results:
451: * TRUE if should be silent
452: *
453: * Side Effects:
454: * None
455: *-----------------------------------------------------------------------
456: */
457: Boolean
1.28 wiz 458: Targ_Silent(GNode *gn)
1.1 cgd 459: {
460: if (beSilent || gn->type & OP_SILENT) {
1.63 rillig 461: return TRUE;
1.1 cgd 462: } else {
1.63 rillig 463: return FALSE;
1.1 cgd 464: }
465: }
466:
467: /*-
468: *-----------------------------------------------------------------------
469: * Targ_Precious --
470: * See if the given target is precious
471: *
1.28 wiz 472: * Input:
473: * gn the node to check
474: *
1.1 cgd 475: * Results:
476: * TRUE if it is precious. FALSE otherwise
477: *
478: * Side Effects:
479: * None
480: *-----------------------------------------------------------------------
481: */
482: Boolean
1.28 wiz 483: Targ_Precious(GNode *gn)
1.1 cgd 484: {
485: if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
1.63 rillig 486: return TRUE;
1.1 cgd 487: } else {
1.63 rillig 488: return FALSE;
1.1 cgd 489: }
490: }
491:
492: /******************* DEBUG INFO PRINTING ****************/
493:
494: static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
1.10 christos 495: /*-
1.1 cgd 496: *-----------------------------------------------------------------------
497: * Targ_SetMain --
498: * Set our idea of the main target we'll be creating. Used for
499: * debugging output.
500: *
1.28 wiz 501: * Input:
502: * gn The main target we'll create
503: *
1.1 cgd 504: * Results:
505: * None.
506: *
507: * Side Effects:
508: * "mainTarg" is set to the main target's node.
509: *-----------------------------------------------------------------------
510: */
511: void
1.28 wiz 512: Targ_SetMain(GNode *gn)
1.1 cgd 513: {
514: mainTarg = gn;
515: }
516:
517: static int
1.57 joerg 518: TargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED)
1.1 cgd 519: {
1.37 christos 520: GNode *gn = (GNode *)gnp;
1.38 dsl 521:
1.45 dsl 522: fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num);
1.38 dsl 523:
524: return 0;
1.1 cgd 525: }
526:
527:
528: int
1.62 riastrad 529: Targ_PrintCmd(void *cmd, void *dummy MAKE_ATTR_UNUSED)
1.1 cgd 530: {
1.43 dsl 531: fprintf(debug_file, "\t%s\n", (char *)cmd);
1.62 riastrad 532: return 0;
1.1 cgd 533: }
534:
535: /*-
536: *-----------------------------------------------------------------------
537: * Targ_FmtTime --
538: * Format a modification time in some reasonable way and return it.
539: *
540: * Results:
541: * The time reformatted.
542: *
543: * Side Effects:
544: * The time is placed in a static area, so it is overwritten
545: * with each call.
546: *
547: *-----------------------------------------------------------------------
548: */
549: char *
1.28 wiz 550: Targ_FmtTime(time_t tm)
1.1 cgd 551: {
552: struct tm *parts;
1.15 christos 553: static char buf[128];
1.1 cgd 554:
1.25 reinoud 555: parts = localtime(&tm);
1.15 christos 556: (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
1.63 rillig 557: return buf;
1.1 cgd 558: }
1.10 christos 559:
1.1 cgd 560: /*-
561: *-----------------------------------------------------------------------
562: * Targ_PrintType --
563: * Print out a type field giving only those attributes the user can
564: * set.
565: *
566: * Results:
567: *
568: * Side Effects:
569: *
570: *-----------------------------------------------------------------------
571: */
572: void
1.52 christos 573: Targ_PrintType(int type)
1.1 cgd 574: {
1.28 wiz 575: int tbit;
1.10 christos 576:
1.43 dsl 577: #define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break
578: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break
1.1 cgd 579:
580: type &= ~OP_OPMASK;
581:
582: while (type) {
1.52 christos 583: tbit = 1 << (ffs(type) - 1);
1.1 cgd 584: type &= ~tbit;
585:
586: switch(tbit) {
587: PRINTBIT(OPTIONAL);
588: PRINTBIT(USE);
589: PRINTBIT(EXEC);
590: PRINTBIT(IGNORE);
591: PRINTBIT(PRECIOUS);
592: PRINTBIT(SILENT);
593: PRINTBIT(MAKE);
594: PRINTBIT(JOIN);
595: PRINTBIT(INVISIBLE);
596: PRINTBIT(NOTMAIN);
597: PRINTDBIT(LIB);
598: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.43 dsl 599: case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break;
1.1 cgd 600: PRINTDBIT(ARCHV);
1.26 pk 601: PRINTDBIT(MADE);
602: PRINTDBIT(PHONY);
1.1 cgd 603: }
604: }
605: }
606:
1.45 dsl 607: static const char *
608: made_name(enum enum_made made)
609: {
610: switch (made) {
611: case UNMADE: return "unmade";
612: case DEFERRED: return "deferred";
613: case REQUESTED: return "requested";
614: case BEINGMADE: return "being made";
615: case MADE: return "made";
616: case UPTODATE: return "up-to-date";
617: case ERROR: return "error when made";
618: case ABORTED: return "aborted";
619: default: return "unknown enum_made value";
620: }
621: }
622:
1.1 cgd 623: /*-
624: *-----------------------------------------------------------------------
625: * TargPrintNode --
626: * print the contents of a node
627: *-----------------------------------------------------------------------
628: */
1.40 dsl 629: int
1.55 dsl 630: Targ_PrintNode(void *gnp, void *passp)
1.1 cgd 631: {
1.37 christos 632: GNode *gn = (GNode *)gnp;
1.40 dsl 633: int pass = passp ? *(int *)passp : 0;
1.45 dsl 634:
635: fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n",
636: gn->name, gn->cohort_num, gn->flags, gn->type, gn->made);
637: if (gn->flags == 0)
638: return 0;
639:
1.1 cgd 640: if (!OP_NOP(gn->type)) {
1.43 dsl 641: fprintf(debug_file, "#\n");
1.1 cgd 642: if (gn == mainTarg) {
1.43 dsl 643: fprintf(debug_file, "# *** MAIN TARGET ***\n");
1.1 cgd 644: }
1.45 dsl 645: if (pass >= 2) {
1.1 cgd 646: if (gn->unmade) {
1.43 dsl 647: fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1 cgd 648: } else {
1.43 dsl 649: fprintf(debug_file, "# No unmade children\n");
1.1 cgd 650: }
1.22 christos 651: if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
1.1 cgd 652: if (gn->mtime != 0) {
1.43 dsl 653: fprintf(debug_file, "# last modified %s: %s\n",
1.1 cgd 654: Targ_FmtTime(gn->mtime),
1.45 dsl 655: made_name(gn->made));
1.1 cgd 656: } else if (gn->made != UNMADE) {
1.43 dsl 657: fprintf(debug_file, "# non-existent (maybe): %s\n",
1.45 dsl 658: made_name(gn->made));
1.1 cgd 659: } else {
1.43 dsl 660: fprintf(debug_file, "# unmade\n");
1.1 cgd 661: }
662: }
663: if (!Lst_IsEmpty (gn->iParents)) {
1.43 dsl 664: fprintf(debug_file, "# implicit parents: ");
1.44 dsl 665: Lst_ForEach(gn->iParents, TargPrintName, NULL);
1.43 dsl 666: fprintf(debug_file, "\n");
1.1 cgd 667: }
1.41 dsl 668: } else {
669: if (gn->unmade)
1.43 dsl 670: fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1 cgd 671: }
672: if (!Lst_IsEmpty (gn->parents)) {
1.43 dsl 673: fprintf(debug_file, "# parents: ");
1.44 dsl 674: Lst_ForEach(gn->parents, TargPrintName, NULL);
1.43 dsl 675: fprintf(debug_file, "\n");
1.1 cgd 676: }
1.45 dsl 677: if (!Lst_IsEmpty (gn->order_pred)) {
678: fprintf(debug_file, "# order_pred: ");
679: Lst_ForEach(gn->order_pred, TargPrintName, NULL);
1.43 dsl 680: fprintf(debug_file, "\n");
1.42 apb 681: }
1.45 dsl 682: if (!Lst_IsEmpty (gn->order_succ)) {
683: fprintf(debug_file, "# order_succ: ");
684: Lst_ForEach(gn->order_succ, TargPrintName, NULL);
1.43 dsl 685: fprintf(debug_file, "\n");
1.39 dsl 686: }
1.10 christos 687:
1.43 dsl 688: fprintf(debug_file, "%-16s", gn->name);
1.1 cgd 689: switch (gn->type & OP_OPMASK) {
690: case OP_DEPENDS:
1.43 dsl 691: fprintf(debug_file, ": "); break;
1.1 cgd 692: case OP_FORCE:
1.43 dsl 693: fprintf(debug_file, "! "); break;
1.1 cgd 694: case OP_DOUBLEDEP:
1.43 dsl 695: fprintf(debug_file, ":: "); break;
1.1 cgd 696: }
1.34 christos 697: Targ_PrintType(gn->type);
1.45 dsl 698: Lst_ForEach(gn->children, TargPrintName, NULL);
1.43 dsl 699: fprintf(debug_file, "\n");
1.44 dsl 700: Lst_ForEach(gn->commands, Targ_PrintCmd, NULL);
1.43 dsl 701: fprintf(debug_file, "\n\n");
1.20 mycroft 702: if (gn->type & OP_DOUBLEDEP) {
1.44 dsl 703: Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass);
1.1 cgd 704: }
705: }
1.63 rillig 706: return 0;
1.1 cgd 707: }
708:
709: /*-
710: *-----------------------------------------------------------------------
711: * TargPrintOnlySrc --
712: * Print only those targets that are just a source.
713: *
714: * Results:
715: * 0.
716: *
717: * Side Effects:
1.23 wiz 718: * The name of each file is printed preceded by #\t
1.1 cgd 719: *
720: *-----------------------------------------------------------------------
721: */
722: static int
1.57 joerg 723: TargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED)
1.4 jtc 724: {
1.37 christos 725: GNode *gn = (GNode *)gnp;
1.45 dsl 726: if (!OP_NOP(gn->type))
727: return 0;
1.4 jtc 728:
1.45 dsl 729: fprintf(debug_file, "#\t%s [%s] ",
730: gn->name, gn->path ? gn->path : gn->name);
731: Targ_PrintType(gn->type);
732: fprintf(debug_file, "\n");
733:
734: return 0;
1.1 cgd 735: }
736:
737: /*-
738: *-----------------------------------------------------------------------
739: * Targ_PrintGraph --
740: * print the entire graph. heh heh
741: *
1.28 wiz 742: * Input:
743: * pass Which pass this is. 1 => no processing
744: * 2 => processing done
745: *
1.1 cgd 746: * Results:
747: * none
748: *
749: * Side Effects:
750: * lots o' output
751: *-----------------------------------------------------------------------
752: */
1.3 cgd 753: void
1.28 wiz 754: Targ_PrintGraph(int pass)
1.1 cgd 755: {
1.43 dsl 756: fprintf(debug_file, "#*** Input graph:\n");
1.44 dsl 757: Lst_ForEach(allTargets, Targ_PrintNode, &pass);
1.43 dsl 758: fprintf(debug_file, "\n\n");
759: fprintf(debug_file, "#\n# Files that are only sources:\n");
1.44 dsl 760: Lst_ForEach(allTargets, TargPrintOnlySrc, NULL);
1.43 dsl 761: fprintf(debug_file, "#*** Global Variables:\n");
1.34 christos 762: Var_Dump(VAR_GLOBAL);
1.43 dsl 763: fprintf(debug_file, "#*** Command-line Variables:\n");
1.34 christos 764: Var_Dump(VAR_CMD);
1.43 dsl 765: fprintf(debug_file, "\n");
1.1 cgd 766: Dir_PrintDirectories();
1.43 dsl 767: fprintf(debug_file, "\n");
1.1 cgd 768: Suff_PrintAll();
1.19 mycroft 769: }
770:
1.42 apb 771: /*-
772: *-----------------------------------------------------------------------
773: * TargPropagateNode --
774: * Propagate information from a single node to related nodes if
775: * appropriate.
776: *
777: * Input:
778: * gnp The node that we are processing.
779: *
780: * Results:
781: * Always returns 0, for the benefit of Lst_ForEach().
782: *
783: * Side Effects:
784: * Information is propagated from this node to cohort or child
785: * nodes.
786: *
787: * If the node was defined with "::", then TargPropagateCohort()
788: * will be called for each cohort node.
789: *
790: * If the node has recursive predecessors, then
791: * TargPropagateRecpred() will be called for each recursive
792: * predecessor.
793: *-----------------------------------------------------------------------
794: */
1.19 mycroft 795: static int
1.57 joerg 796: TargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED)
1.19 mycroft 797: {
1.37 christos 798: GNode *gn = (GNode *)gnp;
1.45 dsl 799:
1.20 mycroft 800: if (gn->type & OP_DOUBLEDEP)
1.34 christos 801: Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp);
1.63 rillig 802: return 0;
1.19 mycroft 803: }
804:
1.42 apb 805: /*-
806: *-----------------------------------------------------------------------
807: * TargPropagateCohort --
808: * Propagate some bits in the type mask from a node to
809: * a related cohort node.
810: *
811: * Input:
812: * cnp The node that we are processing.
813: * gnp Another node that has cnp as a cohort.
814: *
815: * Results:
816: * Always returns 0, for the benefit of Lst_ForEach().
817: *
818: * Side Effects:
819: * cnp's type bitmask is modified to incorporate some of the
820: * bits from gnp's type bitmask. (XXX need a better explanation.)
821: *-----------------------------------------------------------------------
822: */
823: static int
1.55 dsl 824: TargPropagateCohort(void *cgnp, void *pgnp)
1.42 apb 825: {
826: GNode *cgn = (GNode *)cgnp;
827: GNode *pgn = (GNode *)pgnp;
828:
829: cgn->type |= pgn->type & ~OP_OPMASK;
1.63 rillig 830: return 0;
1.42 apb 831: }
832:
833: /*-
834: *-----------------------------------------------------------------------
835: * Targ_Propagate --
836: * Propagate information between related nodes. Should be called
837: * after the makefiles are parsed but before any action is taken.
838: *
839: * Results:
840: * none
841: *
842: * Side Effects:
843: * Information is propagated between related nodes throughout the
844: * graph.
845: *-----------------------------------------------------------------------
846: */
1.19 mycroft 847: void
1.28 wiz 848: Targ_Propagate(void)
1.19 mycroft 849: {
1.44 dsl 850: Lst_ForEach(allTargets, TargPropagateNode, NULL);
1.1 cgd 851: }
CVSweb <webmaster@jp.NetBSD.org>