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
56static void *hash_alloc(size_t, void *);
57static void hash_free(void *, size_t, void *);
58static void *element_alloc(size_t, void *);
59static void setup_definition(struct macro_definition *, const char *,
60    const char *);
61
62static struct ohash_info macro_info = {
63	offsetof(struct ndblock, name),
64	NULL, hash_alloc, hash_free, element_alloc };
65
66struct ohash macros;
67
68/* Support routines for hash tables.  */
69void *
70hash_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
78void
79hash_free(void *p, size_t s UNUSED, void *u UNUSED)
80{
81	free(p);
82}
83
84void *
85element_alloc(size_t s, void *u UNUSED)
86{
87	return xalloc(s, "element alloc");
88}
89
90void
91init_macros(void)
92{
93	ohash_init(&macros, 10, &macro_info);
94}
95
96/*
97 * find name in the hash table
98 */
99ndptr
100lookup(const char *name)
101{
102	return ohash_find(&macros, ohash_qlookup(&macros, name));
103}
104
105struct macro_definition *
106lookup_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
117static void
118setup_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
137static ndptr
138create_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
156void
157macro_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
170void
171macro_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
183void
184macro_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
200void
201macro_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
216void
217macro_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
228void
229setup_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
249void
250mark_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
269ndptr
270macro_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
282static void
283recurse(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
298static void
299dump_entry(FILE *f, ndptr n)
300{
301	if (n->d == NULL)
302		return;
303	recurse(f, n, n->d);
304}
305
306void
307dump_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