m4-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: dumpdef a pushdef'd stack


From: Eric Blake
Subject: Re: dumpdef a pushdef'd stack
Date: Wed, 27 Sep 2006 07:20:19 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Thunderbird/1.5.0.7 Mnenhy/0.7.4.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 9/26/2006 2:51 PM:
> As mentioned in the second half of: http://lists.gnu.org/archive/html/m4-
> patches/2006-09/msg00027.html
> 
> 2006-09-26  Eric Blake  <address@hidden>
> 
>       * m4/m4module.h (m4_symbol_print): New prototype.

And in followup, I noticed that macro.c was doing some code duplication.
Even worse, our testsuite did not have ANY coverage of the -l/--arglength
option.  The patch below tweaks the semantics of -l slightly, and adds
tests accordingly.

I would like to do a followup to this patch, which does three things.
First, --arglength currently does not validate its numeric argument, so
'm4 -loops' is equivalent to 'm4 -l0'; I'd like to see the first case at
least warn on the invalid argument.  Second, I'd like to simplify
trace_format in macro.c - using non-standard format modifiers like %l for
optional left quote and %S for length-limited string just looks weird.
The current patch removed one of these uses (debugmode(a)), but not the
other (debugmode(e)).

Third, now that --arglength can affect dumpdef output as well as trace
output, we should be able to tweak it on the fly.  I'm thinking a macro
named debuglen is the best fit here (fitting in with the naming of other
debug* builtins), but I could also be persuaded to name the macro
arglength to match the command-line option.  Or maybe name it debuglen,
deprecate --arglength (as that name isn't quite descriptive of what is
really being length-limited), and introduce --debuglen as a synonym to -l.
 Thoughts?

2006-09-27  Eric Blake  <address@hidden>

        * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import
        strnlen.
        * m4/symtab.c (symbol_value_print): Rename to...
        (m4_symbol_value_print): ...this, and...
        (m4_symbol_print): Update to allow -L length truncation.  Now
        truncation also affects dumpdef output and builtin names.
        * m4/m4private.h (nesting_limit, max_debug_argument_length):
        Switch to size_t.
        * m4/m4module.h (m4_symbol_print): Add parameter.
        (m4_symbol_value_print): New function.
        * modules/m4.c (dumpdef): Allow length truncation.
        * m4/macro.c (trace_pre): Use m4_symbol_print, rather than
        repeating code.
        * doc/m4.texinfo (Invoking m4): Document -l better.
        (Dumpdef, Debug Levels): Document the effect of -l.
        * NEWS: Document this change.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFGnqS84KuGfSFAYARAsJBAJ933m7giRteAB2HheebIy6th8SsqwCgj/AL
mQT+zK5jNYFeKQ43MO6Znlw=
=ygUs
-----END PGP SIGNATURE-----
? ltdl/m4/double-slash-root.m4
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.20
diff -u -p -r1.20 NEWS
--- NEWS        26 Sep 2006 21:21:50 -0000      1.20
+++ NEWS        27 Sep 2006 13:06:27 -0000
@@ -94,6 +94,9 @@ promoted to 2.0.
   either be blind (ie. be unrecognized without arguments), or begin with
   the prefix `m4' or `__'.
 
+* The `-l'/`--arglength' command line argument now affects dumpdef
+  output as well as trace output.
+
 * FIXME: `m4wrap' semantics need an update to FIFO.
 
 * FIXME: include the (long) list of changes in 1.4.x that were not already
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.52
diff -u -p -r1.52 m4.texinfo
--- doc/m4.texinfo      26 Sep 2006 21:21:50 -0000      1.52
+++ doc/m4.texinfo      27 Sep 2006 13:06:29 -0000
@@ -692,9 +692,13 @@ future release.
 
 @item -l @var{NUM}
 @itemx address@hidden
-Restrict the size of the output generated by macro tracing to @var{NUM}
-characters per trace line.  If unspecified or zero, output is
-unlimited.  @xref{Debug Levels}, for more details.
+Restrict the size of the output generated by macro tracing or by
address@hidden to @var{NUM} characters per string.  If unspecified or
+zero, output is unlimited.  @xref{Debug Levels}, for more details.
address@hidden FIXME - should we add a debuglen macro that can alter this
address@hidden setting on the fly?  Also, should we add an option that
address@hidden controls whether output strings are sanitized with escape
address@hidden sequences, so that dumpdef is truly one line per macro?
 
 @item -t @var{NAME}
 @itemx address@hidden
@@ -2640,19 +2644,22 @@ f(popdef(`f')dumpdef(`f'))
 
 @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.
+implied when the @option{--debug} option (@option{-d}, @pxref{Invoking
+m4}) is used in the command line without arguments.  Also, the
address@hidden option (@option{-l}) can affect output, by
+truncating longer strings.
 
