Annotation of src/usr.bin/make/targ.c, Revision 1.64
1.64 ! jsg 1: /* $OpenBSD: targ.c,v 1.63 2012/03/22 13:47:12 espie Exp $ */
1.6 millert 2: /* $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $ */
1.1 deraadt 3:
4: /*
1.31 espie 5: * Copyright (c) 1999 Marc Espie.
6: *
7: * Extensive code changes for the OpenBSD project.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
19: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
22: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30: /*
1.5 millert 31: * Copyright (c) 1988, 1989, 1990, 1993
32: * The Regents of the University of California. All rights reserved.
1.1 deraadt 33: * Copyright (c) 1989 by Berkeley Softworks
34: * All rights reserved.
35: *
36: * This code is derived from software contributed to Berkeley by
37: * Adam de Boor.
38: *
39: * Redistribution and use in source and binary forms, with or without
40: * modification, are permitted provided that the following conditions
41: * are met:
42: * 1. Redistributions of source code must retain the above copyright
43: * notice, this list of conditions and the following disclaimer.
44: * 2. Redistributions in binary form must reproduce the above copyright
45: * notice, this list of conditions and the following disclaimer in the
46: * documentation and/or other materials provided with the distribution.
1.38 millert 47: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: */
63:
64: /*-
65: * targ.c --
1.27 espie 66: * Target nodes are kept into a hash table.
1.1 deraadt 67: *
68: * Interface:
1.31 espie 69: * Targ_Init Initialization procedure.
1.1 deraadt 70: *
1.31 espie 71: * Targ_End Cleanup the module
1.1 deraadt 72: *
1.31 espie 73: * Targ_NewGN Create a new GNode for the passed target
74: * (string). The node is *not* placed in the
75: * hash table, though all its fields are
76: * initialized.
1.1 deraadt 77: *
1.31 espie 78: * Targ_FindNode Find the node for a given target, creating
79: * and storing it if it doesn't exist and the
80: * flags are right (TARG_CREATE)
1.1 deraadt 81: *
1.31 espie 82: * Targ_FindList Given a list of names, find nodes for all
83: * of them, creating nodes if needed.
1.1 deraadt 84: *
1.32 espie 85: * Targ_Ignore Return true if errors should be ignored when
1.31 espie 86: * creating the given target.
1.1 deraadt 87: *
1.32 espie 88: * Targ_Silent Return true if we should be silent when
1.31 espie 89: * creating the given target.
1.1 deraadt 90: *
1.32 espie 91: * Targ_Precious Return true if the target is precious and
1.31 espie 92: * should not be removed if we are interrupted.
1.1 deraadt 93: *
94: * Debugging:
1.31 espie 95: * Targ_PrintGraph Print out the entire graphm all variables
96: * and statistics for the directory cache. Should
97: * print something for suffixes, too, but...
1.1 deraadt 98: */
99:
1.34 espie 100: #include <limits.h>
1.32 espie 101: #include <stddef.h>
102: #include <stdio.h>
1.40 espie 103: #include <stdint.h>
1.33 espie 104: #include <string.h>
1.32 espie 105: #include "config.h"
106: #include "defines.h"
107: #include "ohash.h"
108: #include "stats.h"
109: #include "suff.h"
110: #include "var.h"
111: #include "targ.h"
112: #include "memory.h"
113: #include "gnode.h"
114: #include "extern.h"
115: #include "timestamp.h"
116: #include "lst.h"
1.46 espie 117: #include "node_int.h"
118: #include "nodehashconsts.h"
1.37 espie 119: #ifdef CLEANUP
120: #include <stdlib.h>
121: #endif
1.31 espie 122:
1.57 espie 123: static struct ohash targets; /* hash table of targets */
1.46 espie 124: struct ohash_info gnode_info = {
125: offsetof(GNode, name), NULL, hash_alloc, hash_free, element_alloc
1.42 espie 126: };
1.1 deraadt 127:
1.31 espie 128: static void TargPrintOnlySrc(GNode *);
129: static void TargPrintName(void *);
130: static void TargPrintNode(GNode *, int);
1.10 espie 131: #ifdef CLEANUP
1.37 espie 132: static LIST allTargets;
1.31 espie 133: static void TargFreeGN(void *);
1.10 espie 134: #endif
1.48 espie 135: #define Targ_FindConstantNode(n, f) Targ_FindNodeh(n, sizeof(n), K_##n, f)
136:
1.1 deraadt 137:
1.46 espie 138: GNode *begin_node, *end_node, *interrupt_node, *DEFAULT;
139:
1.1 deraadt 140: void
1.39 espie 141: Targ_Init(void)
1.1 deraadt 142: {
1.42 espie 143: /* A small make file already creates 200 targets. */
144: ohash_init(&targets, 10, &gnode_info);
1.37 espie 145: #ifdef CLEANUP
1.42 espie 146: Lst_Init(&allTargets);
1.37 espie 147: #endif
1.46 espie 148: begin_node = Targ_FindConstantNode(NODE_BEGIN, TARG_CREATE);
149: begin_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
150: end_node = Targ_FindConstantNode(NODE_END, TARG_CREATE);
151: end_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
152: interrupt_node = Targ_FindConstantNode(NODE_INTERRUPT, TARG_CREATE);
153: interrupt_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
154: DEFAULT = Targ_FindConstantNode(NODE_DEFAULT, TARG_CREATE);
155: DEFAULT->type |= OP_DUMMY | OP_NOTMAIN| OP_TRANSFORM | OP_NODEFAULT;
156:
1.1 deraadt 157: }
158:
1.32 espie 159: #ifdef CLEANUP
1.1 deraadt 160: void
1.39 espie 161: Targ_End(void)
1.1 deraadt 162: {
1.42 espie 163: Lst_Every(&allTargets, TargFreeGN);
164: ohash_delete(&targets);
1.32 espie 165: }
1.10 espie 166: #endif
1.1 deraadt 167:
168: GNode *
1.46 espie 169: Targ_NewGNi(const char *name, const char *ename)
1.1 deraadt 170: {
1.42 espie 171: GNode *gn;
1.1 deraadt 172:
1.42 espie 173: gn = ohash_create_entry(&gnode_info, name, &ename);
174: gn->path = NULL;
1.46 espie 175: if (name[0] == '-' && name[1] == 'l')
1.42 espie 176: gn->type = OP_LIB;
1.46 espie 177: else
1.42 espie 178: gn->type = 0;
1.46 espie 179:
180: gn->special = SPECIAL_NONE;
181: gn->unmade = 0;
1.51 espie 182: gn->must_make = false;
1.53 espie 183: gn->built_status = UNKNOWN;
1.42 espie 184: gn->childMade = false;
1.46 espie 185: gn->order = 0;
1.42 espie 186: ts_set_out_of_date(gn->mtime);
187: ts_set_out_of_date(gn->cmtime);
188: Lst_Init(&gn->cohorts);
189: Lst_Init(&gn->parents);
190: Lst_Init(&gn->children);
191: Lst_Init(&gn->successors);
192: Lst_Init(&gn->preds);
193: SymTable_Init(&gn->context);
1.63 espie 194: gn->origin.lineno = 0;
195: gn->origin.fname = NULL;
1.50 espie 196: gn->impliedsrc = NULL;
1.42 espie 197: Lst_Init(&gn->commands);
1.56 espie 198: Lst_Init(&gn->expanded);
199: gn->suffix = NULL;
1.57 espie 200: gn->next = NULL;
201: gn->basename = NULL;
202: gn->sibling = gn;
203: gn->build_lock = false;
1.1 deraadt 204:
1.31 espie 205: #ifdef STATS_GN_CREATION
1.42 espie 206: STAT_GN_COUNT++;
1.10 espie 207: #endif
1.1 deraadt 208:
1.37 espie 209: #ifdef CLEANUP
1.42 espie 210: Lst_AtEnd(&allTargets, gn);
1.37 espie 211: #endif
1.42 espie 212: return gn;
1.1 deraadt 213: }
214:
1.10 espie 215: #ifdef CLEANUP
1.1 deraadt 216: static void
1.39 espie 217: TargFreeGN(void *gnp)
1.1 deraadt 218: {
1.42 espie 219: GNode *gn = (GNode *)gnp;
1.1 deraadt 220:
1.42 espie 221: efree(gn->path);
222: Lst_Destroy(&gn->cohorts, NOFREE);
223: Lst_Destroy(&gn->parents, NOFREE);
224: Lst_Destroy(&gn->children, NOFREE);
225: Lst_Destroy(&gn->successors, NOFREE);
226: Lst_Destroy(&gn->preds, NOFREE);
227: Lst_Destroy(&gn->commands, NOFREE);
228: SymTable_Destroy(&gn->context);
229: free(gn);
1.1 deraadt 230: }
1.10 espie 231: #endif
1.1 deraadt 232:
1.46 espie 233: GNode *
234: Targ_FindNodei(const char *name, const char *ename, int flags)
235: {
236: uint32_t hv;
237:
238: hv = ohash_interval(name, &ename);
239: return Targ_FindNodeih(name, ename, hv, flags);
240: }
1.1 deraadt 241:
242: GNode *
1.46 espie 243: Targ_FindNodeih(const char *name, const char *ename, uint32_t hv, int flags)
1.1 deraadt 244: {
1.46 espie 245: GNode *gn;
1.42 espie 246: unsigned int slot;
1.27 espie 247:
1.46 espie 248: slot = ohash_lookup_interval(&targets, name, ename, hv);
1.27 espie 249:
1.42 espie 250: gn = ohash_find(&targets, slot);
1.31 espie 251:
1.42 espie 252: if (gn == NULL && (flags & TARG_CREATE)) {
253: gn = Targ_NewGNi(name, ename);
254: ohash_insert(&targets, slot, gn);
255: }
1.1 deraadt 256:
1.42 espie 257: return gn;
1.1 deraadt 258: }
259:
1.20 espie 260: void
1.46 espie 261: Targ_FindList(Lst nodes, Lst names)
1.1 deraadt 262: {
1.46 espie 263: LstNode ln;
264: GNode *gn;
1.42 espie 265: char *name;
266:
267: for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {
268: name = (char *)Lst_Datum(ln);
269: gn = Targ_FindNode(name, TARG_CREATE);
270: /* Note: Lst_AtEnd must come before the Lst_Concat so the nodes
271: * are added to the list in the order in which they were
272: * encountered in the makefile. */
273: Lst_AtEnd(nodes, gn);
274: if (gn->type & OP_DOUBLEDEP)
275: Lst_Concat(nodes, &gn->cohorts);
276: }
1.1 deraadt 277: }
278:
1.32 espie 279: bool
1.39 espie 280: Targ_Ignore(GNode *gn)
1.1 deraadt 281: {
1.42 espie 282: if (ignoreErrors || gn->type & OP_IGNORE)
283: return true;
284: else
285: return false;
1.1 deraadt 286: }
287:
1.32 espie 288: bool
1.39 espie 289: Targ_Silent(GNode *gn)
1.1 deraadt 290: {
1.42 espie 291: if (beSilent || gn->type & OP_SILENT)
292: return true;
293: else
294: return false;
1.1 deraadt 295: }
296:
1.32 espie 297: bool
1.39 espie 298: Targ_Precious(GNode *gn)
1.1 deraadt 299: {
1.58 espie 300: if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP|OP_PHONY)))
1.42 espie 301: return true;
302: else
303: return false;
1.1 deraadt 304: }
305:
1.17 espie 306: static void
1.39 espie 307: TargPrintName(void *gnp)
1.1 deraadt 308: {
1.42 espie 309: GNode *gn = (GNode *)gnp;
310: printf("%s ", gn->name);
1.1 deraadt 311: }
312:
313:
1.17 espie 314: void
1.39 espie 315: Targ_PrintCmd(void *cmd)
1.1 deraadt 316: {
1.42 espie 317: printf("\t%s\n", (char *)cmd);
1.1 deraadt 318: }
319:
320: void
1.39 espie 321: Targ_PrintType(int type)
1.1 deraadt 322: {
1.42 espie 323: int tbit;
1.5 millert 324:
1.46 espie 325: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
326: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
1.42 espie 327:
328: type &= ~OP_OPMASK;
329:
330: while (type) {
331: tbit = 1 << (ffs(type) - 1);
332: type &= ~tbit;
333:
334: switch (tbit) {
335: PRINTBIT(OPTIONAL);
336: PRINTBIT(USE);
337: PRINTBIT(EXEC);
338: PRINTBIT(IGNORE);
339: PRINTBIT(PRECIOUS);
340: PRINTBIT(SILENT);
341: PRINTBIT(MAKE);
342: PRINTBIT(JOIN);
343: PRINTBIT(INVISIBLE);
344: PRINTBIT(NOTMAIN);
345: PRINTDBIT(LIB);
346: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.45 espie 347: case OP_MEMBER:
348: if (DEBUG(TARG))
349: printf(".MEMBER ");
1.42 espie 350: break;
351: PRINTDBIT(ARCHV);
352: }
1.46 espie 353: }
1.1 deraadt 354: }
1.54 espie 355: const char *
1.52 espie 356: status_to_string(GNode *gn)
357: {
358: switch (gn->built_status) {
1.53 espie 359: case UNKNOWN:
360: return "unknown";
1.52 espie 361: case MADE:
362: return "made";
363: case UPTODATE:
364: return "up-to-date";
365: case ERROR:
366: return "error when made";
367: case ABORTED:
368: return "aborted";
369: default:
370: return "other status";
371: }
372: }
1.1 deraadt 373:
1.17 espie 374: static void
1.39 espie 375: TargPrintNode(GNode *gn, int pass)
1.1 deraadt 376: {
1.42 espie 377: if (OP_NOP(gn->type))
378: return;
1.1 deraadt 379: printf("#\n");
380: if (pass == 2) {
1.46 espie 381: printf("# %d unmade children\n", gn->unmade);
1.42 espie 382: if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
383: if (!is_out_of_date(gn->mtime)) {
384: printf("# last modified %s: %s\n",
1.46 espie 385: time_to_string(gn->mtime),
1.52 espie 386: status_to_string(gn));
1.53 espie 387: } else if (gn->built_status != UNKNOWN) {
1.42 espie 388: printf("# non-existent (maybe): %s\n",
1.52 espie 389: status_to_string(gn));
1.42 espie 390: } else {
391: printf("# unmade\n");
392: }
393: }
1.1 deraadt 394: }
1.19 espie 395: if (!Lst_IsEmpty(&gn->parents)) {
1.42 espie 396: printf("# parents: ");
397: Lst_Every(&gn->parents, TargPrintName);
398: fputc('\n', stdout);
1.1 deraadt 399: }
1.50 espie 400: if (gn->impliedsrc)
401: printf("# implied source: %s\n", gn->impliedsrc->name);
1.5 millert 402:
1.1 deraadt 403: printf("%-16s", gn->name);
404: switch (gn->type & OP_OPMASK) {
1.42 espie 405: case OP_DEPENDS:
1.1 deraadt 406: printf(": "); break;
1.42 espie 407: case OP_FORCE:
1.1 deraadt 408: printf("! "); break;
1.42 espie 409: case OP_DOUBLEDEP:
1.1 deraadt 410: printf(":: "); break;
411: }
1.17 espie 412: Targ_PrintType(gn->type);
1.19 espie 413: Lst_Every(&gn->children, TargPrintName);
1.17 espie 414: fputc('\n', stdout);
1.19 espie 415: Lst_Every(&gn->commands, Targ_PrintCmd);
1.1 deraadt 416: printf("\n\n");
1.27 espie 417: if (gn->type & OP_DOUBLEDEP) {
1.42 espie 418: LstNode ln;
1.31 espie 419:
1.42 espie 420: for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln))
421: TargPrintNode((GNode *)Lst_Datum(ln), pass);
1.27 espie 422: }
1.1 deraadt 423: }
424:
1.17 espie 425: static void
1.39 espie 426: TargPrintOnlySrc(GNode *gn)
1.1 deraadt 427: {
1.60 espie 428: if (OP_NOP(gn->type) && gn->special == SPECIAL_NONE &&
1.47 espie 429: !(gn->type & OP_DUMMY))
1.42 espie 430: printf("#\t%s [%s]\n", gn->name,
431: gn->path != NULL ? gn->path : gn->name);
1.1 deraadt 432: }
433:
434: void
1.39 espie 435: Targ_PrintGraph(int pass) /* Which pass this is. 1 => no processing
1.31 espie 436: * 2 => processing done */
1.1 deraadt 437: {
1.42 espie 438: GNode *gn;
439: unsigned int i;
1.27 espie 440:
1.42 espie 441: printf("#*** Input graph:\n");
442: for (gn = ohash_first(&targets, &i); gn != NULL;
443: gn = ohash_next(&targets, &i))
444: TargPrintNode(gn, pass);
445: printf("\n\n");
446: printf("#\n# Files that are only sources:\n");
447: for (gn = ohash_first(&targets, &i); gn != NULL;
448: gn = ohash_next(&targets, &i))
1.46 espie 449: TargPrintOnlySrc(gn);
1.42 espie 450: Var_Dump();
451: printf("\n");
1.46 espie 452: #ifdef DEBUG_DIRECTORY_CACHE
453: Dir_PrintDirectories();
454: printf("\n");
455: #endif
1.42 espie 456: Suff_PrintAll();
1.49 espie 457: }
458:
1.57 espie 459: struct ohash *
460: targets_hash()
1.49 espie 461: {
1.57 espie 462: return &targets;
1.1 deraadt 463: }