Annotation of src/usr.bin/make/dump.c, Revision 1.3
1.3 ! espie 1: /* $OpenBSD: dump.c,v 1.2 2012/10/02 10:29:30 espie Exp $ */
1.1 espie 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: */
1.2 espie 26: #include <stdint.h>
27: #include <stddef.h>
28: #include <stdio.h>
29: #include <string.h>
30: #include <stdlib.h>
31: #include <limits.h>
32: #include "ohash.h"
1.1 espie 33: #include "defines.h"
1.2 espie 34: #include "gnode.h"
1.1 espie 35: #include "dump.h"
36: #include "targ.h"
1.2 espie 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 = emalloc(sizeof(void *) * (n+1));
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: GNode *gn = (GNode *)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:
1.3 ! espie 111: case SPECIAL_NOTHING:
1.2 espie 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((GNode *)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;
1.1 espie 204:
205: void
206: dump_data(void)
207: {
1.2 espie 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);
1.1 espie 222: }