Annotation of src/usr.bin/make/dump.c, Revision 1.2
1.2 ! espie 1: /* $OpenBSD: dump.c,v 1.1 2012/09/21 07:55:20 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:
! 111: case SPECIAL_DEPRECATED:
! 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: bool first;
! 187:
! 188: printf("# Input graph:\n");
! 189: for (i = 0; t[i] != NULL; i++)
! 190: TargPrintNode(t[i], full);
! 191: printf("\n\n");
! 192:
! 193: dump_special(t, ".PHONY", OP_PHONY);
! 194: dump_special(t, ".PRECIOUS", OP_PRECIOUS);
! 195: dump_special(t, ".SILENT", OP_SILENT);
! 196: dump_special(t, ".IGNORE", OP_IGNORE);
! 197: printf("# Other target names:\n");
! 198: for (i = 0; t[i] != NULL; i++)
! 199: TargPrintOnlySrc(t[i]);
! 200: printf("\n");
! 201: free(t);
! 202: }
! 203:
! 204: static bool dumped_once = false;
1.1 espie 205:
206: void
207: dump_data(void)
208: {
1.2 ! espie 209: Var_Dump();
! 210: Suff_PrintAll();
! 211: targ_dump(false);
! 212: dumped_once = true;
! 213: }
! 214:
! 215: void
! 216: post_mortem(void)
! 217: {
! 218: if (!dumped_once) {
! 219: Var_Dump();
! 220: Suff_PrintAll();
! 221: }
! 222: targ_dump(true);
1.1 espie 223: }