Annotation of src/usr.bin/m4/look.c, Revision 1.24
1.24 ! espie 1: /* $OpenBSD: look.c,v 1.23 2014/05/12 19:11:19 espie Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /*
4: * Copyright (c) 1989, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * Ozan Yigit at York University.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
1.11 millert 18: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: /*
36: * look.c
37: * Facility: m4 macro processor
38: * by: oz
39: */
40:
41: #include <stdio.h>
42: #include <stdlib.h>
1.18 espie 43: #include <stdint.h>
1.3 espie 44: #include <stddef.h>
1.1 deraadt 45: #include <string.h>
1.13 espie 46: #include <ohash.h>
1.1 deraadt 47: #include "mdef.h"
48: #include "stdd.h"
49: #include "extern.h"
50:
1.23 espie 51: static void *hash_calloc(size_t, size_t, void *);
52: static void hash_free(void *, void *);
1.15 espie 53: static void *element_alloc(size_t, void *);
1.22 marco 54: static void setup_definition(struct macro_definition *, const char *,
1.13 espie 55: const char *);
1.24 ! espie 56: static void free_definition(char *);
! 57: static void keep(char *);
! 58: static int string_in_use(const char *);
1.13 espie 59:
60: static struct ohash_info macro_info = {
61: offsetof(struct ndblock, name),
1.23 espie 62: NULL, hash_calloc, hash_free, element_alloc };
1.13 espie 63:
1.15 espie 64: struct ohash macros;
65:
66: /* Support routines for hash tables. */
67: void *
1.23 espie 68: hash_calloc(size_t n, size_t s, void *u UNUSED)
1.15 espie 69: {
1.23 espie 70: void *storage = xcalloc(n, s, "hash alloc");
1.15 espie 71: return storage;
72: }
73:
74: void
1.23 espie 75: hash_free(void *p, void *u UNUSED)
1.15 espie 76: {
77: free(p);
78: }
79:
80: void *
1.23 espie 81: element_alloc(size_t s, void *u UNUSED)
1.15 espie 82: {
1.16 espie 83: return xalloc(s, "element alloc");
1.15 espie 84: }
1.13 espie 85:
86: void
87: init_macros()
88: {
1.15 espie 89: ohash_init(¯os, 10, ¯o_info);
1.1 deraadt 90: }
91:
92: /*
93: * find name in the hash table
94: */
1.22 marco 95: ndptr
1.10 espie 96: lookup(const char *name)
1.1 deraadt 97: {
1.13 espie 98: return ohash_find(¯os, ohash_qlookup(¯os, name));
1.12 espie 99: }
100:
101: struct macro_definition *
102: lookup_macro_definition(const char *name)
103: {
104: ndptr p;
105:
1.15 espie 106: p = ohash_find(¯os, ohash_qlookup(¯os, name));
1.12 espie 107: if (p)
1.13 espie 108: return p->d;
1.12 espie 109: else
110: return NULL;
111: }
112:
1.22 marco 113: static void
1.13 espie 114: setup_definition(struct macro_definition *d, const char *defn, const char *name)
1.12 espie 115: {
1.14 espie 116: ndptr p;
1.12 espie 117:
1.13 espie 118: if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0 &&
1.14 espie 119: (p = macro_getbuiltin(defn+sizeof(BUILTIN_MARKER)-1)) != NULL) {
120: d->type = macro_builtin_type(p);
1.13 espie 121: d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1);
122: } else {
123: if (!*defn)
124: d->defn = null;
125: else
126: d->defn = xstrdup(defn);
127: d->type = MACRTYPE;
128: }
129: if (STREQ(name, defn))
130: d->type |= RECDEF;
131: }
132:
133: static ndptr
134: create_entry(const char *name)
135: {
136: const char *end = NULL;
137: unsigned int i;
138: ndptr n;
139:
140: i = ohash_qlookupi(¯os, name, &end);
141: n = ohash_find(¯os, i);
142: if (n == NULL) {
143: n = ohash_create_entry(¯o_info, name, &end);
144: ohash_insert(¯os, i, n);
1.15 espie 145: n->trace_flags = FLAG_NO_TRACE;
1.14 espie 146: n->builtin_type = MACRTYPE;
1.13 espie 147: n->d = NULL;
1.12 espie 148: }
1.13 espie 149: return n;
1.12 espie 150: }
151:
152: void
153: macro_define(const char *name, const char *defn)
154: {
1.13 espie 155: ndptr n = create_entry(name);
156: if (n->d != NULL) {
157: if (n->d->defn != null)
1.24 ! espie 158: free_definition(n->d->defn);
1.13 espie 159: } else {
1.16 espie 160: n->d = xalloc(sizeof(struct macro_definition), NULL);
1.13 espie 161: n->d->next = NULL;
162: }
163: setup_definition(n->d, defn, name);
1.12 espie 164: }
165:
166: void
167: macro_pushdef(const char *name, const char *defn)
168: {
1.13 espie 169: ndptr n;
170: struct macro_definition *d;
1.22 marco 171:
1.13 espie 172: n = create_entry(name);
1.16 espie 173: d = xalloc(sizeof(struct macro_definition), NULL);
1.13 espie 174: d->next = n->d;
175: n->d = d;
176: setup_definition(n->d, defn, name);
1.12 espie 177: }
178:
179: void
180: macro_undefine(const char *name)
181: {
1.13 espie 182: ndptr n = lookup(name);
183: if (n != NULL) {
184: struct macro_definition *r, *r2;
185:
186: for (r = n->d; r != NULL; r = r2) {
187: r2 = r->next;
188: if (r->defn != null)
189: free(r->defn);
190: free(r);
191: }
192: n->d = NULL;
193: }
1.12 espie 194: }
195:
196: void
197: macro_popdef(const char *name)
198: {
1.13 espie 199: ndptr n = lookup(name);
200:
201: if (n != NULL) {
202: struct macro_definition *r = n->d;
203: if (r != NULL) {
204: n->d = r->next;
205: if (r->defn != null)
206: free(r->defn);
207: free(r);
208: }
209: }
1.12 espie 210: }
211:
212: void
213: macro_for_all(void (*f)(const char *, struct macro_definition *))
214: {
1.13 espie 215: ndptr n;
216: unsigned int i;
1.12 espie 217:
1.22 marco 218: for (n = ohash_first(¯os, &i); n != NULL;
1.13 espie 219: n = ohash_next(¯os, &i))
1.19 guenther 220: if (n->d != NULL)
221: f(n->name, n->d);
1.12 espie 222: }
223:
1.22 marco 224: void
1.12 espie 225: setup_builtin(const char *name, unsigned int type)
226: {
1.13 espie 227: ndptr n;
1.20 sthen 228: char *name2;
1.12 espie 229:
1.21 sthen 230: if (prefix_builtins) {
1.20 sthen 231: name2 = xalloc(strlen(name)+3+1, NULL);
232: memcpy(name2, "m4_", 3);
233: memcpy(name2 + 3, name, strlen(name)+1);
234: } else
235: name2 = xstrdup(name);
236:
237: n = create_entry(name2);
1.14 espie 238: n->builtin_type = type;
1.16 espie 239: n->d = xalloc(sizeof(struct macro_definition), NULL);
1.20 sthen 240: n->d->defn = name2;
1.13 espie 241: n->d->type = type;
242: n->d->next = NULL;
1.12 espie 243: }
244:
1.15 espie 245: void
246: mark_traced(const char *name, int on)
1.12 espie 247: {
1.15 espie 248: ndptr p;
249: unsigned int i;
1.12 espie 250:
1.15 espie 251: if (name == NULL) {
252: if (on)
253: trace_flags |= TRACE_ALL;
254: else
255: trace_flags &= ~TRACE_ALL;
1.22 marco 256: for (p = ohash_first(¯os, &i); p != NULL;
1.15 espie 257: p = ohash_next(¯os, &i))
1.22 marco 258: p->trace_flags = FLAG_NO_TRACE;
1.15 espie 259: } else {
260: p = create_entry(name);
261: p->trace_flags = on;
262: }
1.1 deraadt 263: }
1.14 espie 264:
1.22 marco 265: ndptr
1.14 espie 266: macro_getbuiltin(const char *name)
267: {
268: ndptr p;
269:
270: p = lookup(name);
271: if (p == NULL || p->builtin_type == MACRTYPE)
272: return NULL;
273: else
274: return p;
275: }
1.24 ! espie 276:
! 277: /* XXX things are slightly more complicated than they seem.
! 278: * a macro may actually be "live" (in the middle of an expansion
! 279: * on the stack.
! 280: * So we actually may need to place it in an array for later...
! 281: */
! 282:
! 283: static int kept_capacity = 0;
! 284: static int kept_size = 0;
! 285: static char **kept = NULL;
! 286:
! 287: static void
! 288: keep(char *ptr)
! 289: {
! 290: if (kept_capacity <= kept_size) {
! 291: if (kept_capacity)
! 292: kept_capacity *= 2;
! 293: else
! 294: kept_capacity = 50;
! 295: kept = xreallocarray(kept, kept_capacity,
! 296: sizeof(char *), "Out of memory while saving %d strings\n",
! 297: kept_capacity);
! 298: }
! 299: kept[kept_size++] = ptr;
! 300: }
! 301:
! 302: static int
! 303: string_in_use(const char *ptr)
! 304: {
! 305: int i;
! 306: for (i = 0; i <= sp; i++) {
! 307: if (sstack[i] == STORAGE_MACRO && mstack[i].sstr == ptr)
! 308: return 1;
! 309: }
! 310: return 0;
! 311: }
! 312:
! 313:
! 314: static void
! 315: free_definition(char *ptr)
! 316: {
! 317: int i;
! 318:
! 319: /* first try to free old strings */
! 320: for (i = 0; i < kept_size; i++) {
! 321: if (!string_in_use(kept[i])) {
! 322: kept_size--;
! 323: free(kept[i]);
! 324: if (i != kept_size)
! 325: kept[i] = kept[kept_size];
! 326: i--;
! 327: }
! 328: }
! 329:
! 330: /* then deal with us */
! 331: if (string_in_use(ptr))
! 332: keep(ptr);
! 333: else
! 334: free(ptr);
! 335: }
! 336: