GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/make/dump.c Lines: 0 84 0.0 %
Date: 2017-11-07 Branches: 0 57 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: dump.c,v 1.9 2016/10/21 16:12:38 espie Exp $ */
2
/*
3
 * Copyright (c) 2012 Marc Espie.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
15
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
18
 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
#include <limits.h>
27
#include <stddef.h>
28
#include <stdint.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <ohash.h>
33
#include "defines.h"
34
#include "gnode.h"
35
#include "dump.h"
36
#include "targ.h"
37
#include "var.h"
38
#include "memory.h"
39
#include "suff.h"
40
#include "lst.h"
41
#include "timestamp.h"
42
#include "dir.h"
43
44
/* since qsort doesn't have user data, this needs to be a global... */
45
static ptrdiff_t cmp_offset;
46
static void targ_dump(bool);
47
48
static int
49
compare_names(const void *a, const void *b)
50
{
51
	const char **pa = (const char **)a;
52
	const char **pb = (const char **)b;
53
	return strcmp((*pa) + cmp_offset, (*pb) + cmp_offset);
54
}
55
56
void *
57
sort_ohash_by_name(struct ohash *h)
58
{
59
	cmp_offset = h->info.key_offset;
60
61
	return sort_ohash(h, compare_names);
62
}
63
64
void *
65
sort_ohash(struct ohash *h, int (*comparison)(const void *, const void *))
66
{
67
	unsigned int i, j;
68
	void *e;
69
	size_t n = ohash_entries(h);
70
	void **t = ereallocarray(NULL, n+1, sizeof(void *));
71
	cmp_offset = h->info.key_offset;
72
73
	for (i = 0, e = ohash_first(h, &j); e != NULL; e = ohash_next(h, &j))
74
	    	t[i++] = e;
75
	qsort(t, n, sizeof(void *), comparison);
76
	/* add an extra entry to be able to figure out the end without needing
77
	 * to keep a counter */
78
	t[n] = NULL;
79
	return t;
80
}
81
82
static void
83
TargPrintName(void *gnp)
84
{
85
	const GNode *gn = gnp;
86
	printf("%s ", gn->name);
87
}
88
89
static void
90
TargPrintOnlySrc(GNode *gn)
91
{
92
	if (OP_NOP(gn->type) && gn->special == SPECIAL_NONE &&
93
	    !(gn->type & OP_DUMMY)) {
94
	    	if (gn->path != NULL)
95
			printf("#\t%s [%s]\n", gn->name,
96
			    strcmp(gn->path, gn->name) == 0 ? "=" : gn->path);
97
		else
98
			printf("#\t%s\n", gn->name);
99
    	}
100
}
101
102
static void
103
TargPrintNode(GNode *gn, bool full)
104
{
105
	if (OP_NOP(gn->type))
106
		return;
107
	switch((gn->special & SPECIAL_MASK)) {
108
	case SPECIAL_SUFFIXES:
109
	case SPECIAL_PHONY:
110
	case SPECIAL_ORDER:
111
	case SPECIAL_NOTHING:
112
	case SPECIAL_MAIN:
113
	case SPECIAL_IGNORE:
114
		return;
115
	default:
116
		break;
117
	}
118
	if (full) {
119
		printf("# %d unmade prerequisites\n", gn->unmade);
120
		if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
121
			if (!is_out_of_date(gn->mtime)) {
122
				printf("# last modified %s: %s\n",
123
				      time_to_string(&gn->mtime),
124
				      status_to_string(gn));
125
			} else if (gn->built_status != UNKNOWN) {
126
				printf("# non-existent (maybe): %s\n",
127
				    status_to_string(gn));
128
			} else {
129
				printf("# unmade\n");
130
			}
131
		}
132
	}
133
	if (!Lst_IsEmpty(&gn->parents)) {
134
		printf("# parent targets: ");
135
		Lst_Every(&gn->parents, TargPrintName);
136
		fputc('\n', stdout);
137
	}
138
	if (gn->impliedsrc)
139
		printf("# implied prerequisite: %s\n", gn->impliedsrc->name);
140
141
	printf("%-16s", gn->name);
142
	switch (gn->type & OP_OPMASK) {
143
	case OP_DEPENDS:
144
		printf(": "); break;
145
	case OP_FORCE:
146
		printf("! "); break;
147
	case OP_DOUBLEDEP:
148
		printf(":: "); break;
149
	}
150
	Targ_PrintType(gn->type);
151
	Lst_Every(&gn->children, TargPrintName);
152
	fputc('\n', stdout);
153
	Lst_Every(&gn->commands, Targ_PrintCmd);
154
	printf("\n\n");
155
	if (gn->type & OP_DOUBLEDEP) {
156
		LstNode ln;
157
158
		for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln))
159
			TargPrintNode(Lst_Datum(ln), full);
160
	}
161
}
162
163
static void
164
dump_special(GNode **t, const char *name, int prop)
165
{
166
	unsigned int i;
167
	bool first = true;
168
169
	for (i = 0; t[i] != NULL; i++)
170
		if (t[i]->type & prop) {
171
			if (first) {
172
				printf("%s:", name);
173
				first = false;
174
			}
175
			printf(" %s", t[i]->name);
176
	    	}
177
	if (!first)
178
		printf("\n\n");
179
}
180
181
static void
182
targ_dump(bool full)
183
{
184
	GNode **t = sort_ohash_by_name(targets_hash());
185
	unsigned int i;
186
187
	printf("#   Input graph:\n");
188
	for (i = 0; t[i] != NULL; i++)
189
		TargPrintNode(t[i], full);
190
	printf("\n\n");
191
192
	dump_special(t, ".PHONY", OP_PHONY);
193
	dump_special(t, ".PRECIOUS", OP_PRECIOUS);
194
	dump_special(t, ".SILENT", OP_SILENT);
195
	dump_special(t, ".IGNORE", OP_IGNORE);
196
	printf("#   Other target names:\n");
197
	for (i = 0; t[i] != NULL; i++)
198
		TargPrintOnlySrc(t[i]);
199
	printf("\n");
200
	free(t);
201
}
202
203
static bool dumped_once = false;
204
205
void
206
dump_data(void)
207
{
208
	Var_Dump();
209
	Suff_PrintAll();
210
	targ_dump(false);
211
	dumped_once = true;
212
}
213
214
void
215
post_mortem(void)
216
{
217
	if (!dumped_once) {
218
		Var_Dump();
219
		Suff_PrintAll();
220
	}
221
	targ_dump(true);
222
}