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: Tue, 10 Oct 2006 06:43:20 -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/27/2006 7:20 AM:
> 
> I would like to do a followup to this patch, which does three things.

All three followups are now done.

> 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)).

This gets the second item, plus a couple other things that were bothering
me about traces.  The debugmode(c) flag was outputting three lines, the
second of which had ??? in the source code (too close to an ANSI trigraph
for my liking), and the second and third lines could never be separated by
any other trace output.  So, this simplifies the output to two lines
(meaning that 'c' just adds a single line, rather than splitting an
existing line into 2).  This adds another feature that I wanted - the
ability to see which macro definition will be used once arguments are
collected.  And thanks to the patch from 1.4.5 ported last month, since we
now always use the definition that was in effect prior to argument
collection (even if argument collection changes the definition of the
macro), this does the right thing.

Also, expansion text is now printed even for non-text expansions (aka
include and defn) (note that this will also make it easier for when I can
finally patch the input engine to concatenate text and builtin tokens into
a single argument).  I decided that it was less confusing to always show
the expansion arrow in the trace when debugmode(e) is enabled, rather than
eliding it when the expansion is the empty string, but if this is a
problem, I don't mind reverting that portion of the patch.  Oh, and
tracing debugmode now works (previously, calling debugmode intentionally
wiped the current trace line, because it had been causing incomplete trace
line output).

2006-10-10  Eric Blake  <address@hidden>

        Trace improvements: debugmode(c) was always printing the last two
        lines paired, combine them; and show non-text expansions.
        * m4/macro.c (trace_prepre): Update to show what the macro will
        expand to.
        (trace_pre): No need to special-case on debugmode(c).
        (trace_post): Likewise.  Also, show non-text expansions.
        (expand_macro): Update caller.  Collecting arguments can change
        debug mode, so cache values beforehand.
        (trace_format): Remove support for unused %l%S%r, and fix support
        for %z to match gcc's attribute((printf)).
        (trace_header): Update caller.
        * m4/input.c (struct m4_input_block): Rename from input_block.
        (struct input_funcs): Add print_func member.
        (file_print, builtin_unget, builtin_print, string_print)
        (m4_input_print): New functions.
        (m4_push_string_finish): Change return type.
        (m4_push_file): Fix missing use of close parameter.
        * m4/debug.c (m4_debug_decode): Don't clear pending traces.
        * m4/m4module.h (m4_input_print): New prototype.
        * tests/builtins.at (debug, esyscmd, multiquotes, syscmd): Update
        to match behavior change.
        * tests/options.at (--debug): Likewise.
        * tests/macros.at (Propagation of traceon)
        (Propagation of --trace): Likewise.
        * tests/others.at (stderr closed, stdout closed, stdin closed):
        Likewise.
        * doc/m4.texinfo (Forloop): Simplify.
        (Trace): Update to changed behavior.
        (Debugmode): Document this change.
        * src/main.c (usage): Likewise.
        * NEWS: Likewise.

- --
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

iD8DBQFFK5Vn84KuGfSFAYARAg4iAJ43dsO0O34guaBcC/TwMk+k9WzZqgCgj5qd
Su3DS4Vwg+cX73yAhCvjY/4=
=Xf8q
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.25
diff -u -p -r1.25 NEWS
--- NEWS        6 Oct 2006 15:24:10 -0000       1.25
+++ NEWS        10 Oct 2006 12:40:26 -0000
@@ -60,10 +60,13 @@ promoted to 2.0.
 
 * New `m' flag to `-d'/`--debug' option or `debugmode' macro traces
   actions related to module loading and unloading, and affects `dumpdef'
-  output to show where builtins come from.  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.
+  and trace output to show where builtins come from.  New `s' flag shows
+  the entire stack of `pushdef' definitions during `dumpdef'.  The `c' flag
+  has been updated to output two lines instead of three (since the last two
+  had always been paired), and to add information to the first line to show
+  the definition of the macro being expanded.  The 'e' flag has been
+  updated to output non-text expansions.  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.60
diff -u -p -r1.60 m4.texinfo
--- doc/m4.texinfo      6 Oct 2006 18:24:31 -0000       1.60
+++ doc/m4.texinfo      10 Oct 2006 12:40:28 -0000
@@ -2508,16 +2508,14 @@ Here is the actual implementation of @co
 
 @comment ignore
 @example
-define(`forloop',
-  `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')')
+define(`forloop', `pushdef(`$1', `$2')_forloop($@@)popdef(`$1')')
 define(`_forloop',
-  `$4`'ifelse($1, `$3', ,
-    `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
+       `$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@@)')')
 @end example
 
-Notice the careful use of quotes.  Only three macro arguments are
+Notice the careful use of quotes.  Certain macro arguments are
 unquoted, each for its own reason.  Try to find out @emph{why} these
-three arguments are left unquoted, and see what happens if they are
+arguments are left unquoted, and see what happens if they are
 quoted.
 
 Now, even though these two macros are useful, they are still not robust
