Annotation of src/usr.bin/make/targ.c, Revision 1.93
1.93 ! rillig 1: /* $NetBSD: targ.c,v 1.92 2020/09/24 07:11:29 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:
71: /*-
72: * targ.c --
73: * Functions for maintaining the Lst allTargets. Target nodes are
1.77 rillig 74: * kept in two structures: a Lst and a hash table.
1.1 cgd 75: *
76: * Interface:
77: * Targ_Init Initialization procedure.
78: *
1.4 jtc 79: * Targ_End Cleanup the module
80: *
1.12 christos 81: * Targ_List Return the list of all targets so far.
82: *
1.1 cgd 83: * Targ_NewGN Create a new GNode for the passed target
84: * (string). The node is *not* placed in the
85: * hash table, though all its fields are
86: * initialized.
87: *
88: * Targ_FindNode Find the node for a given target, creating
89: * and storing it if it doesn't exist and the
90: * flags are right (TARG_CREATE)
91: *
92: * Targ_FindList Given a list of names, find nodes for all
93: * of them. If a name doesn't exist and the
94: * TARG_NOCREATE flag was given, an error message
95: * is printed. Else, if a name doesn't exist,
96: * its node is created.
97: *
98: * Targ_Ignore Return TRUE if errors should be ignored when
99: * creating the given target.
100: *
101: * Targ_Silent Return TRUE if we should be silent when
102: * creating the given target.
103: *
104: * Targ_Precious Return TRUE if the target is precious and
105: * should not be removed if we are interrupted.
106: *
1.42 apb 107: * Targ_Propagate Propagate information between related
108: * nodes. Should be called after the
109: * makefiles are parsed but before any
110: * action is taken.
111: *
1.1 cgd 112: * Debugging:
113: * Targ_PrintGraph Print out the entire graphm all variables
114: * and statistics for the directory cache. Should
115: * print something for suffixes, too, but...
116: */
117:
118: #include <stdio.h>
119: #include <time.h>
1.28 wiz 120:
1.1 cgd 121: #include "make.h"
1.3 cgd 122: #include "dir.h"
1.1 cgd 123:
1.88 rillig 124: /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
1.93 ! rillig 125: MAKE_RCSID("$NetBSD: targ.c,v 1.92 2020/09/24 07:11:29 rillig Exp $");
1.88 rillig 126:
1.89 rillig 127: static GNodeList *allTargets; /* the list of all targets found so far */
1.18 mycroft 128: #ifdef CLEANUP
1.89 rillig 129: static GNodeList *allGNs; /* List of all the GNodes */
1.18 mycroft 130: #endif
1.1 cgd 131: static Hash_Table targets; /* a hash table of same */
132:
1.55 dsl 133: static int TargPrintOnlySrc(void *, void *);
1.18 mycroft 134: #ifdef CLEANUP
1.55 dsl 135: static void TargFreeGN(void *);
1.18 mycroft 136: #endif
1.4 jtc 137:
1.1 cgd 138: void
1.28 wiz 139: Targ_Init(void)
1.1 cgd 140: {
1.65 rillig 141: allTargets = Lst_Init();
1.83 rillig 142: Hash_InitTable(&targets);
1.1 cgd 143: }
144:
1.4 jtc 145: void
1.28 wiz 146: Targ_End(void)
1.4 jtc 147: {
1.64 sjg 148: Targ_Stats();
1.18 mycroft 149: #ifdef CLEANUP
1.76 rillig 150: Lst_Free(allTargets);
1.73 rillig 151: if (allGNs != NULL)
1.76 rillig 152: Lst_Destroy(allGNs, TargFreeGN);
1.4 jtc 153: Hash_DeleteTable(&targets);
1.18 mycroft 154: #endif
1.12 christos 155: }
156:
1.64 sjg 157: void
158: Targ_Stats(void)
159: {
160: Hash_DebugStats(&targets, "targets");
161: }
162:
1.77 rillig 163: /* Return the list of all targets. */
1.89 rillig 164: GNodeList *
1.28 wiz 165: Targ_List(void)
1.12 christos 166: {
167: return allTargets;
1.4 jtc 168: }
169:
1.77 rillig 170: /* Create and initialize a new graph node. The gnode is added to the list of
171: * all gnodes.
1.1 cgd 172: *
1.28 wiz 173: * Input:
1.91 rillig 174: * name the name of the node, such as "clean", "src.c", ".END"
1.1 cgd 175: */
176: GNode *
1.29 christos 177: Targ_NewGN(const char *name)
1.1 cgd 178: {
1.28 wiz 179: GNode *gn;
1.1 cgd 180:
1.53 joerg 181: gn = bmake_malloc(sizeof(GNode));
182: gn->name = bmake_strdup(name);
1.11 christos 183: gn->uname = NULL;
1.29 christos 184: gn->path = NULL;
1.77 rillig 185: gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : 0;
1.1 cgd 186: gn->unmade = 0;
1.27 pk 187: gn->unmade_cohorts = 0;
1.45 dsl 188: gn->cohort_num[0] = 0;
1.27 pk 189: gn->centurion = NULL;
1.1 cgd 190: gn->made = UNMADE;
1.16 christos 191: gn->flags = 0;
1.56 christos 192: gn->checked = 0;
193: gn->mtime = 0;
194: gn->cmgn = NULL;
1.80 rillig 195: gn->implicitParents = Lst_Init();
1.65 rillig 196: gn->cohorts = Lst_Init();
197: gn->parents = Lst_Init();
198: gn->children = Lst_Init();
199: gn->order_pred = Lst_Init();
200: gn->order_succ = Lst_Init();
1.83 rillig 201: Hash_InitTable(&gn->context);
1.65 rillig 202: gn->commands = Lst_Init();
1.3 cgd 203: gn->suffix = NULL;
1.77 rillig 204: gn->fname = NULL;
1.21 christos 205: gn->lineno = 0;
1.1 cgd 206:
1.18 mycroft 207: #ifdef CLEANUP
1.4 jtc 208: if (allGNs == NULL)
1.65 rillig 209: allGNs = Lst_Init();
1.76 rillig 210: Lst_Append(allGNs, gn);
1.18 mycroft 211: #endif
1.4 jtc 212:
1.63 rillig 213: return gn;
1.1 cgd 214: }
215:
1.18 mycroft 216: #ifdef CLEANUP
1.4 jtc 217: static void
1.55 dsl 218: TargFreeGN(void *gnp)
1.4 jtc 219: {
1.37 christos 220: GNode *gn = (GNode *)gnp;
1.4 jtc 221:
222: free(gn->name);
1.61 christos 223: free(gn->uname);
224: free(gn->path);
1.4 jtc 225:
1.80 rillig 226: Lst_Free(gn->implicitParents);
1.76 rillig 227: Lst_Free(gn->cohorts);
228: Lst_Free(gn->parents);
229: Lst_Free(gn->children);
230: Lst_Free(gn->order_succ);
231: Lst_Free(gn->order_pred);
1.17 mycroft 232: Hash_DeleteTable(&gn->context);
1.76 rillig 233: Lst_Free(gn->commands);
1.77 rillig 234:
235: /* XXX: does gn->suffix need to be freed? It is reference-counted. */
236: /* gn->fname points to name allocated when file was opened, don't free */
237:
1.36 christos 238: free(gn);
1.4 jtc 239: }
1.18 mycroft 240: #endif
1.4 jtc 241:
242:
1.77 rillig 243: /* Find a node in the list using the given name for matching.
244: * If the node is created, it is added to the .ALLTARGETS list.
1.1 cgd 245: *
1.28 wiz 246: * Input:
247: * name the name to find
1.77 rillig 248: * flags flags governing events when target not found
1.28 wiz 249: *
1.1 cgd 250: * Results:
1.77 rillig 251: * The node in the list if it was. If it wasn't, return NULL if
1.1 cgd 252: * flags was TARG_NOCREATE or the newly created and initialized node
253: * if it was TARG_CREATE
254: */
255: GNode *
1.29 christos 256: Targ_FindNode(const char *name, int flags)
1.1 cgd 257: {
258: GNode *gn; /* node in that element */
1.60 manu 259: Hash_Entry *he = NULL; /* New or used hash entry for node */
1.1 cgd 260: Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */
261: /* an entry for the node */
262:
1.45 dsl 263: if (!(flags & (TARG_CREATE | TARG_NOHASH))) {
264: he = Hash_FindEntry(&targets, name);
265: if (he == NULL)
1.54 dsl 266: return NULL;
1.45 dsl 267: return (GNode *)Hash_GetValue(he);
268: }
1.1 cgd 269:
1.45 dsl 270: if (!(flags & TARG_NOHASH)) {
1.34 christos 271: he = Hash_CreateEntry(&targets, name, &isNew);
1.45 dsl 272: if (!isNew)
273: return (GNode *)Hash_GetValue(he);
1.1 cgd 274: }
275:
1.45 dsl 276: gn = Targ_NewGN(name);
277: if (!(flags & TARG_NOHASH))
278: Hash_SetValue(he, gn);
279: Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
1.76 rillig 280: Lst_Append(allTargets, gn);
1.50 dsl 281: if (doing_depend)
282: gn->flags |= FROM_DEPEND;
1.45 dsl 283: return gn;
1.1 cgd 284: }
285:
1.90 rillig 286: /* Return the .END node, which contains the commands to be executed when
287: * everything else is done. */
288: GNode *Targ_GetEndNode(void)
289: {
290: /* Save the node locally to avoid having to search for it all the time. */
291: static GNode *endNode = NULL;
292: if (endNode == NULL) {
293: endNode = Targ_FindNode(".END", TARG_CREATE);
294: endNode->type = OP_SPECIAL;
295: }
296: return endNode;
297: }
298:
1.77 rillig 299: /* Make a complete list of GNodes from the given list of names.
300: * If flags is TARG_CREATE, nodes will be created for all names in
301: * names which do not yet have graph nodes. If flags is TARG_NOCREATE,
302: * an error message will be printed for each name which can't be found.
1.1 cgd 303: *
1.28 wiz 304: * Input:
305: * name list of names to find
306: * flags flags used if no node is found for a given name
307: *
1.1 cgd 308: * Results:
309: * A complete list of graph nodes corresponding to all instances of all
1.10 christos 310: * the names in names.
1.1 cgd 311: */
1.89 rillig 312: GNodeList *
313: Targ_FindList(StringList *names, int flags)
1.1 cgd 314: {
1.89 rillig 315: GNodeList *nodes;
316: StringListNode *ln;
1.1 cgd 317:
1.65 rillig 318: nodes = Lst_Init();
1.1 cgd 319:
1.76 rillig 320: Lst_Open(names);
321: while ((ln = Lst_Next(names)) != NULL) {
1.89 rillig 322: char *name = LstNode_Datum(ln);
323: GNode *gn = Targ_FindNode(name, flags);
1.54 dsl 324: if (gn != NULL) {
1.76 rillig 325: Lst_Append(nodes, gn);
1.1 cgd 326: } else if (flags == TARG_NOCREATE) {
1.34 christos 327: Error("\"%s\" -- target unknown.", name);
1.1 cgd 328: }
329: }
1.76 rillig 330: Lst_Close(names);
1.63 rillig 331: return nodes;
1.1 cgd 332: }
333:
1.77 rillig 334: /* Return true if should ignore errors when creating gn. */
1.1 cgd 335: Boolean
1.28 wiz 336: Targ_Ignore(GNode *gn)
1.1 cgd 337: {
1.77 rillig 338: return ignoreErrors || gn->type & OP_IGNORE;
1.1 cgd 339: }
340:
1.77 rillig 341: /* Return true if be silent when creating gn. */
1.1 cgd 342: Boolean
1.28 wiz 343: Targ_Silent(GNode *gn)
1.1 cgd 344: {
1.77 rillig 345: return beSilent || gn->type & OP_SILENT;
1.1 cgd 346: }
347:
1.77 rillig 348: /* See if the given target is precious. */
1.1 cgd 349: Boolean
1.28 wiz 350: Targ_Precious(GNode *gn)
1.1 cgd 351: {
1.77 rillig 352: return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP);
1.1 cgd 353: }
354:
355: /******************* DEBUG INFO PRINTING ****************/
356:
357: static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
1.77 rillig 358:
359: /* Set our idea of the main target we'll be creating. Used for debugging
360: * output. */
1.1 cgd 361: void
1.28 wiz 362: Targ_SetMain(GNode *gn)
1.1 cgd 363: {
364: mainTarg = gn;
365: }
366:
1.86 rillig 367: static void
1.89 rillig 368: PrintNodeNames(GNodeList *gnodes)
1.1 cgd 369: {
1.89 rillig 370: GNodeListNode *node;
1.38 dsl 371:
1.85 rillig 372: for (node = Lst_First(gnodes); node != NULL; node = LstNode_Next(node)) {
373: GNode *gn = LstNode_Datum(node);
374: fprintf(debug_file, " %s%s", gn->name, gn->cohort_num);
375: }
376: }
1.38 dsl 377:
1.85 rillig 378: static void
1.89 rillig 379: PrintNodeNamesLine(const char *label, GNodeList *gnodes)
1.85 rillig 380: {
381: if (Lst_IsEmpty(gnodes))
382: return;
383: fprintf(debug_file, "# %s:", label);
384: PrintNodeNames(gnodes);
385: fprintf(debug_file, "\n");
1.1 cgd 386: }
387:
1.84 rillig 388: void
389: Targ_PrintCmds(GNode *gn)
390: {
1.93 ! rillig 391: StringListNode *node = Lst_First(gn->commands);
! 392: for (; node != NULL; node = LstNode_Next(node)) {
! 393: const char *cmd = LstNode_Datum(node);
! 394: fprintf(debug_file, "\t%s\n", cmd);
! 395: }
1.84 rillig 396: }
397:
1.77 rillig 398: /* Format a modification time in some reasonable way and return it.
399: * The time is placed in a static area, so it is overwritten with each call. */
1.1 cgd 400: char *
1.28 wiz 401: Targ_FmtTime(time_t tm)
1.1 cgd 402: {
403: struct tm *parts;
1.15 christos 404: static char buf[128];
1.1 cgd 405:
1.25 reinoud 406: parts = localtime(&tm);
1.15 christos 407: (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
1.63 rillig 408: return buf;
1.1 cgd 409: }
1.10 christos 410:
1.77 rillig 411: /* Print out a type field giving only those attributes the user can set. */
1.1 cgd 412: void
1.52 christos 413: Targ_PrintType(int type)
1.1 cgd 414: {
1.28 wiz 415: int tbit;
1.10 christos 416:
1.82 rillig 417: #define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, " ." #attr); break
418: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, " ." #attr); break
1.1 cgd 419:
420: type &= ~OP_OPMASK;
421:
422: while (type) {
1.52 christos 423: tbit = 1 << (ffs(type) - 1);
1.1 cgd 424: type &= ~tbit;
425:
426: switch(tbit) {
427: PRINTBIT(OPTIONAL);
428: PRINTBIT(USE);
429: PRINTBIT(EXEC);
430: PRINTBIT(IGNORE);
431: PRINTBIT(PRECIOUS);
432: PRINTBIT(SILENT);
433: PRINTBIT(MAKE);
434: PRINTBIT(JOIN);
435: PRINTBIT(INVISIBLE);
436: PRINTBIT(NOTMAIN);
437: PRINTDBIT(LIB);
438: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.82 rillig 439: case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, " .MEMBER"); break;
1.1 cgd 440: PRINTDBIT(ARCHV);
1.26 pk 441: PRINTDBIT(MADE);
442: PRINTDBIT(PHONY);
1.1 cgd 443: }
444: }
445: }
446:
1.45 dsl 447: static const char *
1.71 rillig 448: made_name(GNodeMade made)
1.45 dsl 449: {
450: switch (made) {
451: case UNMADE: return "unmade";
452: case DEFERRED: return "deferred";
453: case REQUESTED: return "requested";
454: case BEINGMADE: return "being made";
455: case MADE: return "made";
456: case UPTODATE: return "up-to-date";
457: case ERROR: return "error when made";
458: case ABORTED: return "aborted";
459: default: return "unknown enum_made value";
460: }
461: }
462:
1.87 rillig 463: static int
464: PrintNode(void *gnp, void *passp)
1.1 cgd 465: {
1.87 rillig 466: GNode *gn = gnp;
467: int pass = *(const int *)passp;
1.45 dsl 468:
1.72 rillig 469: fprintf(debug_file, "# %s%s", gn->name, gn->cohort_num);
470: GNode_FprintDetails(debug_file, ", ", gn, "\n");
1.45 dsl 471: if (gn->flags == 0)
472: return 0;
473:
1.1 cgd 474: if (!OP_NOP(gn->type)) {
1.43 dsl 475: fprintf(debug_file, "#\n");
1.1 cgd 476: if (gn == mainTarg) {
1.43 dsl 477: fprintf(debug_file, "# *** MAIN TARGET ***\n");
1.1 cgd 478: }
1.45 dsl 479: if (pass >= 2) {
1.1 cgd 480: if (gn->unmade) {
1.43 dsl 481: fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1 cgd 482: } else {
1.43 dsl 483: fprintf(debug_file, "# No unmade children\n");
1.1 cgd 484: }
1.22 christos 485: if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
1.1 cgd 486: if (gn->mtime != 0) {
1.43 dsl 487: fprintf(debug_file, "# last modified %s: %s\n",
1.1 cgd 488: Targ_FmtTime(gn->mtime),
1.45 dsl 489: made_name(gn->made));
1.1 cgd 490: } else if (gn->made != UNMADE) {
1.43 dsl 491: fprintf(debug_file, "# non-existent (maybe): %s\n",
1.45 dsl 492: made_name(gn->made));
1.1 cgd 493: } else {
1.43 dsl 494: fprintf(debug_file, "# unmade\n");
1.1 cgd 495: }
496: }
1.85 rillig 497: PrintNodeNamesLine("implicit parents", gn->implicitParents);
1.41 dsl 498: } else {
499: if (gn->unmade)
1.43 dsl 500: fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1 cgd 501: }
1.85 rillig 502: PrintNodeNamesLine("parents", gn->parents);
503: PrintNodeNamesLine("order_pred", gn->order_pred);
504: PrintNodeNamesLine("order_succ", gn->order_succ);
1.10 christos 505:
1.43 dsl 506: fprintf(debug_file, "%-16s", gn->name);
1.1 cgd 507: switch (gn->type & OP_OPMASK) {
508: case OP_DEPENDS:
1.82 rillig 509: fprintf(debug_file, ":"); break;
1.1 cgd 510: case OP_FORCE:
1.82 rillig 511: fprintf(debug_file, "!"); break;
1.1 cgd 512: case OP_DOUBLEDEP:
1.82 rillig 513: fprintf(debug_file, "::"); break;
1.1 cgd 514: }
1.34 christos 515: Targ_PrintType(gn->type);
1.85 rillig 516: PrintNodeNames(gn->children);
1.43 dsl 517: fprintf(debug_file, "\n");
1.84 rillig 518: Targ_PrintCmds(gn);
1.43 dsl 519: fprintf(debug_file, "\n\n");
1.20 mycroft 520: if (gn->type & OP_DOUBLEDEP) {
1.92 rillig 521: Lst_ForEachUntil(gn->cohorts, PrintNode, passp);
1.1 cgd 522: }
523: }
1.63 rillig 524: return 0;
1.1 cgd 525: }
526:
1.87 rillig 527: /* Print the contents of a node. */
528: void
529: Targ_PrintNode(GNode *gn, int pass)
530: {
531: PrintNode(gn, &pass);
532: }
533:
534: void
1.89 rillig 535: Targ_PrintNodes(GNodeList *gnodes, int pass)
1.87 rillig 536: {
1.92 rillig 537: Lst_ForEachUntil(gnodes, PrintNode, &pass);
1.87 rillig 538: }
539:
1.77 rillig 540: /* Print only those targets that are just a source.
541: * The name of each file is printed, preceded by #\t. */
1.1 cgd 542: static int
1.57 joerg 543: TargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED)
1.4 jtc 544: {
1.37 christos 545: GNode *gn = (GNode *)gnp;
1.45 dsl 546: if (!OP_NOP(gn->type))
547: return 0;
1.4 jtc 548:
1.82 rillig 549: fprintf(debug_file, "#\t%s [%s]",
1.45 dsl 550: gn->name, gn->path ? gn->path : gn->name);
551: Targ_PrintType(gn->type);
552: fprintf(debug_file, "\n");
553:
554: return 0;
1.1 cgd 555: }
556:
1.77 rillig 557: /* Input:
558: * pass 1 => before processing
559: * 2 => after processing
560: * 3 => after processing, an error occurred
1.1 cgd 561: */
1.3 cgd 562: void
1.28 wiz 563: Targ_PrintGraph(int pass)
1.1 cgd 564: {
1.43 dsl 565: fprintf(debug_file, "#*** Input graph:\n");
1.92 rillig 566: Lst_ForEachUntil(allTargets, PrintNode, &pass);
1.43 dsl 567: fprintf(debug_file, "\n\n");
568: fprintf(debug_file, "#\n# Files that are only sources:\n");
1.92 rillig 569: Lst_ForEachUntil(allTargets, TargPrintOnlySrc, NULL);
1.43 dsl 570: fprintf(debug_file, "#*** Global Variables:\n");
1.34 christos 571: Var_Dump(VAR_GLOBAL);
1.43 dsl 572: fprintf(debug_file, "#*** Command-line Variables:\n");
1.34 christos 573: Var_Dump(VAR_CMD);
1.43 dsl 574: fprintf(debug_file, "\n");
1.1 cgd 575: Dir_PrintDirectories();
1.43 dsl 576: fprintf(debug_file, "\n");
1.1 cgd 577: Suff_PrintAll();
1.19 mycroft 578: }
579:
1.78 rillig 580: /* Propagate some type information to cohort nodes (those from the ::
581: * dependency operator).
1.77 rillig 582: *
1.78 rillig 583: * Should be called after the makefiles are parsed but before any action is
584: * taken. */
585: void
586: Targ_Propagate(void)
1.19 mycroft 587: {
1.89 rillig 588: GNodeListNode *pn, *cn;
1.45 dsl 589:
1.78 rillig 590: for (pn = Lst_First(allTargets); pn != NULL; pn = LstNode_Next(pn)) {
1.79 rillig 591: GNode *pgn = LstNode_Datum(pn);
1.19 mycroft 592:
1.78 rillig 593: if (!(pgn->type & OP_DOUBLEDEP))
594: continue;
1.42 apb 595:
1.78 rillig 596: for (cn = Lst_First(pgn->cohorts); cn != NULL; cn = LstNode_Next(cn)) {
1.79 rillig 597: GNode *cgn = LstNode_Datum(cn);
1.42 apb 598:
1.78 rillig 599: cgn->type |= pgn->type & ~OP_OPMASK;
600: }
601: }
1.1 cgd 602: }
CVSweb <webmaster@jp.NetBSD.org>