Annotation of src/usr.bin/make/targ.c, Revision 1.85
1.85 ! espie 1: /* $OpenBSD: targ.c,v 1.84 2020/01/13 15:41:53 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_NewGN Create a new GNode for the passed target
72: * (string). The node is *not* placed in the
73: * hash table, though all its fields are
74: * initialized.
1.1 deraadt 75: *
1.31 espie 76: * Targ_FindNode Find the node for a given target, creating
77: * and storing it if it doesn't exist and the
78: * flags are right (TARG_CREATE)
1.1 deraadt 79: *
1.31 espie 80: * Targ_FindList Given a list of names, find nodes for all
81: * of them, creating nodes if needed.
1.1 deraadt 82: *
1.32 espie 83: * Targ_Ignore Return true if errors should be ignored when
1.31 espie 84: * creating the given target.
1.1 deraadt 85: *
1.32 espie 86: * Targ_Silent Return true if we should be silent when
1.31 espie 87: * creating the given target.
1.1 deraadt 88: *
1.32 espie 89: * Targ_Precious Return true if the target is precious and
1.31 espie 90: * should not be removed if we are interrupted.
1.1 deraadt 91: *
92: * Debugging:
1.31 espie 93: * Targ_PrintGraph Print out the entire graphm all variables
94: * and statistics for the directory cache. Should
95: * print something for suffixes, too, but...
1.1 deraadt 96: */
97:
1.34 espie 98: #include <limits.h>
1.32 espie 99: #include <stddef.h>
1.70 espie 100: #include <stdint.h>
1.32 espie 101: #include <stdio.h>
1.67 espie 102: #include <stdlib.h>
1.33 espie 103: #include <string.h>
1.70 espie 104: #include <ohash.h>
1.32 espie 105: #include "config.h"
106: #include "defines.h"
107: #include "stats.h"
108: #include "suff.h"
109: #include "var.h"
110: #include "targ.h"
111: #include "memory.h"
112: #include "gnode.h"
113: #include "extern.h"
114: #include "timestamp.h"
115: #include "lst.h"
1.46 espie 116: #include "node_int.h"
117: #include "nodehashconsts.h"
1.67 espie 118: #include "dump.h"
1.31 espie 119:
1.57 espie 120: static struct ohash targets; /* hash table of targets */
1.46 espie 121: struct ohash_info gnode_info = {
1.75 espie 122: offsetof(GNode, name), NULL, hash_calloc, hash_free, element_alloc
1.42 espie 123: };
1.1 deraadt 124:
1.83 espie 125: static GNode *Targ_mk_node(const char *, const char *, unsigned int,
126: unsigned char, unsigned int);
1.48 espie 127:
1.83 espie 128: #define Targ_mk_constant(n, type) \
129: Targ_mk_special_node(n, sizeof(n), K_##n, type, SPECIAL_NONE, 0)
1.1 deraadt 130:
1.46 espie 131: GNode *begin_node, *end_node, *interrupt_node, *DEFAULT;
132:
1.1 deraadt 133: void
1.39 espie 134: Targ_Init(void)
1.1 deraadt 135: {
1.42 espie 136: /* A small make file already creates 200 targets. */
137: ohash_init(&targets, 10, &gnode_info);
1.83 espie 138: begin_node = Targ_mk_constant(NODE_BEGIN,
139: OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT);
140: end_node = Targ_mk_constant(NODE_END,
141: OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT);
142: interrupt_node = Targ_mk_constant(NODE_INTERRUPT,
143: OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT);
144: DEFAULT = Targ_mk_constant(NODE_DEFAULT,
145: OP_DUMMY | OP_NOTMAIN| OP_TRANSFORM | OP_NODEFAULT);
1.46 espie 146:
1.1 deraadt 147: }
148:
1.83 espie 149: static GNode *
150: Targ_mk_node(const char *name, const char *ename,
151: unsigned int type, unsigned char special, unsigned int special_op)
1.1 deraadt 152: {
1.42 espie 153: GNode *gn;
1.1 deraadt 154:
1.42 espie 155: gn = ohash_create_entry(&gnode_info, name, &ename);
156: gn->path = NULL;
1.83 espie 157: gn->type = type;
158: gn->special = special;
159: gn->special_op = special_op;
1.80 espie 160: gn->children_left = 0;
1.51 espie 161: gn->must_make = false;
1.53 espie 162: gn->built_status = UNKNOWN;
1.78 espie 163: gn->in_cycle = false;
1.80 espie 164: gn->child_rebuilt = false;
1.46 espie 165: gn->order = 0;
1.42 espie 166: ts_set_out_of_date(gn->mtime);
1.71 espie 167: gn->youngest = gn;
1.42 espie 168: Lst_Init(&gn->cohorts);
169: Lst_Init(&gn->parents);
170: Lst_Init(&gn->children);
1.80 espie 171: Lst_Init(&gn->predecessors);
1.42 espie 172: Lst_Init(&gn->successors);
1.81 espie 173: SymTable_Init(&gn->localvars);
1.50 espie 174: gn->impliedsrc = NULL;
1.42 espie 175: Lst_Init(&gn->commands);
1.56 espie 176: gn->suffix = NULL;
1.57 espie 177: gn->next = NULL;
178: gn->basename = NULL;
179: gn->sibling = gn;
1.69 espie 180: gn->groupling = NULL;
1.1 deraadt 181:
1.31 espie 182: #ifdef STATS_GN_CREATION
1.42 espie 183: STAT_GN_COUNT++;
1.10 espie 184: #endif
1.1 deraadt 185:
1.42 espie 186: return gn;
1.1 deraadt 187: }
188:
1.46 espie 189: GNode *
1.83 espie 190: Targ_NewGNi(const char *name, const char *ename)
1.46 espie 191: {
1.83 espie 192: return Targ_mk_node(name, ename, OP_ZERO, SPECIAL_NONE, 0);
1.46 espie 193: }
1.1 deraadt 194:
195: GNode *
1.83 espie 196: Targ_FindNodei(const char *name, const char *ename, int flags)
1.1 deraadt 197: {
1.83 espie 198: uint32_t hv;
1.46 espie 199: GNode *gn;
1.42 espie 200: unsigned int slot;
1.27 espie 201:
1.83 espie 202: hv = ohash_interval(name, &ename);
203:
1.46 espie 204: slot = ohash_lookup_interval(&targets, name, ename, hv);
1.27 espie 205:
1.42 espie 206: gn = ohash_find(&targets, slot);
1.31 espie 207:
1.42 espie 208: if (gn == NULL && (flags & TARG_CREATE)) {
209: gn = Targ_NewGNi(name, ename);
210: ohash_insert(&targets, slot, gn);
211: }
1.1 deraadt 212:
1.42 espie 213: return gn;
1.1 deraadt 214: }
215:
1.83 espie 216: GNode *
217: Targ_mk_special_node(const char *name, size_t n, uint32_t hv,
218: unsigned int type, unsigned char special, unsigned int special_op)
219: {
220: GNode *gn;
221: unsigned int slot;
222: const char *ename = name + n - 1;
223:
224: slot = ohash_lookup_interval(&targets, name, ename, hv);
225:
226: assert(ohash_find(&targets, slot) == NULL);
227:
228: gn = Targ_mk_node(name, ename, type, special, special_op);
229: ohash_insert(&targets, slot, gn);
230:
231: return gn;
232: }
233:
1.20 espie 234: void
1.46 espie 235: Targ_FindList(Lst nodes, Lst names)
1.1 deraadt 236: {
1.46 espie 237: LstNode ln;
238: GNode *gn;
1.42 espie 239: char *name;
240:
241: for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {
1.77 espie 242: name = Lst_Datum(ln);
1.42 espie 243: gn = Targ_FindNode(name, TARG_CREATE);
244: /* Note: Lst_AtEnd must come before the Lst_Concat so the nodes
245: * are added to the list in the order in which they were
246: * encountered in the makefile. */
247: Lst_AtEnd(nodes, gn);
248: if (gn->type & OP_DOUBLEDEP)
249: Lst_Concat(nodes, &gn->cohorts);
250: }
1.1 deraadt 251: }
252:
1.32 espie 253: bool
1.39 espie 254: Targ_Ignore(GNode *gn)
1.1 deraadt 255: {
1.42 espie 256: if (ignoreErrors || gn->type & OP_IGNORE)
257: return true;
258: else
259: return false;
1.1 deraadt 260: }
261:
1.32 espie 262: bool
1.39 espie 263: Targ_Silent(GNode *gn)
1.1 deraadt 264: {
1.42 espie 265: if (beSilent || gn->type & OP_SILENT)
266: return true;
267: else
268: return false;
1.1 deraadt 269: }
270:
1.32 espie 271: bool
1.39 espie 272: Targ_Precious(GNode *gn)
1.1 deraadt 273: {
1.58 espie 274: if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP|OP_PHONY)))
1.42 espie 275: return true;
276: else
277: return false;
1.84 espie 278: }
279:
280: bool
281: node_is_real(GNode *gn)
282: {
283: return (gn->type & OP_DUMMY) == 0;
1.1 deraadt 284: }
285:
1.17 espie 286: void
1.66 espie 287: Targ_PrintCmd(void *p)
1.1 deraadt 288: {
1.76 espie 289: const struct command *cmd = p;
1.66 espie 290: printf("\t%s\n", cmd->string);
1.1 deraadt 291: }
292:
293: void
1.39 espie 294: Targ_PrintType(int type)
1.1 deraadt 295: {
1.42 espie 296: int tbit;
1.5 millert 297:
1.46 espie 298: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
299: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
1.42 espie 300:
301: type &= ~OP_OPMASK;
302:
303: while (type) {
304: tbit = 1 << (ffs(type) - 1);
305: type &= ~tbit;
306:
307: switch (tbit) {
308: PRINTBIT(OPTIONAL);
309: PRINTBIT(USE);
310: PRINTBIT(IGNORE);
311: PRINTBIT(PRECIOUS);
312: PRINTBIT(SILENT);
313: PRINTBIT(MAKE);
314: PRINTBIT(INVISIBLE);
315: PRINTBIT(NOTMAIN);
316: /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.45 espie 317: case OP_MEMBER:
318: if (DEBUG(TARG))
319: printf(".MEMBER ");
1.42 espie 320: break;
321: PRINTDBIT(ARCHV);
322: }
1.46 espie 323: }
1.1 deraadt 324: }
1.67 espie 325:
1.54 espie 326: const char *
1.52 espie 327: status_to_string(GNode *gn)
328: {
329: switch (gn->built_status) {
1.53 espie 330: case UNKNOWN:
331: return "unknown";
1.79 espie 332: case REBUILT:
1.52 espie 333: return "made";
334: case UPTODATE:
335: return "up-to-date";
336: case ERROR:
337: return "error when made";
338: case ABORTED:
339: return "aborted";
340: default:
341: return "other status";
342: }
1.49 espie 343: }
344:
1.57 espie 345: struct ohash *
346: targets_hash()
1.49 espie 347: {
1.57 espie 348: return &targets;
1.65 espie 349: }