@@ -2814,22 +2812,22 @@ $ @kbd{m4 -d}
 traceon
 @result{}
 define(`foo', `bar')
address@hidden: -1- define(`foo', `bar')
address@hidden: -1- define(`foo', `bar') -> `'
 @result{}
 foo # traced, even though foo was not defined at traceon
 @error{}m4trace: -1- foo -> `bar'
 @result{}bar # traced, even though foo was not defined at traceon
 traceoff(`foo')
address@hidden: -1- traceoff(`foo')
address@hidden: -1- traceoff(`foo') -> `'
 @result{}
 foo # traced, since global tracing is still on
 @error{}m4trace: -1- foo -> `bar'
 @result{}bar # traced, since global tracing is still on
 traceon(`foo')
address@hidden: -1- traceon(`foo')
address@hidden: -1- traceon(`foo') -> `'
 @result{}
 traceoff
address@hidden: -1- traceoff
address@hidden: -1- traceoff -> `'
 @result{}
 foo # traced, since foo is now traced by name
 @error{}m4trace: -1- foo -> `bar'
@@ -2914,15 +2912,15 @@ invoking the macro.  Arguments are subje
 specified by @code{debuglen} (@pxref{Debuglen}).
 
 @item c
-In trace output, show several trace lines for each macro call.  A line
-is shown when the macro is seen, but before the arguments are collected;
-a second line when the arguments have been collected and a third line
-after the call has completed.
+In trace output, show an additional line for each macro call, prior to
+the arguments being collected, that shows the definition of the macro
+that will be used for the expansion.  The definition is subject to
+length truncation specified by @code{debuglen} (@pxref{Debuglen}).
 
 @item e
-In trace output, show the expansion of each macro call, if it is not
-void.  The expansion is subject to length truncation specified by
address@hidden (@pxref{Debuglen}).
+In trace output, show the expansion of each macro call.  The expansion
+is subject to length truncation specified by @code{debuglen}
+(@pxref{Debuglen}).
 
 @item f
 In debug and trace output, include the name of the current input file in
@@ -2938,8 +2936,9 @@ output line.
 
 @item m
 In debug output, print a message each time a module is manipulated
-(@pxref{Modules}).  In dumpdef output, follow builtin macros with their
-module name, surrounded by braces (@address@hidden@}}).
+(@pxref{Modules}).  In trace output when the @samp{c} flag is in effect,
+and in dumpdef output, follow builtin macros with their module name,
+surrounded by braces (@address@hidden@}}).
 
 @item p
 In debug output, print a message when a named file is found through the
@@ -2996,10 +2995,12 @@ encountered, an error is issued.
 The expansion of @code{debugmode} is void.
 @end deffn
 
address@hidden options: -d-V
 @example
-define(`foo', `FOO')
+$ @kbd{m4}
+define(`foo', `FOO$1')
 @result{}
-traceon(`foo')
+traceon(`foo', `divnum')
 @result{}
 debugmode()
 @result{}
@@ -3011,11 +3012,16 @@ debugmode
 foo
 @error{}m4trace: -1- foo
 @result{}FOO
-debugmode(`+l')
+debugmode(`+clmx')
address@hidden
+foo(divnum)
address@hidden:8: -1- id 8: foo ... = FOO$1
address@hidden:8: -2- id 9: divnum ... = <divnum>@address@hidden
address@hidden:8: -2- id 9: divnum
address@hidden:8: -1- id 8: foo
address@hidden
+debugmode(`-m')
 @result{}
-foo
address@hidden:8: -1- foo
address@hidden
 @end example
 
 @node Debuglen
Index: m4/debug.c
===================================================================
RCS file: /sources/m4/m4/m4/debug.c,v
retrieving revision 1.28
diff -u -p -r1.28 debug.c
--- m4/debug.c  5 Oct 2006 23:07:28 -0000       1.28
+++ m4/debug.c  10 Oct 2006 12:40:28 -0000
@@ -104,12 +104,6 @@ m4_debug_decode (m4 *context, int previo
        }
     }
 
-  /* This is to avoid screwing up the trace output due to changes in the
-     debug_level.  */
-
-  obstack_free (&context->trace_messages,
-               obstack_finish (&context->trace_messages));
-
   switch (mode)
     {
     case '\0':
Index: m4/input.c
===================================================================
RCS file: /sources/m4/m4/m4/input.c,v
retrieving revision 1.49
diff -u -p -r1.49 input.c
--- m4/input.c  4 Oct 2006 03:57:00 -0000       1.49
+++ m4/input.c  10 Oct 2006 12:40:28 -0000
@@ -33,7 +33,7 @@
    text), single characters, or quoted builtin definitions (as returned by
    the builtin "defn").  Unread input is organized in a stack,
    implemented with an obstack.  Each input source is described by a
-   "struct input_block".  The obstack is "input_stack".  The top of the
+   "struct m4_input_block".  The obstack is "input_stack".  The top of the
    input stack is "isp".
 
    Each input_block has an associated struct input_funcs, that defines
@@ -71,34 +71,34 @@
 
 static int   file_peek                 (void);
 static int   file_read                 (m4 *);
-static void  file_unget                (int ch);
-static void  file_clean                (m4 *context);
-static void  init_builtin_token        (m4 *context, m4_symbol_value *token);
+static void  file_unget                (int);
+static void  file_clean                (m4 *);
+static void  init_builtin_token        (m4 *, m4_symbol_value *);
 static int   builtin_peek              (void);
 static int   builtin_read              (m4 *);
-static bool  match_input               (m4 *context, const unsigned char *s,
-                                        bool);
-static int   next_char                 (m4 *context);
-static int   peek_char                 (m4 *context);
-static void  pop_input                 (m4 *context);
+static bool  match_input               (m4 *, const unsigned char *, bool);
+static int   next_char                 (m4 *);
+static int   peek_char                 (m4 *);
+static void  pop_input                 (m4 *);
 static int   single_peek               (void);
 static int   single_read               (m4 *);
 static int   string_peek               (void);
 static int   string_read               (m4 *);
-static void  string_unget              (int ch);
-static void  unget_input               (int ch);
+static void  string_unget              (int);
+static void  unget_input               (int);
 
 struct input_funcs
 {
-  int (*peek_func) (void);     /* function to peek input */
-  int (*read_func) (m4 *);     /* function to read input */
-  void (*unget_func) (int);    /* function to unread input */
-  void (*clean_func) (m4 *);   /* function to clean up */
+  int  (*peek_func)    (void); /* function to peek input */
+  int  (*read_func)    (m4 *); /* function to read input */
+  void (*unget_func)   (int);  /* function to unread input */
+  void (*clean_func)   (m4 *); /* function to clean up */
+  void (*print_func)   (m4 *, m4_obstack *); /* output trace expansion */
 };
 
-struct input_block
+struct m4_input_block
 {
-  struct input_block *prev;    /* previous input_block on the input stack */
+  m4_input_block *prev;                /* previous input_block on the input 
stack */
   struct input_funcs *funcs;   /* functions on this input_block */
 
   union
@@ -133,7 +133,7 @@ struct input_block
          m4_hash *arg_signature; /* argument signature for builtin.  */
          unsigned int min_args;  /* argv minima for the builtin. */
          unsigned int max_args;  /* argv maxima for the builtin. */
-         bool traced;    /* true iff builtin is traced. */
+         bool traced;            /* true iff builtin is traced. */
          bool read;              /* true iff block has been read. */
        }
       u_b;
@@ -141,8 +141,6 @@ struct input_block
   u;
 };
 
-typedef struct input_block input_block;
-
 
 /* Obstack for storing individual tokens.  */
 static m4_obstack token_stack;
@@ -161,13 +159,13 @@ static m4_obstack *current_input;
 static char *token_bottom;
 
 /* Pointer to top of current_input.  */
-static input_block *isp;
+static m4_input_block *isp;
 
 /* Pointer to top of wrapup_stack.  */
-static input_block *wsp;
+static m4_input_block *wsp;
 
 /* Aux. for handling split m4_push_string ().  */
-static input_block *next;
+static m4_input_block *next;
 
 /* Flag for next_char () to increment current_line.  */
 static bool start_of_input_line;
@@ -249,8 +247,17 @@ file_clean (m4 *context)
     m4_set_output_line (context, -1);
 }
 
+static void
+file_print (m4 *context, m4_obstack *obs)
+{
+  const char *text = m4_get_current_file (context);
+  obstack_grow (obs, "<file: ", strlen ("<file: "));
+  obstack_grow (obs, text, strlen (text));
+  obstack_1grow (obs, '>');
+}
+
 static struct input_funcs file_funcs = {
-  file_peek, file_read, file_unget, file_clean
+  file_peek, file_read, file_unget, file_clean, file_print
 };
 
 /* m4_push_file () pushes an input file FP with name TITLE on the
@@ -264,9 +271,9 @@ static struct input_funcs file_funcs = {
   alone is taken as belonging to the line it ends, and the current
   line number is not incremented until the next character is read.  */
 void
-m4_push_file (m4 *context, FILE *fp, const char *title, bool close)
+m4_push_file (m4 *context, FILE *fp, const char *title, bool close_file)
 {
-  input_block *i;
+  m4_input_block *i;
 
   if (next != NULL)
     {
@@ -277,12 +284,13 @@ m4_push_file (m4 *context, FILE *fp, con
   m4_debug_message (context, M4_DEBUG_TRACE_INPUT,
                    _("input read from %s"), title);
 
-  i = (input_block *) obstack_alloc (current_input,
-                                    sizeof (struct input_block));
+  i = (m4_input_block *) obstack_alloc (current_input,
+                                       sizeof (m4_input_block));
   i->funcs = &file_funcs;
 
   i->u.u_f.file = fp;
   i->u.u_f.end = false;
+  i->u.u_f.close = close_file;
   i->u.u_f.name = m4_get_current_file (context);
   i->u.u_f.lineno = m4_get_current_line (context);
   i->u.u_f.out_lineno = m4_get_output_line (context);
@@ -300,7 +308,7 @@ m4_push_file (m4 *context, FILE *fp, con
 static int
 builtin_peek (void)
 {
-  if (isp->u.u_b.read == true)
+  if (isp->u.u_b.read)
     return CHAR_RETRY;
 
   return CHAR_BUILTIN;
@@ -309,15 +317,43 @@ builtin_peek (void)
 static int
 builtin_read (m4 *context M4_GNUC_UNUSED)
 {
-  if (isp->u.u_b.read == true)
+  if (isp->u.u_b.read)
     return CHAR_RETRY;
 
   isp->u.u_b.read = true;
   return CHAR_BUILTIN;
 }
 
+static void
+builtin_unget (int ch)
+{
+  assert (ch == CHAR_BUILTIN && isp->u.u_b.read);
+  isp->u.u_b.read = false;
+}
+
+static void
+builtin_print (m4 *context, m4_obstack *obs)
+{
+  const m4_builtin *bp;
+  const char *text;
+
+  bp = m4_builtin_find_by_func (NULL, isp->u.u_b.func);
+  assert (bp);
+  text = bp->name;
+  obstack_1grow (obs, '<');
+  obstack_grow (obs, text, strlen (text));
+  obstack_1grow (obs, '>');
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_MODULE))
+    {
+      text = m4_get_module_name (isp->u.u_b.handle);
+      obstack_1grow (obs, '{');
+      obstack_grow (obs, text, strlen (text));
+      obstack_1grow (obs, '}');
+    }
+}
+
 static struct input_funcs builtin_funcs = {
-  builtin_peek, builtin_read, NULL, NULL
+  builtin_peek, builtin_read, builtin_unget, NULL, builtin_print
 };
 
 /* m4_push_builtin () pushes TOKEN, which contains a builtin's
@@ -327,7 +363,7 @@ static struct input_funcs builtin_funcs 
 void
 m4_push_builtin (m4_symbol_value *token)
 {
-  input_block *i;
+  m4_input_block *i;
 
   /* Make sure we were passed a builtin function type token.  */
   assert (m4_is_symbol_value_func (token));
@@ -338,8 +374,8 @@ m4_push_builtin (m4_symbol_value *token)
       next = NULL;
     }
 
-  i = (input_block *) obstack_alloc (current_input,
-                                    sizeof (struct input_block));
+  i = (m4_input_block *) obstack_alloc (current_input,
+                                       sizeof (m4_input_block));
   i->funcs = &builtin_funcs;
 
   i->u.u_b.func                = m4_get_symbol_value_func (token);
@@ -372,14 +408,14 @@ single_read (m4 *context M4_GNUC_UNUSED)
 }
 
 static struct input_funcs single_funcs = {
-  single_peek, single_read, NULL, NULL
+  single_peek, single_read, NULL, NULL, NULL
 };
 
 /* Push a single character CH on to the input stack.  */
 void
 m4_push_single (int ch)
 {
-  input_block *i;
+  m4_input_block *i;
 
   if (next != NULL)
     {
@@ -387,8 +423,8 @@ m4_push_single (int ch)
       next = NULL;
     }
 
-  i = (input_block *) obstack_alloc (current_input,
-                                    sizeof (struct input_block));
+  i = (m4_input_block *) obstack_alloc (current_input,
+                                       sizeof (m4_input_block));
 
   i->funcs = &single_funcs;
 
@@ -424,8 +460,27 @@ string_unget (int ch)
     m4_push_single (ch);
 }
 
+static void
+string_print (m4 *context, m4_obstack *obs)
+{
+  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);
+  const char *text = isp->u.u_s.start;
+  size_t 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));
+}
+
 static struct input_funcs string_funcs = {
-  string_peek, string_read, string_unget, NULL
+  string_peek, string_read, string_unget, NULL, string_print
 };
 
 /* First half of m4_push_string ().  The pointer next points to the new
@@ -439,28 +494,29 @@ m4_push_string_init (m4 *context)
       abort ();
     }
 
-  next = (input_block *) obstack_alloc (current_input,
-                                       sizeof (struct input_block));
+  next = (m4_input_block *) obstack_alloc (current_input,
+                                          sizeof (m4_input_block));
   next->funcs = &string_funcs;
 
   return current_input;
 }
 
 /* Last half of m4_push_string ().  If next is now NULL, a call to
-   m4_push_file () has invalidated the previous call to
-   m4_push_string_init (), so we just give up.  If the new object is
-   void, we do not push it.  The function m4_push_string_finish ()
-   returns a pointer to the finished object.  This pointer is only for
-   temporary use, since reading the next token might release the memory
-   used for the object.  */
-
-const char *
+   m4_push_file () or m4_push_builtin () has pushed a different input
+   block to the top of the stack.  If the new object is void, we do
+   not push it.  The function m4_push_string_finish () returns the
+   opaque finished object, whether that is still a string or has been
+   replaced by a file or builtin; this object can then be used in
+   m4_input_print () during tracing.  This pointer is only for
+   temporary use, since reading the next token might release the
+   memory used for the object.  */
+m4_input_block *
 m4_push_string_finish (void)
 {
-  const char *ret = NULL;
+  m4_input_block *ret = NULL;
 
   if (next == NULL)
-    return NULL;
+    return isp;
 
   if (obstack_object_size (current_input) > 0)
     {
@@ -468,8 +524,7 @@ m4_push_string_finish (void)
       next->u.u_s.start = obstack_finish (current_input);
       next->u.u_s.current = next->u.u_s.start;
       next->prev = isp;
-      isp = next;
-      ret = isp->u.u_s.start;  /* for immediate use only */
+      ret = isp = next;
     }
   else
     obstack_free (current_input, next); /* people might leave garbage on it. */
@@ -477,6 +532,33 @@ m4_push_string_finish (void)
   return ret;
 }
 
+/* When tracing, print a summary of the contents of the input block
+   created by push_string_init/push_string_finish to OBS.  */
+void
+m4_input_print (m4 *context, m4_obstack *obs, m4_input_block *input)
+{
+  assert (context && obs);
+  if (input == NULL)
+    {
+      bool quote = m4_is_debug_bit (context, M4_DEBUG_TRACE_QUOTE);
+      if (quote)
+       {
+         const char *lquote = m4_get_syntax_lquote (M4SYNTAX);
+         const char *rquote = m4_get_syntax_rquote (M4SYNTAX);
+         obstack_grow (obs, lquote, strlen (lquote));
+         obstack_grow (obs, rquote, strlen (rquote));
+       }
+    }
+  else
+    {
+      void (*f) (m4 *, m4_obstack *);
+
+      f = input->funcs->print_func;
+      assert (f);
+      f (context, obs);
+    }
+}
+
 /* The function m4_push_wrapup () pushes a string on the wrapup stack.
    When the normal input stack gets empty, the wrapup stack will become
    the input stack, and m4_push_string () and m4_push_file () will
@@ -488,8 +570,10 @@ m4_push_string_finish (void)
 void
 m4_push_wrapup (const char *s)
 {
-  input_block *i = (input_block *) obstack_alloc (wrapup_stack,
-                                                 sizeof (struct input_block));
+  m4_input_block *i;
+
+  i = (m4_input_block *) obstack_alloc (wrapup_stack,
+                                       sizeof (m4_input_block));
   i->prev = wsp;
 
   i->funcs = &string_funcs;
@@ -508,7 +592,7 @@ m4_push_wrapup (const char *s)
 static void
 pop_input (m4 *context)
 {
-  input_block *tmp = isp->prev;
+  m4_input_block *tmp = isp->prev;
 
   if (isp->funcs->clean_func != NULL)
     (*isp->funcs->clean_func) (context);
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.92
diff -u -p -r1.92 m4module.h
--- m4/m4module.h       7 Oct 2006 17:33:28 -0000       1.92
+++ m4/m4module.h       10 Oct 2006 12:40:28 -0000
@@ -36,6 +36,7 @@ typedef struct m4             m4;
 typedef struct m4_builtin      m4_builtin;
 typedef struct m4_macro                m4_macro;
 typedef struct m4_symbol_value m4_symbol_value;
+typedef struct m4_input_block  m4_input_block;
 
 typedef struct obstack         m4_obstack;
 typedef lt_dlsymlist           m4_export;
@@ -396,13 +397,14 @@ extern    void    m4_skip_line    (m4 *context, c
 
 /* push back input */
 
-extern void    m4_push_file    (m4 *context, FILE *, const char *, bool);
-extern void    m4_push_single  (int ch);
+extern void    m4_push_file    (m4 *, FILE *, const char *, bool);
+extern void    m4_push_single  (int);
 extern void    m4_push_builtin (m4_symbol_value *);
-extern m4_obstack *m4_push_string_init (m4 *context);
-extern const char *m4_push_string_finish (void);
+extern m4_obstack      *m4_push_string_init    (m4 *);
+extern m4_input_block  *m4_push_string_finish  (void);
 extern void    m4_push_wrapup  (const char *);
 extern bool    m4_pop_wrapup   (void);
+extern void    m4_input_print  (m4 *, m4_obstack *, m4_input_block *);
 
 
 
Index: m4/macro.c
===================================================================
RCS file: /sources/m4/m4/m4/macro.c,v
retrieving revision 1.57
diff -u -p -r1.57 macro.c
--- m4/macro.c  29 Sep 2006 12:26:07 -0000      1.57
+++ m4/macro.c  10 Oct 2006 12:40:28 -0000
@@ -25,31 +25,26 @@
 
 #include "m4private.h"
 
-static void    collect_arguments (m4 *context, const char *name,
-                                 m4_symbol *symbol, m4_obstack *argptr,
-                                 m4_obstack *arguments);
-static void    expand_macro      (m4 *context, const char *name,
-                                 m4_symbol *symbol);
-static void    expand_token      (m4 *context, m4_obstack *obs,
-                                 m4__token_type type, m4_symbol_value *token);
-static bool    expand_argument   (m4 *context, m4_obstack *obs,
-                                 m4_symbol_value *argp);
-
-static void    process_macro    (m4 *context, m4_symbol_value *value,
-                                 m4_obstack *expansion, int argc,
-                                 m4_symbol_value **argv);
+#include "intprops.h"
 
-static void    trace_prepre     (m4 *context, const char *, size_t);
-static void    trace_pre        (m4 *context, const char *, size_t, int,
+static void    collect_arguments (m4 *, const char *, m4_symbol *,
+                                 m4_obstack *, m4_obstack *);
+static void    expand_macro      (m4 *, const char *, m4_symbol *);
+static void    expand_token      (m4 *, m4_obstack *, m4__token_type,
+                                 m4_symbol_value *);
+static bool    expand_argument   (m4 *, m4_obstack *, m4_symbol_value *);
+static void    process_macro    (m4 *, m4_symbol_value *, m4_obstack *, int,
                                  m4_symbol_value **);
-static void    trace_post       (m4 *context, const char *, size_t, int,
-                                 m4_symbol_value **, const char *);
 
-/* It would be nice if we could use M4_GNUC_PRINTF(2, 3) on
-   trace_format, but since we don't accept the same set of modifiers,
-   it would lead to compiler warnings.  */
-static void    trace_format     (m4 *context, const char *fmt, ...);
+static void    trace_prepre     (m4 *, const char *, size_t,
+                                 m4_symbol_value *);
+static void    trace_pre        (m4 *, const char *, size_t, int,
+                                 m4_symbol_value **);
+static void    trace_post       (m4 *, const char *, size_t, int,
+                                 m4_symbol_value **, m4_input_block *, bool);
 
+static void    trace_format     (m4 *, const char *, ...)
+  M4_GNUC_PRINTF(2, 3);
 static void    trace_header     (m4 *, size_t);
 static void    trace_flush      (m4 *);
 
@@ -228,14 +223,22 @@ expand_macro (m4 *context, const char *n
   m4_symbol_value **argv;
   int argc;
   m4_obstack *expansion;
-  const char *expanded;
+  m4_input_block *expanded;
   bool traced;
+  bool trace_expansion = false;
   size_t my_call_id;
   m4_symbol_value *value;
 
   /* Grab the current value of this macro, because it may change while
-     collecting arguments.  */
+     collecting arguments.  Likewise, grab any state needed during
+     tracing.  */
   value = m4_get_symbol_value (symbol);
+  traced = (m4_is_debug_bit (context, M4_DEBUG_TRACE_ALL)
+           || m4_get_symbol_traced (symbol));
+  if (traced)
+    trace_expansion = m4_is_debug_bit (context, M4_DEBUG_TRACE_EXPANSION);
+
+  /* Prepare for macro expansion.  */
   VALUE_PENDING (value)++;
   expansion_level++;
   if (m4_get_nesting_limit_opt (context) > 0
@@ -247,14 +250,11 @@ recursion limit of %d exceeded, use -L<N
   macro_call_id++;
   my_call_id = macro_call_id;
 
-  traced = (m4_is_debug_bit (context, M4_DEBUG_TRACE_ALL)
-           || m4_get_symbol_traced (symbol));
-
   obstack_init (&argptr);
   obstack_init (&arguments);
 
   if (traced && m4_is_debug_bit (context, M4_DEBUG_TRACE_CALL))
-    trace_prepre (context, name, my_call_id);
+    trace_prepre (context, name, my_call_id, value);
 
   collect_arguments (context, name, symbol, &argptr, &arguments);
 
@@ -269,7 +269,8 @@ recursion limit of %d exceeded, use -L<N
   expanded = m4_push_string_finish ();
 
   if (traced)
-    trace_post (context, name, my_call_id, argc, argv, expanded);
+    trace_post (context, name, my_call_id, argc, argv, expanded,
+               trace_expansion);
 
   --expansion_level;
   --VALUE_PENDING (value);
@@ -478,21 +479,14 @@ process_macro (m4 *context, m4_symbol_va
    various builtins.  */
 
 /* Tracing output is formatted here, by a simplified printf-to-obstack
-  function trace_format ().  Understands only %S (length-limited
-  string), %s, %d, %z (size_t value), %l (optional left quote) and %r
-  (optional right quote).  */
+   function trace_format ().  Understands only %s, %d, %zu (size_t
+   value).  */
 static void
 trace_format (m4 *context, const char *fmt, ...)
 {
   va_list args;
   char ch;
-
-  int d;
-  size_t z;
-  char nbuf[32];
   const char *s;
-  int slen;
-  int maxlen;
 
   va_start (args, fmt);
 
@@ -504,58 +498,48 @@ trace_format (m4 *context, const char *f
       if (ch == '\0')
        break;
 
-      maxlen = 0;
       switch (*fmt++)
        {
-       case 'S':
-         maxlen = m4_get_max_debug_arg_length_opt (context);
-         /* fall through */
-
        case 's':
          s = va_arg (args, const char *);
          break;
 
-       case 'l':
-         s = m4_is_debug_bit (context, M4_DEBUG_TRACE_QUOTE)
-               ? m4_get_syntax_lquote (M4SYNTAX)
-               : "";
-         break;
-
-       case 'r':
-         s = m4_is_debug_bit(context, M4_DEBUG_TRACE_QUOTE)
-               ? m4_get_syntax_rquote (M4SYNTAX)
-               : "";
-         break;
-
        case 'd':
-         d = va_arg (args, int);
-         sprintf (nbuf, "%d", d);
-         s = nbuf;
+         {
+           int d = va_arg (args, int);
+           char nbuf[INT_BUFSIZE_BOUND (int)];
+
+           sprintf (nbuf, "%d", d);
+           s = nbuf;
+         }
          break;
 
        case 'z':
-         if (sizeof (size_t) < sizeof (int))
-           z = va_arg (args, int);
-         else
-           z = va_arg (args, size_t);
-         /* FIXME - it would be nice to assume POSIX-mandated %zu.  */
-         sprintf (nbuf, "%lu", (unsigned long) z);
-         s = nbuf;
+         /* GNU assumption: Although POSIX allows size_t to be just
+            16 bits, independently of int, GNU assumes is at least as
+            big as int.  Likewise, although POSIX allows size_t to be
+            bigger than unsigned long in some compilation
+            environments, GNU assumes that size_t always fits in
+            unsigned long.  Unfortunately, GNU does not assume that
+            %zu is portable, yet.  */
+         ch = *fmt++;
+         assert (ch == 'u');
+         assert (sizeof (size_t) >= sizeof (int));
+         {
+           size_t z = va_arg (args, size_t);
+           char nbuf[INT_BUFSIZE_BOUND (size_t)];
+
+           sprintf (nbuf, "%lu", (unsigned long) z);
+           s = nbuf;
+         }
          break;
 
        default:
-         s = "";
+         abort ();
          break;
        }
 
-      slen = strlen (s);
-      if (maxlen == 0 || maxlen > slen)
-       obstack_grow (&context->trace_messages, s, slen);
-      else
-       {
-         obstack_grow (&context->trace_messages, s, maxlen);
-         obstack_grow (&context->trace_messages, "...", 3);
-       }
+      obstack_grow (&context->trace_messages, s, strlen (s));
     }
 
   va_end (args);
@@ -573,9 +557,9 @@ trace_header (m4 *context, size_t id)
       if (m4_is_debug_bit (context, M4_DEBUG_TRACE_LINE))
        trace_format (context, "%d:", m4_get_current_line (context));
     }
-  trace_format (context, " -%z- ", expansion_level);
+  trace_format (context, " -%zu- ", expansion_level);
   if (m4_is_debug_bit (context, M4_DEBUG_TRACE_CALLID))
-    trace_format (context, "id %z: ", id);
+    trace_format (context, "id %zu: ", id);
 }
 
 /* Print current tracing line, and clear the obstack.  */
@@ -595,11 +579,19 @@ trace_flush (m4 *context)
 /* Do pre-argument-collction tracing for macro NAME.  Used from
    expand_macro ().  */
 static void
-trace_prepre (m4 *context, const char *name, size_t id)
+trace_prepre (m4 *context, const char *name, size_t id, m4_symbol_value *value)
 {
+  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);
+  bool module = m4_is_debug_bit (context, M4_DEBUG_TRACE_MODULE);
+
   trace_header (context, id);
-  trace_format (context, "%s ...", name);
-  trace_flush  (context);
+  trace_format (context, "%s ... = ", name);
+  m4_symbol_value_print (value, &context->trace_messages,
+                        quote, lquote, rquote, arg_length, module);
+  trace_flush (context);
 }
 
 /* Format the parts of a trace line, that can be made before the macro is
@@ -632,29 +624,19 @@ trace_pre (m4 *context, const char *name
        }
       trace_format (context, ")");
     }
-
-  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_CALL))
-    {
-      trace_format (context, " -> ???");
-      trace_flush  (context);
-    }
 }
 
 /* Format the final part of a trace line and print it all.  Used from
    expand_macro ().  */
 static void
 trace_post (m4 *context, const char *name, size_t id,
-           int argc, m4_symbol_value **argv, const char *expanded)
+           int argc, m4_symbol_value **argv, m4_input_block *expanded,
+           bool trace_expansion)
 {
-  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_CALL))
-    {
-      trace_header (context, id);
-      trace_format (context, "%s%s", name, (argc > 1) ? "(...)" : "");
-    }
-
-  if (expanded && m4_is_debug_bit (context, M4_DEBUG_TRACE_EXPANSION))
+  if (trace_expansion)
     {
-      trace_format (context, " -> %l%S%r", expanded);
+      trace_format (context, " -> ");
+      m4_input_print (context, &context->trace_messages, expanded);
     }
 
   trace_flush (context);
Index: src/main.c
===================================================================
RCS file: /sources/m4/m4/src/main.c,v
retrieving revision 1.94
diff -u -p -r1.94 main.c
--- src/main.c  6 Oct 2006 15:24:10 -0000       1.94
+++ src/main.c  10 Oct 2006 12:40:28 -0000
@@ -139,19 +139,19 @@ Debugging:\n\
 \n\
 FLAGS is any of:\n\
   a   show actual arguments in trace\n\
-  c   show before collect, after collect and after call in trace\n\
+  c   show definition line 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 module information in debug and dumpdef\n\
+  m   show module information in trace, debug, and dumpdef\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 named traceon state\n\
-  x   add a unique macro call id in trace, useful with c\n\
+  x   include unique macro call id in trace, useful with c\n\
   V   shorthand for all of the above flags\n\
 "), stdout);
       fputs (_("\
Index: tests/builtins.at
===================================================================
RCS file: /sources/m4/m4/tests/builtins.at,v
retrieving revision 1.22
diff -u -p -r1.22 builtins.at
--- tests/builtins.at   6 Oct 2006 18:24:31 -0000       1.22
+++ tests/builtins.at   10 Oct 2006 12:40:28 -0000
@@ -40,15 +40,12 @@ AT_DATA([[expout]],
 ]])
 
 AT_DATA([[experr]],
-[[m4trace: -1- countdown ...
-m4trace: -1- countdown(`2') -> ???
-m4trace: -1- countdown(...) -> `2 ifelse(eval(2 > 0), 1, `countdown(decr(2))', 
`Liftoff')'
-m4trace: -1- countdown ...
-m4trace: -1- countdown(`1') -> ???
-m4trace: -1- countdown(...) -> `1 ifelse(eval(1 > 0), 1, `countdown(decr(1))', 
`Liftoff')'
-m4trace: -1- countdown ...
-m4trace: -1- countdown(`0') -> ???
-m4trace: -1- countdown(...) -> `0 ifelse(eval(0 > 0), 1, `countdown(decr(0))', 
`Liftoff')'
+[[m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, 
`countdown(decr($1))', `Liftoff')'
+m4trace: -1- countdown(`2') -> `2 ifelse(eval(2 > 0), 1, `countdown(decr(2))', 
`Liftoff')'
+m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, 
`countdown(decr($1))', `Liftoff')'
+m4trace: -1- countdown(`1') -> `1 ifelse(eval(1 > 0), 1, `countdown(decr(1))', 
`Liftoff')'
+m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, 
`countdown(decr($1))', `Liftoff')'
+m4trace: -1- countdown(`0') -> `0 ifelse(eval(0 > 0), 1, `countdown(decr(0))', 
`Liftoff')'
 ]])
 
 AT_CHECK_M4([debug.m4], 0, expout, experr)
@@ -143,7 +140,7 @@ AT_DATA([in.m4], [[esyscmd(`echo hi >&3'
 AT_CHECK_M4([3>&-], [0], [], [stderr], [in.m4])
 mv stderr experr
 AT_CHECK_M4([--debugfile=trace -tdnl 3>&-], [0], [], [experr], [in.m4])
-AT_CHECK([cat trace], [0], [[m4trace: -1- dnl
+AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `'
 ]])
 
 dnl Ensure that esyscmd does not inherit any unnecessary fds from diversions.
@@ -455,31 +452,31 @@ foo bar
 ]])
 
 AT_DATA([[experr]],
-[[m4trace: -1- changequote(`[', `]')
-m4trace: -1- dnl
-m4trace: -1- changequote([``], [''])
-m4trace: -1- dnl
-m4trace: -1- define(``foo'', ````FOO'''')
-m4trace: -1- dnl
+[[m4trace: -1- changequote(`[', `]') -> []
+m4trace: -1- dnl -> []
+m4trace: -1- changequote([``], ['']) -> ``''
+m4trace: -1- dnl -> ``''
+m4trace: -1- define(``foo'', ````FOO'''') -> ``''
+m4trace: -1- dnl -> ``''
 foo:   ````FOO''''
-m4trace: -1- dumpdef(``foo'')
-m4trace: -1- dnl
-m4trace: -1- changequote(``!'', ``!'')
-m4trace: -1- dnl
+m4trace: -1- dumpdef(``foo'') -> ``''
+m4trace: -1- dnl -> ``''
+m4trace: -1- changequote(``!'', ``!'') -> !!
+m4trace: -1- dnl -> !!
 m4trace: -1- foo -> !``FOO''!
 foo:   !``FOO''!
-m4trace: -1- dumpdef(!foo!)
-m4trace: -1- dnl
-m4trace: -1- define(!bar!, !BAR!)
+m4trace: -1- dumpdef(!foo!) -> !!
+m4trace: -1- dnl -> !!
+m4trace: -1- define(!bar!, !BAR!) -> !!
 m4trace: -1- bar -> !BAR!
-m4trace: -1- changequote(!>*>*>*>*>!, !<*<*<*<*<!)
-m4trace: -1- dnl
+m4trace: -1- changequote(!>*>*>*>*>!, !<*<*<*<*<!) -> >*>*>*>*><*<*<*<*<
+m4trace: -1- dnl -> >*>*>*>*><*<*<*<*<
 m4trace: -1- foo -> >*>*>*>*>``FOO''<*<*<*<*<
 m4trace: -1- bar -> >*>*>*>*>BAR<*<*<*<*<
 bar:   >*>*>*>*>BAR<*<*<*<*<
 foo:   >*>*>*>*>``FOO''<*<*<*<*<
-m4trace: -1- dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<)
-m4trace: -1- dnl
+m4trace: -1- dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<) -> 
>*>*>*>*><*<*<*<*<
+m4trace: -1- dnl -> >*>*>*>*><*<*<*<*<
 ]])
 
 AT_CHECK_M4([multiquotes.m4], 0, expout, experr)
@@ -636,7 +633,7 @@ AT_DATA([in.m4], [[syscmd(`echo hi >&3')
 AT_CHECK_M4([3>&-], [0], [], [stderr], [in.m4])
 mv stderr experr
 AT_CHECK_M4([--debugfile=trace -tdnl 3>&-], [0], [], [experr], [in.m4])
-AT_CHECK([cat trace], [0], [[m4trace: -1- dnl
+AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `'
 ]])
 
 dnl Ensure that syscmd does not inherit any unnecessary fds from diversions.
Index: tests/macros.at
===================================================================
RCS file: /sources/m4/m4/tests/macros.at,v
retrieving revision 1.9
diff -u -p -r1.9 macros.at
--- tests/macros.at     20 Sep 2006 04:04:29 -0000      1.9
+++ tests/macros.at     10 Oct 2006 12:40:28 -0000
@@ -233,7 +233,7 @@ m4trace: -1- _hanoi
 m4trace: -2- eval
 m4trace: -1- ifelse
 m4trace: -1- move
-
+m4trace: -1- debugmode
 m4trace: -1- hanoi(`2') -> `_hanoi(`2', source, destination, auxilliary)'
 m4trace: -1- _hanoi(`2', `source', `destination', `auxilliary') -> 
`ifelse(eval(`2'<=1), 1, `move(source, destination)',
 `_hanoi(decr(2), source, auxilliary, destination)move(source, 
destination)_hanoi(decr(2), auxilliary, destination, source)')'
@@ -255,7 +255,7 @@ m4trace: -2- eval(`1<=1') -> `1'
 m4trace: -1- ifelse(`1', `1', `move(auxilliary, destination)', 
`_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, 
destination)_hanoi(decr(1), source, destination, auxilliary)') -> 
`move(auxilliary, destination)'
 m4trace: -1- move(`auxilliary', `destination') -> `Move one disk from 
`auxilliary' to `destination'.
 '
-m4trace: -1- debugmode
+m4trace: -1- debugmode -> @&t@
 m4trace: -1- _hanoi(2, source, destination, auxilliary) -> 
ifelse(eval(`2'<=1), 1, `move(source, destination)',
 `_hanoi(decr(2), source, auxilliary, destination)move(source, 
destination)_hanoi(decr(2), auxilliary, destination, source)')
 m4trace: -1- _hanoi(1, source, auxilliary, destination) -> 
ifelse(eval(`1'<=1), 1, `move(source, auxilliary)',
@@ -333,9 +333,9 @@ AT_DATA([[expout]],
 ]])
 
 AT_DATA([[experr]],
-[[m4trace: -1- define(`my_define', <define>)
-m4trace: -1- define(`my_define', <define>)
-m4trace: -1- define(`foo', `bar')
+[[m4trace: -1- define(`my_define', <define>) -> `'
+m4trace: -1- define(`my_define', <define>) -> `'
+m4trace: -1- define(`foo', `bar') -> `'
 ]])
 
 AT_CHECK_M4([trace2.m4], 0, expout, experr)
@@ -395,9 +395,9 @@ AT_DATA([[expout]],
 ]])
 
 AT_DATA([[experr]],
-[[m4trace: -1- define(`my_define', <define>)
-m4trace: -1- define(`my_define', <define>)
-m4trace: -1- define(`foo', `bar')
+[[m4trace: -1- define(`my_define', <define>) -> `'
+m4trace: -1- define(`my_define', <define>) -> `'
+m4trace: -1- define(`foo', `bar') -> `'
 ]])
 
 AT_CHECK_M4([-t define -daeq trace3.m4], 0, expout, experr)
Index: tests/options.at
===================================================================
RCS file: /sources/m4/m4/tests/options.at,v
retrieving revision 1.17
diff -u -p -r1.17 options.at
--- tests/options.at    6 Oct 2006 15:24:10 -0000       1.17
+++ tests/options.at    10 Oct 2006 12:40:28 -0000
@@ -168,12 +168,10 @@ m4debug: module gnu: builtins loaded
 m4debug: module gnu: macros loaded
 m4debug: path search for `in' found `in'
 m4debug: input read from in
-m4trace:in:1: -1- id 1: divnum ...
-m4trace:in:1: -1- id 1: divnum -> ???
+m4trace:in:1: -1- id 1: divnum ... = <divnum>{m4}
 m4trace:in:1: -1- id 1: divnum -> `0'
-m4trace:in:2: -1- id 2: len ...
-m4trace:in:2: -1- id 2: len(`abc') -> ???
-m4trace:in:2: -1- id 2: len(...) -> `3'
+m4trace:in:2: -1- id 2: len ... = <len>{m4}
+m4trace:in:2: -1- id 2: len(`abc') -> `3'
 m4debug:in:3: input exhausted
 m4debug: module gnu: symbols unloaded
 m4debug: module gnu: finish hook called
Index: tests/others.at
===================================================================
RCS file: /sources/m4/m4/tests/others.at,v
retrieving revision 1.23
diff -u -p -r1.23 others.at
--- tests/others.at     7 Oct 2006 05:02:56 -0000       1.23
+++ tests/others.at     10 Oct 2006 12:40:28 -0000
@@ -387,7 +387,7 @@ AT_DATA([in.m4], [[errprint(`hello world
 ]])
 AT_CHECK_M4([--debugfile=trace -terrprint 2>&-], [1], [], [], [in.m4])
 AT_CHECK([cat trace], [0], [[m4trace: -1- errprint(`hello world
-')
+') -> `'
 ]])
 
 dnl spilled diversion file must not collide with closed stderr
@@ -442,9 +442,10 @@ AT_CHECK_M4([-], [1], [],
 [[m4:stdin:1: error reading file `stdin'
 ]], [-])
 
-dnl only error once when stdin must be read
+dnl error once per command-line attempt to read stdin
 AT_CHECK_M4([- in.m4 -], [1], [[hello world
 ]], [[m4:stdin:1: error reading file `stdin'
+m4:stdin:1: error reading file `stdin'
 ]], [-])
 
 dnl command line and trace file must not collide with stdin
@@ -454,7 +455,7 @@ mv stderr experr
 AT_DATA([in.m4], [[syscmd(`cat')dnl
 ]])
 AT_CHECK_M4([--debugfile=trace -tdnl in.m4], [0], [], [experr], [-])
-AT_CHECK([cat trace], [0], [[m4trace: -1- dnl
+AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `'
 ]])
 
 dnl diversions must not collide with stdin
@@ -525,7 +526,7 @@ dnl
 AT_CHECK_M4([--debugfile=trace -tdnl >&-], [1], [],
 [[m4: write error: Bad file descriptor
 ]], [in.m4])
-AT_CHECK([cat trace], [0], [[m4trace: -1- dnl
+AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `'
 ]])
 
 dnl esyscmd always has valid stdout

reply via email to

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