* m4/symtab.c (m4_symbol_rename): New function that performs a low
[m4/ericb.git] / m4 / symtab.c
blobc6a71e2202f0f9f4fb10c4e866b7bc02da2f9a87
1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2001, 2005
3 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301 USA
21 #include "m4private.h"
23 #define DEBUG_SYM /* Define this to see runtime debug info. */
24 #undef DEBUG_SYM
26 /* This file handles all the low level work around the symbol table. The
27 symbol table is an abstract hash table type implemented in hash.c. Each
28 symbol is represented by `struct m4_symbol', which is stored in the hash
29 table keyed by the symbol name. As a special case, to facilitate the
30 "pushdef" and "popdef" builtins, the value stored against each key is a
31 stack of `m4_symbol_value'. All the value entries for a symbol name are
32 simply ordered on the stack by age. The most recently pushed definition
33 will then always be the first found.
35 Also worthy of mention is the way traced symbols are managed: the trace
36 bit is associated with a particular symbol name. If a symbol is
37 undefined and then redefined, it does not lose its trace bit (in GNU
38 mode). This is achieved by not removing traced symbol names from the
39 symbol table, even if their value stack is empty. That way, when the
40 name is given a new value, it is pushed onto the empty stack, and the
41 trace bit attached to the name was never lost. There is a small amount
42 of fluff in these functions to make sure that such symbols (with empty
43 value stacks) are invisible to the users of this module. */
45 #define M4_SYMTAB_DEFAULT_SIZE 2047
47 struct m4_symbol_table {
48 m4_hash *table;
49 bool *nuke_trace_bit; /* default: &(context->no_gnu_ext_opt) */
52 static m4_symbol *symtab_fetch (m4_symbol_table*, const char *);
53 static void symbol_popval (m4_symbol *symbol);
54 static void * symbol_destroy_CB (m4_symbol_table *symtab, const char *name,
55 m4_symbol *symbol, void *ignored);
56 static void * arg_destroy_CB (m4_hash *hash, const void *name,
57 void *arg, void *ignored);
58 static void * arg_copy_CB (m4_hash *src, const void *name,
59 void *arg, m4_hash *dest);
63 /* -- SYMBOL TABLE MANAGEMENT --
65 These functions are used to manage a symbol table as a whole. */
67 m4_symbol_table *
68 m4_symtab_create (size_t size, bool *nuke_trace_bit)
70 m4_symbol_table *symtab = xmalloc (sizeof *symtab);
72 symtab->table = m4_hash_new (size ? size : M4_SYMTAB_DEFAULT_SIZE,
73 m4_hash_string_hash, m4_hash_string_cmp);
74 symtab->nuke_trace_bit = nuke_trace_bit;
75 return symtab;
78 void
79 m4_symtab_delete (m4_symbol_table *symtab)
81 assert (symtab);
82 assert (symtab->table);
84 m4_symtab_apply (symtab, symbol_destroy_CB, NULL);
85 m4_hash_delete (symtab->table);
86 free (symtab);
89 void *
90 m4_symtab_apply (m4_symbol_table *symtab,
91 m4_symtab_apply_func *func, void *userdata)
93 m4_hash_iterator *place = NULL;
94 void * result = NULL;
96 assert (symtab);
97 assert (symtab->table);
98 assert (func);
100 while ((place = m4_get_hash_iterator_next (symtab->table, place)))
102 result = (*func) (symtab,
103 (const char *) m4_get_hash_iterator_key (place),
104 (m4_symbol *) m4_get_hash_iterator_value (place),
105 userdata);
107 if (result != NULL)
108 break;
111 return result;
114 static m4_symbol *
115 symtab_fetch (m4_symbol_table *symtab, const char *name)
117 m4_symbol **psymbol;
118 m4_symbol *symbol;
120 assert (symtab);
121 assert (name);
123 psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
124 if (psymbol)
126 symbol = *psymbol;
128 else
130 symbol = xzalloc (sizeof *symbol);
131 m4_hash_insert (symtab->table, xstrdup (name), symbol);
134 return symbol;
137 /* Remove every symbol that references the given module handle from
138 the symbol table. */
139 void
140 m4__symtab_remove_module_references (m4_symbol_table *symtab, lt_dlhandle handle)
142 m4_hash_iterator *place = 0;
144 assert (handle);
146 /* Traverse each symbol name in the hash table. */
147 while ((place = m4_get_hash_iterator_next (symtab->table, place)))
149 m4_symbol *symbol = (m4_symbol *) m4_get_hash_iterator_value (place);
150 m4_symbol_value *data = m4_get_symbol_value (symbol);
152 /* For symbols that have token data... */
153 if (data)
155 /* Purge any shadowed references. */
156 while (VALUE_NEXT (data))
158 m4_symbol_value *next = VALUE_NEXT (data);
160 if (VALUE_HANDLE (next) == handle)
162 VALUE_NEXT (data) = VALUE_NEXT (next);
164 if (next->type == M4_SYMBOL_TEXT)
165 free (m4_get_symbol_value_text (next));
166 free (next);
168 else
169 data = next;
172 /* Purge the live reference if necessary. */
173 if (SYMBOL_HANDLE (symbol) == handle)
174 m4_symbol_popdef (symtab, m4_get_hash_iterator_key (place));
180 /* This callback is used exclusively by m4_symtab_delete(), to cleanup
181 the memory used by the symbol table. As such, the trace bit is reset
182 on every symbol so that m4_symbol_popdef() doesn't try to preserve
183 the table entry. */
184 static void *
185 symbol_destroy_CB (m4_symbol_table *symtab, const char *name, m4_symbol *symbol,
186 void *ignored)
188 char *key = xstrdup ((char *) name);
190 m4_set_symbol_traced (symbol, false);
192 while (key && m4_hash_lookup (symtab->table, key))
193 m4_symbol_popdef (symtab, key);
195 free (key);
197 return NULL;
202 /* -- SYMBOL MANAGEMENT --
204 The following functions manipulate individual symbols within
205 an existing table. */
207 /* Return the symbol associated to NAME, or else NULL. */
208 m4_symbol *
209 m4_symbol_lookup (m4_symbol_table *symtab, const char *name)
211 m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
213 /* If just searching, return status of search -- if only an empty
214 struct is returned, that is treated as a failed lookup. */
215 return (psymbol && m4_get_symbol_value (*psymbol)) ? *psymbol : 0;
219 /* Insert NAME into the symbol table. If there is already a symbol
220 associated with NAME, push the new VALUE on top of the value stack
221 for this symbol. Otherwise create a new association. */
222 m4_symbol *
223 m4_symbol_pushdef (m4_symbol_table *symtab, const char *name, m4_symbol_value *value)
225 m4_symbol *symbol;
227 assert (symtab);
228 assert (name);
229 assert (value);
231 symbol = symtab_fetch (symtab, name);
232 VALUE_NEXT (value) = m4_get_symbol_value (symbol);
233 symbol->value = value;
235 assert (m4_get_symbol_value (symbol));
237 return symbol;
240 /* Return the symbol associated with NAME in the symbol table, creating
241 a new symbol if necessary. In either case set the symbol's VALUE. */
242 m4_symbol *
243 m4_symbol_define (m4_symbol_table *symtab,
244 const char *name, m4_symbol_value *value)
246 m4_symbol *symbol;
248 assert (symtab);
249 assert (name);
250 assert (value);
252 symbol = symtab_fetch (symtab, name);
253 if (m4_get_symbol_value (symbol))
254 symbol_popval (symbol);
256 VALUE_NEXT (value) = m4_get_symbol_value (symbol);
257 symbol->value = value;
259 assert (m4_get_symbol_value (symbol));
261 return symbol;
264 /* Pop the topmost value stack entry from the symbol associated with
265 NAME, deleting it from the table entirely if that was the last
266 remaining value in the stack. */
267 void
268 m4_symbol_popdef (m4_symbol_table *symtab, const char *name)
270 m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
272 assert (psymbol);
273 assert (*psymbol);
274 assert (symtab->nuke_trace_bit);
276 symbol_popval (*psymbol);
278 /* Only remove the hash table entry if the last value in the
279 symbol value stack was successfully removed. */
280 if (!m4_get_symbol_value (*psymbol))
281 if (*symtab->nuke_trace_bit || !m4_get_symbol_traced (*psymbol))
283 DELETE (*psymbol);
284 free (m4_hash_remove (symtab->table, name));
288 static void
289 symbol_popval (m4_symbol *symbol)
291 m4_symbol_value *stale;
293 assert (symbol);
295 stale = m4_get_symbol_value (symbol);
297 if (stale)
299 symbol->value = VALUE_NEXT (stale);
301 if (VALUE_ARG_SIGNATURE (stale))
303 m4_hash_apply (VALUE_ARG_SIGNATURE (stale), arg_destroy_CB, NULL);
304 m4_hash_delete (VALUE_ARG_SIGNATURE (stale));
306 if (m4_is_symbol_value_text (stale))
307 free (m4_get_symbol_value_text (stale));
308 free (stale);
312 m4_symbol *
313 m4_symbol_rename (m4_symbol_table *symtab, const char *name, const char *rename)
315 m4_symbol *symbol = NULL;
316 m4_symbol **psymbol;
318 assert (symtab);
319 assert (name);
320 assert (rename);
322 /* Use a low level hash fetch, so we can save the symbol value when
323 removing the symbol name from the symbol table. */
324 psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
326 if (psymbol)
328 symbol = *psymbol;
330 /* Remove the old name from the symbol table. */
331 free (m4_hash_remove (symtab->table, name));
332 assert (!m4_hash_lookup (symtab->table, name));
334 m4_hash_insert (symtab->table, xstrdup (rename), *psymbol);
336 /* else
337 NAME does not name a symbol in symtab->table! */
339 return symbol;
343 /* Callback used by m4_symbol_popdef () to release the memory used
344 by values in the arg_signature hash. */
345 static void *
346 arg_destroy_CB (m4_hash *hash, const void *name, void *arg, void *ignored)
348 struct m4_symbol_arg *token_arg = (struct m4_symbol_arg *) arg;
350 assert (name);
351 assert (hash);
353 if (SYMBOL_ARG_DEFAULT (token_arg))
354 DELETE (SYMBOL_ARG_DEFAULT (token_arg));
355 free (token_arg);
356 free (m4_hash_remove (hash, (const char *) name));
358 return NULL;
361 void
362 m4_symbol_value_copy (m4_symbol_value *dest, m4_symbol_value *src)
364 m4_symbol_value *next;
366 assert (dest);
367 assert (src);
369 if (m4_is_symbol_value_text (dest))
370 free (m4_get_symbol_value_text (dest));
372 if (VALUE_ARG_SIGNATURE (dest))
374 m4_hash_apply (VALUE_ARG_SIGNATURE (dest), arg_destroy_CB, NULL);
375 m4_hash_delete (VALUE_ARG_SIGNATURE (dest));
378 /* Copy the valuecontents over, being careful to preserve
379 the next pointer. */
380 next = VALUE_NEXT (dest);
381 bcopy (src, dest, sizeof (m4_symbol_value));
382 VALUE_NEXT (dest) = next;
384 /* Caller is supposed to free text token strings, so we have to
385 copy the string not just its address in that case. */
386 if (m4_is_symbol_value_text (src))
387 m4_set_symbol_value_text (dest, xstrdup (m4_get_symbol_value_text (src)));
389 if (VALUE_ARG_SIGNATURE (src))
390 VALUE_ARG_SIGNATURE (dest) = m4_hash_dup (VALUE_ARG_SIGNATURE (src),
391 arg_copy_CB);
394 static void *
395 arg_copy_CB (m4_hash *src, const void *name, void *arg, m4_hash *dest)
397 m4_hash_insert ((m4_hash *) dest, name, arg);
398 return NULL;
401 bool
402 m4_set_symbol_name_traced (m4_symbol_table *symtab, const char *name)
404 m4_symbol *symbol;
406 assert (symtab);
407 assert (name);
409 symbol = symtab_fetch (symtab, name);
411 return m4_set_symbol_traced (symbol, true);
415 /* Define these functions at the end, so that calls in the file use the
416 faster macro version from m4module.h. */
418 /* Pop all values from the symbol associated with NAME. */
419 #undef m4_symbol_delete
420 void
421 m4_symbol_delete (m4_symbol_table *symtab, const char *name)
423 while (m4_symbol_lookup (symtab, name))
424 m4_symbol_popdef (symtab, name);
427 #undef m4_get_symbol_traced
428 bool
429 m4_get_symbol_traced (m4_symbol *symbol)
431 assert (symbol);
432 return symbol->traced;
435 #undef m4_set_symbol_traced
436 bool
437 m4_set_symbol_traced (m4_symbol *symbol, bool value)
439 assert (symbol);
440 return symbol->traced = value;
443 #undef m4_symbol_value_create
444 m4_symbol_value *
445 m4_symbol_value_create (void)
447 return xzalloc (sizeof (m4_symbol_value));
450 #undef m4_get_symbol_value
451 m4_symbol_value *
452 m4_get_symbol_value (m4_symbol *symbol)
454 assert (symbol);
455 return symbol->value;
458 #undef m4_is_symbol_value_text
459 bool
460 m4_is_symbol_value_text (m4_symbol_value *value)
462 assert (value);
463 return (value->type == M4_SYMBOL_TEXT);
466 #undef m4_is_symbol_value_func
467 bool
468 m4_is_symbol_value_func (m4_symbol_value *value)
470 assert (value);
471 return (value->type == M4_SYMBOL_FUNC);
474 #undef m4_is_symbol_value_void
475 bool
476 m4_is_symbol_value_void (m4_symbol_value *value)
478 assert (value);
479 return (value->type == M4_SYMBOL_VOID);
482 #undef m4_get_symbol_value_text
483 char *
484 m4_get_symbol_value_text (m4_symbol_value *value)
486 assert (value);
487 return value->u.text;
490 #undef m4_get_symbol_value_func
491 m4_builtin_func *
492 m4_get_symbol_value_func (m4_symbol_value *value)
494 assert (value);
495 return value->u.func;
498 #undef m4_set_symbol_value_text
499 void
500 m4_set_symbol_value_text (m4_symbol_value *value, char *text)
502 assert (value);
503 assert (text);
505 value->type = M4_SYMBOL_TEXT;
506 value->u.text = text;
509 #undef m4_set_symbol_value_func
510 void
511 m4_set_symbol_value_func (m4_symbol_value *value, m4_builtin_func *func)
513 assert (value);
514 assert (func);
516 value->type = M4_SYMBOL_FUNC;
517 value->u.func = func;
522 #ifdef DEBUG_SYM
524 static void *symtab_dump (m4_symbol_table *symtab);
525 static void dump_symbol_CB (m4_symbol_table *symtab, const char *name,
526 m4_symbol *symbol, void *userdata);
527 static void *
528 symtab_dump (m4_symbol_table *symtab)
530 return symtab_apply (symtab, dump_symbol_CB, NULL);
533 static void *dump_symbol_CB (m4_symbol_table *symtab, const char *name,
534 m4_symbol *symbol, void *ignored)
536 m4_symbol_value *value = m4_get_symbol_value (symbol);
537 int flags = value ? SYMBOL_FLAGS (symbol) : 0;
538 lt_dlhandle handle = value ? SYMBOL_HANDLE (symbol) : 0;
539 const char * module_name = handle ? m4_get_module_name (handle) : "NONE";
540 const m4_builtin *bp;
542 fprintf (stderr, "%10s: (%d%s) %s=",
543 handle ? m4_get_module_name (handle) : "NONE",
544 value ? VALUE_FLAGS (value) : 0,
545 m4_get_symbol_traced (symbol) ? "!" : "", name);
547 if (!value)
548 fputs ("<!UNDEFINED!>", stderr);
549 else
550 switch (value->type)
552 case M4_SYMBOL_TEXT:
553 fputs (m4_get_symbol_text (symbol), stderr);
554 break;
556 case M4_SYMBOL_FUNC:
557 bp = m4_builtin_find_by_func (handle, m4_get_symbol_func (symbol));
558 fprintf (stderr, "<%s>",
559 bp ? bp->name : "!ERROR!");
560 break;
561 case M4_SYMBOL_VOID:
562 fputs ("<!VOID!>", stderr);
563 break;
565 fputc ('\n', stderr);
567 #endif /* DEBUG_SYM */