1/*	$NetBSD: sym.c,v 1.1.1.1 2009/10/26 00:27:03 christos Exp $	*/
2
3/* sym - symbol table routines */
4
5/*  Copyright (c) 1990 The Regents of the University of California. */
6/*  All rights reserved. */
7
8/*  This code is derived from software contributed to Berkeley by */
9/*  Vern Paxson. */
10
11/*  The United States Government has rights in this work pursuant */
12/*  to contract no. DE-AC03-76SF00098 between the United States */
13/*  Department of Energy and the University of California. */
14
15/*  This file is part of flex. */
16
17/*  Redistribution and use in source and binary forms, with or without */
18/*  modification, are permitted provided that the following conditions */
19/*  are met: */
20
21/*  1. Redistributions of source code must retain the above copyright */
22/*     notice, this list of conditions and the following disclaimer. */
23/*  2. Redistributions in binary form must reproduce the above copyright */
24/*     notice, this list of conditions and the following disclaimer in the */
25/*     documentation and/or other materials provided with the distribution. */
26
27/*  Neither the name of the University nor the names of its contributors */
28/*  may be used to endorse or promote products derived from this software */
29/*  without specific prior written permission. */
30
31/*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
32/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
33/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
34/*  PURPOSE. */
35
36#include "flexdef.h"
37
38/* Variables for symbol tables:
39 * sctbl - start-condition symbol table
40 * ndtbl - name-definition symbol table
41 * ccltab - character class text symbol table
42 */
43
44struct hash_entry {
45	struct hash_entry *prev, *next;
46	char   *name;
47	char   *str_val;
48	int     int_val;
49};
50
51typedef struct hash_entry **hash_table;
52
53#define NAME_TABLE_HASH_SIZE 101
54#define START_COND_HASH_SIZE 101
55#define CCL_HASH_SIZE 101
56
57static struct hash_entry *ndtbl[NAME_TABLE_HASH_SIZE];
58static struct hash_entry *sctbl[START_COND_HASH_SIZE];
59static struct hash_entry *ccltab[CCL_HASH_SIZE];
60
61
62/* declare functions that have forward references */
63
64static int addsym PROTO ((register char[], char *, int, hash_table, int));
65static struct hash_entry *findsym PROTO ((register const char *sym,
66					  hash_table table,
67
68					  int table_size));
69static int hashfunct PROTO ((register const char *, int));
70
71
72/* addsym - add symbol and definitions to symbol table
73 *
74 * -1 is returned if the symbol already exists, and the change not made.
75 */
76
77static int addsym (sym, str_def, int_def, table, table_size)
78     register char sym[];
79     char   *str_def;
80     int     int_def;
81     hash_table table;
82     int     table_size;
83{
84	int     hash_val = hashfunct (sym, table_size);
85	register struct hash_entry *sym_entry = table[hash_val];
86	register struct hash_entry *new_entry;
87	register struct hash_entry *successor;
88
89	while (sym_entry) {
90		if (!strcmp (sym, sym_entry->name)) {	/* entry already exists */
91			return -1;
92		}
93
94		sym_entry = sym_entry->next;
95	}
96
97	/* create new entry */
98	new_entry = (struct hash_entry *)
99		flex_alloc (sizeof (struct hash_entry));
100
101	if (new_entry == NULL)
102		flexfatal (_("symbol table memory allocation failed"));
103
104	if ((successor = table[hash_val]) != 0) {
105		new_entry->next = successor;
106		successor->prev = new_entry;
107	}
108	else
109		new_entry->next = NULL;
110
111	new_entry->prev = NULL;
112	new_entry->name = sym;
113	new_entry->str_val = str_def;
114	new_entry->int_val = int_def;
115
116	table[hash_val] = new_entry;
117
118	return 0;
119}
120
121
122/* cclinstal - save the text of a character class */
123
124void    cclinstal (ccltxt, cclnum)
125     Char    ccltxt[];
126     int     cclnum;
127{
128	/* We don't bother checking the return status because we are not
129	 * called unless the symbol is new.
130	 */
131
132	(void) addsym ((char *) copy_unsigned_string (ccltxt),
133		       (char *) 0, cclnum, ccltab, CCL_HASH_SIZE);
134}
135
136
137/* ccllookup - lookup the number associated with character class text
138 *
139 * Returns 0 if there's no CCL associated with the text.
140 */
141
142int     ccllookup (ccltxt)
143     Char    ccltxt[];
144{
145	return findsym ((char *) ccltxt, ccltab, CCL_HASH_SIZE)->int_val;
146}
147
148
149/* findsym - find symbol in symbol table */
150
151static struct hash_entry *findsym (sym, table, table_size)
152     register const char *sym;
153     hash_table table;
154     int     table_size;
155{
156	static struct hash_entry empty_entry = {
157		(struct hash_entry *) 0, (struct hash_entry *) 0,
158		(char *) 0, (char *) 0, 0,
159	};
160	register struct hash_entry *sym_entry =
161
162		table[hashfunct (sym, table_size)];
163
164	while (sym_entry) {
165		if (!strcmp (sym, sym_entry->name))
166			return sym_entry;
167		sym_entry = sym_entry->next;
168	}
169
170	return &empty_entry;
171}
172
173/* hashfunct - compute the hash value for "str" and hash size "hash_size" */
174
175static int hashfunct (str, hash_size)
176     register const char *str;
177     int     hash_size;
178{
179	register int hashval;
180	register int locstr;
181
182	hashval = 0;
183	locstr = 0;
184
185	while (str[locstr]) {
186		hashval = (hashval << 1) + (unsigned char) str[locstr++];
187		hashval %= hash_size;
188	}
189
190	return hashval;
191}
192
193
194/* ndinstal - install a name definition */
195
196void    ndinstal (name, definition)
197     const char *name;
198     Char    definition[];
199{
200
201	if (addsym (copy_string (name),
202		    (char *) copy_unsigned_string (definition), 0,
203		    ndtbl, NAME_TABLE_HASH_SIZE))
204			synerr (_("name defined twice"));
205}
206
207
208/* ndlookup - lookup a name definition
209 *
210 * Returns a nil pointer if the name definition does not exist.
211 */
212
213Char   *ndlookup (nd)
214     const char *nd;
215{
216	return (Char *) findsym (nd, ndtbl, NAME_TABLE_HASH_SIZE)->str_val;
217}
218
219
220/* scextend - increase the maximum number of start conditions */
221
222void    scextend ()
223{
224	current_max_scs += MAX_SCS_INCREMENT;
225
226	++num_reallocs;
227
228	scset = reallocate_integer_array (scset, current_max_scs);
229	scbol = reallocate_integer_array (scbol, current_max_scs);
230	scxclu = reallocate_integer_array (scxclu, current_max_scs);
231	sceof = reallocate_integer_array (sceof, current_max_scs);
232	scname = reallocate_char_ptr_array (scname, current_max_scs);
233}
234
235
236/* scinstal - make a start condition
237 *
238 * NOTE
239 *    The start condition is "exclusive" if xcluflg is true.
240 */
241
242void    scinstal (str, xcluflg)
243     const char *str;
244     int     xcluflg;
245{
246
247	if (++lastsc >= current_max_scs)
248		scextend ();
249
250	scname[lastsc] = copy_string (str);
251
252	if (addsym (scname[lastsc], (char *) 0, lastsc,
253		    sctbl, START_COND_HASH_SIZE))
254			format_pinpoint_message (_
255						 ("start condition %s declared twice"),
256str);
257
258	scset[lastsc] = mkstate (SYM_EPSILON);
259	scbol[lastsc] = mkstate (SYM_EPSILON);
260	scxclu[lastsc] = xcluflg;
261	sceof[lastsc] = false;
262}
263
264
265/* sclookup - lookup the number associated with a start condition
266 *
267 * Returns 0 if no such start condition.
268 */
269
270int     sclookup (str)
271     const char *str;
272{
273	return findsym (str, sctbl, START_COND_HASH_SIZE)->int_val;
274}
275