jcs's openbsd hax
openbsd
at jcs 222 lines 5.5 kB view raw
1/* $OpenBSD: dump.c,v 1.12 2020/01/26 12:41:21 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... */ 45static ptrdiff_t cmp_offset; 46static void targ_dump(bool); 47 48static int 49compare_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 56void * 57sort_ohash_by_name(struct ohash *h) 58{ 59 cmp_offset = h->info.key_offset; 60 61 return sort_ohash(h, compare_names); 62} 63 64void * 65sort_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 82static void 83TargPrintName(void *gnp) 84{ 85 const GNode *gn = gnp; 86 printf("%s ", gn->name); 87} 88 89static void 90TargPrintOnlySrc(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 102static void 103TargPrintNode(GNode *gn, bool full) 104{ 105 if (OP_NOP(gn->type)) 106 return; 107 switch(gn->special) { 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->children_left); 120 if (! (gn->type & OP_USE)) { 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 163static void 164dump_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 181static void 182targ_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 203static bool dumped_once = false; 204 205void 206dump_data(void) 207{ 208 Var_Dump(); 209 Suff_PrintAll(); 210 targ_dump(false); 211 dumped_once = true; 212} 213 214void 215post_mortem(void) 216{ 217 if (!dumped_once) { 218 Var_Dump(); 219 Suff_PrintAll(); 220 } 221 targ_dump(true); 222}