GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/make/targ.c Lines: 61 92 66.3 %
Date: 2017-11-07 Branches: 13 45 28.9 %

Line Branch Exec Source
1
/*	$OpenBSD: targ.c,v 1.78 2017/06/22 17:08:20 espie Exp $ */
2
/*	$NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $	*/
3
4
/*
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
/*
31
 * Copyright (c) 1988, 1989, 1990, 1993
32
 *	The Regents of the University of California.  All rights reserved.
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.
47
 * 3. Neither the name of the University nor the names of its contributors
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 --
66
 *		Target nodes are kept into a hash table.
67
 *
68
 * Interface:
69
 *	Targ_Init		Initialization procedure.
70
 *
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.
75
 *
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)
79
 *
80
 *	Targ_FindList		Given a list of names, find nodes for all
81
 *				of them, creating nodes if needed.
82
 *
83
 *	Targ_Ignore		Return true if errors should be ignored when
84
 *				creating the given target.
85
 *
86
 *	Targ_Silent		Return true if we should be silent when
87
 *				creating the given target.
88
 *
89
 *	Targ_Precious		Return true if the target is precious and
90
 *				should not be removed if we are interrupted.
91
 *
92
 * Debugging:
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...
96
 */
97
98
#include <limits.h>
99
#include <stddef.h>
100
#include <stdint.h>
101
#include <stdio.h>
102
#include <stdlib.h>
103
#include <string.h>
104
#include <ohash.h>
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"
116
#include "node_int.h"
117
#include "nodehashconsts.h"
118
#include "dump.h"
119
120
static struct ohash targets;	/* hash table of targets */
121
struct ohash_info gnode_info = {
122
	offsetof(GNode, name), NULL, hash_calloc, hash_free, element_alloc
123
};
124
125
#define Targ_FindConstantNode(n, f) Targ_FindNodeh(n, sizeof(n), K_##n, f)
126
127
128
GNode *begin_node, *end_node, *interrupt_node, *DEFAULT;
129
130
void
131
Targ_Init(void)
132
{
133
	/* A small make file already creates 200 targets.  */
134
68248
	ohash_init(&targets, 10, &gnode_info);
135
34124
	begin_node = Targ_FindConstantNode(NODE_BEGIN, TARG_CREATE);
136
34124
	begin_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
137
34124
	end_node = Targ_FindConstantNode(NODE_END, TARG_CREATE);
138
34124
	end_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
139
34124
	interrupt_node = Targ_FindConstantNode(NODE_INTERRUPT, TARG_CREATE);
140
34124
	interrupt_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
141
34124
	DEFAULT = Targ_FindConstantNode(NODE_DEFAULT, TARG_CREATE);
142
34124
	DEFAULT->type |= OP_DUMMY | OP_NOTMAIN| OP_TRANSFORM | OP_NODEFAULT;
143
144
34124
}
145
146
GNode *
147
Targ_NewGNi(const char *name, const char *ename)
148
{
149
	GNode *gn;
150
151
10784717
	gn = ohash_create_entry(&gnode_info, name, &ename);
152
10784717
	gn->path = NULL;
153
10784717
	gn->type = 0;
154
10784717
	gn->special = SPECIAL_NONE;
155
10784717
	gn->unmade = 0;
156
10784717
	gn->must_make = false;
157
10784717
	gn->built_status = UNKNOWN;
158
10784717
	gn->in_cycle = false;
159
10784717
	gn->childMade =	false;
160
10784717
	gn->order = 0;
161
10784717
	ts_set_out_of_date(gn->mtime);
162
10784717
	gn->youngest = gn;
163
10784717
	Lst_Init(&gn->cohorts);
164
10784717
	Lst_Init(&gn->parents);
165
10784717
	Lst_Init(&gn->children);
166
10784717
	Lst_Init(&gn->successors);
167
10784717
	Lst_Init(&gn->preds);
168
10784717
	SymTable_Init(&gn->context);
169
10784717
	gn->impliedsrc = NULL;
170
10784717
	Lst_Init(&gn->commands);
171
10784717
	gn->suffix = NULL;
172
10784717
	gn->next = NULL;
173
10784717
	gn->basename = NULL;
174
10784717
	gn->sibling = gn;
175
10784717
	gn->groupling = NULL;
176
177
#ifdef STATS_GN_CREATION
178
	STAT_GN_COUNT++;
179
#endif
180
181
10784717
	return gn;
182
}
183
184
GNode *
185
Targ_FindNodei(const char *name, const char *ename, int flags)
186
{
187
	uint32_t hv;
188
189
28772873
	hv = ohash_interval(name, &ename);
190
28772873
	return Targ_FindNodeih(name, ename, hv, flags);
191
}
192
193
GNode *
194
Targ_FindNodeih(const char *name, const char *ename, uint32_t hv, int flags)
195
{
196
	GNode *gn;
197
	unsigned int slot;
198
199
59934426
	slot = ohash_lookup_interval(&targets, name, ename, hv);
200
201
29967213
	gn = ohash_find(&targets, slot);
202
203

44847471
	if (gn == NULL && (flags & TARG_CREATE)) {
204
9322890
		gn = Targ_NewGNi(name, ename);
205
9322890
		ohash_insert(&targets, slot, gn);
206
9322890
	}
207
208
29967213
	return gn;
209
}
210
211
void
212
Targ_FindList(Lst nodes, Lst names)
213
{
214
	LstNode ln;
215
	GNode *gn;
216
	char *name;
217
218
170155
	for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {
219
34046
		name = Lst_Datum(ln);
220
34046
		gn = Targ_FindNode(name, TARG_CREATE);
221
		/* Note: Lst_AtEnd must come before the Lst_Concat so the nodes
222
		 * are added to the list in the order in which they were
223
		 * encountered in the makefile.  */
224
34046
		Lst_AtEnd(nodes, gn);
225
34046
		if (gn->type & OP_DOUBLEDEP)
226
38
			Lst_Concat(nodes, &gn->cohorts);
227
	}
228
34021
}
229
230
bool
231
Targ_Ignore(GNode *gn)
232
{
233

370251
	if (ignoreErrors || gn->type & OP_IGNORE)
234
		return true;
235
	else
236
123417
		return false;
237
123417
}
238
239
bool
240
Targ_Silent(GNode *gn)
241
{
242

370251
	if (beSilent || gn->type & OP_SILENT)
243
3967
		return true;
244
	else
245
119450
		return false;
246
123417
}
247
248
bool
249
Targ_Precious(GNode *gn)
250
{
251
	if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP|OP_PHONY)))
