131129d4fSBaptiste Daroussin /* $OpenBSD: look.c,v 1.24 2014/12/21 09:33:12 espie Exp $ */
2acc9d408SJuli Mallett
3*8a16b7a1SPedro F. Giffuni /*-
4*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
5*8a16b7a1SPedro F. Giffuni *
69b50d902SRodney W. Grimes * Copyright (c) 1989, 1993
79b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved.
89b50d902SRodney W. Grimes *
99b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by
109b50d902SRodney W. Grimes * Ozan Yigit at York University.
119b50d902SRodney W. Grimes *
129b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
139b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions
149b50d902SRodney W. Grimes * are met:
159b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
169b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
179b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
189b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
199b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution.
20a841e1ebSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors
219b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software
229b50d902SRodney W. Grimes * without specific prior written permission.
239b50d902SRodney W. Grimes *
249b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
259b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
269b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
279b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
289b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
299b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
309b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
319b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
329b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
339b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
349b50d902SRodney W. Grimes * SUCH DAMAGE.
359b50d902SRodney W. Grimes */
36acc9d408SJuli Mallett #include <sys/cdefs.h>
379b50d902SRodney W. Grimes /*
389b50d902SRodney W. Grimes * look.c
399b50d902SRodney W. Grimes * Facility: m4 macro processor
409b50d902SRodney W. Grimes * by: oz
419b50d902SRodney W. Grimes */
429b50d902SRodney W. Grimes
439b50d902SRodney W. Grimes #include <sys/types.h>
449b50d902SRodney W. Grimes #include <stdio.h>
459b50d902SRodney W. Grimes #include <stdlib.h>
46a841e1ebSBaptiste Daroussin #include <stdint.h>
47acc9d408SJuli Mallett #include <stddef.h>
489b50d902SRodney W. Grimes #include <string.h>
49a841e1ebSBaptiste Daroussin #include <ohash.h>
509b50d902SRodney W. Grimes #include "mdef.h"
519b50d902SRodney W. Grimes #include "stdd.h"
529b50d902SRodney W. Grimes #include "extern.h"
539b50d902SRodney W. Grimes
5488497f0cSBaptiste Daroussin static void *hash_calloc(size_t, size_t, void *);
5588497f0cSBaptiste Daroussin static void hash_free(void *, void *);
56a841e1ebSBaptiste Daroussin static void *element_alloc(size_t, void *);
57a841e1ebSBaptiste Daroussin static void setup_definition(struct macro_definition *, const char *,
58a841e1ebSBaptiste Daroussin const char *);
5931129d4fSBaptiste Daroussin static void free_definition(char *);
6031129d4fSBaptiste Daroussin static void keep(char *);
6131129d4fSBaptiste Daroussin static int string_in_use(const char *);
62acc9d408SJuli Mallett
63a841e1ebSBaptiste Daroussin static struct ohash_info macro_info = {
64a841e1ebSBaptiste Daroussin offsetof(struct ndblock, name),
6588497f0cSBaptiste Daroussin NULL, hash_calloc, hash_free, element_alloc };
66a841e1ebSBaptiste Daroussin
67a841e1ebSBaptiste Daroussin struct ohash macros;
68a841e1ebSBaptiste Daroussin
69a841e1ebSBaptiste Daroussin /* Support routines for hash tables. */
70a841e1ebSBaptiste Daroussin void *
hash_calloc(size_t n,size_t s,void * u __unused)7188497f0cSBaptiste Daroussin hash_calloc(size_t n, size_t s, void *u __unused)
729b50d902SRodney W. Grimes {
7388497f0cSBaptiste Daroussin void *storage = xcalloc(n, s, "hash alloc");
74a841e1ebSBaptiste Daroussin return storage;
75a841e1ebSBaptiste Daroussin }
76a841e1ebSBaptiste Daroussin
77a841e1ebSBaptiste Daroussin void
hash_free(void * p,void * u __unused)7888497f0cSBaptiste Daroussin hash_free(void *p, void *u __unused)
79a841e1ebSBaptiste Daroussin {
80a841e1ebSBaptiste Daroussin free(p);
81a841e1ebSBaptiste Daroussin }
82a841e1ebSBaptiste Daroussin
83a841e1ebSBaptiste Daroussin void *
element_alloc(size_t s,void * u __unused)8488497f0cSBaptiste Daroussin element_alloc(size_t s, void *u __unused)
85a841e1ebSBaptiste Daroussin {
86a841e1ebSBaptiste Daroussin return xalloc(s, "element alloc");
87a841e1ebSBaptiste Daroussin }
88a841e1ebSBaptiste Daroussin
89a841e1ebSBaptiste Daroussin void
init_macros(void)90a841e1ebSBaptiste Daroussin init_macros(void)
91a841e1ebSBaptiste Daroussin {
92a841e1ebSBaptiste Daroussin ohash_init(¯os, 10, ¯o_info);
939b50d902SRodney W. Grimes }
949b50d902SRodney W. Grimes
959b50d902SRodney W. Grimes /*
969b50d902SRodney W. Grimes * find name in the hash table
979b50d902SRodney W. Grimes */
989b50d902SRodney W. Grimes ndptr
lookup(const char * name)99bd2bfb58SJuli Mallett lookup(const char *name)
1009b50d902SRodney W. Grimes {
101a841e1ebSBaptiste Daroussin return ohash_find(¯os, ohash_qlookup(¯os, name));
1029b50d902SRodney W. Grimes }
1039b50d902SRodney W. Grimes
104a841e1ebSBaptiste Daroussin struct macro_definition *
lookup_macro_definition(const char * name)105a841e1ebSBaptiste Daroussin lookup_macro_definition(const char *name)
1069b50d902SRodney W. Grimes {
1079b50d902SRodney W. Grimes ndptr p;
1089b50d902SRodney W. Grimes
109a841e1ebSBaptiste Daroussin p = ohash_find(¯os, ohash_qlookup(¯os, name));
110a841e1ebSBaptiste Daroussin if (p)
111a841e1ebSBaptiste Daroussin return p->d;
112a841e1ebSBaptiste Daroussin else
113a841e1ebSBaptiste Daroussin return NULL;
1149b50d902SRodney W. Grimes }
1159b50d902SRodney W. Grimes
1169b50d902SRodney W. Grimes static void
setup_definition(struct macro_definition * d,const char * defn,const char * name)117a841e1ebSBaptiste Daroussin setup_definition(struct macro_definition *d, const char *defn, const char *name)
1189b50d902SRodney W. Grimes {
119a841e1ebSBaptiste Daroussin ndptr p;
120a841e1ebSBaptiste Daroussin
121a841e1ebSBaptiste Daroussin if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0 &&
122a841e1ebSBaptiste Daroussin (p = macro_getbuiltin(defn+sizeof(BUILTIN_MARKER)-1)) != NULL) {
123a841e1ebSBaptiste Daroussin d->type = macro_builtin_type(p);
124a841e1ebSBaptiste Daroussin d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1);
125a841e1ebSBaptiste Daroussin } else {
126a841e1ebSBaptiste Daroussin if (!*defn)
127a841e1ebSBaptiste Daroussin d->defn = __DECONST(char *, null);
128a841e1ebSBaptiste Daroussin else
129a841e1ebSBaptiste Daroussin d->defn = xstrdup(defn);
130a841e1ebSBaptiste Daroussin d->type = MACRTYPE;
131a841e1ebSBaptiste Daroussin }
132a841e1ebSBaptiste Daroussin if (STREQ(name, defn))
133a841e1ebSBaptiste Daroussin d->type |= RECDEF;
1349b50d902SRodney W. Grimes }
1359b50d902SRodney W. Grimes
136a841e1ebSBaptiste Daroussin static ndptr
create_entry(const char * name)137a841e1ebSBaptiste Daroussin create_entry(const char *name)
138a841e1ebSBaptiste Daroussin {
139a841e1ebSBaptiste Daroussin const char *end = NULL;
140a841e1ebSBaptiste Daroussin unsigned int i;
141a841e1ebSBaptiste Daroussin ndptr n;
142a841e1ebSBaptiste Daroussin
143a841e1ebSBaptiste Daroussin i = ohash_qlookupi(¯os, name, &end);
144a841e1ebSBaptiste Daroussin n = ohash_find(¯os, i);
145a841e1ebSBaptiste Daroussin if (n == NULL) {
146a841e1ebSBaptiste Daroussin n = ohash_create_entry(¯o_info, name, &end);
147a841e1ebSBaptiste Daroussin ohash_insert(¯os, i, n);
148a841e1ebSBaptiste Daroussin n->trace_flags = FLAG_NO_TRACE;
149a841e1ebSBaptiste Daroussin n->builtin_type = MACRTYPE;
150a841e1ebSBaptiste Daroussin n->d = NULL;
151a841e1ebSBaptiste Daroussin }
152a841e1ebSBaptiste Daroussin return n;
153a841e1ebSBaptiste Daroussin }
154a841e1ebSBaptiste Daroussin
1559b50d902SRodney W. Grimes void
macro_define(const char * name,const char * defn)156a841e1ebSBaptiste Daroussin macro_define(const char *name, const char *defn)
1579b50d902SRodney W. Grimes {
158a841e1ebSBaptiste Daroussin ndptr n = create_entry(name);
159a841e1ebSBaptiste Daroussin if (n->d != NULL) {
160a841e1ebSBaptiste Daroussin if (n->d->defn != null)
16131129d4fSBaptiste Daroussin free_definition(n->d->defn);
162a841e1ebSBaptiste Daroussin } else {
163a841e1ebSBaptiste Daroussin n->d = xalloc(sizeof(struct macro_definition), NULL);
164a841e1ebSBaptiste Daroussin n->d->next = NULL;
165a841e1ebSBaptiste Daroussin }
166a841e1ebSBaptiste Daroussin setup_definition(n->d, defn, name);
167a841e1ebSBaptiste Daroussin }
1689b50d902SRodney W. Grimes
169a841e1ebSBaptiste Daroussin void
macro_pushdef(const char * name,const char * defn)170a841e1ebSBaptiste Daroussin macro_pushdef(const char *name, const char *defn)
171a841e1ebSBaptiste Daroussin {
172a841e1ebSBaptiste Daroussin ndptr n;
173a841e1ebSBaptiste Daroussin struct macro_definition *d;
174a841e1ebSBaptiste Daroussin
175a841e1ebSBaptiste Daroussin n = create_entry(name);
176a841e1ebSBaptiste Daroussin d = xalloc(sizeof(struct macro_definition), NULL);
177a841e1ebSBaptiste Daroussin d->next = n->d;
178a841e1ebSBaptiste Daroussin n->d = d;
179a841e1ebSBaptiste Daroussin setup_definition(n->d, defn, name);
1809b50d902SRodney W. Grimes }
181a841e1ebSBaptiste Daroussin
182a841e1ebSBaptiste Daroussin void
macro_undefine(const char * name)183a841e1ebSBaptiste Daroussin macro_undefine(const char *name)
184a841e1ebSBaptiste Daroussin {
185a841e1ebSBaptiste Daroussin ndptr n = lookup(name);
186a841e1ebSBaptiste Daroussin if (n != NULL) {
187a841e1ebSBaptiste Daroussin struct macro_definition *r, *r2;
188a841e1ebSBaptiste Daroussin
189a841e1ebSBaptiste Daroussin for (r = n->d; r != NULL; r = r2) {
190a841e1ebSBaptiste Daroussin r2 = r->next;
191a841e1ebSBaptiste Daroussin if (r->defn != null)
192a841e1ebSBaptiste Daroussin free(r->defn);
193a841e1ebSBaptiste Daroussin free(r);
1949b50d902SRodney W. Grimes }
195a841e1ebSBaptiste Daroussin n->d = NULL;
1969b50d902SRodney W. Grimes }
1979b50d902SRodney W. Grimes }
198a841e1ebSBaptiste Daroussin
199a841e1ebSBaptiste Daroussin void
macro_popdef(const char * name)200a841e1ebSBaptiste Daroussin macro_popdef(const char *name)
201a841e1ebSBaptiste Daroussin {
202a841e1ebSBaptiste Daroussin ndptr n = lookup(name);
203a841e1ebSBaptiste Daroussin
204a841e1ebSBaptiste Daroussin if (n != NULL) {
205a841e1ebSBaptiste Daroussin struct macro_definition *r = n->d;
206a841e1ebSBaptiste Daroussin if (r != NULL) {
207a841e1ebSBaptiste Daroussin n->d = r->next;
208a841e1ebSBaptiste Daroussin if (r->defn != null)
209a841e1ebSBaptiste Daroussin free(r->defn);
210a841e1ebSBaptiste Daroussin free(r);
211a841e1ebSBaptiste Daroussin }
212a841e1ebSBaptiste Daroussin }
213a841e1ebSBaptiste Daroussin }
214a841e1ebSBaptiste Daroussin
215a841e1ebSBaptiste Daroussin void
macro_for_all(void (* f)(const char *,struct macro_definition *))216a841e1ebSBaptiste Daroussin macro_for_all(void (*f)(const char *, struct macro_definition *))
217a841e1ebSBaptiste Daroussin {
218a841e1ebSBaptiste Daroussin ndptr n;
219a841e1ebSBaptiste Daroussin unsigned int i;
220a841e1ebSBaptiste Daroussin
221a841e1ebSBaptiste Daroussin for (n = ohash_first(¯os, &i); n != NULL;
222a841e1ebSBaptiste Daroussin n = ohash_next(¯os, &i))
223a841e1ebSBaptiste Daroussin if (n->d != NULL)
224a841e1ebSBaptiste Daroussin f(n->name, n->d);
225a841e1ebSBaptiste Daroussin }
226a841e1ebSBaptiste Daroussin
227a841e1ebSBaptiste Daroussin void
setup_builtin(const char * name,unsigned int type)228a841e1ebSBaptiste Daroussin setup_builtin(const char *name, unsigned int type)
229a841e1ebSBaptiste Daroussin {
230a841e1ebSBaptiste Daroussin ndptr n;
231a841e1ebSBaptiste Daroussin char *name2;
232a841e1ebSBaptiste Daroussin
233a841e1ebSBaptiste Daroussin if (prefix_builtins) {
234a841e1ebSBaptiste Daroussin name2 = xalloc(strlen(name)+3+1, NULL);
235a841e1ebSBaptiste Daroussin memcpy(name2, "m4_", 3);
236a841e1ebSBaptiste Daroussin memcpy(name2 + 3, name, strlen(name)+1);
237a841e1ebSBaptiste Daroussin } else
238a841e1ebSBaptiste Daroussin name2 = xstrdup(name);
239a841e1ebSBaptiste Daroussin
240a841e1ebSBaptiste Daroussin n = create_entry(name2);
241a841e1ebSBaptiste Daroussin n->builtin_type = type;
242a841e1ebSBaptiste Daroussin n->d = xalloc(sizeof(struct macro_definition), NULL);
243a841e1ebSBaptiste Daroussin n->d->defn = name2;
244a841e1ebSBaptiste Daroussin n->d->type = type;
245a841e1ebSBaptiste Daroussin n->d->next = NULL;
246a841e1ebSBaptiste Daroussin }
247a841e1ebSBaptiste Daroussin
248a841e1ebSBaptiste Daroussin void
mark_traced(const char * name,int on)249a841e1ebSBaptiste Daroussin mark_traced(const char *name, int on)
250a841e1ebSBaptiste Daroussin {
251a841e1ebSBaptiste Daroussin ndptr p;
252a841e1ebSBaptiste Daroussin unsigned int i;
253a841e1ebSBaptiste Daroussin
254a841e1ebSBaptiste Daroussin if (name == NULL) {
255a841e1ebSBaptiste Daroussin if (on)
256a841e1ebSBaptiste Daroussin trace_flags |= TRACE_ALL;
257a841e1ebSBaptiste Daroussin else
258a841e1ebSBaptiste Daroussin trace_flags &= ~TRACE_ALL;
259a841e1ebSBaptiste Daroussin for (p = ohash_first(¯os, &i); p != NULL;
260a841e1ebSBaptiste Daroussin p = ohash_next(¯os, &i))
261a841e1ebSBaptiste Daroussin p->trace_flags = FLAG_NO_TRACE;
262a841e1ebSBaptiste Daroussin } else {
263a841e1ebSBaptiste Daroussin p = create_entry(name);
264a841e1ebSBaptiste Daroussin p->trace_flags = on;
265a841e1ebSBaptiste Daroussin }
266a841e1ebSBaptiste Daroussin }
267a841e1ebSBaptiste Daroussin
268a841e1ebSBaptiste Daroussin ndptr
macro_getbuiltin(const char * name)269a841e1ebSBaptiste Daroussin macro_getbuiltin(const char *name)
270a841e1ebSBaptiste Daroussin {
271a841e1ebSBaptiste Daroussin ndptr p;
272a841e1ebSBaptiste Daroussin
273a841e1ebSBaptiste Daroussin p = lookup(name);
274a841e1ebSBaptiste Daroussin if (p == NULL || p->builtin_type == MACRTYPE)
275a841e1ebSBaptiste Daroussin return NULL;
276a841e1ebSBaptiste Daroussin else
277a841e1ebSBaptiste Daroussin return p;
2789b50d902SRodney W. Grimes }
27931129d4fSBaptiste Daroussin
28031129d4fSBaptiste Daroussin /* XXX things are slightly more complicated than they seem.
28131129d4fSBaptiste Daroussin * a macro may actually be "live" (in the middle of an expansion
28231129d4fSBaptiste Daroussin * on the stack.
28331129d4fSBaptiste Daroussin * So we actually may need to place it in an array for later...
28431129d4fSBaptiste Daroussin */
28531129d4fSBaptiste Daroussin
28631129d4fSBaptiste Daroussin static int kept_capacity = 0;
28731129d4fSBaptiste Daroussin static int kept_size = 0;
28831129d4fSBaptiste Daroussin static char **kept = NULL;
28931129d4fSBaptiste Daroussin
29031129d4fSBaptiste Daroussin static void
keep(char * ptr)29131129d4fSBaptiste Daroussin keep(char *ptr)
29231129d4fSBaptiste Daroussin {
29331129d4fSBaptiste Daroussin if (kept_capacity <= kept_size) {
29431129d4fSBaptiste Daroussin if (kept_capacity)
29531129d4fSBaptiste Daroussin kept_capacity *= 2;
29631129d4fSBaptiste Daroussin else
29731129d4fSBaptiste Daroussin kept_capacity = 50;
29831129d4fSBaptiste Daroussin kept = xreallocarray(kept, kept_capacity,
29931129d4fSBaptiste Daroussin sizeof(char *), "Out of memory while saving %d strings\n",
30031129d4fSBaptiste Daroussin kept_capacity);
30131129d4fSBaptiste Daroussin }
30231129d4fSBaptiste Daroussin kept[kept_size++] = ptr;
30331129d4fSBaptiste Daroussin }
30431129d4fSBaptiste Daroussin
30531129d4fSBaptiste Daroussin static int
string_in_use(const char * ptr)30631129d4fSBaptiste Daroussin string_in_use(const char *ptr)
30731129d4fSBaptiste Daroussin {
30831129d4fSBaptiste Daroussin int i;
30931129d4fSBaptiste Daroussin for (i = 0; i <= sp; i++) {
31031129d4fSBaptiste Daroussin if (sstack[i] == STORAGE_MACRO && mstack[i].sstr == ptr)
31131129d4fSBaptiste Daroussin return 1;
31231129d4fSBaptiste Daroussin }
31331129d4fSBaptiste Daroussin return 0;
31431129d4fSBaptiste Daroussin }
31531129d4fSBaptiste Daroussin
31631129d4fSBaptiste Daroussin
31731129d4fSBaptiste Daroussin static void
free_definition(char * ptr)31831129d4fSBaptiste Daroussin free_definition(char *ptr)
31931129d4fSBaptiste Daroussin {
32031129d4fSBaptiste Daroussin int i;
32131129d4fSBaptiste Daroussin
32231129d4fSBaptiste Daroussin /* first try to free old strings */
32331129d4fSBaptiste Daroussin for (i = 0; i < kept_size; i++) {
32431129d4fSBaptiste Daroussin if (!string_in_use(kept[i])) {
32531129d4fSBaptiste Daroussin kept_size--;
32631129d4fSBaptiste Daroussin free(kept[i]);
32731129d4fSBaptiste Daroussin if (i != kept_size)
32831129d4fSBaptiste Daroussin kept[i] = kept[kept_size];
32931129d4fSBaptiste Daroussin i--;
33031129d4fSBaptiste Daroussin }
33131129d4fSBaptiste Daroussin }
33231129d4fSBaptiste Daroussin
33331129d4fSBaptiste Daroussin /* then deal with us */
33431129d4fSBaptiste Daroussin if (string_in_use(ptr))
33531129d4fSBaptiste Daroussin keep(ptr);
33631129d4fSBaptiste Daroussin else
33731129d4fSBaptiste Daroussin free(ptr);
33831129d4fSBaptiste Daroussin }
33931129d4fSBaptiste Daroussin
340