Annotation of src/usr.bin/make/targ.c, Revision 1.44
1.44 ! dsl 1: /* $NetBSD: targ.c,v 1.43 2006/10/15 08:38:22 dsl 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.44 ! dsl 72: static char rcsid[] = "$NetBSD: targ.c,v 1.43 2006/10/15 08:38:22 dsl 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.44 ! dsl 79: __RCSID("$NetBSD: targ.c,v 1.43 2006/10/15 08:38:22 dsl 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.28 wiz 147: static int TargPrintOnlySrc(ClientData, ClientData);
148: static int TargPrintName(ClientData, ClientData);
1.18 mycroft 149: #ifdef CLEANUP
1.28 wiz 150: static void TargFreeGN(ClientData);
1.18 mycroft 151: #endif
1.28 wiz 152: static int TargPropagateCohort(ClientData, ClientData);
153: static int TargPropagateNode(ClientData, ClientData);
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.34 christos 170: allTargets = Lst_Init(FALSE);
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.18 mycroft 189: #ifdef CLEANUP
1.4 jtc 190: Lst_Destroy(allTargets, NOFREE);
191: if (allGNs)
192: Lst_Destroy(allGNs, TargFreeGN);
193: Hash_DeleteTable(&targets);
1.18 mycroft 194: #endif
1.12 christos 195: }
196:
197: /*-
198: *-----------------------------------------------------------------------
199: * Targ_List --
200: * Return the list of all targets
201: *
202: * Results:
203: * The list of all targets.
204: *
205: * Side Effects:
206: * None
207: *-----------------------------------------------------------------------
208: */
209: Lst
1.28 wiz 210: Targ_List(void)
1.12 christos 211: {
212: return allTargets;
1.4 jtc 213: }
214:
215: /*-
216: *-----------------------------------------------------------------------
1.1 cgd 217: * Targ_NewGN --
218: * Create and initialize a new graph node
219: *
1.28 wiz 220: * Input:
221: * name the name to stick in the new node
222: *
1.1 cgd 223: * Results:
224: * An initialized graph node with the name field filled with a copy
225: * of the passed name
226: *
227: * Side Effects:
1.4 jtc 228: * The gnode is added to the list of all gnodes.
1.1 cgd 229: *-----------------------------------------------------------------------
230: */
231: GNode *
1.29 christos 232: Targ_NewGN(const char *name)
1.1 cgd 233: {
1.28 wiz 234: GNode *gn;
1.1 cgd 235:
1.34 christos 236: gn = emalloc(sizeof(GNode));
237: gn->name = estrdup(name);
1.11 christos 238: gn->uname = NULL;
1.29 christos 239: gn->path = NULL;
1.1 cgd 240: if (name[0] == '-' && name[1] == 'l') {
241: gn->type = OP_LIB;
242: } else {
243: gn->type = 0;
244: }
245: gn->unmade = 0;
1.27 pk 246: gn->unmade_cohorts = 0;
247: gn->centurion = NULL;
1.1 cgd 248: gn->made = UNMADE;
1.16 christos 249: gn->flags = 0;
1.6 christos 250: gn->order = 0;
1.1 cgd 251: gn->mtime = gn->cmtime = 0;
1.34 christos 252: gn->iParents = Lst_Init(FALSE);
253: gn->cohorts = Lst_Init(FALSE);
254: gn->parents = Lst_Init(FALSE);
1.42 apb 255: gn->ancestors = Lst_Init(FALSE);
1.34 christos 256: gn->children = Lst_Init(FALSE);
257: gn->successors = Lst_Init(FALSE);
258: gn->preds = Lst_Init(FALSE);
1.42 apb 259: gn->recpreds = Lst_Init(FALSE);
1.17 mycroft 260: Hash_InitTable(&gn->context, 0);
1.34 christos 261: gn->commands = Lst_Init(FALSE);
1.3 cgd 262: gn->suffix = NULL;
1.21 christos 263: gn->lineno = 0;
264: gn->fname = NULL;
1.1 cgd 265:
1.18 mycroft 266: #ifdef CLEANUP
1.4 jtc 267: if (allGNs == NULL)
268: allGNs = Lst_Init(FALSE);
1.44 ! dsl 269: Lst_AtEnd(allGNs, gn);
1.18 mycroft 270: #endif
1.4 jtc 271:
1.1 cgd 272: return (gn);
273: }
274:
1.18 mycroft 275: #ifdef CLEANUP
1.1 cgd 276: /*-
277: *-----------------------------------------------------------------------
1.4 jtc 278: * TargFreeGN --
279: * Destroy a GNode
280: *
281: * Results:
282: * None.
283: *
284: * Side Effects:
285: * None.
286: *-----------------------------------------------------------------------
287: */
288: static void
1.28 wiz 289: TargFreeGN(ClientData gnp)
1.4 jtc 290: {
1.37 christos 291: GNode *gn = (GNode *)gnp;
1.4 jtc 292:
293:
294: free(gn->name);
1.11 christos 295: if (gn->uname)
296: free(gn->uname);
1.4 jtc 297: if (gn->path)
298: free(gn->path);
1.21 christos 299: if (gn->fname)
300: free(gn->fname);
1.4 jtc 301:
302: Lst_Destroy(gn->iParents, NOFREE);
303: Lst_Destroy(gn->cohorts, NOFREE);
304: Lst_Destroy(gn->parents, NOFREE);
1.42 apb 305: Lst_Destroy(gn->ancestors, NOFREE);
1.4 jtc 306: Lst_Destroy(gn->children, NOFREE);
307: Lst_Destroy(gn->successors, NOFREE);
308: Lst_Destroy(gn->preds, NOFREE);
1.42 apb 309: Lst_Destroy(gn->recpreds, NOFREE);
1.17 mycroft 310: Hash_DeleteTable(&gn->context);
1.4 jtc 311: Lst_Destroy(gn->commands, NOFREE);
1.36 christos 312: free(gn);
1.4 jtc 313: }
1.18 mycroft 314: #endif
1.4 jtc 315:
316:
317: /*-
318: *-----------------------------------------------------------------------
1.1 cgd 319: * Targ_FindNode --
320: * Find a node in the list using the given name for matching
321: *
1.28 wiz 322: * Input:
323: * name the name to find
324: * flags flags governing events when target not
325: * found
326: *
1.1 cgd 327: * Results:
328: * The node in the list if it was. If it wasn't, return NILGNODE of
329: * flags was TARG_NOCREATE or the newly created and initialized node
330: * if it was TARG_CREATE
331: *
332: * Side Effects:
333: * Sometimes a node is created and added to the list
334: *-----------------------------------------------------------------------
335: */
336: GNode *
1.29 christos 337: Targ_FindNode(const char *name, int flags)
1.1 cgd 338: {
339: GNode *gn; /* node in that element */
340: Hash_Entry *he; /* New or used hash entry for node */
341: Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */
342: /* an entry for the node */
343:
344:
345: if (flags & TARG_CREATE) {
1.34 christos 346: he = Hash_CreateEntry(&targets, name, &isNew);
1.1 cgd 347: if (isNew) {
1.34 christos 348: gn = Targ_NewGN(name);
1.35 christos 349: Hash_SetValue(he, gn);
1.24 tv 350: Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
1.44 ! dsl 351: (void)Lst_AtEnd(allTargets, gn);
1.1 cgd 352: }
353: } else {
1.34 christos 354: he = Hash_FindEntry(&targets, name);
1.1 cgd 355: }
356:
1.37 christos 357: if (he == NULL) {
1.1 cgd 358: return (NILGNODE);
359: } else {
1.35 christos 360: return ((GNode *)Hash_GetValue(he));
1.1 cgd 361: }
362: }
363:
364: /*-
365: *-----------------------------------------------------------------------
366: * Targ_FindList --
1.10 christos 367: * Make a complete list of GNodes from the given list of names
1.1 cgd 368: *
1.28 wiz 369: * Input:
370: * name list of names to find
371: * flags flags used if no node is found for a given name
372: *
1.1 cgd 373: * Results:
374: * A complete list of graph nodes corresponding to all instances of all
1.10 christos 375: * the names in names.
1.1 cgd 376: *
377: * Side Effects:
378: * If flags is TARG_CREATE, nodes will be created for all names in
379: * names which do not yet have graph nodes. If flags is TARG_NOCREATE,
380: * an error message will be printed for each name which can't be found.
381: * -----------------------------------------------------------------------
382: */
383: Lst
1.28 wiz 384: Targ_FindList(Lst names, int flags)
1.1 cgd 385: {
386: Lst nodes; /* result list */
1.28 wiz 387: LstNode ln; /* name list element */
388: GNode *gn; /* node in tLn */
389: char *name;
1.1 cgd 390:
1.34 christos 391: nodes = Lst_Init(FALSE);
1.1 cgd 392:
1.34 christos 393: if (Lst_Open(names) == FAILURE) {
1.1 cgd 394: return (nodes);
395: }
1.34 christos 396: while ((ln = Lst_Next(names)) != NILLNODE) {
1.1 cgd 397: name = (char *)Lst_Datum(ln);
1.34 christos 398: gn = Targ_FindNode(name, flags);
1.1 cgd 399: if (gn != NILGNODE) {
400: /*
401: * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
402: * are added to the list in the order in which they were
403: * encountered in the makefile.
404: */
1.44 ! dsl 405: (void)Lst_AtEnd(nodes, gn);
1.1 cgd 406: } else if (flags == TARG_NOCREATE) {
1.34 christos 407: Error("\"%s\" -- target unknown.", name);
1.1 cgd 408: }
409: }
1.34 christos 410: Lst_Close(names);
1.1 cgd 411: return (nodes);
412: }
413:
414: /*-
415: *-----------------------------------------------------------------------
416: * Targ_Ignore --
417: * Return true if should ignore errors when creating gn
418: *
1.28 wiz 419: * Input:
420: * gn node to check for
421: *
1.1 cgd 422: * Results:
423: * TRUE if should ignore errors
424: *
425: * Side Effects:
426: * None
427: *-----------------------------------------------------------------------
428: */
429: Boolean
1.28 wiz 430: Targ_Ignore(GNode *gn)
1.1 cgd 431: {
432: if (ignoreErrors || gn->type & OP_IGNORE) {
433: return (TRUE);
434: } else {
435: return (FALSE);
436: }
437: }
438:
439: /*-
440: *-----------------------------------------------------------------------
441: * Targ_Silent --
442: * Return true if be silent when creating gn
443: *
1.28 wiz 444: * Input:
445: * gn node to check for
446: *
1.1 cgd 447: * Results:
448: * TRUE if should be silent
449: *
450: * Side Effects:
451: * None
452: *-----------------------------------------------------------------------
453: */
454: Boolean
1.28 wiz 455: Targ_Silent(GNode *gn)
1.1 cgd 456: {
457: if (beSilent || gn->type & OP_SILENT) {
458: return (TRUE);
459: } else {
460: return (FALSE);
461: }
462: }
463:
464: /*-
465: *-----------------------------------------------------------------------
466: * Targ_Precious --
467: * See if the given target is precious
468: *
1.28 wiz 469: * Input:
470: * gn the node to check
471: *
1.1 cgd 472: * Results:
473: * TRUE if it is precious. FALSE otherwise
474: *
475: * Side Effects:
476: * None
477: *-----------------------------------------------------------------------
478: */
479: Boolean
1.28 wiz 480: Targ_Precious(GNode *gn)
1.1 cgd 481: {
482: if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
483: return (TRUE);
484: } else {
485: return (FALSE);
486: }
487: }
488:
489: /******************* DEBUG INFO PRINTING ****************/
490:
491: static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
1.10 christos 492: /*-
1.1 cgd 493: *-----------------------------------------------------------------------
494: * Targ_SetMain --
495: * Set our idea of the main target we'll be creating. Used for
496: * debugging output.
497: *
1.28 wiz 498: * Input:
499: * gn The main target we'll create
500: *
1.1 cgd 501: * Results:
502: * None.
503: *
504: * Side Effects:
505: * "mainTarg" is set to the main target's node.
506: *-----------------------------------------------------------------------
507: */
508: void
1.28 wiz 509: Targ_SetMain(GNode *gn)
1.1 cgd 510: {
511: mainTarg = gn;
512: }
513:
1.38 dsl 514: #define PrintWait (ClientData)1
515: #define PrintPath (ClientData)2
516:
1.1 cgd 517: static int
1.38 dsl 518: TargPrintName(ClientData gnp, ClientData pflags)
1.1 cgd 519: {
1.38 dsl 520: static int last_order;
1.37 christos 521: GNode *gn = (GNode *)gnp;
1.38 dsl 522:
523: if (pflags == PrintWait && gn->order > last_order)
1.43 dsl 524: fprintf(debug_file, ".WAIT ");
1.38 dsl 525: last_order = gn->order;
526:
1.43 dsl 527: fprintf(debug_file, "%s ", gn->name);
1.38 dsl 528:
1.1 cgd 529: #ifdef notdef
1.38 dsl 530: if (pflags == PrintPath) {
1.1 cgd 531: if (gn->path) {
1.43 dsl 532: fprintf(debug_file, "[%s] ", gn->path);
1.1 cgd 533: }
534: if (gn == mainTarg) {
1.43 dsl 535: fprintf(debug_file, "(MAIN NAME) ");
1.1 cgd 536: }
537: }
1.3 cgd 538: #endif /* notdef */
1.38 dsl 539:
540: return 0;
1.1 cgd 541: }
542:
543:
544: int
1.28 wiz 545: Targ_PrintCmd(ClientData cmd, ClientData dummy)
1.1 cgd 546: {
1.43 dsl 547: fprintf(debug_file, "\t%s\n", (char *)cmd);
1.4 jtc 548: return (dummy ? 0 : 0);
1.1 cgd 549: }
550:
551: /*-
552: *-----------------------------------------------------------------------
553: * Targ_FmtTime --
554: * Format a modification time in some reasonable way and return it.
555: *
556: * Results:
557: * The time reformatted.
558: *
559: * Side Effects:
560: * The time is placed in a static area, so it is overwritten
561: * with each call.
562: *
563: *-----------------------------------------------------------------------
564: */
565: char *
1.28 wiz 566: Targ_FmtTime(time_t tm)
1.1 cgd 567: {
568: struct tm *parts;
1.15 christos 569: static char buf[128];
1.1 cgd 570:
1.25 reinoud 571: parts = localtime(&tm);
1.15 christos 572: (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
1.1 cgd 573: return(buf);
574: }
1.10 christos 575:
1.1 cgd 576: /*-
577: *-----------------------------------------------------------------------
578: * Targ_PrintType --
579: * Print out a type field giving only those attributes the user can
580: * set.
581: *
582: * Results:
583: *
584: * Side Effects:
585: *
586: *-----------------------------------------------------------------------
587: */
588: void
1.28 wiz 589: Targ_PrintType(int type)
1.1 cgd 590: {
1.28 wiz 591: int tbit;
1.10 christos 592:
1.43 dsl 593: #define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break
594: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break
1.1 cgd 595:
596: type &= ~OP_OPMASK;
597:
598: while (type) {
599: tbit = 1 << (ffs(type) - 1);
600: type &= ~tbit;
601:
602: switch(tbit) {
603: PRINTBIT(OPTIONAL);
604: PRINTBIT(USE);
605: PRINTBIT(EXEC);
606: PRINTBIT(IGNORE);
607: PRINTBIT(PRECIOUS);
608: PRINTBIT(SILENT);
609: PRINTBIT(MAKE);
610: PRINTBIT(JOIN);
611: PRINTBIT(INVISIBLE);
612: PRINTBIT(NOTMAIN);
613: PRINTDBIT(LIB);
614: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.43 dsl 615: case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break;
1.1 cgd 616: PRINTDBIT(ARCHV);
1.26 pk 617: PRINTDBIT(MADE);
618: PRINTDBIT(PHONY);
1.1 cgd 619: }
620: }
621: }
622:
623: /*-
624: *-----------------------------------------------------------------------
625: * TargPrintNode --
626: * print the contents of a node
627: *-----------------------------------------------------------------------
628: */
1.40 dsl 629: int
630: Targ_PrintNode(ClientData gnp, ClientData passp)
1.1 cgd 631: {
1.37 christos 632: GNode *gn = (GNode *)gnp;
1.40 dsl 633: int pass = passp ? *(int *)passp : 0;
1.1 cgd 634: if (!OP_NOP(gn->type)) {
1.43 dsl 635: fprintf(debug_file, "#\n");
1.1 cgd 636: if (gn == mainTarg) {
1.43 dsl 637: fprintf(debug_file, "# *** MAIN TARGET ***\n");
1.1 cgd 638: }
639: if (pass == 2) {
640: if (gn->unmade) {
1.43 dsl 641: fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1 cgd 642: } else {
1.43 dsl 643: fprintf(debug_file, "# No unmade children\n");
1.1 cgd 644: }
1.22 christos 645: if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
1.1 cgd 646: if (gn->mtime != 0) {
1.43 dsl 647: fprintf(debug_file, "# last modified %s: %s\n",
1.1 cgd 648: Targ_FmtTime(gn->mtime),
649: (gn->made == UNMADE ? "unmade" :
650: (gn->made == MADE ? "made" :
651: (gn->made == UPTODATE ? "up-to-date" :
652: "error when made"))));
653: } else if (gn->made != UNMADE) {
1.43 dsl 654: fprintf(debug_file, "# non-existent (maybe): %s\n",
1.1 cgd 655: (gn->made == MADE ? "made" :
656: (gn->made == UPTODATE ? "up-to-date" :
657: (gn->made == ERROR ? "error when made" :
658: "aborted"))));
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.42 apb 677: if (!Lst_IsEmpty (gn->children)) {
1.43 dsl 678: fprintf(debug_file, "# children: ");
1.44 ! dsl 679: Lst_ForEach(gn->children, TargPrintName, NULL);
1.43 dsl 680: fprintf(debug_file, "\n");
1.42 apb 681: }
1.39 dsl 682: if (!Lst_IsEmpty (gn->preds)) {
1.43 dsl 683: fprintf(debug_file, "# preds: ");
1.44 ! dsl 684: Lst_ForEach(gn->preds, TargPrintName, NULL);
1.43 dsl 685: fprintf(debug_file, "\n");
1.39 dsl 686: }
1.42 apb 687: if (!Lst_IsEmpty (gn->recpreds)) {
1.43 dsl 688: fprintf(debug_file, "# recpreds: ");
1.44 ! dsl 689: Lst_ForEach(gn->recpreds, TargPrintName, NULL);
1.43 dsl 690: fprintf(debug_file, "\n");
1.42 apb 691: }
1.39 dsl 692: if (!Lst_IsEmpty (gn->successors)) {
1.43 dsl 693: fprintf(debug_file, "# successors: ");
1.44 ! dsl 694: Lst_ForEach(gn->successors, TargPrintName, NULL);
1.43 dsl 695: fprintf(debug_file, "\n");
1.39 dsl 696: }
1.10 christos 697:
1.43 dsl 698: fprintf(debug_file, "%-16s", gn->name);
1.1 cgd 699: switch (gn->type & OP_OPMASK) {
700: case OP_DEPENDS:
1.43 dsl 701: fprintf(debug_file, ": "); break;
1.1 cgd 702: case OP_FORCE:
1.43 dsl 703: fprintf(debug_file, "! "); break;
1.1 cgd 704: case OP_DOUBLEDEP:
1.43 dsl 705: fprintf(debug_file, ":: "); break;
1.1 cgd 706: }
1.34 christos 707: Targ_PrintType(gn->type);
1.38 dsl 708: Lst_ForEach(gn->children, TargPrintName, PrintWait);
1.43 dsl 709: fprintf(debug_file, "\n");
1.44 ! dsl 710: Lst_ForEach(gn->commands, Targ_PrintCmd, NULL);
1.43 dsl 711: fprintf(debug_file, "\n\n");
1.20 mycroft 712: if (gn->type & OP_DOUBLEDEP) {
1.44 ! dsl 713: Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass);
1.1 cgd 714: }
715: }
716: return (0);
717: }
718:
719: /*-
720: *-----------------------------------------------------------------------
721: * TargPrintOnlySrc --
722: * Print only those targets that are just a source.
723: *
724: * Results:
725: * 0.
726: *
727: * Side Effects:
1.23 wiz 728: * The name of each file is printed preceded by #\t
1.1 cgd 729: *
730: *-----------------------------------------------------------------------
731: */
732: static int
1.28 wiz 733: TargPrintOnlySrc(ClientData gnp, ClientData dummy)
1.4 jtc 734: {
1.37 christos 735: GNode *gn = (GNode *)gnp;
1.4 jtc 736: if (OP_NOP(gn->type))
1.43 dsl 737: fprintf(debug_file, "#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);
1.4 jtc 738:
739: return (dummy ? 0 : 0);
1.1 cgd 740: }
741:
742: /*-
743: *-----------------------------------------------------------------------
744: * Targ_PrintGraph --
745: * print the entire graph. heh heh
746: *
1.28 wiz 747: * Input:
748: * pass Which pass this is. 1 => no processing
749: * 2 => processing done
750: *
1.1 cgd 751: * Results:
752: * none
753: *
754: * Side Effects:
755: * lots o' output
756: *-----------------------------------------------------------------------
757: */
1.3 cgd 758: void
1.28 wiz 759: Targ_PrintGraph(int pass)
1.1 cgd 760: {
1.43 dsl 761: fprintf(debug_file, "#*** Input graph:\n");
1.44 ! dsl 762: Lst_ForEach(allTargets, Targ_PrintNode, &pass);
1.43 dsl 763: fprintf(debug_file, "\n\n");
764: fprintf(debug_file, "#\n# Files that are only sources:\n");
1.44 ! dsl 765: Lst_ForEach(allTargets, TargPrintOnlySrc, NULL);
1.43 dsl 766: fprintf(debug_file, "#*** Global Variables:\n");
1.34 christos 767: Var_Dump(VAR_GLOBAL);
1.43 dsl 768: fprintf(debug_file, "#*** Command-line Variables:\n");
1.34 christos 769: Var_Dump(VAR_CMD);
1.43 dsl 770: fprintf(debug_file, "\n");
1.1 cgd 771: Dir_PrintDirectories();
1.43 dsl 772: fprintf(debug_file, "\n");
1.1 cgd 773: Suff_PrintAll();
1.19 mycroft 774: }
775:
1.42 apb 776: /*-
777: *-----------------------------------------------------------------------
778: * TargAppendAncestor -
779: * Appends a single ancestor to a node's list of ancestors,
780: * ignoring duplicates.
781: *
782: * Input:
783: * ancestorgnp An ancestor to be added to a list.
784: * thisgnp The node whose ancestor list will be changed.
785: *
786: * Results:
787: * Always returns 0, for the benefit of Lst_ForEach().
788: *
789: * Side Effects:
790: * May modify the ancestors list of the node we are
791: * examining.
792: *-----------------------------------------------------------------------
793: */
794: static int
795: TargAppendAncestor(ClientData ancestorgnp, ClientData thisgnp)
796: {
797: GNode *ancestorgn = (GNode *)ancestorgnp;
798: GNode *thisgn = (GNode *)thisgnp;
799:
800: if (Lst_Member(thisgn->ancestors, ancestorgn) == NILLNODE) {
1.44 ! dsl 801: (void)Lst_AtEnd(thisgn->ancestors, ancestorgn);
1.42 apb 802: }
803: return (0);
804: }
805:
806: /*-
807: *-----------------------------------------------------------------------
808: * TargAppendParentAncestors -
809: * Appends all ancestors of a parent node to the ancestor list of a
810: * given node, ignoring duplicates.
811: *
812: * Input:
813: * parentgnp A parent node whose ancestor list will be
814: * propagated to another node.
815: * thisgnp The node whose ancestor list will be changed.
816: *
817: * Results:
818: * Always returns 0, for the benefit of Lst_ForEach().
819: *
820: * Side Effects:
821: * May modify the ancestors list of the node we are
822: * examining.
823: *-----------------------------------------------------------------------
824: */
825: static int
826: TargAppendParentAncestors(ClientData parentgnp, ClientData thisgnp)
827: {
828: GNode *parentgn = (GNode *)parentgnp;
829: GNode *thisgn = (GNode *)thisgnp;
830:
831: Lst_ForEach(parentgn->ancestors, TargAppendAncestor, thisgn);
832: return (0);
833: }
834:
835: /*-
836: *-----------------------------------------------------------------------
837: * TargInitAncestors -
838: * Initialises the ancestor list of a node and all the
839: * node's ancestors.
840: *
841: * Input:
842: * thisgnp The node that we are examining.
843: *
844: * Results:
845: * Always returns 0, for the benefit of Lst_ForEach().
846: *
847: * Side Effects:
848: * May initialise the ancestors list of the node we are
849: * examining and all its ancestors. Does nothing if the
850: * list has already been initialised.
851: *-----------------------------------------------------------------------
852: */
1.19 mycroft 853: static int
1.42 apb 854: TargInitAncestors(ClientData thisgnp, ClientData junk __unused)
855: {
856: GNode *thisgn = (GNode *)thisgnp;
857:
858: if (Lst_IsEmpty (thisgn->ancestors)) {
859: /*
860: * Add our parents to our ancestor list before recursing, to
861: * ensure that loops in the dependency graph will not result in
862: * infinite recursion.
863: */
864: Lst_ForEach(thisgn->parents, TargAppendAncestor, thisgn);
865: Lst_ForEach(thisgn->iParents, TargAppendAncestor, thisgn);
866: /* Recursively initialise our parents' ancestor lists */
1.44 ! dsl 867: Lst_ForEach(thisgn->parents, TargInitAncestors, NULL);
! 868: Lst_ForEach(thisgn->iParents, TargInitAncestors, NULL);
1.42 apb 869: /* Our parents' ancestors are also our ancestors */
870: Lst_ForEach(thisgn->parents, TargAppendParentAncestors, thisgn);
871: Lst_ForEach(thisgn->iParents, TargAppendParentAncestors, thisgn);
872: }
873: return (0);
874: }
875:
876: /*-
877: *-----------------------------------------------------------------------
878: * TargHasAncestor -
879: * Checks whether one node is an ancestor of another node.
880: *
881: * If called with both arguments pointing to the
882: * same node, checks whether the node is part of a cycle
883: * in the graph.
884: *
885: * Input:
886: * thisgnp The node whose ancestor list we are examining.
887: * seekgnp The node that we are seeking in the
888: * ancestor list.
889: *
890: * Results:
891: * TRUE if seekgn is an ancestor of thisgn; FALSE if not.
892: *
893: * Side Effects:
894: * Initialises the ancestors list in thisgnp and all its ancestors.
895: *-----------------------------------------------------------------------
896: */
897: static Boolean
898: TargHasAncestor(ClientData thisgnp, ClientData seekgnp)
899: {
900: GNode *thisgn = (GNode *)thisgnp;
901: GNode *seekgn = (GNode *)seekgnp;
902:
1.44 ! dsl 903: TargInitAncestors(thisgn, NULL);
1.42 apb 904: if (Lst_Member(thisgn->ancestors, seekgn) != NILLNODE) {
905: return (TRUE);
906: }
907: return (FALSE);
908: }
909:
910: /*-
911: *-----------------------------------------------------------------------
912: * TargPropagateRecpredChild --
913: * Create a new predecessor/successor relationship between a pair
914: * of nodes, and recursively propagate the relationship to all
915: * children of the successor node.
916: *
917: * If there is already a predecessor/successor relationship
918: * in the opposite direction, or if there is already an
919: * ancestor/descendent relationship in the oposite direction, then
920: * we avoid adding the new relationship, because that would cause a
921: * cycle in the graph.
922: *
923: * Input:
924: * succgnp Successor node.
925: * predgnp Predecessor node.
926: *
927: * Results:
928: * Always returns 0, for the benefit of Lst_ForEach().
929: *
930: * Side Effects:
931: * preds/successors information is modified for predgnp, succgnp,
932: * and recursively for all children of succgnp.
933: *-----------------------------------------------------------------------
934: */
935: static int
936: TargPropagateRecpredChild(ClientData succgnp, ClientData predgnp)
937: {
938: GNode *succgn = (GNode *)succgnp;
939: GNode *predgn = (GNode *)predgnp;
940: Boolean debugmore = FALSE; /* how much debugging? */
941:
942: /* Ignore if succgn == predgn */
943: if (succgn == predgn) {
944: if (DEBUG(TARG) && debugmore) {
1.43 dsl 945: fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (identical)\n",
1.42 apb 946: predgn->name, succgn->name);
947: }
948: return (0);
949: }
950: /* Pre-existing pred/successor relationship
951: * in the opposite direction takes precedence. */
952: if (Lst_Member(succgn->successors, predgn) != NILLNODE) {
953: if (DEBUG(TARG) && debugmore) {
1.43 dsl 954: fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (opposite)\n",
1.42 apb 955: predgn->name, succgn->name);
956: }
957: return (0);
958: }
959: /* Pre-existing descendent/ancestor relationship in the opposite
960: * direction takes precedence. */
961: if (TargHasAncestor(succgn, predgn)) {
962: if (DEBUG(TARG) && debugmore) {
1.43 dsl 963: fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (ancestor)\n",
1.42 apb 964: predgn->name, succgn->name);
965: }
966: return (0);
967: }
968: /* Note the new pred/successor relationship. */
969: if (DEBUG(TARG)) {
1.43 dsl 970: fprintf(debug_file, "# TargPropagateRecpredChild: propagating %s - %s\n",
1.42 apb 971: predgn->name, succgn->name);
972: }
973: if (Lst_Member(succgn->preds, predgn) == NILLNODE) {
1.44 ! dsl 974: (void)Lst_AtEnd(succgn->preds, predgn);
! 975: (void)Lst_AtEnd(predgn->successors, succgn);
1.42 apb 976: }
977: /* Recurse, provided there's not a cycle. */
978: if (! TargHasAncestor(succgn, succgn)) {
979: Lst_ForEach(succgn->children, TargPropagateRecpredChild, predgn);
980: }
981: return (0);
982: }
983:
984: /*-
985: *-----------------------------------------------------------------------
986: * TargPropagateRecpred --
987: * Recursively propagate information about a single predecessor
988: * node, from a single successor node to all children of the
989: * successor node.
990: *
991: * Input:
992: * predgnp Predecessor node.
993: * succgnp Successor node.
994: *
995: * Results:
996: * Always returns 0, for the benefit of Lst_ForEach().
997: *
998: * Side Effects:
999: * preds/successors information is modified for predgnp, succgnp,
1000: * and recursively for all children of succgnp.
1001: *
1002: * The real work is done by TargPropagateRecpredChild(), which
1003: * will be called for each child of the successor node.
1004: *-----------------------------------------------------------------------
1005: */
1006: static int
1007: TargPropagateRecpred(ClientData predgnp, ClientData succgnp)
1.19 mycroft 1008: {
1.42 apb 1009: GNode *predgn = (GNode *)predgnp;
1010: GNode *succgn = (GNode *)succgnp;
1.19 mycroft 1011:
1.42 apb 1012: Lst_ForEach(succgn->children, TargPropagateRecpredChild, predgn);
1.19 mycroft 1013: return (0);
1014: }
1015:
1.42 apb 1016: /*-
1017: *-----------------------------------------------------------------------
1018: * TargPropagateNode --
1019: * Propagate information from a single node to related nodes if
1020: * appropriate.
1021: *
1022: * Input:
1023: * gnp The node that we are processing.
1024: *
1025: * Results:
1026: * Always returns 0, for the benefit of Lst_ForEach().
1027: *
1028: * Side Effects:
1029: * Information is propagated from this node to cohort or child
1030: * nodes.
1031: *
1032: * If the node was defined with "::", then TargPropagateCohort()
1033: * will be called for each cohort node.
1034: *
1035: * If the node has recursive predecessors, then
1036: * TargPropagateRecpred() will be called for each recursive
1037: * predecessor.
1038: *-----------------------------------------------------------------------
1039: */
1.19 mycroft 1040: static int
1.33 jmc 1041: TargPropagateNode(ClientData gnp, ClientData junk __unused)
1.19 mycroft 1042: {
1.37 christos 1043: GNode *gn = (GNode *)gnp;
1.20 mycroft 1044: if (gn->type & OP_DOUBLEDEP)
1.34 christos 1045: Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp);
1.42 apb 1046: Lst_ForEach(gn->recpreds, TargPropagateRecpred, gnp);
1.19 mycroft 1047: return (0);
1048: }
1049:
1.42 apb 1050: /*-
1051: *-----------------------------------------------------------------------
1052: * TargPropagateCohort --
1053: * Propagate some bits in the type mask from a node to
1054: * a related cohort node.
1055: *
1056: * Input:
1057: * cnp The node that we are processing.
1058: * gnp Another node that has cnp as a cohort.
1059: *
1060: * Results:
1061: * Always returns 0, for the benefit of Lst_ForEach().
1062: *
1063: * Side Effects:
1064: * cnp's type bitmask is modified to incorporate some of the
1065: * bits from gnp's type bitmask. (XXX need a better explanation.)
1066: *-----------------------------------------------------------------------
1067: */
1068: static int
1069: TargPropagateCohort(ClientData cgnp, ClientData pgnp)
1070: {
1071: GNode *cgn = (GNode *)cgnp;
1072: GNode *pgn = (GNode *)pgnp;
1073:
1074: cgn->type |= pgn->type & ~OP_OPMASK;
1075: return (0);
1076: }
1077:
1078: /*-
1079: *-----------------------------------------------------------------------
1080: * Targ_Propagate --
1081: * Propagate information between related nodes. Should be called
1082: * after the makefiles are parsed but before any action is taken.
1083: *
1084: * Results:
1085: * none
1086: *
1087: * Side Effects:
1088: * Information is propagated between related nodes throughout the
1089: * graph.
1090: *-----------------------------------------------------------------------
1091: */
1.19 mycroft 1092: void
1.28 wiz 1093: Targ_Propagate(void)
1.19 mycroft 1094: {
1.44 ! dsl 1095: Lst_ForEach(allTargets, TargPropagateNode, NULL);
1.1 cgd 1096: }
CVSweb <webmaster@jp.NetBSD.org>