address@hidden options: -ds
address@hidden options: -ds -l3
 @example
-$ @kbd{m4 -ds}
-pushdef(`foo', `1')
+$ @kbd{m4 -ds -l 3}
+pushdef(`foo', `1 long string')
 @result{}
 pushdef(`foo', defn(`divnum'))
 @result{}
 pushdef(`foo', `3')
 @result{}
 dumpdef(`foo')
address@hidden:@tabchar{}3, <divnum>, 1
address@hidden:@tabchar{}3, <div...>, 1 l...
 @result{}
 @end example
 
@@ -2883,7 +2890,9 @@ following:
 @table @code
 @item a
 In trace output, show the actual arguments that were collected before
-invoking the macro.
+invoking the macro.  Arguments are subject to length truncation
+specified by the command line option @option{--arglength}
+(@option{-l}).
 
 @item c
 In trace output, show several trace lines for each macro call.  A line
@@ -2893,7 +2902,8 @@ after the call has completed.
 
 @item e
 In trace output, show the expansion of each macro call, if it is not
-void.
+void.  The expansion is subject to length truncation specified by the
+command line option @option{--arglength} (@option{-l}).
 
 @item f
 In debug and trace output, include the name of the current input file in
@@ -2948,6 +2958,26 @@ If no flags are specified with the @opti
 @samp{aeq}. Many examples in this manual show their output using
 default flags.
 
address@hidden FIXME - add a new macro debuglen (or some other spelling) that
address@hidden allows changing the -l/--arglength option on the fly?  If so,
address@hidden add a new node here describing it.
+Also, the option @option{--arglength} (@option{-l}) can affect trace
+and dumpdef output.  If the option is specified to a non-zero value,
+then strings longer than that length are truncated, and @samp{...}
+included in the output to show that truncation took place.  This allows
+reducing the size of the debug output in the face of arbitrarily long
+macro arguments or definitions.
+
address@hidden options: -l4 -techo
address@hidden
+$ @kbd{m4 -d -l 4 -t echo}
+define(`echo', `$@')
address@hidden
+echo(`long string')
address@hidden: -1- echo(`long...') -> ``lon...'
address@hidden string
address@hidden example
+
 @cindex @acronym{GNU} extensions
 There is a builtin macro @code{debugmode}, which allows on-the-fly control of
 the debugging output format:
Index: ltdl/m4/gnulib-cache.m4
===================================================================
RCS file: /sources/m4/m4/ltdl/m4/gnulib-cache.m4,v
retrieving revision 1.10
diff -u -p -r1.10 gnulib-cache.m4
--- ltdl/m4/gnulib-cache.m4     1 Sep 2006 23:11:05 -0000       1.10
+++ ltdl/m4/gnulib-cache.m4     27 Sep 2006 13:06:29 -0000
@@ -15,11 +15,11 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gnu 
--m4-base=ltdl/m4 --doc-base=doc --aux-dir=ltdl/config --libtool 
--macro-prefix=M4 assert binary-io cloexec close-stream dirname error exit fdl 
filenamecat fopen-safer free gendocs gettext gnupload mkstemp obstack progname 
regex regexprops-generic stdbool stdlib-safer strtol unlocked-io verror xalloc 
xalloc-die xstrndup xvasprintf
+#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gnu 
--m4-base=ltdl/m4 --doc-base=doc --aux-dir=ltdl/config --libtool 
--macro-prefix=M4 assert binary-io cloexec close-stream dirname error exit fdl 
filenamecat fopen-safer free gendocs gettext gnupload mkstemp obstack progname 
regex regexprops-generic stdbool stdlib-safer strnlen strtol unlocked-io verror 
xalloc xalloc-die xstrndup xvasprintf
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
-gl_MODULES([assert binary-io cloexec close-stream dirname error exit fdl 
filenamecat fopen-safer free gendocs gettext gnupload mkstemp obstack progname 
regex regexprops-generic stdbool stdlib-safer strtol unlocked-io verror xalloc 
xalloc-die xstrndup xvasprintf])
+gl_MODULES([assert binary-io cloexec close-stream dirname error exit fdl 
filenamecat fopen-safer free gendocs gettext gnupload mkstemp obstack progname 
regex regexprops-generic stdbool stdlib-safer strnlen strtol unlocked-io verror 
xalloc xalloc-die xstrndup xvasprintf])
 gl_AVOID([])
 gl_SOURCE_BASE([gnu])
 gl_M4_BASE([ltdl/m4])
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.87
diff -u -p -r1.87 m4module.h
--- m4/m4module.h       26 Sep 2006 21:21:50 -0000      1.87
+++ m4/m4module.h       27 Sep 2006 13:06:29 -0000
@@ -137,9 +137,9 @@ extern void         m4_delete       (m4 *);
        M4FIELD(m4_obstack,        trace_messages, trace_messages)      \
        M4FIELD(int,               exit_status,    exit_status)         \
        M4FIELD(bool,   no_gnu_extensions_opt,     no_gnu_extensions)   \
-       M4FIELD(int,    nesting_limit_opt,         nesting_limit)       \
+       M4FIELD(size_t, nesting_limit_opt,         nesting_limit)       \
        M4FIELD(int,    debug_level_opt,           debug_level)         \
-       M4FIELD(int,    max_debug_arg_length_opt,  max_debug_arg_length)\
+       M4FIELD(size_t, max_debug_arg_length_opt,  max_debug_arg_length)\
        M4FIELD(int,    regexp_syntax_opt,         regexp_syntax)       \
 
 
@@ -216,8 +216,11 @@ extern m4_symbol_value *m4_get_symbol_va
 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);
+extern void    m4_symbol_value_print   (m4_symbol_value *, m4_obstack *, bool,
+                                        const char *, const char *, size_t);
+extern void    m4_symbol_print         (m4_symbol *, m4_obstack *, bool,
+                                        const char *, const char *, bool,
+                                        size_t);
 
 #define m4_is_symbol_void(symbol)                                      \
        (m4_is_symbol_value_void (m4_get_symbol_value (symbol)))
Index: m4/m4private.h
===================================================================
RCS file: /sources/m4/m4/m4/m4private.h,v
retrieving revision 1.63
diff -u -p -r1.63 m4private.h
--- m4/m4private.h      26 Sep 2006 13:19:26 -0000      1.63
+++ m4/m4private.h      27 Sep 2006 13:06:29 -0000
@@ -63,9 +63,9 @@ struct m4 {
 
   /* Option flags  (set in src/main.c).  */
   bool         no_gnu_extensions;              /* -G */
-  int          nesting_limit;                  /* -L */
+  size_t       nesting_limit;                  /* -L */
   int          debug_level;                    /* -d */
-  int          max_debug_arg_length;           /* -l */
+  size_t       max_debug_arg_length;           /* -l */
   int          regexp_syntax;                  /* -r */
   int          opt_flags;
 
Index: m4/macro.c
===================================================================
RCS file: /sources/m4/m4/m4/macro.c,v
retrieving revision 1.54
diff -u -p -r1.54 macro.c
--- m4/macro.c  27 Sep 2006 12:24:53 -0000      1.54
+++ m4/macro.c  27 Sep 2006 13:06:29 -0000
@@ -188,8 +188,8 @@ expand_argument (m4 *context, m4_obstack
          break;
 
        case M4_TOKEN_EOF:
-           m4_error_at_line (context, EXIT_FAILURE, 0, file, line,
-                             _("end of file in argument list"));
+          m4_error_at_line (context, EXIT_FAILURE, 0, file, line,
+                            _("end of file in argument list"));
          break;
 
        case M4_TOKEN_WORD:
@@ -608,45 +608,25 @@ trace_pre (m4 *context, const char *name
           int argc, m4_symbol_value **argv)
 {
   int i;
-  const m4_builtin *bp;
 
   trace_header (context, id);
   trace_format (context, "%s", name);
 
   if ((argc > 1) && m4_is_debug_bit (context, M4_DEBUG_TRACE_ARGS))
     {
-      trace_format (context, "(");
+      bool quote = m4_is_debug_bit (context, M4_DEBUG_TRACE_QUOTE);
+      const char *lquote = m4_get_syntax_lquote (M4SYNTAX);
+      const char *rquote = m4_get_syntax_rquote (M4SYNTAX);
+      size_t arg_length = m4_get_max_debug_arg_length_opt (context);
 
+      trace_format (context, "(");
       for (i = 1; i < argc; i++)
        {
          if (i != 1)
            trace_format (context, ", ");
 
-         if (m4_is_symbol_value_text (argv[i]))
-           {
-             trace_format (context, "%l%S%r", M4ARG (i));
-           }
-         else if (m4_is_symbol_value_func (argv[i]))
-           {
-             bp = m4_builtin_find_by_func (NULL,
-                                           m4_get_symbol_value_func(argv[i]));
-             if (bp == NULL)
-               {
-                 assert (!"INTERNAL ERROR: builtin not found in table!");
-                 abort ();
-               }
-             trace_format (context, "<%s>", bp->name);
-           }
-         else if (m4_is_symbol_value_placeholder (argv[i]))
-           {
-             trace_format (context, "<placeholder for %s>",
-                           m4_get_symbol_value_placeholder (argv[i]));
-           }
-         else
-           {
-             assert (!"INTERNAL ERROR: bad token data type (trace_pre ())");
-             abort ();
-           }
+         m4_symbol_value_print (argv[i], &context->trace_messages,
+                                quote, lquote, rquote, arg_length);
        }
       trace_format (context, ")");
     }
Index: m4/symtab.c
===================================================================
RCS file: /sources/m4/m4/m4/symtab.c,v
retrieving revision 1.61
diff -u -p -r1.61 symtab.c
--- m4/symtab.c 26 Sep 2006 21:21:50 -0000      1.61
+++ m4/symtab.c 27 Sep 2006 13:06:29 -0000
@@ -20,6 +20,8 @@
 
 #include "m4private.h"
 
+#include "strnlen.h"
+
 /* Define this to see runtime debug info.  Implied by DEBUG.  */
 /*#define DEBUG_SYM */
 
@@ -57,8 +59,6 @@ static void *   arg_destroy_CB        (m4_hash 
                                         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 --
@@ -463,54 +463,63 @@ m4_set_symbol_name_traced (m4_symbol_tab
 }
 
 /* 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)
+   surround a text definition by LQUOTE and RQUOTE.  If ARG_LENGTH is
+   non-zero, then truncate text definitions to that length.  */
+void
+m4_symbol_value_print (m4_symbol_value *value, m4_obstack *obs, bool quote,
+                      const char *lquote, const char *rquote,
+                      size_t arg_length)
 {
+  const char *text;
+  size_t len;
+
   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)));
+      text = 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, '>');
+      text = bp->name;
+      lquote = "<";
+      rquote = ">";
+      quote = true;
     }
   else if (m4_is_symbol_value_placeholder (value))
     {
+      text = m4_get_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, '>');
+      lquote = "<placeholder for ";
+      rquote = ">";
+      quote = true;
     }
   else
     {
       assert (!"invalid token in symbol_value_print");
       abort ();
     }
+
+  len = arg_length ? strnlen (text, arg_length) : strlen (text);
+  if (quote)
+    obstack_grow (obs, lquote, strlen (lquote));
+  obstack_grow (obs, text, len);
+  if (len == arg_length && text[len] != '\0')
+    obstack_grow (obs, "...", 3);
+  if (quote)
+    obstack_grow (obs, rquote, strlen (rquote));
 }
 
 /* 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.  */
+   surround each text definition by LQUOTE and RQUOTE.  If STACK, then
+   append all pushdef'd values, rather than just the top.  If
+   ARG_LENGTH is non-zero, then truncate text definitions to that
+   length.  */
 void
 m4_symbol_print (m4_symbol *symbol, m4_obstack *obs, bool quote,
-                const char *lquote, const char *rquote, bool stack)
+                const char *lquote, const char *rquote, bool stack,
+                size_t arg_length)
 {
   m4_symbol_value *value;
 
@@ -518,7 +527,7 @@ m4_symbol_print (m4_symbol *symbol, m4_o
   assert (obs);
 
   value = m4_get_symbol_value (symbol);
-  symbol_value_print (value, obs, quote, lquote, rquote);
+  m4_symbol_value_print (value, obs, quote, lquote, rquote, arg_length);
   if (stack)
     {
       value = VALUE_NEXT (value);
@@ -526,7 +535,8 @@ m4_symbol_print (m4_symbol *symbol, m4_o
        {
          obstack_1grow (obs, ',');
          obstack_1grow (obs, ' ');
-         symbol_value_print (value, obs, quote, lquote, rquote);
+         m4_symbol_value_print (value, obs, quote, lquote, rquote,
+                                arg_length);
          value = VALUE_NEXT (value);
        }
     }
Index: modules/m4.c
===================================================================
RCS file: /sources/m4/m4/modules/m4.c,v
retrieving revision 1.74
diff -u -p -r1.74 m4.c
--- modules/m4.c        27 Sep 2006 12:24:53 -0000      1.74
+++ modules/m4.c        27 Sep 2006 13:06:29 -0000
@@ -367,9 +367,10 @@ M4BUILTIN_HANDLER (dumpdef)
 {
   m4_dump_symbol_data data;
   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);
+  bool stack = m4_is_debug_bit (context, M4_DEBUG_TRACE_STACK);
+  size_t arg_length = m4_get_max_debug_arg_length_opt (context);
 
   data.obs = obs;
   m4_dump_symbols (context, &data, argc, argv, true);
@@ -382,7 +383,7 @@ M4BUILTIN_HANDLER (dumpdef)
       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);
+      m4_symbol_print (symbol, obs, quote, lquote, rquote, stack, arg_length);
       obstack_1grow (obs, '\n');
     }
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]