GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/make/targ.c Lines: 65 97 67.0 %
Date: 2016-12-06 Branches: 12 45 26.7 %

Line Branch Exec Source
1
/*	$OpenBSD: targ.c,v 1.76 2015/01/23 22:35:58 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
729
{
133
	/* A small make file already creates 200 targets.  */
134
729
	ohash_init(&targets, 10, &gnode_info);
135
729
	begin_node = Targ_FindConstantNode(NODE_BEGIN, TARG_CREATE);
136
729
	begin_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
137
729
	end_node = Targ_FindConstantNode(NODE_END, TARG_CREATE);
138
729
	end_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
139
729
	interrupt_node = Targ_FindConstantNode(NODE_INTERRUPT, TARG_CREATE);
140
729
	interrupt_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
141
729
	DEFAULT = Targ_FindConstantNode(NODE_DEFAULT, TARG_CREATE);
142
729
	DEFAULT->type |= OP_DUMMY | OP_NOTMAIN| OP_TRANSFORM | OP_NODEFAULT;
143
144
729
}
145
146
GNode *
147
Targ_NewGNi(const char *name, const char *ename)
148
84705
{
149
	GNode *gn;
150
151
84705
	gn = ohash_create_entry(&gnode_info, name, &ename);
152
84705
	gn->path = NULL;
153
84705
	gn->type = 0;
154
84705
	gn->special = SPECIAL_NONE;
155
84705
	gn->unmade = 0;
156
84705
	gn->must_make = false;
157
84705
	gn->built_status = UNKNOWN;
158
84705
	gn->childMade =	false;
159
84705
	gn->order = 0;
160
84705
	ts_set_out_of_date(gn->mtime);
161
84705
	gn->youngest = gn;
162
84705
	Lst_Init(&gn->cohorts);
163
84705
	Lst_Init(&gn->parents);
164
84705
	Lst_Init(&gn->children);
165
84705
	Lst_Init(&gn->successors);
166
84705
	Lst_Init(&gn->preds);
167
84705
	SymTable_Init(&gn->context);
168
84705
	gn->impliedsrc = NULL;
169
84705
	Lst_Init(&gn->commands);
170
84705
	gn->suffix = NULL;
171
84705
	gn->next = NULL;
172
84705
	gn->basename = NULL;
173
84705
	gn->sibling = gn;
174
84705
	gn->groupling = NULL;
175
176
#ifdef STATS_GN_CREATION
177
	STAT_GN_COUNT++;
178
#endif
179
180
84705
	return gn;
181
}
182
183
GNode *
184
Targ_FindNodei(const char *name, const char *ename, int flags)
185
124689
{
186
	uint32_t hv;
187
188
124689
	hv = ohash_interval(name, &ename);
189
124689
	return Targ_FindNodeih(name, ename, hv, flags);
190
}
191
192
GNode *
193
Targ_FindNodeih(const char *name, const char *ename, uint32_t hv, int flags)
194
150204
{
195
	GNode *gn;
196
	unsigned int slot;
197
198
150204
	slot = ohash_lookup_interval(&targets, name, ename, hv);
199
200
150204
	gn = ohash_find(&targets, slot);
201
202

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

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

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