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