Re: dumpdef a pushdef'd stack

Eric Blake <[email protected]>
Newsgroups gmane.comp.gnu.m4.patches
Message-ID <[email protected]>
-----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  <[email protected]>
> 
> 	* 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  <[email protected]>

	* 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             [email protected]
-----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-----

_______________________________________________
M4-patches mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/m4-patches
m4.patch166 (text/plain, 15.9 KB)
? 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 --arglength=@var{NUM}
-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
+@code{dumpdef} to @var{NUM} characters per string.  If unspecified or
+zero, output is unlimited.  @xref{Debug Levels}, for more details.
+@comment FIXME - should we add a debuglen macro that can alter this
+@comment setting on the fly?  Also, should we add an option that
+@comment controls whether output strings are sanitized with escape
+@comment sequences, so that dumpdef is truly one line per macro?
 
 @item -t @var{NAME}
 @itemx --trace=@var{NAME}
@@ -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
+@option{--arglength} option (@option{-l}) can affect output, by
+truncating longer strings.
 
-@comment options: -ds
+@comment 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')
-@error{}foo:@tabchar{}3, <divnum>, 1
+@error{}foo:@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.
 
+@comment FIXME - add a new macro debuglen (or some other spelling) that
+@comment allows changing the -l/--arglength option on the fly?  If so,
+@comment 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.
+
+@comment options: -l4 -techo
+@example
+$ @kbd{m4 -d -l 4 -t echo}
+define(`echo', `$@')
+@result{}
+echo(`long string')
+@error{}m4trace: -1- echo(`long...') -> ``lon...'
+@result{}long string
+@end 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');
     }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.