Fix regression in command line -D option, from 2006-08-25.
[m4.git] / m4 / symtab.c
blobf302fe8b8db2ca0aaabc5bbdebf91bf80af045ad
1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2001, 2005, 2006,
3 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU M4.
7 GNU M4 is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU M4 is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 #include "m4private.h"
25 /* Define this to see runtime debug info. Implied by DEBUG. */
26 /*#define DEBUG_SYM */
28 /* This file handles all the low level work around the symbol table. The
29 symbol table is an abstract hash table type implemented in hash.c. Each
30 symbol is represented by `struct m4_symbol', which is stored in the hash
31 table keyed by the symbol name. As a special case, to facilitate the
32 "pushdef" and "popdef" builtins, the value stored against each key is a
33 stack of `m4_symbol_value'. All the value entries for a symbol name are
34 simply ordered on the stack by age. The most recently pushed definition
35 will then always be the first found.
37 Also worthy of mention is the way traced symbols are managed: the
38 trace bit is associated with a particular symbol name. If a symbol
39 is undefined and then redefined, it does not lose its trace bit.
40 This is achieved by not removing traced symbol names from the
41 symbol table, even if their value stack is empty. That way, when
42 the name is given a new value, it is pushed onto the empty stack,
43 and the trace bit attached to the name was never lost. There is a
44 small amount of fluff in these functions to make sure that such
45 symbols (with empty value stacks) are invisible to the users of
46 this module. */
48 #define M4_SYMTAB_DEFAULT_SIZE 2047
50 struct m4_symbol_table {
51 m4_hash *table;
54 static m4_symbol *symtab_fetch (m4_symbol_table*, const char *);
55 static void symbol_popval (m4_symbol *symbol);
56 static void * symbol_destroy_CB (m4_symbol_table *symtab,
57 const char *name,
58 m4_symbol *symbol, void *ignored);
59 static void * arg_destroy_CB (m4_hash *hash, const void *name,
60 void *arg, void *ignored);
61 static void * arg_copy_CB (m4_hash *src, const void *name,
62 void *arg, m4_hash *dest);
65 /* -- SYMBOL TABLE MANAGEMENT --
67 These functions are used to manage a symbol table as a whole. */
69 m4_symbol_table *
70 m4_symtab_create (size_t size)
72 m4_symbol_table *symtab = xmalloc (sizeof *symtab);
74 symtab->table = m4_hash_new (size ? size : M4_SYMTAB_DEFAULT_SIZE,
75 m4_hash_string_hash, m4_hash_string_cmp);
76 return symtab;
79 void
80 m4_symtab_delete (m4_symbol_table *symtab)
82 assert (symtab);
83 assert (symtab->table);
85 m4_symtab_apply (symtab, true, symbol_destroy_CB, NULL);
86 m4_hash_delete (symtab->table);
87 free (symtab);
90 /* For every symbol in SYMTAB, execute the callback FUNC with the name
91 and value of the symbol being visited, and the opaque parameter
92 USERDATA. Skip undefined symbols that are placeholders for
93 traceon, unless INCLUDE_TRACE is true. If FUNC returns non-NULL,
94 abort the iteration and return the same result; otherwise return
95 NULL when iteration completes. */
96 void *
97 m4_symtab_apply (m4_symbol_table *symtab, bool include_trace,
98 m4_symtab_apply_func *func, void *userdata)
100 m4_hash_iterator *place = NULL;
101 void * result = NULL;
103 assert (symtab);
104 assert (symtab->table);
105 assert (func);
107 while ((place = m4_get_hash_iterator_next (symtab->table, place)))
109 m4_symbol *symbol = m4_get_hash_iterator_value (place);
110 if (symbol->value || include_trace)
111 result = func (symtab, (const char *) m4_get_hash_iterator_key (place),
112 symbol, userdata);
114 if (result != NULL)
116 m4_free_hash_iterator (symtab->table, place);
117 break;
121 return result;
124 /* Ensure that NAME exists in the table, creating an entry if needed. */
125 static m4_symbol *
126 symtab_fetch (m4_symbol_table *symtab, const char *name)
128 m4_symbol **psymbol;
129 m4_symbol *symbol;
131 assert (symtab);
132 assert (name);
134 psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
135 if (psymbol)
137 symbol = *psymbol;
139 else
141 symbol = xzalloc (sizeof *symbol);
142 m4_hash_insert (symtab->table, xstrdup (name), symbol);
145 return symbol;
148 /* Remove every symbol that references the given module from
149 the symbol table. */
150 void
151 m4__symtab_remove_module_references (m4_symbol_table *symtab,
152 m4_module *module)
154 m4_hash_iterator *place = 0;
156 assert (module);
158 /* Traverse each symbol name in the hash table. */
159 while ((place = m4_get_hash_iterator_next (symtab->table, place)))
161 m4_symbol *symbol = (m4_symbol *) m4_get_hash_iterator_value (place);
162 m4_symbol_value *data = m4_get_symbol_value (symbol);
164 /* For symbols that have token data... */
165 if (data)
167 /* Purge any shadowed references. */
168 while (VALUE_NEXT (data))
170 m4_symbol_value *next = VALUE_NEXT (data);
172 if (VALUE_MODULE (next) == module)
174 VALUE_NEXT (data) = VALUE_NEXT (next);
176 assert (next->type != M4_SYMBOL_PLACEHOLDER);
177 m4_symbol_value_delete (next);
179 else
180 data = next;
183 /* Purge the live reference if necessary. */
184 if (SYMBOL_MODULE (symbol) == module)
185 m4_symbol_popdef (symtab, m4_get_hash_iterator_key (place));
191 /* This callback is used exclusively by m4_symtab_delete(), to cleanup
192 the memory used by the symbol table. As such, the trace bit is reset
193 on every symbol so that m4_symbol_popdef() doesn't try to preserve
194 the table entry. */
195 static void *
196 symbol_destroy_CB (m4_symbol_table *symtab, const char *name,
197 m4_symbol *symbol, void *ignored)
199 char *key = xstrdup ((char *) name);
201 symbol->traced = false;
203 while (key && m4_hash_lookup (symtab->table, key))
204 m4_symbol_popdef (symtab, key);
206 free (key);
208 return NULL;
213 /* -- SYMBOL MANAGEMENT --
215 The following functions manipulate individual symbols within
216 an existing table. */
218 /* Return the symbol associated to NAME, or else NULL. */
219 m4_symbol *
220 m4_symbol_lookup (m4_symbol_table *symtab, const char *name)
222 m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
224 /* If just searching, return status of search -- if only an empty
225 struct is returned, that is treated as a failed lookup. */
226 return (psymbol && m4_get_symbol_value (*psymbol)) ? *psymbol : NULL;
230 /* Insert NAME into the symbol table. If there is already a symbol
231 associated with NAME, push the new VALUE on top of the value stack
232 for this symbol. Otherwise create a new association. */
233 m4_symbol *
234 m4_symbol_pushdef (m4_symbol_table *symtab, const char *name,
235 m4_symbol_value *value)
237 m4_symbol *symbol;
239 assert (symtab);
240 assert (name);
241 assert (value);
243 symbol = symtab_fetch (symtab, name);
244 VALUE_NEXT (value) = m4_get_symbol_value (symbol);
245 symbol->value = value;
247 assert (m4_get_symbol_value (symbol));
249 return symbol;
252 /* Return the symbol associated with NAME in the symbol table, creating
253 a new symbol if necessary. In either case set the symbol's VALUE. */
254 m4_symbol *
255 m4_symbol_define (m4_symbol_table *symtab,
256 const char *name, m4_symbol_value *value)
258 m4_symbol *symbol;
260 assert (symtab);
261 assert (name);
262 assert (value);
264 symbol = symtab_fetch (symtab, name);
265 if (m4_get_symbol_value (symbol))
266 symbol_popval (symbol);
268 VALUE_NEXT (value) = m4_get_symbol_value (symbol);
269 symbol->value = value;
271 assert (m4_get_symbol_value (symbol));
273 return symbol;
276 /* Pop the topmost value stack entry from the symbol associated with
277 NAME, deleting it from the table entirely if that was the last
278 remaining value in the stack. */
279 void
280 m4_symbol_popdef (m4_symbol_table *symtab, const char *name)
282 m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
284 assert (psymbol);
285 assert (*psymbol);
287 symbol_popval (*psymbol);
289 /* Only remove the hash table entry if the last value in the
290 symbol value stack was successfully removed. */
291 if (!m4_get_symbol_value (*psymbol) && !m4_get_symbol_traced (*psymbol))
293 DELETE (*psymbol);
294 free (m4_hash_remove (symtab->table, name));
298 /* Remove the top-most value from SYMBOL's stack. */
299 static void
300 symbol_popval (m4_symbol *symbol)
302 m4_symbol_value *stale;
304 assert (symbol);
306 stale = m4_get_symbol_value (symbol);
308 if (stale)
310 symbol->value = VALUE_NEXT (stale);
311 m4_symbol_value_delete (stale);
315 /* Remove VALUE from the symbol table, and mark it as deleted. If no
316 expansions are pending, reclaim its resources. */
317 void
318 m4_symbol_value_delete (m4_symbol_value *value)
320 if (VALUE_PENDING (value) > 0)
321 BIT_SET (VALUE_FLAGS (value), VALUE_DELETED_BIT);
322 else
324 if (VALUE_ARG_SIGNATURE (value))
326 m4_hash_apply (VALUE_ARG_SIGNATURE (value), arg_destroy_CB, NULL);
327 m4_hash_delete (VALUE_ARG_SIGNATURE (value));
329 switch (value->type)
331 case M4_SYMBOL_TEXT:
332 free ((char *) m4_get_symbol_value_text (value));
333 break;
334 case M4_SYMBOL_PLACEHOLDER:
335 free ((char *) m4_get_symbol_value_placeholder (value));
336 break;
337 case M4_SYMBOL_VOID:
338 case M4_SYMBOL_FUNC:
339 break;
340 default:
341 assert (!"m4_symbol_value_delete");
342 abort ();
344 free (value);
348 m4_symbol *
349 m4_symbol_rename (m4_symbol_table *symtab, const char *name,
350 const char *newname)
352 m4_symbol *symbol = NULL;
353 m4_symbol **psymbol;
355 assert (symtab);
356 assert (name);
357 assert (newname);
359 /* Use a low level hash fetch, so we can save the symbol value when
360 removing the symbol name from the symbol table. */
361 psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, name);
363 if (psymbol)
365 symbol = *psymbol;
367 /* Remove the old name from the symbol table. */
368 free (m4_hash_remove (symtab->table, name));
369 assert (!m4_hash_lookup (symtab->table, name));
371 m4_hash_insert (symtab->table, xstrdup (newname), *psymbol);
373 /* else
374 NAME does not name a symbol in symtab->table! */
376 return symbol;
380 /* Callback used by m4_symbol_popdef () to release the memory used
381 by values in the arg_signature hash. */
382 static void *
383 arg_destroy_CB (m4_hash *hash, const void *name, void *arg, void *ignored)
385 struct m4_symbol_arg *token_arg = (struct m4_symbol_arg *) arg;
387 assert (name);
388 assert (hash);
390 if (SYMBOL_ARG_DEFAULT (token_arg))
391 DELETE (SYMBOL_ARG_DEFAULT (token_arg));
392 free (token_arg);
393 free (m4_hash_remove (hash, (const char *) name));
395 return NULL;
398 void
399 m4_symbol_value_copy (m4_symbol_value *dest, m4_symbol_value *src)
401 m4_symbol_value *next;
403 assert (dest);
404 assert (src);
406 switch (dest->type)
408 case M4_SYMBOL_TEXT:
409 free ((char *) m4_get_symbol_value_text (dest));
410 break;
411 case M4_SYMBOL_PLACEHOLDER:
412 free ((char *) m4_get_symbol_value_placeholder (dest));
413 break;
414 case M4_SYMBOL_VOID:
415 case M4_SYMBOL_FUNC:
416 break;
417 default:
418 assert (!"m4_symbol_value_delete");
419 abort ();
422 if (VALUE_ARG_SIGNATURE (dest))
424 m4_hash_apply (VALUE_ARG_SIGNATURE (dest), arg_destroy_CB, NULL);
425 m4_hash_delete (VALUE_ARG_SIGNATURE (dest));
428 /* Copy the value contents over, being careful to preserve
429 the next pointer. */
430 next = VALUE_NEXT (dest);
431 memcpy (dest, src, sizeof (m4_symbol_value));
432 VALUE_NEXT (dest) = next;
434 /* Caller is supposed to free text token strings, so we have to
435 copy the string not just its address in that case. */
436 switch (src->type)
438 case M4_SYMBOL_TEXT:
440 size_t len = m4_get_symbol_value_len (src);
441 unsigned int age = m4_get_symbol_value_quote_age (src);
442 m4_set_symbol_value_text (dest,
443 xmemdup (m4_get_symbol_value_text (src),
444 len + 1), len, age);
446 break;
447 case M4_SYMBOL_FUNC:
448 /* Nothing further to do. */
449 break;
450 case M4_SYMBOL_PLACEHOLDER:
451 m4_set_symbol_value_placeholder (dest,
452 xstrdup (m4_get_symbol_value_placeholder
453 (src)));
454 break;
455 case M4_SYMBOL_COMP:
457 m4__symbol_chain *chain = src->u.u_c.chain;
458 size_t len = 0;
459 char *str;
460 char *p;
461 while (chain)
463 /* TODO for now, only text links are supported. */
464 assert (chain->type == M4__CHAIN_STR);
465 len += chain->u.u_s.len;
466 chain = chain->next;
468 p = str = xcharalloc (len + 1);
469 chain = src->u.u_c.chain;
470 while (chain)
472 memcpy (p, chain->u.u_s.str, chain->u.u_s.len);
473 p += chain->u.u_s.len;
474 chain = chain->next;
476 *p = '\0';
477 m4_set_symbol_value_text (dest, str, len, 0);
479 break;
480 default:
481 assert (!"m4_symbol_value_copy");
482 abort ();
484 if (VALUE_ARG_SIGNATURE (src))
485 VALUE_ARG_SIGNATURE (dest) = m4_hash_dup (VALUE_ARG_SIGNATURE (src),
486 arg_copy_CB);
489 static void *
490 arg_copy_CB (m4_hash *src, const void *name, void *arg, m4_hash *dest)
492 m4_hash_insert ((m4_hash *) dest, name, arg);
493 return NULL;
496 /* Set the tracing status of the symbol NAME to TRACED. This takes a
497 name, rather than a symbol, since we hide macros that are traced
498 but otherwise undefined from normal lookups, but still can affect
499 their tracing status. Return true iff the macro was previously
500 traced. */
501 bool
502 m4_set_symbol_name_traced (m4_symbol_table *symtab, const char *name,
503 bool traced)
505 m4_symbol *symbol;
506 bool result;
508 assert (symtab);
509 assert (name);
511 if (traced)
512 symbol = symtab_fetch (symtab, name);
513 else
515 m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (symtab->table,
516 name);
517 if (!psymbol)
518 return false;
519 symbol = *psymbol;
522 result = symbol->traced;
523 symbol->traced = traced;
524 if (!traced && !m4_get_symbol_value (symbol))
526 /* Free an undefined entry once it is no longer traced. */
527 assert (result);
528 free (symbol);
529 free (m4_hash_remove (symtab->table, name));
532 return result;
535 /* Grow OBS with a text representation of VALUE. If QUOTES, then use
536 it to surround a text definition. If MAXLEN, then truncate text
537 definitions to *MAXLEN, and adjust by how many characters are
538 printed. If MODULE, then include which module defined a builtin.
539 Return true if the output was truncated. QUOTES and MODULE do not
540 count against the truncation length. */
541 bool
542 m4_symbol_value_print (m4_symbol_value *value, m4_obstack *obs,
543 const m4_string_pair *quotes, size_t *maxlen,
544 bool module)
546 const char *text;
547 const m4_builtin *bp;
548 m4__symbol_chain *chain;
549 size_t len = maxlen ? *maxlen : SIZE_MAX;
550 bool result = false;
552 switch (value->type)
554 case M4_SYMBOL_TEXT:
555 if (m4_shipout_string_trunc (obs, m4_get_symbol_value_text (value),
556 m4_get_symbol_value_len (value), quotes,
557 &len))
558 result = true;
559 break;
560 case M4_SYMBOL_FUNC:
561 bp = m4_get_symbol_value_builtin (value);
562 obstack_1grow (obs, '<');
563 obstack_grow (obs, bp->name, strlen (bp->name));
564 obstack_1grow (obs, '>');
565 break;
566 case M4_SYMBOL_PLACEHOLDER:
567 text = m4_get_symbol_value_placeholder (value);
568 obstack_1grow (obs, '<');
569 obstack_1grow (obs, '<');
570 obstack_grow (obs, text, strlen (text));
571 obstack_1grow (obs, '>');
572 obstack_1grow (obs, '>');
573 break;
574 case M4_SYMBOL_COMP:
575 chain = value->u.u_c.chain;
576 if (quotes)
577 obstack_grow (obs, quotes->str1, quotes->len1);
578 while (chain && !result)
580 switch (chain->type)
582 case M4__CHAIN_STR:
583 if (m4_shipout_string_trunc (obs, chain->u.u_s.str,
584 chain->u.u_s.len, NULL, &len))
585 result = true;
586 break;
587 case M4__CHAIN_ARGV:
588 if (m4_arg_print (obs, chain->u.u_a.argv, chain->u.u_a.index,
589 chain->u.u_a.quotes, &len, module))
590 result = true;
591 break;
592 default:
593 assert (!"m4_symbol_value_print");
594 abort ();
596 chain = chain->next;
598 if (quotes)
599 obstack_grow (obs, quotes->str2, quotes->len2);
600 assert (!module);
601 break;
602 default:
603 assert (!"m4_symbol_value_print");
604 abort ();
607 if (module && VALUE_MODULE (value))
609 obstack_1grow (obs, '{');
610 text = m4_get_module_name (VALUE_MODULE (value));
611 obstack_grow (obs, text, strlen (text));
612 obstack_1grow (obs, '}');
614 if (maxlen)
615 *maxlen = len;
616 return result;
619 /* Grow OBS with a text representation of SYMBOL. If QUOTES, then use
620 it to surround each text definition. If STACK, then append all
621 pushdef'd values, rather than just the top. If ARG_LENGTH is less
622 than SIZE_MAX, then truncate text definitions to that length. If
623 MODULE, then include which module defined a builtin. QUOTES and
624 MODULE do not count toward truncation. */
625 void
626 m4_symbol_print (m4_symbol *symbol, m4_obstack *obs,
627 const m4_string_pair *quotes, bool stack, size_t arg_length,
628 bool module)
630 m4_symbol_value *value;
631 size_t len = arg_length;
633 assert (symbol);
634 assert (obs);
636 value = m4_get_symbol_value (symbol);
637 m4_symbol_value_print (value, obs, quotes, &len, module);
638 if (stack)
640 value = VALUE_NEXT (value);
641 while (value)
643 obstack_1grow (obs, ',');
644 obstack_1grow (obs, ' ');
645 len = arg_length;
646 m4_symbol_value_print (value, obs, quotes, &len, module);
647 value = VALUE_NEXT (value);
653 /* Define these functions at the end, so that calls in the file use the
654 faster macro version from m4module.h. */
656 /* Pop all values from the symbol associated with NAME. */
657 #undef m4_symbol_delete
658 void
659 m4_symbol_delete (m4_symbol_table *symtab, const char *name)
661 while (m4_symbol_lookup (symtab, name))
662 m4_symbol_popdef (symtab, name);
665 #undef m4_get_symbol_traced
666 bool
667 m4_get_symbol_traced (m4_symbol *symbol)
669 assert (symbol);
670 return symbol->traced;
673 #undef m4_symbol_value_create
674 m4_symbol_value *
675 m4_symbol_value_create (void)
677 m4_symbol_value *value = xzalloc (sizeof (m4_symbol_value));
678 VALUE_MAX_ARGS (value) = SIZE_MAX;
679 return value;
682 #undef m4_symbol_value_groks_macro
683 bool
684 m4_symbol_value_groks_macro (m4_symbol_value *value)
686 assert (value);
687 return BIT_TEST (value->flags, VALUE_MACRO_ARGS_BIT);
690 #undef m4_get_symbol_value
691 m4_symbol_value *
692 m4_get_symbol_value (m4_symbol *symbol)
694 assert (symbol);
695 return symbol->value;
698 #undef m4_is_symbol_value_text
699 bool
700 m4_is_symbol_value_text (m4_symbol_value *value)
702 assert (value);
703 return (value->type == M4_SYMBOL_TEXT);
706 #undef m4_is_symbol_value_func
707 bool
708 m4_is_symbol_value_func (m4_symbol_value *value)
710 assert (value);
711 return (value->type == M4_SYMBOL_FUNC);
714 #undef m4_is_symbol_value_placeholder
715 bool
716 m4_is_symbol_value_placeholder (m4_symbol_value *value)
718 assert (value);
719 return (value->type == M4_SYMBOL_PLACEHOLDER);
722 #undef m4_is_symbol_value_void
723 bool
724 m4_is_symbol_value_void (m4_symbol_value *value)
726 assert (value);
727 return (value->type == M4_SYMBOL_VOID);
730 #undef m4_get_symbol_value_text
731 const char *
732 m4_get_symbol_value_text (m4_symbol_value *value)
734 assert (value && value->type == M4_SYMBOL_TEXT);
735 return value->u.u_t.text;
738 #undef m4_get_symbol_value_len
739 size_t
740 m4_get_symbol_value_len (m4_symbol_value *value)
742 assert (value && value->type == M4_SYMBOL_TEXT);
743 return value->u.u_t.len;
746 #undef m4_get_symbol_value_quote_age
747 unsigned int
748 m4_get_symbol_value_quote_age (m4_symbol_value *value)
750 assert (value && value->type == M4_SYMBOL_TEXT);
751 return value->u.u_t.quote_age;
754 #undef m4_get_symbol_value_func
755 m4_builtin_func *
756 m4_get_symbol_value_func (m4_symbol_value *value)
758 assert (value && value->type == M4_SYMBOL_FUNC);
759 return value->u.builtin->func;
762 #undef m4_get_symbol_value_builtin
763 const m4_builtin *
764 m4_get_symbol_value_builtin (m4_symbol_value *value)
766 assert (value && value->type == M4_SYMBOL_FUNC);
767 return value->u.builtin;
770 #undef m4_get_symbol_value_placeholder
771 const char *
772 m4_get_symbol_value_placeholder (m4_symbol_value *value)
774 assert (value && value->type == M4_SYMBOL_PLACEHOLDER);
775 return value->u.u_t.text;
778 #undef m4_set_symbol_value_text
779 void
780 m4_set_symbol_value_text (m4_symbol_value *value, const char *text, size_t len,
781 unsigned int quote_age)
783 assert (value && text);
784 /* In practice, it is easier to debug when we guarantee a
785 terminating NUL, even when there are embedded NULs. */
786 assert (!text[len]);
788 value->type = M4_SYMBOL_TEXT;
789 value->u.u_t.text = text;
790 value->u.u_t.len = len;
791 value->u.u_t.quote_age = quote_age;
794 #undef m4_set_symbol_value_builtin
795 void
796 m4_set_symbol_value_builtin (m4_symbol_value *value, const m4_builtin *builtin)
798 assert (value);
799 assert (builtin);
801 value->type = M4_SYMBOL_FUNC;
802 value->u.builtin = builtin;
805 #undef m4_set_symbol_value_placeholder
806 void
807 m4_set_symbol_value_placeholder (m4_symbol_value *value, const char *text)
809 assert (value);
810 assert (text);
812 value->type = M4_SYMBOL_PLACEHOLDER;
813 value->u.u_t.text = text;
814 value->u.u_t.len = SIZE_MAX; /* len is not tracked for placeholders. */
818 #ifdef DEBUG_SYM
820 static void *dump_symbol_CB (m4_symbol_table *symtab, const char *name,
821 m4_symbol *symbol, void *userdata);
822 static M4_GNUC_UNUSED void *
823 symtab_dump (m4_symbol_table *symtab)
825 return m4_symtab_apply (symtab, true, dump_symbol_CB, NULL);
828 static void *
829 dump_symbol_CB (m4_symbol_table *symtab, const char *name,
830 m4_symbol *symbol, void *ignored)
832 m4_symbol_value *value = m4_get_symbol_value (symbol);
833 int flags = value ? SYMBOL_FLAGS (symbol) : 0;
834 m4_module * module = value ? SYMBOL_MODULE (symbol) : NULL;
835 const char * module_name = module ? m4_get_module_name (module) : "NONE";
837 xfprintf (stderr, "%10s: (%d%s) %s=", module_name, flags,
838 m4_get_symbol_traced (symbol) ? "!" : "", name);
840 if (!value)
841 fputs ("<!UNDEFINED!>", stderr);
842 else if (m4_is_symbol_value_void (value))
843 fputs ("<!VOID!>", stderr);
844 else
846 m4_obstack obs;
847 obstack_init (&obs);
848 m4_symbol_value_print (value, &obs, false, NULL, NULL, SIZE_MAX, true);
849 xfprintf (stderr, "%s", (char *) obstack_finish (&obs));
850 obstack_free (&obs, NULL);
852 fputc ('\n', stderr);
853 return NULL;
855 #endif /* DEBUG_SYM */