35 |
static size_t m4_symtab_hash (const void *key); |
static size_t m4_symtab_hash (const void *key); |
36 |
static int m4_symtab_cmp (const void *key, const void *try); |
static int m4_symtab_cmp (const void *key, const void *try); |
37 |
static void m4_token_data_delete (m4_token_data *data); |
static void m4_token_data_delete (m4_token_data *data); |
38 |
static void m4_symbol_popdef (m4_symbol *symbol); |
static void m4_symbol_pop (m4_symbol *symbol); |
39 |
static void m4_symbol_delete (m4_symbol *symbol); |
static void m4_symbol_del (m4_symbol *symbol); |
40 |
|
|
41 |
|
|
42 |
/* Pointer to symbol table. */ |
/* Pointer to symbol table. */ |
89 |
} |
} |
90 |
|
|
91 |
void |
void |
92 |
m4_symbol_popdef (m4_symbol *symbol) |
m4_symbol_pop (m4_symbol *symbol) |
93 |
{ |
{ |
94 |
m4_token_data *stale; |
m4_token_data *stale; |
95 |
|
|
96 |
assert (symbol); |
assert (symbol); |
97 |
assert (M4_SYMBOL_DATA_NEXT (symbol)); |
assert (M4_SYMBOL_DATA_NEXT (symbol)); |
98 |
|
|
99 |
stale = M4_SYMBOL_DATA (symbol); |
stale = M4_SYMBOL_DATA (symbol); |
100 |
M4_SYMBOL_DATA (symbol) = M4_TOKEN_DATA_NEXT (stale); |
M4_SYMBOL_DATA (symbol) = M4_TOKEN_DATA_NEXT (stale); |
101 |
|
|
102 |
#ifndef NDEBUG |
#ifndef NDEBUG |
107 |
|
|
108 |
/* Free all storage associated with a symbol. */ |
/* Free all storage associated with a symbol. */ |
109 |
void |
void |
110 |
m4_symbol_delete (m4_symbol *symbol) |
m4_symbol_del (m4_symbol *symbol) |
111 |
{ |
{ |
112 |
assert (symbol); |
assert (symbol); |
113 |
|
|
114 |
while (M4_SYMBOL_DATA_NEXT (symbol)) |
while (M4_SYMBOL_DATA_NEXT (symbol)) |
115 |
m4_symbol_popdef (symbol); |
m4_symbol_pop (symbol); |
116 |
|
|
117 |
assert (M4_SYMBOL_DATA_NEXT (symbol) == 0); |
assert (M4_SYMBOL_DATA_NEXT (symbol) == 0); |
118 |
|
|
123 |
XFREE (symbol); |
XFREE (symbol); |
124 |
} |
} |
125 |
|
|
126 |
/* Search in, and manipulation of the symbol table, are all done by |
|
127 |
m4_lookup_symbol (). It basically hashes NAME to a list in the symbol |
/* Dispatch on all the following 5 functions. |
128 |
table, and searched this list for the first occurence of a symbol with |
|
129 |
the name. |
Search in, and manipulation of the symbol table, are all done by |
130 |
|
m4_lookup_symbol (). It basically hashes NAME to a list in the |
131 |
The MODE parameter determines what m4_lookup_symbol () will do. It can |
symbol table, and searched this list for the first occurence of a |
132 |
either just do a lookup, do a lookup and insert if not present, do an |
symbol with the name. |
133 |
insertion even if the name is already in the list, delete the first |
|
134 |
occurrence of the name on the list or delete all occurences of the name |
The MODE parameter determines what m4_lookup_symbol () will do. It |
135 |
on the list. */ |
can either just do a lookup, do a lookup and insert if not present, |
136 |
|
do an insertion even if the name is already in the list, delete the |
137 |
|
first occurrence of the name on the list or delete all occurences |
138 |
|
of the name on the list. */ |
139 |
m4_symbol * |
m4_symbol * |
140 |
m4_lookup_symbol (const char *name, m4_symbol_lookup_t mode) |
m4_lookup_symbol (const char *name, m4_symbol_lookup_t mode) |
141 |
{ |
{ |
|
m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name); |
|
|
|
|
142 |
switch (mode) |
switch (mode) |
143 |
{ |
{ |
144 |
case M4_SYMBOL_LOOKUP: |
case M4_SYMBOL_LOOKUP: |
145 |
/* If just searching, return status of search. */ |
return m4_symbol_lookup (name); |
|
return psymbol ? *psymbol : 0; |
|
146 |
|
|
147 |
case M4_SYMBOL_INSERT: |
case M4_SYMBOL_INSERT: |
148 |
/* Return the symbol, if the name was found in the table. |
return m4_symbol_insert (name); |
|
Otherwise, just insert the name, and return the new symbol. */ |
|
|
if (psymbol) |
|
|
return *psymbol; |
|
|
/* NOBREAK */ |
|
149 |
|
|
150 |
case M4_SYMBOL_PUSHDEF: |
case M4_SYMBOL_PUSHDEF: |
151 |
/* Insert a name in the symbol table. If there is already a symbol |
return m4_symbol_pushdef (name); |
|
with the name, push the new value on top of the value stack for |
|
|
this symbol. */ |
|
|
{ |
|
|
m4_symbol *symbol = 0; |
|
|
m4_token_data *value = XCALLOC (m4_token_data, 1); |
|
|
|
|
|
if (psymbol) |
|
|
{ |
|
|
symbol = *psymbol; |
|
|
M4_TOKEN_DATA_NEXT (value)= M4_SYMBOL_DATA (symbol); |
|
|
} |
|
|
else |
|
|
symbol = XCALLOC (m4_symbol, 1); |
|
|
|
|
|
M4_SYMBOL_DATA (symbol) = value; |
|
|
M4_SYMBOL_TYPE (symbol) = M4_TOKEN_VOID; |
|
|
|
|
|
if (!psymbol) |
|
|
m4_hash_insert (m4_symtab, xstrdup (name), symbol); |
|
|
|
|
|
return symbol; |
|
|
} |
|
152 |
|
|
153 |
case M4_SYMBOL_POPDEF: |
case M4_SYMBOL_POPDEF: |
154 |
/* Delete the first occurence of a symbol with NAME. */ |
m4_symbol_popdef (name); |
|
if (psymbol) |
|
|
{ |
|
|
if (M4_SYMBOL_DATA_NEXT (*psymbol)) |
|
|
m4_symbol_popdef (*psymbol); |
|
|
else |
|
|
{ |
|
|
xfree (m4_hash_remove (m4_symtab, name)); |
|
|
m4_symbol_delete (*psymbol); |
|
|
} |
|
|
} |
|
155 |
return 0; |
return 0; |
156 |
|
|
157 |
case M4_SYMBOL_DELETE: |
case M4_SYMBOL_DELETE: |
158 |
/* Delete all occurences of symbols with NAME. */ |
m4_symbol_delete (name); |
|
if (psymbol) |
|
|
{ |
|
|
xfree (m4_hash_remove (m4_symtab, name)); |
|
|
m4_symbol_delete (*psymbol); |
|
|
} |
|
|
else |
|
|
M4ERROR ((warning_status, 0, |
|
|
_("INTERNAL ERROR: Attempt to delete non-existant symbol: %s"), |
|
|
name)); |
|
159 |
return 0; |
return 0; |
160 |
} |
} |
161 |
|
|
162 |
M4ERROR ((warning_status, 0, |
M4ERROR ((warning_status, 0, |
163 |
_("INTERNAL ERROR: Illegal mode to m4_symbol_lookup_t (%s, %d)"), |
_("INTERNAL ERROR: Illegal mode to m4_symbol_lookup (%s, %d)"), |
164 |
name, mode)); |
name, mode)); |
165 |
abort (); |
abort (); |
166 |
/*NOTREACHED*/ |
/*NOTREACHED*/ |
167 |
return 0; |
return 0; |
168 |
} |
} |
169 |
|
|
170 |
/* The following function removes from the symbol table, every symbol |
|
171 |
that references the given module handle. */ |
/* Return the symbol associated to NAME, or else NULL. */ |
172 |
|
m4_symbol * |
173 |
|
m4_symbol_lookup (const char *name) |
174 |
|
{ |
175 |
|
m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name); |
176 |
|
|
177 |
|
/* If just searching, return status of search. */ |
178 |
|
return psymbol ? *psymbol : 0; |
179 |
|
} |
180 |
|
|
181 |
|
|
182 |
|
/* Push a new slot associted to NAME, and return it. */ |
183 |
|
m4_symbol * |
184 |
|
m4_symbol_pushdef (const char *name) |
185 |
|
{ |
186 |
|
m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name); |
187 |
|
|
188 |
|
/* Insert a name in the symbol table. If there is already a symbol |
189 |
|
with the name, push the new value on top of the value stack for |
190 |
|
this symbol. */ |
191 |
|
m4_symbol *symbol = 0; |
192 |
|
m4_token_data *value = XCALLOC (m4_token_data, 1); |
193 |
|
|
194 |
|
if (psymbol) |
195 |
|
{ |
196 |
|
symbol = *psymbol; |
197 |
|
M4_TOKEN_DATA_NEXT (value) = M4_SYMBOL_DATA (symbol); |
198 |
|
} |
199 |
|
else |
200 |
|
symbol = XCALLOC (m4_symbol, 1); |
201 |
|
|
202 |
|
M4_SYMBOL_DATA (symbol) = value; |
203 |
|
M4_SYMBOL_TYPE (symbol) = M4_TOKEN_VOID; |
204 |
|
|
205 |
|
if (!psymbol) |
206 |
|
m4_hash_insert (m4_symtab, xstrdup (name), symbol); |
207 |
|
|
208 |
|
return symbol; |
209 |
|
} |
210 |
|
|
211 |
|
|
212 |
|
/* Return a slot associated to NAME, creating it if needed. */ |
213 |
|
m4_symbol * |
214 |
|
m4_symbol_insert (const char *name) |
215 |
|
{ |
216 |
|
return (m4_symbol *) (m4_symbol_lookup (name) || m4_symbol_pushdef (name)); |
217 |
|
} |
218 |
|
|
219 |
|
|
220 |
|
/* Remove the topmost definition associated to NAME. */ |
221 |
|
void |
222 |
|
m4_symbol_popdef (const char *name) |
223 |
|
{ |
224 |
|
m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name); |
225 |
|
|
226 |
|
if (!psymbol) |
227 |
|
M4ERROR ((warning_status, 0, |
228 |
|
"INTERNAL ERROR: m4_symbol_popdef (%s)", name)); |
229 |
|
|
230 |
|
if (M4_SYMBOL_DATA_NEXT (*psymbol)) |
231 |
|
m4_symbol_pop (*psymbol); |
232 |
|
else |
233 |
|
{ |
234 |
|
xfree (m4_hash_remove (m4_symtab, name)); |
235 |
|
m4_symbol_del (*psymbol); |
236 |
|
} |
237 |
|
} |
238 |
|
|
239 |
|
|
240 |
|
/* Remove all the definitions associated with NAME. */ |
241 |
|
void |
242 |
|
m4_symbol_delete (const char *name) |
243 |
|
{ |
244 |
|
m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (m4_symtab, name); |
245 |
|
|
246 |
|
if (!psymbol) |
247 |
|
M4ERROR ((warning_status, 0, |
248 |
|
"INTERNAL ERROR: m4_symbol_delete (%s)", name)); |
249 |
|
|
250 |
|
if (psymbol) |
251 |
|
{ |
252 |
|
xfree (m4_hash_remove (m4_symtab, name)); |
253 |
|
m4_symbol_del (*psymbol); |
254 |
|
} |
255 |
|
} |
256 |
|
|
257 |
|
|
258 |
|
/* Remove every symbol that references the given module handle from |
259 |
|
the symbol table. */ |
260 |
void |
void |
261 |
m4_remove_table_reference_symbols (lt_dlhandle handle) |
m4_remove_table_reference_symbols (lt_dlhandle handle) |
262 |
{ |
{ |
287 |
if (M4_SYMBOL_HANDLE (symbol) == handle) |
if (M4_SYMBOL_HANDLE (symbol) == handle) |
288 |
{ |
{ |
289 |
if (M4_SYMBOL_DATA_NEXT (symbol)) |
if (M4_SYMBOL_DATA_NEXT (symbol)) |
290 |
m4_symbol_popdef (symbol); |
m4_symbol_pop (symbol); |
291 |
else |
else |
292 |
{ |
{ |
293 |
xfree (m4_hash_remove (m4_symtab, m4_hash_iterator_key (place))); |
xfree (m4_hash_remove (m4_symtab, m4_hash_iterator_key (place))); |
294 |
m4_symbol_delete (symbol); |
m4_symbol_del (symbol); |
295 |
} |
} |
296 |
} |
} |
297 |
} |
} |