Commit | Line | Data |
---|---|---|
0875b58f | 1 | /* -*-c-*- |
2 | * | |
0875b58f | 3 | * Symbol table management |
4 | * | |
5 | * (c) 1998 Straylight/Edgeware | |
6 | */ | |
7 | ||
d4efbcd9 | 8 | /*----- Licensing notice --------------------------------------------------* |
0875b58f | 9 | * |
10 | * This file is part of the mLib utilities library. | |
11 | * | |
12 | * mLib is free software; you can redistribute it and/or modify | |
c846879c | 13 | * it under the terms of the GNU Library General Public License as |
14 | * published by the Free Software Foundation; either version 2 of the | |
15 | * License, or (at your option) any later version. | |
d4efbcd9 | 16 | * |
0875b58f | 17 | * mLib is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
c846879c | 20 | * GNU Library General Public License for more details. |
d4efbcd9 | 21 | * |
c846879c | 22 | * You should have received a copy of the GNU Library General Public |
0bd98442 | 23 | * License along with mLib; if not, write to the Free |
24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
25 | * MA 02111-1307, USA. | |
0875b58f | 26 | */ |
27 | ||
0875b58f | 28 | /*----- Header files ------------------------------------------------------*/ |
29 | ||
30 | /* --- ANSI headers --- */ | |
31 | ||
32 | #include <stdio.h> | |
33 | #include <stdlib.h> | |
34 | #include <string.h> | |
35 | ||
36 | /* --- Local headers --- */ | |
37 | ||
38 | #include "alloc.h" | |
20eb516f | 39 | #include "arena.h" |
d4d7a053 | 40 | #include "bits.h" |
0875b58f | 41 | #include "exc.h" |
03d53b73 | 42 | #include "hash.h" |
36188114 | 43 | #include "macros.h" |
0875b58f | 44 | #include "sub.h" |
45 | #include "sym.h" | |
6f444bda | 46 | #include "unihash.h" |
0875b58f | 47 | |
0875b58f | 48 | /*----- Main code ---------------------------------------------------------*/ |
49 | ||
34b97201 | 50 | /* --- @sym_create@ --- * |
0875b58f | 51 | * |
a7a37c4a | 52 | * Arguments: @sym_table *t@ = symbol table to initialize |
0875b58f | 53 | * |
54 | * Returns: --- | |
55 | * | |
a7a37c4a | 56 | * Use: Initializes the given symbol table. Raises @EXC_NOMEM@ if |
0875b58f | 57 | * there isn't enough memory. |
58 | */ | |
59 | ||
34b97201 | 60 | void sym_create(sym_table *t) |
0875b58f | 61 | { |
03d53b73 | 62 | hash_create(&t->t, SYM_INITSZ); |
20eb516f | 63 | t->s = &sub_global; |
03d53b73 | 64 | t->load = SYM_LIMIT(SYM_INITSZ); |
0875b58f | 65 | } |
66 | ||
34b97201 | 67 | /* --- @sym_destroy@ --- * |
0875b58f | 68 | * |
69 | * Arguments: @sym_table *t@ = pointer to symbol table in question | |
70 | * | |
71 | * Returns: --- | |
72 | * | |
73 | * Use: Destroys a symbol table, freeing all the memory it used to | |
74 | * occupy. | |
75 | */ | |
76 | ||
34b97201 | 77 | void sym_destroy(sym_table *t) |
0875b58f | 78 | { |
03d53b73 | 79 | sym_iter i; |
0875b58f | 80 | |
03d53b73 | 81 | SYM_MKITER(&i, t); |
82 | for (;;) { | |
83 | sym_base *p; | |
84 | SYM_NEXT(&i, p); | |
85 | if (!p) | |
86 | break; | |
20eb516f | 87 | x_free(t->t.a, p); |
0875b58f | 88 | } |
03d53b73 | 89 | hash_destroy(&t->t); |
0875b58f | 90 | } |
91 | ||
92 | /* --- @sym_find@ --- * | |
93 | * | |
94 | * Arguments: @sym_table *t@ = pointer to symbol table in question | |
6f444bda | 95 | * @const char *n@ = pointer to symbol name to look up |
0875b58f | 96 | * @long l@ = length of the name string or negative to measure |
97 | * @size_t sz@ = size of desired symbol object, or zero | |
98 | * @unsigned *f@ = pointer to a flag, or null. | |
99 | * | |
100 | * Returns: The address of a @sym_base@ structure, or null if not found | |
101 | * and @sz@ is zero. | |
102 | * | |
103 | * Use: Looks up a symbol in a given symbol table. The name is | |
104 | * passed by the address of its first character. The length | |
105 | * may be given, in which case the name may contain arbitrary | |
106 | * binary data, or it may be given as a negative number, in | |
107 | * which case the length of the name is calculated as | |
03d53b73 | 108 | * @strlen(n) + 1@. |
0875b58f | 109 | * |
110 | * The return value is the address of a pointer to a @sym_base@ | |
111 | * block (which may have other things on the end, as above). If | |
112 | * the symbol could be found, the return value points to the | |
113 | * symbol block. If the symbol wasn't there, then if @sz@ is | |
114 | * nonzero, a new symbol is created and its address is returned; | |
115 | * otherwise a null pointer is returned. The exception | |
116 | * @EXC_NOMEM@ is raised if the block can't be allocated. | |
117 | * | |
118 | * The value of @*f@ indicates whether a new symbol entry was | |
119 | * created: a nonzero value indicates that an old value was | |
120 | * found. | |
121 | */ | |
122 | ||
123 | void *sym_find(sym_table *t, const char *n, long l, size_t sz, unsigned *f) | |
124 | { | |
d4d7a053 | 125 | uint32 hash; |
126 | size_t len = 0; | |
03d53b73 | 127 | hash_base **bin, **p; |
128 | sym_base *q; | |
0875b58f | 129 | |
130 | /* --- Find the correct bin --- */ | |
131 | ||
ec6770dd | 132 | len = l < 0 ? strlen(n) : l; |
6f444bda | 133 | hash = UNIHASH(&unihash_global, n, len); |
03d53b73 | 134 | bin = HASH_BIN(&t->t, hash); |
0875b58f | 135 | |
136 | /* --- Search the bin list --- */ | |
137 | ||
03d53b73 | 138 | for (p = bin; *p; p = &(*p)->next) { |
139 | q = (sym_base *)*p; | |
36188114 MW |
140 | if (hash == q->b.hash && len == q->len && |
141 | MEMCMP(n, ==, SYM_NAME(q), len)) { | |
03d53b73 | 142 | |
0875b58f | 143 | /* --- Found a match --- * |
144 | * | |
145 | * As a minor, and probably pointless, tweak, move the item to the | |
146 | * front of its bin list. | |
147 | */ | |
148 | ||
03d53b73 | 149 | (*p) = q->b.next; |
150 | q->b.next = *bin; | |
151 | *bin = &q->b; | |
0875b58f | 152 | |
153 | /* --- Return the block --- */ | |
154 | ||
d4d7a053 | 155 | if (f) *f = 1; |
156 | return (q); | |
0875b58f | 157 | } |
0875b58f | 158 | } |
159 | ||
160 | /* --- Couldn't find the item there --- */ | |
161 | ||
d4d7a053 | 162 | if (f) *f = 0; |
163 | if (!sz) return (0); | |
0875b58f | 164 | |
2ae5376b | 165 | /* --- Create a new symbol block and initialize it --- * |
166 | * | |
167 | * The name is attached to the end of the symbol block. | |
168 | */ | |
0875b58f | 169 | |
ec6770dd | 170 | q = x_alloc(t->t.a, sz + len + 1); |
20eb516f | 171 | q->b.next = *bin; |
172 | q->b.hash = hash; | |
2ae5376b | 173 | q->name = (char *)q + sz; |
174 | memcpy(q->name, n, len); | |
ec6770dd | 175 | q->name[len] = 0; |
20eb516f | 176 | q->len = len; |
03d53b73 | 177 | *bin = &q->b; |
0875b58f | 178 | |
179 | /* --- Consider growing the array --- */ | |
180 | ||
03d53b73 | 181 | if (t->load) |
182 | t->load--; | |
183 | if (!t->load && hash_extend(&t->t)) | |
2ae5376b | 184 | t->load = SYM_LIMIT(t->t.mask + 1); |
0875b58f | 185 | |
186 | /* --- Finished that, so return the new symbol block --- */ | |
187 | ||
03d53b73 | 188 | return (q); |
0875b58f | 189 | } |
190 | ||
191 | /* --- @sym_remove@ --- * | |
192 | * | |
c6e0eaf0 | 193 | * Arguments: @sym_table *t@ = pointer to a symbol table object |
03d53b73 | 194 | * @void *p@ = pointer to symbol table entry |
0875b58f | 195 | * |
196 | * Returns: --- | |
197 | * | |
198 | * Use: Removes the object from the symbol table. The space occupied | |
199 | * by the object and its name is freed; anything else attached | |
200 | * to the entry should already be gone by this point. | |
201 | */ | |
202 | ||
03d53b73 | 203 | void sym_remove(sym_table *t, void *p) |
0875b58f | 204 | { |
03d53b73 | 205 | sym_base *q = p; |
206 | hash_remove(&t->t, &q->b); | |
20eb516f | 207 | xfree(q); |
03d53b73 | 208 | t->load++; |
0875b58f | 209 | } |
210 | ||
34b97201 | 211 | /* --- @sym_mkiter@ --- * |
0875b58f | 212 | * |
213 | * Arguments: @sym_iter *i@ = pointer to an iterator object | |
214 | * @sym_table *t@ = pointer to a symbol table object | |
215 | * | |
216 | * Returns: --- | |
217 | * | |
218 | * Use: Creates a new symbol table iterator which may be used to | |
219 | * iterate through a symbol table. | |
220 | */ | |
221 | ||
03d53b73 | 222 | void sym_mkiter(sym_iter *i, sym_table *t) { SYM_MKITER(i, t); } |
0875b58f | 223 | |
224 | /* --- @sym_next@ --- * | |
225 | * | |
226 | * Arguments: @sym_iter *i@ = pointer to iterator object | |
227 | * | |
228 | * Returns: Pointer to the next symbol found, or null when finished. | |
229 | * | |
230 | * Use: Returns the next symbol from the table. Symbols are not | |
231 | * returned in any particular order. | |
232 | */ | |
233 | ||
234 | void *sym_next(sym_iter *i) | |
235 | { | |
03d53b73 | 236 | void *p; |
237 | SYM_NEXT(i, p); | |
0875b58f | 238 | return (p); |
239 | } | |
240 | ||
0875b58f | 241 | /*----- That's all, folks -------------------------------------------------*/ |