252
		return true;
253
	else
254
		return false;
255
}
256
257
void
258
Targ_PrintCmd(void *p)
259
{
260
	const struct command *cmd = p;
261
	printf("\t%s\n", cmd->string);
262
}
263
264
void
265
Targ_PrintType(int type)
266
{
267
	int    tbit;
268
269
#define PRINTBIT(attr)	case CONCAT(OP_,attr): printf("." #attr " "); break
270
#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
271
272
	type &= ~OP_OPMASK;
273
274
	while (type) {
275
		tbit = 1 << (ffs(type) - 1);
276
		type &= ~tbit;
277
278
		switch (tbit) {
279
		PRINTBIT(OPTIONAL);
280
		PRINTBIT(USE);
281
		PRINTBIT(EXEC);
282
		PRINTBIT(IGNORE);
283
		PRINTBIT(PRECIOUS);
284
		PRINTBIT(SILENT);
285
		PRINTBIT(MAKE);
286
		PRINTBIT(JOIN);
287
		PRINTBIT(INVISIBLE);
288
		PRINTBIT(NOTMAIN);
289
		/*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
290
		case OP_MEMBER:
291
			if (DEBUG(TARG))
292
				printf(".MEMBER ");
293
			break;
294
		PRINTDBIT(ARCHV);
295
		}
296
    }
297
}
298
299
const char *
300
status_to_string(GNode *gn)
301
{
302
	switch (gn->built_status) {
303
	case UNKNOWN:
304
		return "unknown";
305
	case MADE:
306
		return "made";
307
	case UPTODATE:
308
		return "up-to-date";
309
	case ERROR:
310
		return "error when made";
311
	case ABORTED:
312
		return "aborted";
313
	default:
314
		return "other status";
315
	}
316
}
317
318
struct ohash *
319
targets_hash()
320
{
321
68136
	return &targets;
322
}
323
324
GNode *
325
Targ_FindNodeh(const char *name, size_t n, uint32_t hv, int flags)
326
{
327
272992
	return Targ_FindNodeih(name, name + n - 1, hv, flags);
328
}