xref: /netbsd-src/usr.bin/m4/look.c (revision 59e8ea8f4c41224bb164038885d42752a098cc0c)
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(&macros, 10, &macro_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(&macros, ohash_qlookup(&macros, 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(&macros, ohash_qlookup(&macros, 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(&macros, name, &end);
145 	n = ohash_find(&macros, i);
146 	if (n == NULL) {
147 		n = ohash_create_entry(&macro_info, name, &end);
148 		ohash_insert(&macros, 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(&macros, &i); n != NULL;
223 	    n = ohash_next(&macros, &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(&macros, &i); p != NULL;
261 		    p = ohash_next(&macros, &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(&macros, &i); n != NULL;
312 	    n = ohash_next(&macros, &i))
313 		dump_entry(f, n);
314 }
315 #endif
316