jcs's openbsd hax
openbsd
at jcs 343 lines 9.3 kB view raw
1/* $OpenBSD: targ.c,v 1.88 2024/06/18 02:11:03 millert 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 93#include <limits.h> 94#include <stddef.h> 95#include <stdint.h> 96#include <stdio.h> 97#include <stdlib.h> 98#include <string.h> 99#include <ohash.h> 100#include "defines.h" 101#include "stats.h" 102#include "suff.h" 103#include "var.h" 104#include "targ.h" 105#include "memory.h" 106#include "gnode.h" 107#include "extern.h" 108#include "timestamp.h" 109#include "lst.h" 110#include "node_int.h" 111#include "nodehashconsts.h" 112#include "dump.h" 113 114static struct ohash targets; /* hash table of targets */ 115struct ohash_info gnode_info = { 116 offsetof(GNode, name), NULL, hash_calloc, hash_free, element_alloc 117}; 118 119static GNode *Targ_mk_node(const char *, const char *, unsigned int, 120 unsigned char, unsigned int); 121 122#define Targ_mk_constant(n, type) \ 123 Targ_mk_special_node(n, sizeof(n), K_##n, type, SPECIAL_NONE, 0) 124 125GNode *begin_node, *end_node, *interrupt_node, *DEFAULT; 126 127void 128Targ_Init(void) 129{ 130 /* A small make file already creates 200 targets. */ 131 ohash_init(&targets, 10, &gnode_info); 132 begin_node = Targ_mk_constant(NODE_BEGIN, 133 OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT); 134 end_node = Targ_mk_constant(NODE_END, 135 OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT); 136 interrupt_node = Targ_mk_constant(NODE_INTERRUPT, 137 OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT); 138 DEFAULT = Targ_mk_constant(NODE_DEFAULT, 139 OP_DUMMY | OP_NOTMAIN| OP_TRANSFORM | OP_NODEFAULT); 140 141} 142 143static GNode * 144Targ_mk_node(const char *name, const char *ename, 145 unsigned int type, unsigned char special, unsigned int special_op) 146{ 147 GNode *gn; 148 149 gn = ohash_create_entry(&gnode_info, name, &ename); 150 gn->path = NULL; 151 gn->type = type; 152 gn->special = special; 153 gn->special_op = special_op; 154 gn->children_left = 0; 155 gn->must_make = false; 156 gn->built_status = UNKNOWN; 157 gn->in_cycle = false; 158 gn->child_rebuilt = false; 159 gn->order = 0; 160 ts_set_out_of_date(gn->mtime); 161 gn->youngest = gn; 162 Lst_Init(&gn->cohorts); 163 Lst_Init(&gn->parents); 164 Lst_Init(&gn->children); 165 Lst_Init(&gn->predecessors); 166 Lst_Init(&gn->successors); 167 SymTable_Init(&gn->localvars); 168 gn->impliedsrc = NULL; 169 Lst_Init(&gn->commands); 170 gn->suffix = NULL; 171 gn->next = NULL; 172 gn->basename = NULL; 173 gn->sibling = gn; 174 gn->groupling = NULL; 175 176#ifdef STATS_GN_CREATION 177 STAT_GN_COUNT++; 178#endif 179 180 return gn; 181} 182 183GNode * 184Targ_NewGNi(const char *name, const char *ename) 185{ 186 return Targ_mk_node(name, ename, OP_ZERO, SPECIAL_NONE, 0); 187} 188 189GNode * 190Targ_FindNodei(const char *name, const char *ename, int flags) 191{ 192 uint32_t hv; 193 GNode *gn; 194 unsigned int slot; 195 196 hv = ohash_interval(name, &ename); 197 198 slot = ohash_lookup_interval(&targets, name, ename, hv); 199 200 gn = ohash_find(&targets, slot); 201 202 if (gn == NULL && (flags & TARG_CREATE)) { 203 gn = Targ_NewGNi(name, ename); 204 ohash_insert(&targets, slot, gn); 205 } 206 207 return gn; 208} 209 210GNode * 211Targ_mk_special_node(const char *name, size_t n, uint32_t hv, 212 unsigned int type, unsigned char special, unsigned int special_op) 213{ 214 GNode *gn; 215 unsigned int slot; 216 const char *ename = name + n - 1; 217 218 slot = ohash_lookup_interval(&targets, name, ename, hv); 219 220 assert(ohash_find(&targets, slot) == NULL); 221 222 gn = Targ_mk_node(name, ename, type, special, special_op); 223 ohash_insert(&targets, slot, gn); 224 225 return gn; 226} 227 228void 229Targ_FindList(Lst nodes, Lst names) 230{ 231 LstNode ln; 232 GNode *gn; 233 char *name; 234 235 for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) { 236 name = Lst_Datum(ln); 237 gn = Targ_FindNode(name, TARG_CREATE); 238 /* Note: Lst_AtEnd must come before the Lst_Concat so the nodes 239 * are added to the list in the order in which they were 240 * encountered in the makefile. */ 241 Lst_AtEnd(nodes, gn); 242 if (gn->type & OP_DOUBLEDEP) 243 Lst_Concat(nodes, &gn->cohorts); 244 } 245} 246 247bool 248Targ_Ignore(GNode *gn) 249{ 250 if (ignoreErrors || gn->type & OP_IGNORE) 251 return true; 252 else 253 return false; 254} 255 256bool 257Targ_Silent(GNode *gn) 258{ 259 if (beSilent || gn->type & OP_SILENT) 260 return true; 261 else 262 return false; 263} 264 265bool 266Targ_Precious(GNode *gn) 267{ 268 if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP|OP_PHONY))) 269 return true; 270 else 271 return false; 272} 273 274bool 275node_is_real(GNode *gn) 276{ 277 return (gn->type & OP_DUMMY) == 0; 278} 279 280void 281Targ_PrintCmd(void *p) 282{ 283 const struct command *cmd = p; 284 printf("\t%s\n", cmd->string); 285} 286 287void 288Targ_PrintType(int type) 289{ 290 int tbit; 291 292#define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break 293#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break 294 295 type &= ~OP_OPMASK; 296 297 while (type) { 298 tbit = 1 << (ffs(type) - 1); 299 type &= ~tbit; 300 301 switch (tbit) { 302 PRINTBIT(OPTIONAL); 303 PRINTBIT(USE); 304 PRINTBIT(IGNORE); 305 PRINTBIT(PRECIOUS); 306 PRINTBIT(SILENT); 307 PRINTBIT(MAKE); 308 PRINTBIT(INVISIBLE); 309 PRINTBIT(NOTMAIN); 310 /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ 311 case OP_MEMBER: 312 if (DEBUG(TARG)) 313 printf(".MEMBER "); 314 break; 315 PRINTDBIT(ARCHV); 316 } 317 } 318} 319 320const char * 321status_to_string(GNode *gn) 322{ 323 switch (gn->built_status) { 324 case UNKNOWN: 325 return "unknown"; 326 case REBUILT: 327 return "made"; 328 case UPTODATE: 329 return "up-to-date"; 330 case ERROR: 331 return "error when made"; 332 case ABORTED: 333 return "aborted"; 334 default: 335 return "other status"; 336 } 337} 338 339struct ohash * 340targets_hash(void) 341{ 342 return &targets; 343}