1*31129d4fSBaptiste Daroussin /* $OpenBSD: look.c,v 1.24 2014/12/21 09:33:12 espie Exp $ */ 2acc9d408SJuli Mallett 39b50d902SRodney W. Grimes /* 49b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 89b50d902SRodney W. Grimes * Ozan Yigit at York University. 99b50d902SRodney W. Grimes * 109b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 119b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 129b50d902SRodney W. Grimes * are met: 139b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 149b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 159b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 169b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 179b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 18a841e1ebSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors 199b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 209b50d902SRodney W. Grimes * without specific prior written permission. 219b50d902SRodney W. Grimes * 229b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 239b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 249b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 259b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 269b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 279b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 289b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 299b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 309b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 319b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 329b50d902SRodney W. Grimes * SUCH DAMAGE. 339b50d902SRodney W. Grimes */ 34acc9d408SJuli Mallett #include <sys/cdefs.h> 35acc9d408SJuli Mallett __FBSDID("$FreeBSD$"); 369b50d902SRodney W. Grimes 379b50d902SRodney W. Grimes /* 389b50d902SRodney W. Grimes * look.c 399b50d902SRodney W. Grimes * Facility: m4 macro processor 409b50d902SRodney W. Grimes * by: oz 419b50d902SRodney W. Grimes */ 429b50d902SRodney W. Grimes 439b50d902SRodney W. Grimes #include <sys/types.h> 449b50d902SRodney W. Grimes #include <stdio.h> 459b50d902SRodney W. Grimes #include <stdlib.h> 46a841e1ebSBaptiste Daroussin #include <stdint.h> 47acc9d408SJuli Mallett #include <stddef.h> 489b50d902SRodney W. Grimes #include <string.h> 49a841e1ebSBaptiste Daroussin #include <ohash.h> 509b50d902SRodney W. Grimes #include "mdef.h" 519b50d902SRodney W. Grimes #include "stdd.h" 529b50d902SRodney W. Grimes #include "extern.h" 539b50d902SRodney W. Grimes 5488497f0cSBaptiste Daroussin static void *hash_calloc(size_t, size_t, void *); 5588497f0cSBaptiste Daroussin static void hash_free(void *, void *); 56a841e1ebSBaptiste Daroussin static void *element_alloc(size_t, void *); 57a841e1ebSBaptiste Daroussin static void setup_definition(struct macro_definition *, const char *, 58a841e1ebSBaptiste Daroussin const char *); 59*31129d4fSBaptiste Daroussin static void free_definition(char *); 60*31129d4fSBaptiste Daroussin static void keep(char *); 61*31129d4fSBaptiste Daroussin static int string_in_use(const char *); 62acc9d408SJuli Mallett 63a841e1ebSBaptiste Daroussin static struct ohash_info macro_info = { 64a841e1ebSBaptiste Daroussin offsetof(struct ndblock, name), 6588497f0cSBaptiste Daroussin NULL, hash_calloc, hash_free, element_alloc }; 66a841e1ebSBaptiste Daroussin 67a841e1ebSBaptiste Daroussin struct ohash macros; 68a841e1ebSBaptiste Daroussin 69a841e1ebSBaptiste Daroussin /* Support routines for hash tables. */ 70a841e1ebSBaptiste Daroussin void * 7188497f0cSBaptiste Daroussin hash_calloc(size_t n, size_t s, void *u __unused) 729b50d902SRodney W. Grimes { 7388497f0cSBaptiste Daroussin void *storage = xcalloc(n, s, "hash alloc"); 74a841e1ebSBaptiste Daroussin return storage; 75a841e1ebSBaptiste Daroussin } 76a841e1ebSBaptiste Daroussin 77a841e1ebSBaptiste Daroussin void 7888497f0cSBaptiste Daroussin hash_free(void *p, void *u __unused) 79a841e1ebSBaptiste Daroussin { 80a841e1ebSBaptiste Daroussin free(p); 81a841e1ebSBaptiste Daroussin } 82a841e1ebSBaptiste Daroussin 83a841e1ebSBaptiste Daroussin void * 8488497f0cSBaptiste Daroussin element_alloc(size_t s, void *u __unused) 85a841e1ebSBaptiste Daroussin { 86a841e1ebSBaptiste Daroussin return xalloc(s, "element alloc"); 87a841e1ebSBaptiste Daroussin } 88a841e1ebSBaptiste Daroussin 89a841e1ebSBaptiste Daroussin void 90a841e1ebSBaptiste Daroussin init_macros(void) 91a841e1ebSBaptiste Daroussin { 92a841e1ebSBaptiste Daroussin ohash_init(¯os, 10, ¯o_info); 939b50d902SRodney W. Grimes } 949b50d902SRodney W. Grimes 959b50d902SRodney W. Grimes /* 969b50d902SRodney W. Grimes * find name in the hash table 979b50d902SRodney W. Grimes */ 989b50d902SRodney W. Grimes ndptr 99bd2bfb58SJuli Mallett lookup(const char *name) 1009b50d902SRodney W. Grimes { 101a841e1ebSBaptiste Daroussin return ohash_find(¯os, ohash_qlookup(¯os, name)); 1029b50d902SRodney W. Grimes } 1039b50d902SRodney W. Grimes 104a841e1ebSBaptiste Daroussin struct macro_definition * 105a841e1ebSBaptiste Daroussin lookup_macro_definition(const char *name) 1069b50d902SRodney W. Grimes { 1079b50d902SRodney W. Grimes ndptr p; 1089b50d902SRodney W. Grimes 109a841e1ebSBaptiste Daroussin p = ohash_find(¯os, ohash_qlookup(¯os, name)); 110a841e1ebSBaptiste Daroussin if (p) 111a841e1ebSBaptiste Daroussin return p->d; 112a841e1ebSBaptiste Daroussin else 113a841e1ebSBaptiste Daroussin return NULL; 1149b50d902SRodney W. Grimes } 1159b50d902SRodney W. Grimes 1169b50d902SRodney W. Grimes static void 117a841e1ebSBaptiste Daroussin setup_definition(struct macro_definition *d, const char *defn, const char *name) 1189b50d902SRodney W. Grimes { 119a841e1ebSBaptiste Daroussin ndptr p; 120a841e1ebSBaptiste Daroussin 121a841e1ebSBaptiste Daroussin if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0 && 122a841e1ebSBaptiste Daroussin (p = macro_getbuiltin(defn+sizeof(BUILTIN_MARKER)-1)) != NULL) { 123a841e1ebSBaptiste Daroussin d->type = macro_builtin_type(p); 124a841e1ebSBaptiste Daroussin d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1); 125a841e1ebSBaptiste Daroussin } else { 126a841e1ebSBaptiste Daroussin if (!*defn) 127a841e1ebSBaptiste Daroussin d->defn = __DECONST(char *, null); 128a841e1ebSBaptiste Daroussin else 129a841e1ebSBaptiste Daroussin d->defn = xstrdup(defn); 130a841e1ebSBaptiste Daroussin d->type = MACRTYPE; 131a841e1ebSBaptiste Daroussin } 132a841e1ebSBaptiste Daroussin if (STREQ(name, defn)) 133a841e1ebSBaptiste Daroussin d->type |= RECDEF; 1349b50d902SRodney W. Grimes } 1359b50d902SRodney W. Grimes 136a841e1ebSBaptiste Daroussin static ndptr 137a841e1ebSBaptiste Daroussin create_entry(const char *name) 138a841e1ebSBaptiste Daroussin { 139a841e1ebSBaptiste Daroussin const char *end = NULL; 140a841e1ebSBaptiste Daroussin unsigned int i; 141a841e1ebSBaptiste Daroussin ndptr n; 142a841e1ebSBaptiste Daroussin 143a841e1ebSBaptiste Daroussin i = ohash_qlookupi(¯os, name, &end); 144a841e1ebSBaptiste Daroussin n = ohash_find(¯os, i); 145a841e1ebSBaptiste Daroussin if (n == NULL) { 146a841e1ebSBaptiste Daroussin n = ohash_create_entry(¯o_info, name, &end); 147a841e1ebSBaptiste Daroussin ohash_insert(¯os, i, n); 148a841e1ebSBaptiste Daroussin n->trace_flags = FLAG_NO_TRACE; 149a841e1ebSBaptiste Daroussin n->builtin_type = MACRTYPE; 150a841e1ebSBaptiste Daroussin n->d = NULL; 151a841e1ebSBaptiste Daroussin } 152a841e1ebSBaptiste Daroussin return n; 153a841e1ebSBaptiste Daroussin } 154a841e1ebSBaptiste Daroussin 1559b50d902SRodney W. Grimes void 156a841e1ebSBaptiste Daroussin macro_define(const char *name, const char *defn) 1579b50d902SRodney W. Grimes { 158a841e1ebSBaptiste Daroussin ndptr n = create_entry(name); 159a841e1ebSBaptiste Daroussin if (n->d != NULL) { 160a841e1ebSBaptiste Daroussin if (n->d->defn != null) 161*31129d4fSBaptiste Daroussin free_definition(n->d->defn); 162a841e1ebSBaptiste Daroussin } else { 163a841e1ebSBaptiste Daroussin n->d = xalloc(sizeof(struct macro_definition), NULL); 164a841e1ebSBaptiste Daroussin n->d->next = NULL; 165a841e1ebSBaptiste Daroussin } 166a841e1ebSBaptiste Daroussin setup_definition(n->d, defn, name); 167a841e1ebSBaptiste Daroussin } 1689b50d902SRodney W. Grimes 169a841e1ebSBaptiste Daroussin void 170a841e1ebSBaptiste Daroussin macro_pushdef(const char *name, const char *defn) 171a841e1ebSBaptiste Daroussin { 172a841e1ebSBaptiste Daroussin ndptr n; 173a841e1ebSBaptiste Daroussin struct macro_definition *d; 174a841e1ebSBaptiste Daroussin 175a841e1ebSBaptiste Daroussin n = create_entry(name); 176a841e1ebSBaptiste Daroussin d = xalloc(sizeof(struct macro_definition), NULL); 177a841e1ebSBaptiste Daroussin d->next = n->d; 178a841e1ebSBaptiste Daroussin n->d = d; 179a841e1ebSBaptiste Daroussin setup_definition(n->d, defn, name); 1809b50d902SRodney W. Grimes } 181a841e1ebSBaptiste Daroussin 182a841e1ebSBaptiste Daroussin void 183a841e1ebSBaptiste Daroussin macro_undefine(const char *name) 184a841e1ebSBaptiste Daroussin { 185a841e1ebSBaptiste Daroussin ndptr n = lookup(name); 186a841e1ebSBaptiste Daroussin if (n != NULL) { 187a841e1ebSBaptiste Daroussin struct macro_definition *r, *r2; 188a841e1ebSBaptiste Daroussin 189a841e1ebSBaptiste Daroussin for (r = n->d; r != NULL; r = r2) { 190a841e1ebSBaptiste Daroussin r2 = r->next; 191a841e1ebSBaptiste Daroussin if (r->defn != null) 192a841e1ebSBaptiste Daroussin free(r->defn); 193a841e1ebSBaptiste Daroussin free(r); 1949b50d902SRodney W. Grimes } 195a841e1ebSBaptiste Daroussin n->d = NULL; 1969b50d902SRodney W. Grimes } 1979b50d902SRodney W. Grimes } 198a841e1ebSBaptiste Daroussin 199a841e1ebSBaptiste Daroussin void 200a841e1ebSBaptiste Daroussin macro_popdef(const char *name) 201a841e1ebSBaptiste Daroussin { 202a841e1ebSBaptiste Daroussin ndptr n = lookup(name); 203a841e1ebSBaptiste Daroussin 204a841e1ebSBaptiste Daroussin if (n != NULL) { 205a841e1ebSBaptiste Daroussin struct macro_definition *r = n->d; 206a841e1ebSBaptiste Daroussin if (r != NULL) { 207a841e1ebSBaptiste Daroussin n->d = r->next; 208a841e1ebSBaptiste Daroussin if (r->defn != null) 209a841e1ebSBaptiste Daroussin free(r->defn); 210a841e1ebSBaptiste Daroussin free(r); 211a841e1ebSBaptiste Daroussin } 212a841e1ebSBaptiste Daroussin } 213a841e1ebSBaptiste Daroussin } 214a841e1ebSBaptiste Daroussin 215a841e1ebSBaptiste Daroussin void 216a841e1ebSBaptiste Daroussin macro_for_all(void (*f)(const char *, struct macro_definition *)) 217a841e1ebSBaptiste Daroussin { 218a841e1ebSBaptiste Daroussin ndptr n; 219a841e1ebSBaptiste Daroussin unsigned int i; 220a841e1ebSBaptiste Daroussin 221a841e1ebSBaptiste Daroussin for (n = ohash_first(¯os, &i); n != NULL; 222a841e1ebSBaptiste Daroussin n = ohash_next(¯os, &i)) 223a841e1ebSBaptiste Daroussin if (n->d != NULL) 224a841e1ebSBaptiste Daroussin f(n->name, n->d); 225a841e1ebSBaptiste Daroussin } 226a841e1ebSBaptiste Daroussin 227a841e1ebSBaptiste Daroussin void 228a841e1ebSBaptiste Daroussin setup_builtin(const char *name, unsigned int type) 229a841e1ebSBaptiste Daroussin { 230a841e1ebSBaptiste Daroussin ndptr n; 231a841e1ebSBaptiste Daroussin char *name2; 232a841e1ebSBaptiste Daroussin 233a841e1ebSBaptiste Daroussin if (prefix_builtins) { 234a841e1ebSBaptiste Daroussin name2 = xalloc(strlen(name)+3+1, NULL); 235a841e1ebSBaptiste Daroussin memcpy(name2, "m4_", 3); 236a841e1ebSBaptiste Daroussin memcpy(name2 + 3, name, strlen(name)+1); 237a841e1ebSBaptiste Daroussin } else 238a841e1ebSBaptiste Daroussin name2 = xstrdup(name); 239a841e1ebSBaptiste Daroussin 240a841e1ebSBaptiste Daroussin n = create_entry(name2); 241a841e1ebSBaptiste Daroussin n->builtin_type = type; 242a841e1ebSBaptiste Daroussin n->d = xalloc(sizeof(struct macro_definition), NULL); 243a841e1ebSBaptiste Daroussin n->d->defn = name2; 244a841e1ebSBaptiste Daroussin n->d->type = type; 245a841e1ebSBaptiste Daroussin n->d->next = NULL; 246a841e1ebSBaptiste Daroussin } 247a841e1ebSBaptiste Daroussin 248a841e1ebSBaptiste Daroussin void 249a841e1ebSBaptiste Daroussin mark_traced(const char *name, int on) 250a841e1ebSBaptiste Daroussin { 251a841e1ebSBaptiste Daroussin ndptr p; 252a841e1ebSBaptiste Daroussin unsigned int i; 253a841e1ebSBaptiste Daroussin 254a841e1ebSBaptiste Daroussin if (name == NULL) { 255a841e1ebSBaptiste Daroussin if (on) 256a841e1ebSBaptiste Daroussin trace_flags |= TRACE_ALL; 257a841e1ebSBaptiste Daroussin else 258a841e1ebSBaptiste Daroussin trace_flags &= ~TRACE_ALL; 259a841e1ebSBaptiste Daroussin for (p = ohash_first(¯os, &i); p != NULL; 260a841e1ebSBaptiste Daroussin p = ohash_next(¯os, &i)) 261a841e1ebSBaptiste Daroussin p->trace_flags = FLAG_NO_TRACE; 262a841e1ebSBaptiste Daroussin } else { 263a841e1ebSBaptiste Daroussin p = create_entry(name); 264a841e1ebSBaptiste Daroussin p->trace_flags = on; 265a841e1ebSBaptiste Daroussin } 266a841e1ebSBaptiste Daroussin } 267a841e1ebSBaptiste Daroussin 268a841e1ebSBaptiste Daroussin ndptr 269a841e1ebSBaptiste Daroussin macro_getbuiltin(const char *name) 270a841e1ebSBaptiste Daroussin { 271a841e1ebSBaptiste Daroussin ndptr p; 272a841e1ebSBaptiste Daroussin 273a841e1ebSBaptiste Daroussin p = lookup(name); 274a841e1ebSBaptiste Daroussin if (p == NULL || p->builtin_type == MACRTYPE) 275a841e1ebSBaptiste Daroussin return NULL; 276a841e1ebSBaptiste Daroussin else 277a841e1ebSBaptiste Daroussin return p; 2789b50d902SRodney W. Grimes } 279*31129d4fSBaptiste Daroussin 280*31129d4fSBaptiste Daroussin /* XXX things are slightly more complicated than they seem. 281*31129d4fSBaptiste Daroussin * a macro may actually be "live" (in the middle of an expansion 282*31129d4fSBaptiste Daroussin * on the stack. 283*31129d4fSBaptiste Daroussin * So we actually may need to place it in an array for later... 284*31129d4fSBaptiste Daroussin */ 285*31129d4fSBaptiste Daroussin 286*31129d4fSBaptiste Daroussin static int kept_capacity = 0; 287*31129d4fSBaptiste Daroussin static int kept_size = 0; 288*31129d4fSBaptiste Daroussin static char **kept = NULL; 289*31129d4fSBaptiste Daroussin 290*31129d4fSBaptiste Daroussin static void 291*31129d4fSBaptiste Daroussin keep(char *ptr) 292*31129d4fSBaptiste Daroussin { 293*31129d4fSBaptiste Daroussin if (kept_capacity <= kept_size) { 294*31129d4fSBaptiste Daroussin if (kept_capacity) 295*31129d4fSBaptiste Daroussin kept_capacity *= 2; 296*31129d4fSBaptiste Daroussin else 297*31129d4fSBaptiste Daroussin kept_capacity = 50; 298*31129d4fSBaptiste Daroussin kept = xreallocarray(kept, kept_capacity, 299*31129d4fSBaptiste Daroussin sizeof(char *), "Out of memory while saving %d strings\n", 300*31129d4fSBaptiste Daroussin kept_capacity); 301*31129d4fSBaptiste Daroussin } 302*31129d4fSBaptiste Daroussin kept[kept_size++] = ptr; 303*31129d4fSBaptiste Daroussin } 304*31129d4fSBaptiste Daroussin 305*31129d4fSBaptiste Daroussin static int 306*31129d4fSBaptiste Daroussin string_in_use(const char *ptr) 307*31129d4fSBaptiste Daroussin { 308*31129d4fSBaptiste Daroussin int i; 309*31129d4fSBaptiste Daroussin for (i = 0; i <= sp; i++) { 310*31129d4fSBaptiste Daroussin if (sstack[i] == STORAGE_MACRO && mstack[i].sstr == ptr) 311*31129d4fSBaptiste Daroussin return 1; 312*31129d4fSBaptiste Daroussin } 313*31129d4fSBaptiste Daroussin return 0; 314*31129d4fSBaptiste Daroussin } 315*31129d4fSBaptiste Daroussin 316*31129d4fSBaptiste Daroussin 317*31129d4fSBaptiste Daroussin static void 318*31129d4fSBaptiste Daroussin free_definition(char *ptr) 319*31129d4fSBaptiste Daroussin { 320*31129d4fSBaptiste Daroussin int i; 321*31129d4fSBaptiste Daroussin 322*31129d4fSBaptiste Daroussin /* first try to free old strings */ 323*31129d4fSBaptiste Daroussin for (i = 0; i < kept_size; i++) { 324*31129d4fSBaptiste Daroussin if (!string_in_use(kept[i])) { 325*31129d4fSBaptiste Daroussin kept_size--; 326*31129d4fSBaptiste Daroussin free(kept[i]); 327*31129d4fSBaptiste Daroussin if (i != kept_size) 328*31129d4fSBaptiste Daroussin kept[i] = kept[kept_size]; 329*31129d4fSBaptiste Daroussin i--; 330*31129d4fSBaptiste Daroussin } 331*31129d4fSBaptiste Daroussin } 332*31129d4fSBaptiste Daroussin 333*31129d4fSBaptiste Daroussin /* then deal with us */ 334*31129d4fSBaptiste Daroussin if (string_in_use(ptr)) 335*31129d4fSBaptiste Daroussin keep(ptr); 336*31129d4fSBaptiste Daroussin else 337*31129d4fSBaptiste Daroussin free(ptr); 338*31129d4fSBaptiste Daroussin } 339*31129d4fSBaptiste Daroussin 340