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