Annotation of src/usr.bin/make/targ.c, Revision 1.151
1.151 ! rillig 1: /* $NetBSD: targ.c,v 1.150 2020/12/05 15:35:34 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.132 rillig 71: /*
72: * Maintaining the targets and sources, which are both implemented as GNode.
1.1 cgd 73: *
74: * Interface:
1.132 rillig 75: * Targ_Init Initialize the module.
1.1 cgd 76: *
1.132 rillig 77: * Targ_End Clean up the module.
1.4 jtc 78: *
1.106 rillig 79: * Targ_List Return the list of all targets so far.
1.12 christos 80: *
1.128 rillig 81: * GNode_New Create a new GNode for the passed target
1.106 rillig 82: * (string). The node is *not* placed in the
83: * hash table, though all its fields are
84: * initialized.
1.1 cgd 85: *
1.106 rillig 86: * Targ_FindNode Find the node, or return NULL.
1.98 rillig 87: *
1.106 rillig 88: * Targ_GetNode Find the node, or create it.
1.98 rillig 89: *
1.106 rillig 90: * Targ_NewInternalNode
91: * Create an internal node.
1.1 cgd 92: *
1.106 rillig 93: * Targ_FindList Given a list of names, find nodes for all
94: * of them, creating them as necessary.
1.1 cgd 95: *
1.106 rillig 96: * Targ_Ignore Return TRUE if errors should be ignored when
97: * creating the given target.
1.1 cgd 98: *
1.106 rillig 99: * Targ_Silent Return TRUE if we should be silent when
100: * creating the given target.
1.1 cgd 101: *
1.106 rillig 102: * Targ_Precious Return TRUE if the target is precious and
103: * should not be removed if we are interrupted.
1.1 cgd 104: *
1.106 rillig 105: * Targ_Propagate Propagate information between related nodes.
106: * Should be called after the makefiles are parsed
107: * but before any action is taken.
1.42 apb 108: *
1.1 cgd 109: * Debugging:
1.106 rillig 110: * Targ_PrintGraph
1.148 rillig 111: * Print out the entire graph, all variables and
1.106 rillig 112: * statistics for the directory cache. Should print
113: * something for suffixes, too, but...
1.1 cgd 114: */
115:
1.111 rillig 116: #include <time.h>
1.28 wiz 117:
1.111 rillig 118: #include "make.h"
119: #include "dir.h"
1.1 cgd 120:
1.88 rillig 121: /* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
1.151 ! rillig 122: MAKE_RCSID("$NetBSD: targ.c,v 1.150 2020/12/05 15:35:34 rillig Exp $");
1.88 rillig 123:
1.136 rillig 124: /*
125: * All target nodes that appeared on the left-hand side of one of the
126: * dependency operators ':', '::', '!'.
127: */
1.148 rillig 128: static GNodeList allTargets = LST_INIT;
1.133 rillig 129: static HashTable allTargetsByName;
1.130 rillig 130:
1.18 mycroft 131: #ifdef CLEANUP
1.148 rillig 132: static GNodeList allNodes = LST_INIT;
1.1 cgd 133:
1.129 rillig 134: static void GNode_Free(void *);
1.18 mycroft 135: #endif
1.4 jtc 136:
1.1 cgd 137: void
1.28 wiz 138: Targ_Init(void)
1.1 cgd 139: {
1.150 rillig 140: HashTable_Init(&allTargetsByName);
1.1 cgd 141: }
142:
1.4 jtc 143: void
1.28 wiz 144: Targ_End(void)
1.4 jtc 145: {
1.150 rillig 146: Targ_Stats();
1.18 mycroft 147: #ifdef CLEANUP
1.150 rillig 148: Lst_Done(&allTargets);
149: HashTable_Done(&allTargetsByName);
150: Lst_DoneCall(&allNodes, GNode_Free);
1.18 mycroft 151: #endif
1.12 christos 152: }
153:
1.64 sjg 154: void
155: Targ_Stats(void)
156: {
1.150 rillig 157: HashTable_DebugStats(&allTargetsByName, "targets");
1.64 sjg 158: }
159:
1.132 rillig 160: /*
161: * Return the list of all targets, which are all nodes that appear on the
162: * left-hand side of a dependency declaration such as "target: source".
163: * The returned list does not contain pure sources.
164: */
1.89 rillig 165: GNodeList *
1.28 wiz 166: Targ_List(void)
1.12 christos 167: {
1.150 rillig 168: return &allTargets;
1.4 jtc 169: }
170:
1.150 rillig 171: /*
172: * Create a new graph node, but don't register it anywhere.
1.1 cgd 173: *
1.132 rillig 174: * Graph nodes that appear on the left-hand side of a dependency line such
175: * as "target: source" are called targets. XXX: In some cases (like the
176: * .ALLTARGETS variable), all nodes are called targets as well, even if they
177: * never appear on the left-hand side. This is a mistake.
178: *
179: * Typical names for graph nodes are:
180: * "src.c" (an ordinary file)
181: * "clean" (a .PHONY target)
182: * ".END" (a special hook target)
183: * "-lm" (a library)
184: * "libc.a(isspace.o)" (an archive member)
1.1 cgd 185: */
186: GNode *
1.128 rillig 187: GNode_New(const char *name)
1.1 cgd 188: {
1.150 rillig 189: GNode *gn;
1.1 cgd 190:
1.150 rillig 191: gn = bmake_malloc(sizeof *gn);
192: gn->name = bmake_strdup(name);
193: gn->uname = NULL;
194: gn->path = NULL;
195: gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : 0;
196: gn->flags = 0;
197: gn->made = UNMADE;
198: gn->unmade = 0;
199: gn->mtime = 0;
200: gn->youngestChild = NULL;
201: Lst_Init(&gn->implicitParents);
202: Lst_Init(&gn->parents);
203: Lst_Init(&gn->children);
204: Lst_Init(&gn->order_pred);
205: Lst_Init(&gn->order_succ);
206: Lst_Init(&gn->cohorts);
207: gn->cohort_num[0] = '\0';
208: gn->unmade_cohorts = 0;
209: gn->centurion = NULL;
210: gn->checked_seqno = 0;
211: HashTable_Init(&gn->vars);
212: Lst_Init(&gn->commands);
213: gn->suffix = NULL;
214: gn->fname = NULL;
215: gn->lineno = 0;
1.1 cgd 216:
1.18 mycroft 217: #ifdef CLEANUP
1.150 rillig 218: Lst_Append(&allNodes, gn);
1.18 mycroft 219: #endif
1.4 jtc 220:
1.150 rillig 221: return gn;
1.1 cgd 222: }
223:
1.18 mycroft 224: #ifdef CLEANUP
1.4 jtc 225: static void
1.129 rillig 226: GNode_Free(void *gnp)
1.4 jtc 227: {
1.150 rillig 228: GNode *gn = gnp;
1.4 jtc 229:
1.150 rillig 230: free(gn->name);
231: free(gn->uname);
232: free(gn->path);
233:
234: /* Don't free gn->youngestChild since it is not owned by this node. */
235:
236: /*
237: * In the following lists, only free the list nodes, but not the
238: * GNodes in them since these are not owned by this node.
239: */
240: Lst_Done(&gn->implicitParents);
241: Lst_Done(&gn->parents);
242: Lst_Done(&gn->children);
243: Lst_Done(&gn->order_pred);
244: Lst_Done(&gn->order_succ);
245: Lst_Done(&gn->cohorts);
246:
247: /*
248: * Do not free the variables themselves, even though they are owned
249: * by this node.
250: *
251: * XXX: For the nodes that represent targets or sources (and not
252: * VAR_GLOBAL), it should be safe to free the variables as well,
253: * since each node manages the memory for all its variables itself.
254: *
255: * XXX: The GNodes that are only used as variable contexts (VAR_CMD,
256: * VAR_GLOBAL, VAR_INTERNAL) are not freed at all (see Var_End, where
257: * they are not mentioned). These might be freed at all, if their
258: * variable values are indeed not used anywhere else (see Trace_Init
259: * for the only suspicious use).
260: */
261: HashTable_Done(&gn->vars);
262:
263: /*
264: * Do not free the commands themselves, as they may be shared with
265: * other nodes.
266: */
267: Lst_Done(&gn->commands);
268:
269: /*
270: * gn->suffix is not owned by this node.
271: *
272: * XXX: gn->suffix should be unreferenced here. This requires a
273: * thorough check that the reference counting is done correctly in
274: * all places, otherwise a suffix might be freed too early.
275: */
1.77 rillig 276:
1.150 rillig 277: free(gn);
1.4 jtc 278: }
1.18 mycroft 279: #endif
1.4 jtc 280:
1.95 rillig 281: /* Get the existing global node, or return NULL. */
282: GNode *
283: Targ_FindNode(const char *name)
284: {
1.150 rillig 285: return HashTable_FindValue(&allTargetsByName, name);
1.95 rillig 286: }
287:
288: /* Get the existing global node, or create it. */
289: GNode *
290: Targ_GetNode(const char *name)
291: {
1.150 rillig 292: Boolean isNew;
293: HashEntry *he = HashTable_CreateEntry(&allTargetsByName, name, &isNew);
294: if (!isNew)
295: return HashEntry_Get(he);
296:
297: {
298: GNode *gn = Targ_NewInternalNode(name);
299: HashEntry_Set(he, gn);
300: return gn;
301: }
1.95 rillig 302: }
303:
1.132 rillig 304: /*
305: * Create a node, register it in .ALLTARGETS but don't store it in the
1.95 rillig 306: * table of global nodes. This means it cannot be found by name.
307: *
1.132 rillig 308: * This is used for internal nodes, such as cohorts or .WAIT nodes.
309: */
1.95 rillig 310: GNode *
311: Targ_NewInternalNode(const char *name)
312: {
1.150 rillig 313: GNode *gn = GNode_New(name);
314: Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
315: Lst_Append(&allTargets, gn);
316: DEBUG1(TARG, "Adding \"%s\" to all targets.\n", gn->name);
317: if (doing_depend)
318: gn->flags |= FROM_DEPEND;
319: return gn;
1.95 rillig 320: }
321:
1.132 rillig 322: /*
323: * Return the .END node, which contains the commands to be run when
324: * everything else has been made.
325: */
1.90 rillig 326: GNode *Targ_GetEndNode(void)
327: {
1.150 rillig 328: /*
329: * Save the node locally to avoid having to search for it all
330: * the time.
331: */
332: static GNode *endNode = NULL;
333:
334: if (endNode == NULL) {
335: endNode = Targ_GetNode(".END");
336: endNode->type = OP_SPECIAL;
337: }
338: return endNode;
1.90 rillig 339: }
340:
1.149 rillig 341: /* Add the named nodes to the list, creating them as necessary. */
1.147 rillig 342: void
1.149 rillig 343: Targ_FindList(GNodeList *gns, StringList *names)
1.1 cgd 344: {
1.150 rillig 345: StringListNode *ln;
1.149 rillig 346:
1.150 rillig 347: for (ln = names->first; ln != NULL; ln = ln->next) {
348: const char *name = ln->datum;
349: GNode *gn = Targ_GetNode(name);
350: Lst_Append(gns, gn);
351: }
1.1 cgd 352: }
353:
1.149 rillig 354: /*
355: * Return true if errors from shell commands should be ignored when
356: * creating gn.
357: */
1.1 cgd 358: Boolean
1.131 rillig 359: Targ_Ignore(const GNode *gn)
1.1 cgd 360: {
1.150 rillig 361: return opts.ignoreErrors || gn->type & OP_IGNORE;
1.1 cgd 362: }
363:
1.77 rillig 364: /* Return true if be silent when creating gn. */
1.1 cgd 365: Boolean
1.131 rillig 366: Targ_Silent(const GNode *gn)
1.1 cgd 367: {
1.150 rillig 368: return opts.beSilent || gn->type & OP_SILENT;
1.1 cgd 369: }
370:
1.77 rillig 371: /* See if the given target is precious. */
1.1 cgd 372: Boolean
1.131 rillig 373: Targ_Precious(const GNode *gn)
1.1 cgd 374: {
1.150 rillig 375: /* XXX: Why are '::' targets precious? */
376: return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP);
1.1 cgd 377: }
378:
1.132 rillig 379: /*
380: * The main target to be made; only for debugging output.
381: * See mainNode in parse.c for the definitive source.
382: */
383: static GNode *mainTarg;
1.77 rillig 384:
1.132 rillig 385: /* Remember the main target to make; only used for debugging. */
1.1 cgd 386: void
1.28 wiz 387: Targ_SetMain(GNode *gn)
1.1 cgd 388: {
1.150 rillig 389: mainTarg = gn;
1.1 cgd 390: }
391:
1.86 rillig 392: static void
1.89 rillig 393: PrintNodeNames(GNodeList *gnodes)
1.1 cgd 394: {
1.150 rillig 395: GNodeListNode *ln;
1.38 dsl 396:
1.150 rillig 397: for (ln = gnodes->first; ln != NULL; ln = ln->next) {
398: GNode *gn = ln->datum;
399: debug_printf(" %s%s", gn->name, gn->cohort_num);
400: }
1.85 rillig 401: }
1.38 dsl 402:
1.85 rillig 403: static void
1.89 rillig 404: PrintNodeNamesLine(const char *label, GNodeList *gnodes)
1.85 rillig 405: {
1.150 rillig 406: if (Lst_IsEmpty(gnodes))
407: return;
408: debug_printf("# %s:", label);
409: PrintNodeNames(gnodes);
410: debug_printf("\n");
1.1 cgd 411: }
412:
1.84 rillig 413: void
414: Targ_PrintCmds(GNode *gn)
415: {
1.150 rillig 416: StringListNode *ln;
417:
418: for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
419: const char *cmd = ln->datum;
420: debug_printf("\t%s\n", cmd);
421: }
1.84 rillig 422: }
423:
1.150 rillig 424: /*
425: * Format a modification time in some reasonable way and return it.
426: * The time is placed in a static area, so it is overwritten with each call.
427: */
1.1 cgd 428: char *
1.28 wiz 429: Targ_FmtTime(time_t tm)
1.1 cgd 430: {
1.150 rillig 431: struct tm *parts;
432: static char buf[128];
1.1 cgd 433:
1.150 rillig 434: /* TODO: Add special case for 0, which often means ENOENT, to make it
435: * independent from time zones. */
436: parts = localtime(&tm);
437: (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
438: return buf;
1.1 cgd 439: }
1.10 christos 440:
1.77 rillig 441: /* Print out a type field giving only those attributes the user can set. */
1.1 cgd 442: void
1.52 christos 443: Targ_PrintType(int type)
1.1 cgd 444: {
1.150 rillig 445: int tbit;
1.10 christos 446:
1.150 rillig 447: type &= ~OP_OPMASK;
1.1 cgd 448:
1.150 rillig 449: while (type != 0) {
450: tbit = 1 << (ffs(type) - 1);
451: type &= ~tbit;
452:
453: switch (tbit) {
1.151 ! rillig 454: #define PRINTBIT(bit, name) case bit: debug_printf(" " name); break
! 455: #define PRINTDBIT(bit, attr) case bit: if (DEBUG(TARG)) debug_printf(" " attr); break
! 456: PRINTBIT(OP_OPTIONAL, ".OPTIONAL");
! 457: PRINTBIT(OP_USE, ".USE");
! 458: PRINTBIT(OP_EXEC, ".EXEC");
! 459: PRINTBIT(OP_IGNORE, ".IGNORE");
! 460: PRINTBIT(OP_PRECIOUS, ".PRECIOUS");
! 461: PRINTBIT(OP_SILENT, ".SILENT");
! 462: PRINTBIT(OP_MAKE, ".MAKE");
! 463: PRINTBIT(OP_JOIN, ".JOIN");
! 464: PRINTBIT(OP_INVISIBLE, ".INVISIBLE");
! 465: PRINTBIT(OP_NOTMAIN, ".NOTMAIN");
! 466: PRINTDBIT(OP_LIB, ".LIB");
! 467: PRINTDBIT(OP_MEMBER, ".MEMBER");
! 468: PRINTDBIT(OP_ARCHV, ".ARCHV");
! 469: PRINTDBIT(OP_MADE, ".MADE");
! 470: PRINTDBIT(OP_PHONY, ".PHONY");
! 471: #undef PRINTBIT
! 472: #undef PRINTDBIT
1.150 rillig 473: }
1.1 cgd 474: }
475: }
476:
1.45 dsl 477: static const char *
1.71 rillig 478: made_name(GNodeMade made)
1.45 dsl 479: {
1.150 rillig 480: switch (made) {
481: case UNMADE: return "unmade";
482: case DEFERRED: return "deferred";
483: case REQUESTED: return "requested";
484: case BEINGMADE: return "being made";
485: case MADE: return "made";
486: case UPTODATE: return "up-to-date";
487: case ERROR: return "error when made";
488: case ABORTED: return "aborted";
489: default: return "unknown enum_made value";
490: }
1.45 dsl 491: }
492:
1.114 rillig 493: static const char *
494: GNode_OpName(const GNode *gn)
495: {
1.150 rillig 496: switch (gn->type & OP_OPMASK) {
497: case OP_DEPENDS:
498: return ":";
499: case OP_FORCE:
500: return "!";
501: case OP_DOUBLEDEP:
502: return "::";
503: }
504: return "";
1.114 rillig 505: }
506:
1.105 rillig 507: /* Print the contents of a node. */
508: void
509: Targ_PrintNode(GNode *gn, int pass)
1.1 cgd 510: {
1.150 rillig 511: debug_printf("# %s%s", gn->name, gn->cohort_num);
512: GNode_FprintDetails(opts.debug_file, ", ", gn, "\n");
513: if (gn->flags == 0)
514: return;
515:
516: if (!GNode_IsTarget(gn))
517: return;
1.45 dsl 518:
1.107 rillig 519: debug_printf("#\n");
1.150 rillig 520: if (gn == mainTarg)
521: debug_printf("# *** MAIN TARGET ***\n");
522:
1.45 dsl 523: if (pass >= 2) {
1.150 rillig 524: if (gn->unmade > 0)
525: debug_printf("# %d unmade children\n", gn->unmade);
526: else
527: debug_printf("# No unmade children\n");
528: if (!(gn->type & (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC))) {
529: if (gn->mtime != 0) {
530: debug_printf("# last modified %s: %s\n",
531: Targ_FmtTime(gn->mtime),
532: made_name(gn->made));
533: } else if (gn->made != UNMADE) {
534: debug_printf("# non-existent (maybe): %s\n",
535: made_name(gn->made));
536: } else
537: debug_printf("# unmade\n");
1.1 cgd 538: }
1.150 rillig 539: PrintNodeNamesLine("implicit parents", &gn->implicitParents);
1.41 dsl 540: } else {
1.150 rillig 541: if (gn->unmade)
542: debug_printf("# %d unmade children\n", gn->unmade);
1.1 cgd 543: }
1.150 rillig 544:
1.143 rillig 545: PrintNodeNamesLine("parents", &gn->parents);
1.144 rillig 546: PrintNodeNamesLine("order_pred", &gn->order_pred);
547: PrintNodeNamesLine("order_succ", &gn->order_succ);
1.10 christos 548:
1.114 rillig 549: debug_printf("%-16s%s", gn->name, GNode_OpName(gn));
1.34 christos 550: Targ_PrintType(gn->type);
1.143 rillig 551: PrintNodeNames(&gn->children);
1.107 rillig 552: debug_printf("\n");
1.84 rillig 553: Targ_PrintCmds(gn);
1.107 rillig 554: debug_printf("\n\n");
1.150 rillig 555: if (gn->type & OP_DOUBLEDEP)
556: Targ_PrintNodes(&gn->cohorts, pass);
1.1 cgd 557: }
558:
1.87 rillig 559: void
1.89 rillig 560: Targ_PrintNodes(GNodeList *gnodes, int pass)
1.87 rillig 561: {
1.150 rillig 562: GNodeListNode *ln;
563:
564: for (ln = gnodes->first; ln != NULL; ln = ln->next)
565: Targ_PrintNode(ln->datum, pass);
1.87 rillig 566: }
567:
1.100 rillig 568: /* Print only those targets that are just a source. */
1.103 mrg 569: static void
1.100 rillig 570: PrintOnlySources(void)
1.4 jtc 571: {
1.150 rillig 572: GNodeListNode *ln;
1.100 rillig 573:
1.150 rillig 574: for (ln = allTargets.first; ln != NULL; ln = ln->next) {
575: GNode *gn = ln->datum;
576: if (GNode_IsTarget(gn))
577: continue;
578:
579: debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn));
580: Targ_PrintType(gn->type);
581: debug_printf("\n");
582: }
1.1 cgd 583: }
584:
1.150 rillig 585: /*
586: * Input:
1.77 rillig 587: * pass 1 => before processing
588: * 2 => after processing
589: * 3 => after processing, an error occurred
1.1 cgd 590: */
1.3 cgd 591: void
1.28 wiz 592: Targ_PrintGraph(int pass)
1.1 cgd 593: {
1.150 rillig 594: debug_printf("#*** Input graph:\n");
595: Targ_PrintNodes(&allTargets, pass);
596: debug_printf("\n");
597: debug_printf("\n");
1.135 rillig 598:
1.150 rillig 599: debug_printf("#\n");
600: debug_printf("# Files that are only sources:\n");
601: PrintOnlySources();
1.135 rillig 602:
1.150 rillig 603: debug_printf("#*** Global Variables:\n");
604: Var_Dump(VAR_GLOBAL);
1.135 rillig 605:
1.150 rillig 606: debug_printf("#*** Command-line Variables:\n");
607: Var_Dump(VAR_CMDLINE);
1.135 rillig 608:
1.150 rillig 609: debug_printf("\n");
610: Dir_PrintDirectories();
611: debug_printf("\n");
1.135 rillig 612:
1.150 rillig 613: Suff_PrintAll();
1.19 mycroft 614: }
615:
1.150 rillig 616: /*
617: * Propagate some type information to cohort nodes (those from the '::'
1.78 rillig 618: * dependency operator).
1.77 rillig 619: *
1.78 rillig 620: * Should be called after the makefiles are parsed but before any action is
1.150 rillig 621: * taken.
622: */
1.78 rillig 623: void
624: Targ_Propagate(void)
1.19 mycroft 625: {
1.150 rillig 626: GNodeListNode *ln, *cln;
1.45 dsl 627:
1.150 rillig 628: for (ln = allTargets.first; ln != NULL; ln = ln->next) {
629: GNode *gn = ln->datum;
630: GNodeType type = gn->type;
1.19 mycroft 631:
1.150 rillig 632: if (!(type & OP_DOUBLEDEP))
633: continue;
1.42 apb 634:
1.150 rillig 635: for (cln = gn->cohorts.first; cln != NULL; cln = cln->next) {
636: GNode *cohort = cln->datum;
1.42 apb 637:
1.150 rillig 638: cohort->type |= type & ~OP_OPMASK;
639: }
1.78 rillig 640: }
1.1 cgd 641: }
CVSweb <webmaster@jp.NetBSD.org>