Home | History | Annotate | Line # | Download | only in m4
      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 *
     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
     79 hash_free(void *p, size_t s UNUSED, void *u UNUSED)
     80 {
     81 	free(p);
     82 }
     83 
     84 void *
     85 element_alloc(size_t s, void *u UNUSED)
     86 {
     87 	return xalloc(s, "element alloc");
     88 }
     89 
     90 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
    100 lookup(const char *name)
    101 {
    102 	return ohash_find(&macros, ohash_qlookup(&macros, name));
    103 }
    104 
    105 struct macro_definition *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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