xref: /netbsd-src/usr.bin/m4/look.c (revision daf6c4152fcddc27c445489775ed1f66ab4ea9a9)
1 /*	$NetBSD: look.c,v 1.11 2009/10/26 21:11:28 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.11 2009/10/26 21:11:28 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 *
70 hash_alloc(s, u)
71 	size_t s;
72 	void *u 	UNUSED;
73 {
74 	void *storage = xalloc(s, "hash alloc");
75 	if (storage)
76 		memset(storage, 0, s);
77 	return storage;
78 }
79 
80 void
81 hash_free(p, s, u)
82 	void *p;
83 	size_t s	UNUSED;
84 	void *u 	UNUSED;
85 {
86 	free(p);
87 }
88 
89 void *
90 element_alloc(s, u)
91 	size_t s;
92 	void *u 	UNUSED;
93 {
94 	return xalloc(s, "element alloc");
95 }
96 
97 void
98 init_macros()
99 {
100 	ohash_init(&macros, 10, &macro_info);
101 }
102 
103 /*
104  * find name in the hash table
105  */
106 ndptr
107 lookup(const char *name)
108 {
109 	return ohash_find(&macros, ohash_qlookup(&macros, name));
110 }
111 
112 struct macro_definition *
113 lookup_macro_definition(const char *name)
114 {
115 	ndptr p;
116 
117 	p = ohash_find(&macros, ohash_qlookup(&macros, name));
118 	if (p)
119 		return p->d;
120 	else
121 		return NULL;
122 }
123 
124 static void
125 setup_definition(struct macro_definition *d, const char *defn, const char *name)
126 {
127 	ndptr p;
128 
129 	if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0 &&
130 	    (p = macro_getbuiltin(defn+sizeof(BUILTIN_MARKER)-1)) != NULL) {
131 		d->type = macro_builtin_type(p);
132 		d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1);
133 	} else {
134 		if (!*defn)
135 			d->defn = xstrdup(null);
136 		else
137 			d->defn = xstrdup(defn);
138 		d->type = MACRTYPE;
139 	}
140 	if (STREQ(name, defn))
141 		d->type |= RECDEF;
142 }
143 
144 static ndptr
145 create_entry(const char *name)
146 {
147 	const char *end = NULL;
148 	unsigned int i;
149 	ndptr n;
150 
151 	i = ohash_qlookupi(&macros, name, &end);
152 	n = ohash_find(&macros, i);
153 	if (n == NULL) {
154 		n = ohash_create_entry(&macro_info, name, &end);
155 		ohash_insert(&macros, i, n);
156 		n->trace_flags = FLAG_NO_TRACE;
157 		n->builtin_type = MACRTYPE;
158 		n->d = NULL;
159 	}
160 	return n;
161 }
162 
163 void
164 macro_define(const char *name, const char *defn)
165 {
166 	ndptr n = create_entry(name);
167 	if (n->d != NULL) {
168 		if (n->d->defn != null)
169 			free(n->d->defn);
170 	} else {
171 		n->d = xalloc(sizeof(struct macro_definition), NULL);
172 		n->d->next = NULL;
173 	}
174 	setup_definition(n->d, defn, name);
175 }
176 
177 void
178 macro_pushdef(const char *name, const char *defn)
179 {
180 	ndptr n;
181 	struct macro_definition *d;
182 
183 	n = create_entry(name);
184 	d = xalloc(sizeof(struct macro_definition), NULL);
185 	d->next = n->d;
186 	n->d = d;
187 	setup_definition(n->d, defn, name);
188 }
189 
190 void
191 macro_undefine(const char *name)
192 {
193 	ndptr n = lookup(name);
194 	if (n != NULL) {
195 		struct macro_definition *r, *r2;
196 
197 		for (r = n->d; r != NULL; r = r2) {
198 			r2 = r->next;
199 			if (r->defn != null)
200 				free(r->defn);
201 			free(r);
202 		}
203 		n->d = NULL;
204 	}
205 }
206 
207 void
208 macro_popdef(const char *name)
209 {
210 	ndptr n = lookup(name);
211 
212 	if (n != NULL) {
213 		struct macro_definition *r = n->d;
214 		if (r != NULL) {
215 			n->d = r->next;
216 			if (r->defn != null)
217 				free(r->defn);
218 			free(r);
219 		}
220 	}
221 }
222 
223 void
224 macro_for_all(void (*f)(const char *, struct macro_definition *))
225 {
226 	ndptr n;
227 	unsigned int i;
228 
229 	for (n = ohash_first(&macros, &i); n != NULL;
230 	    n = ohash_next(&macros, &i))
231 		if (n->d != NULL)
232 			f(n->name, n->d);
233 }
234 
235 void
236 setup_builtin(const char *name, unsigned int type)
237 {
238 	ndptr n;
239 	char *name2;
240 
241 	if (prefix_builtins) {
242 		name2 = xalloc(strlen(name)+3+1, NULL);
243 		memcpy(name2, "m4_", 3);
244 		memcpy(name2 + 3, name, strlen(name)+1);
245 	} else
246 		name2 = xstrdup(name);
247 
248 	n = create_entry(name2);
249 	n->builtin_type = type;
250 	n->d = xalloc(sizeof(struct macro_definition), NULL);
251 	n->d->defn = name2;
252 	n->d->type = type;
253 	n->d->next = NULL;
254 }
255 
256 void
257 mark_traced(const char *name, int on)
258 {
259 	ndptr p;
260 	unsigned int i;
261 
262 	if (name == NULL) {
263 		if (on)
264 			trace_flags |= TRACE_ALL;
265 		else
266 			trace_flags &= ~TRACE_ALL;
267 		for (p = ohash_first(&macros, &i); p != NULL;
268 		    p = ohash_next(&macros, &i))
269 		    	p->trace_flags = FLAG_NO_TRACE;
270 	} else {
271 		p = create_entry(name);
272 		p->trace_flags = on;
273 	}
274 }
275 
276 ndptr
277 macro_getbuiltin(const char *name)
278 {
279 	ndptr p;
280 
281 	p = lookup(name);
282 	if (p == NULL || p->builtin_type == MACRTYPE)
283 		return NULL;
284 	else
285 		return p;
286 }
287 
288