dumpdef a pushdef'd stack
Eric Blake <[email protected]>
| Newsgroups | gmane.comp.gnu.m4.patches |
|---|---|
| Message-ID | <[email protected]> |
As mentioned in the second half of: http://lists.gnu.org/archive/html/m4- patches/2006-09/msg00027.html 2006-09-26 Eric Blake <[email protected]> * m4/m4module.h (m4_symbol_print): New prototype. (M4_DEBUG_TRACE_STACK): New enumerator. (m4_is_debug_bit): Allow use without requiring m4private.h. * m4/symtab.c (symbol_value_print, m4_symbol_print): New functions. * modules/m4.c (dump_symbol_CB, m4_dump_symbols): Speed up callback. (dumpdef): Allow printing pushdef'd stacks. * m4/debug.c (m4_debug_decode): Add new 's' debug mode. * src/main.c (usage): Document it. * doc/m4.texinfo (Dumpdef, Debug Levels): Likewise. * NEWS: Likewise. Index: NEWS =================================================================== RCS file: /sources/m4/m4/NEWS,v retrieving revision 1.19 diff -u -r1.19 NEWS --- NEWS 21 Sep 2006 04:12:55 -0000 1.19 +++ NEWS 26 Sep 2006 20:37:23 -0000 @@ -59,9 +59,10 @@ standard error are terminals. * New `m' flag to `-d'/`--debug' option or `debugmode' macro traces - actions related to module loading and unloading. Also, the `--debug' - option now understands `-' and `+' modifiers, the way `debugmode' has - always done. + actions related to module loading and unloading. New `s' flag shows the + entire stack of `pushdef' definitions during `dumpdef'. Also, the + `--debug' option now understands `-' and `+' modifiers, the way + `debugmode' has always done. * The semantics of `traceon' and `traceoff' now match traditional implementations: when called without arguments, they affect global state Index: doc/m4.texinfo =================================================================== RCS file: /sources/m4/m4/doc/m4.texinfo,v retrieving revision 1.51 diff -u -r1.51 m4.texinfo --- doc/m4.texinfo 21 Sep 2006 16:40:03 -0000 1.51 +++ doc/m4.texinfo 26 Sep 2006 20:37:23 -0000 @@ -2638,9 +2638,23 @@ @result{}f1 @end example -@xref{Debug Levels}, for information on controlling the details of the -display; in particular, the @samp{q} flag, implied by @option{-d} in the -example command line, has an impact. +@xref{Debug Levels}, for information on how the @samp{q} and @samp{s} +flags affect the details of the display. Remember, the @samp{q} flag is +implied when @option{-d} is used in the command line without arguments. + +@comment options: -ds +@example +$ @kbd{m4 -ds} +pushdef(`foo', `1') +@result{} +pushdef(`foo', defn(`divnum')) +@result{} +pushdef(`foo', `3') +@result{} +dumpdef(`foo') +@error{}foo:@tabchar{}3, <divnum>, 1 +@result{} +@end example @node Trace @section Tracing macro calls @@ -2900,6 +2914,10 @@ current quotes. This affects traced macros, as well as @code{dumpdef} output. +@item s +Show the entire stack of definitions associated with a symbol via +@code{pushdef}. This affects @code{dumpdef} output. + @item t Trace all macro calls made in this invocation of @code{m4}. This is equivalent to using @code{traceon} without arguments. Index: m4/debug.c =================================================================== RCS file: /sources/m4/m4/m4/debug.c,v retrieving revision 1.25 diff -u -r1.25 debug.c --- m4/debug.c 19 Sep 2006 13:16:08 -0000 1.25 +++ m4/debug.c 26 Sep 2006 20:37:23 -0000 @@ -89,6 +89,10 @@ level |= M4_DEBUG_TRACE_MODULE; break; + case 's': + level |= M4_DEBUG_TRACE_STACK; + break; + case 'V': level |= M4_DEBUG_TRACE_VERBOSE; break; Index: m4/m4module.h =================================================================== RCS file: /sources/m4/m4/m4/m4module.h,v retrieving revision 1.86 diff -u -r1.86 m4module.h --- m4/m4module.h 18 Sep 2006 13:16:44 -0000 1.86 +++ m4/m4module.h 26 Sep 2006 20:37:23 -0000 @@ -113,10 +113,10 @@ /* Error handling. */ extern void m4_error (m4 *, int, int, const char *, ...) M4_GNUC_PRINTF (4, 5); extern void m4_error_at_line (m4 *, int, int, const char *, int, - const char *, ...) M4_GNUC_PRINTF (6, 7); -extern void m4_warn (m4 *, int, const char *, ...) M4_GNUC_PRINTF (3, 4); + const char *, ...) M4_GNUC_PRINTF (6, 7); +extern void m4_warn (m4 *, int, const char *, ...) M4_GNUC_PRINTF (3, 4); extern void m4_warn_at_line (m4 *, int, const char *, int, - const char *, ...) M4_GNUC_PRINTF (5, 6); + const char *, ...) M4_GNUC_PRINTF (5, 6); /* --- CONTEXT MANAGEMENT --- */ @@ -216,6 +216,8 @@ extern bool m4_get_symbol_traced (m4_symbol*); extern bool m4_set_symbol_name_traced (m4_symbol_table*, const char *, bool); +extern void m4_symbol_print (m4_symbol *, m4_obstack *, bool, + const char *, const char *, bool); #define m4_is_symbol_void(symbol) \ (m4_is_symbol_value_void (m4_get_symbol_value (symbol))) @@ -294,16 +296,18 @@ M4_DEBUG_TRACE_CALLID = (1 << 9), /* m: trace module actions */ M4_DEBUG_TRACE_MODULE = (1 << 10), + /* s: trace pushdef stacks */ + M4_DEBUG_TRACE_STACK = (1 << 11), /* V: very verbose -- print everything */ - M4_DEBUG_TRACE_VERBOSE = ((1 << 11) - 1) + M4_DEBUG_TRACE_VERBOSE = ((1 << 12) - 1) }; /* default flags -- equiv: aeq */ #define M4_DEBUG_TRACE_DEFAULT \ - (M4_DEBUG_TRACE_ARGS|M4_DEBUG_TRACE_EXPANSION|M4_DEBUG_TRACE_QUOTE) + (M4_DEBUG_TRACE_ARGS | M4_DEBUG_TRACE_EXPANSION | M4_DEBUG_TRACE_QUOTE) -#define m4_is_debug_bit(C,B) (BIT_TEST (m4_get_debug_level_opt (C), (B))) +#define m4_is_debug_bit(C,B) ((m4_get_debug_level_opt (C) & (B)) != 0) extern int m4_debug_decode (m4 *, int, const char *); extern bool m4_debug_set_output (m4 *, const char *); Index: m4/symtab.c =================================================================== RCS file: /sources/m4/m4/m4/symtab.c,v retrieving revision 1.60 diff -u -r1.60 symtab.c --- m4/symtab.c 18 Sep 2006 13:16:44 -0000 1.60 +++ m4/symtab.c 26 Sep 2006 20:37:23 -0000 @@ -57,7 +57,8 @@ void *arg, void *ignored); static void * arg_copy_CB (m4_hash *src, const void *name, void *arg, m4_hash *dest); - +static void symbol_value_print (m4_symbol_value *, m4_obstack *, bool, + const char *, const char *); /* -- SYMBOL TABLE MANAGEMENT -- @@ -461,6 +462,76 @@ return result; } +/* Grow OBS with a text representation of VALUE. If QUOTE, then + surround a text definition by LQUOTE and RQUOTE. */ +static void +symbol_value_print (m4_symbol_value *value, m4_obstack *obs, bool quote, + const char *lquote, const char *rquote) +{ + if (m4_is_symbol_value_text (value)) + { + if (quote) + { + obstack_grow (obs, lquote, strlen (lquote)); + obstack_grow (obs, m4_get_symbol_value_text (value), + strlen (m4_get_symbol_value_text (value))); + obstack_grow (obs, rquote, strlen (rquote)); + } + else + obstack_grow (obs, m4_get_symbol_value_text (value), + strlen (m4_get_symbol_value_text (value))); + } + else if (m4_is_symbol_value_func (value)) + { + const m4_builtin *bp; + bp = m4_builtin_find_by_func (NULL, m4_get_symbol_value_func (value)); + assert (bp); + obstack_1grow (obs, '<'); + obstack_grow (obs, bp->name, strlen (bp->name)); + obstack_1grow (obs, '>'); + } + else if (m4_is_symbol_value_placeholder (value)) + { + /* FIXME - is it worth translating "placeholder for "? */ + obstack_grow (obs, "<placeholder for ", strlen ("<placeholder for ")); + obstack_grow (obs, m4_get_symbol_value_placeholder (value), + strlen (m4_get_symbol_value_placeholder (value))); + obstack_1grow (obs, '>'); + } + else + { + assert (!"invalid token in symbol_value_print"); + abort (); + } +} + +/* Grow OBS with a text representation of SYMBOL. If QUOTE, then + surround each definition by LQUOTE and RQUOTE. If STACK, then + append all pushdef'd values, rather than just the top. */ +void +m4_symbol_print (m4_symbol *symbol, m4_obstack *obs, bool quote, + const char *lquote, const char *rquote, bool stack) +{ + m4_symbol_value *value; + + assert (symbol); + assert (obs); + + value = m4_get_symbol_value (symbol); + symbol_value_print (value, obs, quote, lquote, rquote); + if (stack) + { + value = VALUE_NEXT (value); + while (value) + { + obstack_1grow (obs, ','); + obstack_1grow (obs, ' '); + symbol_value_print (value, obs, quote, lquote, rquote); + value = VALUE_NEXT (value); + } + } +} + /* Define these functions at the end, so that calls in the file use the faster macro version from m4module.h. */ Index: modules/m4.c =================================================================== RCS file: /sources/m4/m4/modules/m4.c,v retrieving revision 1.72 diff -u -r1.72 m4.c --- modules/m4.c 26 Sep 2006 13:19:26 -0000 1.72 +++ modules/m4.c 26 Sep 2006 20:37:23 -0000 @@ -305,16 +305,22 @@ dump_symbol_CB (m4_symbol_table *ignored, const char *name, m4_symbol *symbol, void *userdata) { + m4_dump_symbol_data *symbol_data = (m4_dump_symbol_data *) userdata; + assert (name); assert (symbol); + assert (!m4_is_symbol_value_void (m4_get_symbol_value (symbol))); - if (!m4_is_symbol_value_void (m4_get_symbol_value (symbol))) + if (symbol_data->size == 0) { - m4_dump_symbol_data *symbol_data = (m4_dump_symbol_data *) userdata; - - obstack_blank (symbol_data->obs, sizeof (const char *)); - symbol_data->base = (const char **) obstack_base (symbol_data->obs); - symbol_data->base[symbol_data->size++] = (const char *) name; + obstack_ptr_grow (symbol_data->obs, name); + symbol_data->size = (obstack_room (symbol_data->obs) + / sizeof (const char *)); + } + else + { + obstack_ptr_grow_fast (symbol_data->obs, name); + symbol_data->size--; } return NULL; @@ -326,8 +332,7 @@ m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, int argc, m4_symbol_value **argv, bool complain) { - data->base = (const char **) obstack_base (data->obs); - data->size = 0; + data->size = obstack_room (data->obs) / sizeof (const char *); if (argc == 1) { @@ -341,19 +346,17 @@ for (i = 1; i < argc; i++) { symbol = m4_symbol_lookup (M4SYMTAB, M4ARG (i)); - if (symbol != NULL - && !m4_is_symbol_value_void (m4_get_symbol_value (symbol))) - { - dump_symbol_CB (NULL, M4ARG (i), symbol, data); - } + if (symbol != NULL) + dump_symbol_CB (NULL, M4ARG (i), symbol, data); else if (complain) m4_warn (context, 0, _("%s: undefined macro `%s'"), M4ARG (0), M4ARG (i)); } } - obstack_finish (data->obs); - qsort ((void*) data->base, data->size, sizeof (const char*), dumpdef_cmp_CB); + data->size = obstack_object_size (data->obs) / sizeof (const char *); + data->base = (const char **) obstack_finish (data->obs); + qsort (data->base, data->size, sizeof (const char *), dumpdef_cmp_CB); } @@ -362,7 +365,10 @@ M4BUILTIN_HANDLER (dumpdef) { m4_dump_symbol_data data; - const m4_builtin *bp; + bool quote = m4_is_debug_bit (context, M4_DEBUG_TRACE_QUOTE); + bool stack = m4_is_debug_bit (context, M4_DEBUG_TRACE_STACK); + const char *lquote = m4_get_syntax_lquote (M4SYNTAX); + const char *rquote = m4_get_syntax_rquote (M4SYNTAX); data.obs = obs; m4_dump_symbols (context, &data, argc, argv, true); @@ -370,37 +376,18 @@ for (; data.size > 0; --data.size, data.base++) { m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, data.base[0]); + assert (symbol); - fprintf (stderr, "%s:\t", data.base[0]); - - if (m4_is_symbol_text (symbol)) - { - if (m4_get_debug_level_opt (context) & M4_DEBUG_TRACE_QUOTE) - fprintf (stderr, "%s%s%s\n", - m4_get_syntax_lquote (M4SYNTAX), - m4_get_symbol_text (symbol), - m4_get_syntax_rquote (M4SYNTAX)); - else - fprintf (stderr, "%s\n", m4_get_symbol_text (symbol)); - } - else if (m4_is_symbol_func (symbol)) - { - bp = m4_builtin_find_by_func (NULL, - m4_get_symbol_func (symbol)); - assert (bp); - fprintf (stderr, "<%s>\n", bp->name); - } - else if (m4_is_symbol_placeholder (symbol)) - { - fprintf (stderr, "<placeholder for %s>\n", - m4_get_symbol_placeholder (symbol)); - } - else - { - assert (!"invalid token in builtin_dumpdef"); - abort (); - } + obstack_grow (obs, data.base[0], strlen (data.base[0])); + obstack_1grow (obs, ':'); + obstack_1grow (obs, '\t'); + m4_symbol_print (symbol, obs, quote, lquote, rquote, stack); + obstack_1grow (obs, '\n'); } + + obstack_1grow (obs, '\0'); + m4_sysval_flush (context); + fputs ((char *) obstack_finish (obs), stderr); } /* The macro "defn" returns the quoted definition of the macro named by @@ -445,9 +432,9 @@ /* Helper macros for readability. */ #if UNIX || defined WEXITSTATUS -# define M4_SYSVAL_EXITBITS(status) \ +# define M4_SYSVAL_EXITBITS(status) \ (WIFEXITED (status) ? WEXITSTATUS (status) : 0) -# define M4_SYSVAL_TERMSIGBITS(status) \ +# define M4_SYSVAL_TERMSIGBITS(status) \ (WIFSIGNALED (status) ? WTERMSIG (status) << 8 : 0) #else /* ! UNIX && ! defined WEXITSTATUS */ Index: src/main.c =================================================================== RCS file: /sources/m4/m4/src/main.c,v retrieving revision 1.87 diff -u -r1.87 main.c --- src/main.c 21 Sep 2006 04:12:55 -0000 1.87 +++ src/main.c 26 Sep 2006 20:37:23 -0000 @@ -137,19 +137,20 @@ fputs (_("\ \n\ FLAGS is any of:\n\ - a show actual arguments\n\ - c show before collect, after collect and after call\n\ - e show expansion\n\ - f say current input file name\n\ - i show changes in input files\n\ - l say current input line number\n\ + a show actual arguments in trace\n\ + c show before collect, after collect and after call in trace\n\ + e show expansion in trace\n\ + f include current input file name in trace and debug\n\ + i show changes in input files in debug\n\ + l include current input line number in trace and debug\n\ "), stdout); fputs (_("\ - m show actions related to modules\n\ - p show results of path searches\n\ - q quote values as necessary, with a or e flag\n\ - t trace for all macro calls, not only traceon'ed\n\ - x add a unique macro call id, useful with c flag\n\ + m show actions related to modules in debug\n\ + p show results of path searches in debug\n\ + q quote values as necessary in dumpdef and trace, useful with a or e\n\ + s show full stack of pushdef values in dumpdef\n\ + t trace all macro calls, regardless of traceon state\n\ + x add a unique macro call id in trace, useful with c\n\ V shorthand for all of the above flags\n\ "), stdout); fputs (_("\