m4-commit
[Top][All Lists]
Advanced

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

[SCM] GNU M4 source repository branch, master, updated. cvs-readonly-86-


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, master, updated. cvs-readonly-86-g6608fa6
Date: Wed, 19 Mar 2008 02:04:34 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU M4 source repository".

http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=6608fa6d084d320401f049b259adcf6b383eaa43

The branch, master has been updated
       via  6608fa6d084d320401f049b259adcf6b383eaa43 (commit)
       via  1761b0d68f12c701abfdcf0a36d955f787849e3c (commit)
       via  44c6706b4fa8c438df0f1ff44a5da6e2b3f8b294 (commit)
      from  6b1c5a2cbd84a5eb48fe352b7bc8c0568a020d62 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6608fa6d084d320401f049b259adcf6b383eaa43
Author: Eric Blake <address@hidden>
Date:   Tue Mar 18 14:00:39 2008 -0600

    Stage 20b: make m4wrap obey POSIX fifo ordering.
    
    * m4/m4module.h (m4_wrap_args): Add prototype.
    * m4/m4private.h (enum m4__symbol_chain_type): Add M4__CHAIN_LOC.
    (struct m4__symbol_chain): Add struct u_l.
    * m4/input.c (m4_push_wrapup_init, m4_push_wrapup_finish): Use
    new link type.
    (composite_peek, composite_read, composite_clean): Handle location
    link.
    * m4/macro.c (m4_wrap_args): New function.
    * modules/m4.c (m4wrap): Use it.
    * doc/m4.texinfo (M4wrap): Sync with branch and POSIX.
    (Extensions): Document extension of multiple arguments.
    (Location, Improved m4wrap): Adjust example to match FIFO order.
    * tests/builtins.at (wrap): Likewise.
    * NEWS: Document this change.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 1761b0d68f12c701abfdcf0a36d955f787849e3c
Author: Eric Blake <address@hidden>
Date:   Mon Mar 17 16:03:57 2008 -0600

    Stage 20a: reduce unget's in input engine.
    
    * m4/input.c (struct input_funcs): Alter read_func prototype.
    (next_char, file_read, buildin_read, string_read, composite_read):
    Add allow_argv parameter.
    (init_builtin_token, init_argv_symbol): Require all prior input to
    be consumed.
    (m4_skip_line, match_input, consume_syntax): Adjust callers.
    (m4__next_token): Consume first byte without peek.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 44c6706b4fa8c438df0f1ff44a5da6e2b3f8b294
Author: Eric Blake <address@hidden>
Date:   Mon Mar 17 08:16:45 2008 -0600

    Update for fresh bootstrap.
    
    * ltdl/m4/gnulib-cache.m4: Updated copyright from upstream.
    
    Signed-off-by: Eric Blake <address@hidden>

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog               |   44 +++++++++++-
 NEWS                    |    6 +-
 doc/m4.texinfo          |   62 ++++++++++++-----
 ltdl/m4/gnulib-cache.m4 |    2 +-
 m4/input.c              |  179 ++++++++++++++++++++++++++++-------------------
 m4/m4module.h           |    2 +-
 m4/m4private.h          |   13 +++-
 m4/macro.c              |   68 ++++++++++++++++++
 modules/m4.c            |    8 +--
 tests/builtins.at       |    2 +-
 10 files changed, 279 insertions(+), 107 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6e602e1..9d3c860 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2008-03-18  Eric Blake  <address@hidden>
+
+       Stage 20b: make m4wrap obey POSIX fifo ordering.
+       Improve input engine to support location changes within symbol
+       chains, then convert m4wrap to always build symbol chain.
+       Memory impact: none.
+       Speed impact: slight penalty, from more m4wrap bookkeeping.
+       * m4/m4module.h (m4_wrap_args): Add prototype.
+       * m4/m4private.h (enum m4__symbol_chain_type): Add M4__CHAIN_LOC.
+       (struct m4__symbol_chain): Add struct u_l.
+       * m4/input.c (m4_push_wrapup_init, m4_push_wrapup_finish): Use
+       new link type.
+       (composite_peek, composite_read, composite_clean): Handle location
+       link.
+       * m4/macro.c (m4_wrap_args): New function.
+       * modules/m4.c (m4wrap): Use it.
+       * doc/m4.texinfo (M4wrap): Sync with branch and POSIX.
+       (Extensions): Document extension of multiple arguments.
+       (Location, Improved m4wrap): Adjust example to match FIFO order.
+       * tests/builtins.at (wrap): Likewise.
+       * NEWS: Document this change.
+
+2008-03-17  Eric Blake  <address@hidden>
+
+       Stage 20a: reduce unget's in input engine.
+       Now that out-of-range input placeholders like CHAR_BUILTIN are
+       consumed outside of next_char, next_token should always consume
+       rather than peek at the first character.  Fewer peeks results in
+       less ungetc overhead.
+       Memory impact: none.
+       Speed impact: noticeable improvement, from fewer function calls.
+       * m4/input.c (struct input_funcs): Alter read_func prototype.
+       (next_char, file_read, buildin_read, string_read, composite_read):
+       Add allow_argv parameter.
+       (init_builtin_token, init_argv_symbol): Require all prior input to
+       be consumed.
+       (m4_skip_line, match_input, consume_syntax): Adjust callers.
+       (m4__next_token): Consume first byte without peek.
+
+       Update for fresh bootstrap.
+       * ltdl/m4/gnulib-cache.m4: Updated copyright from upstream.
+
 2008-03-15  Eric Blake  <address@hidden>
 
        Document join, in order to fix bug in m4wrap example.
@@ -6,7 +48,7 @@
        * Makefile.am (EXTRA_DIST): Add new files.
        * doc/m4.texinfo (Improved m4wrap): New node.
        (Defn, Location): Enhance tests.
-       (Shift): Document the composit macro join.
+       (Shift): Document the composite macro join.
        (Incompatibilities): Move documentation of LIFO vs. FIFO...
        (M4wrap): ...here, to match improved example.
 
diff --git a/NEWS b/NEWS
index 6e2fa40..eea5287 100644
--- a/NEWS
+++ b/NEWS
@@ -91,8 +91,6 @@ promoted to 2.0.
   - FIXME: POSIX recommends using ${10} instead of $10 for the tenth
   positional argument.  We should deprecate $10.
 
- - FIXME: `m4wrap' semantics need an update to FIFO.
-
 ** Removed builtins
 
 *** The experimental `epatsubst' and `eregexp' builtins have been removed
@@ -216,6 +214,10 @@ promoted to 2.0.
 ** Fix regression introduced in 1.4.10b where using `builtin' or `indir'
    to perform nested `shift' calls triggered an assertion failure.
 
+** Fix the `m4wrap' builtin to accumulate wrapped text in FIFO order, as
+   required by POSIX.  The manual mentions a way to restore the LIFO order
+   present in earlier GNU M4 versions.
+
 ** Enhance the `ifdef', `ifelse', and `shift' builtins, as well as all
    user macros, to transparently handle builtin tokens generated by `defn'.
 
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 175d923..6e836f6 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -5204,10 +5204,18 @@ normal input has been exhausted.  This feature is 
normally used to
 initiate cleanup actions before normal exit, e.g., deleting temporary
 files.
 
address@hidden {Builtin (m4)} m4wrap (@var{string}, @dots{})
 To save input text, use the builtin @code{m4wrap}:
-which stores @var{string} and the rest of the arguments in a safe place,
-to be reread when end of input is reached.
+
address@hidden {Builtin (m4)} m4wrap (@var{string}, @dots{})
+Stores @var{string} in a safe place, to be reread when end of input is
+reached.  As a @acronym{GNU} extension, additional arguments are
+concatenated with a space to the @var{string}.
+
+Successive invocations of @code{m4wrap} accumulate saved text in
+first-in, first-out order, as required by @acronym{POSIX}.
+
+The expansion of @code{m4wrap} is void.
+The macro @code{m4wrap} is recognized only with parameters.
 @end deffn
 
 @example
@@ -5225,16 +5233,27 @@ This is the first and last normal input line.
 The saved input is only reread when the end of normal input is seen, and
 not if @code{m4exit} is used to exit @code{m4}.
 
address@hidden FIXME: this contradicts POSIX, which requires that "If the
address@hidden m4wrap macro is used multiple times, the arguments specified
address@hidden shall be processed in the order in which the m4wrap macros were
address@hidden processed."
-It is safe to call @code{m4wrap} from saved text, but then the order in
-which the saved text is reread is undefined.  If @code{m4wrap} is not used
-recursively, the saved pieces of text are reread in the opposite order
-in which they were saved (LIFO---last in, first out).
+It is safe to call @code{m4wrap} from wrapped text, where all the
+recursively wrapped text is deferred until the current wrapped text is
+exhausted.  As of M4 1.4.11, when @code{m4wrap} is not used recursively,
+the saved pieces of text are reread in the same order in which they were
+saved (FIFO---first in, first out), as required by @acronym{POSIX}.
+
address@hidden
+m4wrap(`1
+')
address@hidden
+m4wrap(`2', `3
+')
address@hidden
+^D
address@hidden
address@hidden 3
address@hidden example
 
-It is possible to emulate @acronym{POSIX} behavior even
+However, earlier versions had reverse ordering (LIFO---last in, first
+out), as this behavior is more like the semantics of the C function
address@hidden  It is possible to emulate @acronym{POSIX} behavior even
 with older versions of @acronym{GNU} M4 by including the file
 @address@hidden/@/examples/@/wrapfifo.m4} from the
 distribution:
@@ -5310,13 +5329,13 @@ Invocations of @code{m4wrap} at the same recursion 
level are
 concatenated and rescanned as usual:
 
 @example
-define(`aa', `AA
+define(`ab', `AB
 ')
 @result{}
-m4wrap(`a')m4wrap(`a')
+m4wrap(`a')m4wrap(`b')
 @result{}
 ^D
address@hidden
address@hidden
 @end example
 
 @noindent
@@ -7778,9 +7797,9 @@ m4wrap(`__line__
 ')
 @result{}
 ^D
address@hidden
 @result{}6
 @result{}6
address@hidden
 @end example
 
 The @address@hidden macro behaves like @samp{$0} in shell
@@ -8287,6 +8306,15 @@ once, but @acronym{GNU} @code{m4} correctly handles 
multiple instances
 of @samp{-} on the command line.
 
 @item
address@hidden requires @code{m4wrap} (@pxref{M4wrap}) to act in FIFO
+(first-in, first-out) order, and most other implementations obey this.
+However, versions of @acronym{GNU} @code{m4} earlier than 1.4.11 used
+LIFO order.  Furthermore, @acronym{POSIX} states that only the first
+argument to @code{m4wrap} is saved for later evaluation, but
address@hidden @code{m4} saves and processes all arguments, with output
+separated by spaces.
+
address@hidden
 @acronym{POSIX} states that builtins that require arguments, but are
 called without arguments, have undefined behavior.  Traditional
 implementations simply behave as though empty strings had been passed.
@@ -8943,8 +8971,8 @@ builtin(`m4wrap', ``'define(`bar', 
``$0:'-$1-$*-$#-')bar(`a', `b')
 ')
 @result{}
 ^D
address@hidden:-a-a,b-2-
 @result{}m4wrap0:---0-
address@hidden:-a-a,b-2-
 @end example
 
 Additionally, the computation of @code{_m4wrap_level} and creation of
diff --git a/ltdl/m4/gnulib-cache.m4 b/ltdl/m4/gnulib-cache.m4
index 882db83..958e7b3 100644
--- a/ltdl/m4/gnulib-cache.m4
+++ b/ltdl/m4/gnulib-cache.m4
@@ -1,4 +1,4 @@
-# Copyright (C) 2004-2007 Free Software Foundation, Inc.
+# Copyright (C) 2002-2008 Free Software Foundation, Inc.
 #
 # This file is free software, distributed under the terms of the GNU
 # General Public License.  As a special exception to the GNU General
diff --git a/m4/input.c b/m4/input.c
index 7d27dad..a7f1da9 100644
--- a/m4/input.c
+++ b/m4/input.c
@@ -93,20 +93,24 @@
    between input blocks must update the context accordingly.  */
 
 static int     file_peek               (m4_input_block *, m4 *, bool);
-static int     file_read               (m4_input_block *, m4 *, bool, bool);
+static int     file_read               (m4_input_block *, m4 *, bool, bool,
+                                        bool);
 static void    file_unget              (m4_input_block *, int);
 static bool    file_clean              (m4_input_block *, m4 *, bool);
 static void    file_print              (m4_input_block *, m4 *, m4_obstack *);
 static int     builtin_peek            (m4_input_block *, m4 *, bool);
-static int     builtin_read            (m4_input_block *, m4 *, bool, bool);
+static int     builtin_read            (m4_input_block *, m4 *, bool, bool,
+                                        bool);
 static void    builtin_unget           (m4_input_block *, int);
 static void    builtin_print           (m4_input_block *, m4 *, m4_obstack *);
 static int     string_peek             (m4_input_block *, m4 *, bool);
-static int     string_read             (m4_input_block *, m4 *, bool, bool);
+static int     string_read             (m4_input_block *, m4 *, bool, bool,
+                                        bool);
 static void    string_unget            (m4_input_block *, int);
 static void    string_print            (m4_input_block *, m4 *, m4_obstack *);
 static int     composite_peek          (m4_input_block *, m4 *, bool);
-static int     composite_read          (m4_input_block *, m4 *, bool, bool);
+static int     composite_read          (m4_input_block *, m4 *, bool, bool,
+                                        bool);
 static void    composite_unget         (m4_input_block *, int);
 static bool    composite_clean         (m4_input_block *, m4 *, bool);
 static void    composite_print         (m4_input_block *, m4 *, m4_obstack *);
@@ -115,7 +119,7 @@ static      void    init_builtin_token      (m4 *, 
m4_symbol_value *);
 static void    append_quote_token      (m4 *, m4_obstack *,
                                         m4_symbol_value *);
 static bool    match_input             (m4 *, const char *, bool);
-static int     next_char               (m4 *, bool, bool);
+static int     next_char               (m4 *, bool, bool, bool);
 static int     peek_char               (m4 *, bool);
 static bool    pop_input               (m4 *, bool);
 static void    unget_input             (int);
@@ -138,9 +142,11 @@ struct input_funcs
 
   /* Read input, return an unsigned char, CHAR_BUILTIN if it is a
      builtin, or CHAR_RETRY if none available.  If ALLOW_QUOTE, then
-     CHAR_QUOTE may be returned.  If SAFE, then do not alter the
-     current file or line.  */
-  int  (*read_func)    (m4_input_block *, m4 *, bool allow_quote, bool safe);
+     CHAR_QUOTE may be returned.  If ALLOW_ARGV, then CHAR_ARGV may be
+     returned.  If SAFE, then do not alter the current file or
+     line.  */
+  int  (*read_func)    (m4_input_block *, m4 *, bool allow_quote,
+                        bool allow_argv, bool safe);
 
   /* Unread a single unsigned character or CHAR_BUILTIN, must be the
      same character previously read by read_func.  */
@@ -198,11 +204,7 @@ static m4_obstack token_stack;
 /* Obstack for storing input file names.  */
 static m4_obstack file_names;
 
-/* Wrapup input stack.
-
-   FIXME - m4wrap should be FIFO, which implies a queue, not a stack.
-   While fixing this, m4wrap should also remember what the current
-   file and line are for each chunk of wrapped text.  */
+/* Wrapup input stack.  */
 static m4_obstack *wrapup_stack;
 
 /* Current stack, from input or wrapup.  */
@@ -268,7 +270,7 @@ file_peek (m4_input_block *me, m4 *context M4_GNUC_UNUSED,
 
 static int
 file_read (m4_input_block *me, m4 *context, bool allow_quote M4_GNUC_UNUSED,
-          bool safe M4_GNUC_UNUSED)
+          bool allow_argv M4_GNUC_UNUSED, bool safe M4_GNUC_UNUSED)
 {
   int ch;
 
@@ -394,7 +396,8 @@ builtin_peek (m4_input_block *me, m4 *context 
M4_GNUC_UNUSED,
 
 static int
 builtin_read (m4_input_block *me, m4 *context M4_GNUC_UNUSED,
-             bool allow_quote M4_GNUC_UNUSED, bool safe M4_GNUC_UNUSED)
+             bool allow_quote M4_GNUC_UNUSED, bool allow_argv M4_GNUC_UNUSED,
+             bool safe M4_GNUC_UNUSED)
 {
   /* Not consumed here - wait until init_builtin_token.  */
   return me->u.builtin ? CHAR_BUILTIN : CHAR_RETRY;
@@ -453,7 +456,8 @@ string_peek (m4_input_block *me, m4 *context M4_GNUC_UNUSED,
 
 static int
 string_read (m4_input_block *me, m4 *context M4_GNUC_UNUSED,
-            bool allow_quote M4_GNUC_UNUSED, bool safe M4_GNUC_UNUSED)
+            bool allow_quote M4_GNUC_UNUSED, bool allow_argv M4_GNUC_UNUSED,
+            bool safe M4_GNUC_UNUSED)
 {
   if (!me->u.u_s.len)
     return CHAR_RETRY;
@@ -747,6 +751,8 @@ composite_peek (m4_input_block *me, m4 *context, bool 
allow_argv)
          chain->u.u_a.comma = true;
          m4_push_string_finish ();
          return peek_char (context, allow_argv);
+       case M4__CHAIN_LOC:
+         break;
        default:
          assert (!"composite_peek");
          abort ();
@@ -757,9 +763,11 @@ composite_peek (m4_input_block *me, m4 *context, bool 
allow_argv)
 }
 
 static int
-composite_read (m4_input_block *me, m4 *context, bool allow_quote, bool safe)
+composite_read (m4_input_block *me, m4 *context, bool allow_quote,
+               bool allow_argv, bool safe)
 {
   m4__symbol_chain *chain = me->u.u_c.chain;
+  size_t argc;
   while (chain)
     {
       if (allow_quote && chain->quote_age == m4__quote_age (M4SYNTAX))
@@ -782,7 +790,8 @@ composite_read (m4_input_block *me, m4 *context, bool 
allow_quote, bool safe)
            return CHAR_BUILTIN;
          break;
        case M4__CHAIN_ARGV:
-         if (chain->u.u_a.index == m4_arg_argc (chain->u.u_a.argv))
+         argc = m4_arg_argc (chain->u.u_a.argv);
+         if (chain->u.u_a.index == argc)
            {
              m4__arg_adjust_refcount (context, chain->u.u_a.argv, false);
              break;
@@ -792,6 +801,11 @@ composite_read (m4_input_block *me, m4 *context, bool 
allow_quote, bool safe)
              chain->u.u_a.comma = false;
              return ','; /* FIXME - support M4_SYNTAX_COMMA.  */
            }
+         /* Only return a reference in the quoting is correct and the
+            reference has more than one argument left.  */
+         if (allow_argv && chain->quote_age == m4__quote_age (M4SYNTAX)
+             && chain->u.u_a.quotes && chain->u.u_a.index + 1 < argc)
+           return CHAR_ARGV;
          /* Rather than directly parse argv here, we push another
             input block containing the next unparsed argument from
             argv.  */
@@ -804,7 +818,13 @@ composite_read (m4_input_block *me, m4 *context, bool 
allow_quote, bool safe)
          chain->u.u_a.index++;
          chain->u.u_a.comma = true;
          m4_push_string_finish ();
-         return next_char (context, allow_quote, !safe);
+         return next_char (context, allow_quote, allow_argv, !safe);
+       case M4__CHAIN_LOC:
+         me->file = chain->u.u_l.file;
+         me->line = chain->u.u_l.line;
+         input_change = true;
+         me->u.u_c.chain = chain->next;
+         return next_char (context, allow_quote, allow_argv, !safe);
        default:
          assert (!"composite_read");
          abort ();
@@ -869,6 +889,8 @@ composite_clean (m4_input_block *me, m4 *context, bool 
cleanup)
            }
          m4__arg_adjust_refcount (context, chain->u.u_a.argv, false);
          break;
+       case M4__CHAIN_LOC:
+         return false;
        default:
          assert (!"composite_clean");
          abort ();
@@ -985,14 +1007,36 @@ m4_obstack *
 m4_push_wrapup_init (m4 *context)
 {
   m4_input_block *i;
+  m4__symbol_chain *chain;
 
-  i = (m4_input_block *) obstack_alloc (wrapup_stack, sizeof *i);
-  i->prev = wsp;
-
-  i->funcs = &string_funcs;
-  i->file = m4_get_current_file (context);
-  i->line = m4_get_current_line (context);
-  wsp = i;
+  assert (obstack_object_size (wrapup_stack) == 0);
+  if (wsp)
+    {
+      i = wsp;
+      assert (i->funcs == &composite_funcs && i->u.u_c.end
+             && i->u.u_c.end->type != M4__CHAIN_LOC);
+    }
+  else
+    {
+      i = (m4_input_block *) obstack_alloc (wrapup_stack, sizeof *i);
+      i->prev = wsp;
+      i->funcs = &composite_funcs;
+      i->file = m4_get_current_file (context);
+      i->line = m4_get_current_line (context);
+      i->u.u_c.chain = i->u.u_c.end = NULL;
+      wsp = i;
+    }
+  chain = (m4__symbol_chain *) obstack_alloc (wrapup_stack, sizeof *chain);
+  if (i->u.u_c.end)
+    i->u.u_c.end->next = chain;
+  else
+    i->u.u_c.chain = chain;
+  i->u.u_c.end = chain;
+  chain->next = NULL;
+  chain->type = M4__CHAIN_LOC;
+  chain->quote_age = 0;
+  chain->u.u_l.file = m4_get_current_file (context);
+  chain->u.u_l.line = m4_get_current_line (context);
   return wrapup_stack;
 }
 
@@ -1000,17 +1044,8 @@ m4_push_wrapup_init (m4 *context)
 void
 m4_push_wrapup_finish (void)
 {
-  m4_input_block *i = wsp;
-  if (obstack_object_size (wrapup_stack) == 0)
-    {
-      wsp = i->prev;
-      obstack_free (wrapup_stack, i);
-    }
-  else
-    {
-      i->u.u_s.len = obstack_object_size (wrapup_stack);
-      i->u.u_s.str = (char *) obstack_finish (wrapup_stack);
-    }
+  m4__make_text_link (wrapup_stack, &wsp->u.u_c.chain, &wsp->u.u_c.end);
+  assert (wsp->u.u_c.end->type != M4__CHAIN_LOC);
 }
 
 
@@ -1085,9 +1120,6 @@ m4_pop_wrapup (m4 *context)
 static void
 init_builtin_token (m4 *context, m4_symbol_value *token)
 {
-  int ch = next_char (context, false, true);
-  assert (ch == CHAR_BUILTIN);
-
   if (isp->funcs == &builtin_funcs)
     {
       assert (isp->u.builtin);
@@ -1159,11 +1191,10 @@ init_argv_symbol (m4 *context, m4_obstack *obs, 
m4_symbol_value *value)
 {
   m4__symbol_chain *src_chain;
   m4__symbol_chain *chain;
-  int ch = next_char (context, true, true);
+  int ch;
   const m4_string_pair *comments = m4_get_syntax_comments (M4SYNTAX);
 
-  assert (ch == CHAR_QUOTE && value->type == M4_SYMBOL_VOID
-         && isp->funcs == &composite_funcs
+  assert (value->type == M4_SYMBOL_VOID && isp->funcs == &composite_funcs
          && isp->u.u_c.chain->type == M4__CHAIN_ARGV
          && obs && obstack_object_size (obs) == 0);
 
@@ -1201,7 +1232,7 @@ init_argv_symbol (m4 *context, m4_obstack *obs, 
m4_symbol_value *value)
          || (!m4_has_syntax (M4SYNTAX, *comments->str1,
                              M4_SYNTAX_COMMA | M4_SYNTAX_CLOSE)
              && *comments->str1 != *src_chain->u.u_a.quotes->str1));
-  ch = peek_char (context, false);
+  ch = peek_char (context, true);
   if (!m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_COMMA | M4_SYNTAX_CLOSE))
     {
       isp->u.u_c.chain = src_chain;
@@ -1217,10 +1248,12 @@ init_argv_symbol (m4 *context, m4_obstack *obs, 
m4_symbol_value *value)
    next_char () is used to read and advance the input to the next
    character.  If ALLOW_QUOTE, and the current input matches the
    current quote age, return CHAR_QUOTE and leave consumption of data
-   for append_quote_token.  If RETRY, then avoid returning CHAR_RETRY
-   by popping input.  */
+   for append_quote_token; otherwise, if ALLOW_ARGV, and the current
+   input matches an argv reference with the correct quoting, return
+   CHAR_ARGV and leave consumption of data for init_argv_symbol.  If
+   RETRY, then avoid returning CHAR_RETRY by popping input.  */
 static int
-next_char (m4 *context, bool allow_quote, bool retry)
+next_char (m4 *context, bool allow_quote, bool allow_argv, bool retry)
 {
   int ch;
 
@@ -1240,7 +1273,8 @@ next_char (m4 *context, bool allow_quote, bool retry)
        }
 
       assert (isp->funcs->read_func);
-      while (((ch = isp->funcs->read_func (isp, context, allow_quote, !retry))
+      while (((ch = isp->funcs->read_func (isp, context, allow_quote,
+                                          allow_argv, !retry))
              != CHAR_RETRY)
             || !retry)
        {
@@ -1273,7 +1307,7 @@ peek_char (m4 *context, bool allow_argv)
       if (ch != CHAR_RETRY)
        {
 /*       if (IS_IGNORE (ch)) */
-/*         return next_char (context, false, true); */
+/*         return next_char (context, false, true, true); */
          return ch;
        }
 
@@ -1283,7 +1317,7 @@ peek_char (m4 *context, bool allow_argv)
 
 /* The function unget_input () puts back a character on the input
    stack, using an existing input_block if possible.  This is not safe
-   to call except immediately after next_char(context, allow, false).  */
+   to call except immediately after next_char(context, aq, aa, false).  */
 static void
 unget_input (int ch)
 {
@@ -1301,7 +1335,8 @@ m4_skip_line (m4 *context, const char *name)
   const char *file = m4_get_current_file (context);
   int line = m4_get_current_line (context);
 
-  while ((ch = next_char (context, false, true)) != CHAR_EOF && ch != '\n')
+  while ((ch = next_char (context, false, false, true)) != CHAR_EOF
+        && ch != '\n')
     ;
   if (ch == CHAR_EOF)
     /* current_file changed; use the previous value we cached.  */
@@ -1346,14 +1381,14 @@ match_input (m4 *context, const char *s, bool consume)
   if (s[1] == '\0')
     {
       if (consume)
-       next_char (context, false, true);
+       next_char (context, false, false, true);
       return true;                     /* short match */
     }
 
-  next_char (context, false, true);
+  next_char (context, false, false, true);
   for (n = 1, t = s++; (ch = peek_char (context, false)) == to_uchar (*s++); )
     {
-      next_char (context, false, true);
+      next_char (context, false, false, true);
       n++;
       if (*s == '\0')          /* long match */
        {
@@ -1391,29 +1426,29 @@ static bool
 consume_syntax (m4 *context, m4_obstack *obs, unsigned int syntax)
 {
   int ch;
-  bool allow_quote = m4__safe_quotes (M4SYNTAX);
+  bool allow = m4__safe_quotes (M4SYNTAX);
   assert (syntax);
   while (1)
     {
       /* It is safe to call next_char without first checking
         peek_char, except at input source boundaries, which we detect
         by CHAR_RETRY.  We exploit the fact that CHAR_EOF,
-        CHAR_BUILTIN, and CHAR_QUOTE do not satisfy any syntax
-        categories.  */
-      while ((ch = next_char (context, allow_quote, false)) != CHAR_RETRY
+        CHAR_BUILTIN, CHAR_QUOTE, and CHAR_ARGV do not satisfy any
+        syntax categories.  */
+      while ((ch = next_char (context, allow, allow, false)) != CHAR_RETRY
             && m4_has_syntax (M4SYNTAX, ch, syntax))
        {
          assert (ch < CHAR_EOF);
          obstack_1grow (obs, ch);
        }
-      if (ch == CHAR_RETRY || ch == CHAR_QUOTE)
+      if (ch == CHAR_RETRY || ch == CHAR_QUOTE || ch == CHAR_ARGV)
        {
          ch = peek_char (context, false);
          if (m4_has_syntax (M4SYNTAX, ch, syntax))
            {
              assert (ch < CHAR_EOF);
              obstack_1grow (obs, ch);
-             next_char (context, false, true);
+             next_char (context, false, false, true);
              continue;
            }
          return ch == CHAR_EOF;
@@ -1499,15 +1534,14 @@ m4__next_token (m4 *context, m4_symbol_value *token, 
int *line,
   do {
     obstack_free (&token_stack, token_bottom);
 
-    /* Must consume an input character, but not until CHAR_BUILTIN is
-       handled.  */
-    ch = peek_char (context, allow_argv && m4__quote_age (M4SYNTAX));
+    /* Must consume an input character.  */
+    ch = next_char (context, false, allow_argv && m4__quote_age (M4SYNTAX),
+                   true);
     if (ch == CHAR_EOF)                        /* EOF */
       {
 #ifdef DEBUG_INPUT
        xfprintf (stderr, "next_token -> EOF\n");
 #endif
-       next_char (context, false, true);
        return M4_TOKEN_EOF;
       }
 
@@ -1528,15 +1562,13 @@ m4__next_token (m4 *context, m4_symbol_value *token, 
int *line,
        return M4_TOKEN_ARGV;
       }
 
-    /* Consume character we already peeked at.  */
-    next_char (context, false, true);
     file = m4_get_current_file (context);
     *line = m4_get_current_line (context);
 
     if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ESCAPE))
       {                                        /* ESCAPED WORD */
        obstack_1grow (&token_stack, ch);
-       if ((ch = next_char (context, false, true)) < CHAR_EOF)
+       if ((ch = next_char (context, false, false, true)) < CHAR_EOF)
          {
            obstack_1grow (&token_stack, ch);
            if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ALPHA))
@@ -1564,7 +1596,8 @@ m4__next_token (m4 *context, m4_symbol_value *token, int 
*line,
        type = M4_TOKEN_STRING;
        while (1)
          {
-           ch = next_char (context, obs && m4__quote_age (M4SYNTAX), true);
+           ch = next_char (context, obs && m4__quote_age (M4SYNTAX), false,
+                           true);
            if (ch == CHAR_EOF)
              m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller,
                                _("end of file in string"));
@@ -1581,7 +1614,7 @@ m4__next_token (m4 *context, m4_symbol_value *token, int 
*line,
                    ch = peek_char (context, false);
                    if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_RQUOTE))
                      {
-                       ch = next_char (context, false, true);
+                       ch = next_char (context, false, false, true);
 #ifdef DEBUG_INPUT
                        m4_print_token (context, "next_token", M4_TOKEN_MACDEF,
                                        token);
@@ -1623,7 +1656,7 @@ m4__next_token (m4 *context, m4_symbol_value *token, int 
*line,
        assert (!m4__quote_age (M4SYNTAX));
        while (1)
          {
-           ch = next_char (context, false, true);
+           ch = next_char (context, false, false, true);
            if (ch == CHAR_EOF)
              m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller,
                                _("end of file in string"));
@@ -1641,7 +1674,7 @@ m4__next_token (m4 *context, m4_symbol_value *token, int 
*line,
                    if (MATCH (context, ch, context->syntax->quote.str2,
                               false))
                      {
-                       ch = next_char (context, false, true);
+                       ch = next_char (context, false, false, true);
                        MATCH (context, ch, context->syntax->quote.str2, true);
 #ifdef DEBUG_INPUT
                        m4_print_token (context, "next_token", M4_TOKEN_MACDEF,
@@ -1681,7 +1714,7 @@ m4__next_token (m4 *context, m4_symbol_value *token, int 
*line,
        obstack_1grow (obs_safe, ch);
        while (1)
          {
-           ch = next_char (context, false, true);
+           ch = next_char (context, false, false, true);
            if (ch == CHAR_EOF)
              m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller,
                                _("end of file in comment"));
@@ -1713,7 +1746,7 @@ m4__next_token (m4 *context, m4_symbol_value *token, int 
*line,
                      context->syntax->comm.len1);
        while (1)
          {
-           ch = next_char (context, false, true);
+           ch = next_char (context, false, false, true);
            if (ch == CHAR_EOF)
              m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller,
                                _("end of file in comment"));
diff --git a/m4/m4module.h b/m4/m4module.h
index 6cbe185..357baca 100644
--- a/m4/m4module.h
+++ b/m4/m4module.h
@@ -1,5 +1,4 @@
 /* GNU m4 -- A simple macro processor
-
    Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1999, 2000, 2003,
    2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
@@ -374,6 +373,7 @@ extern void m4_push_arg             (m4 *, m4_obstack *, 
m4_macro_args *,
                                         size_t);
 extern void    m4_push_args            (m4 *, m4_obstack *, m4_macro_args *,
                                         bool, bool);
+extern void    m4_wrap_args            (m4 *, m4_macro_args *);
 
 
 /* --- RUNTIME DEBUGGING --- */
diff --git a/m4/m4private.h b/m4/m4private.h
index 5ff7c95..86f18e8 100644
--- a/m4/m4private.h
+++ b/m4/m4private.h
@@ -1,7 +1,6 @@
 /* GNU m4 -- A simple macro processor
-
-   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1998, 1999, 2004, 2005,
-   2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1998, 1999, 2004,
+   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
    This file is part of GNU M4.
 
@@ -212,7 +211,8 @@ enum m4__symbol_chain_type
 {
   M4__CHAIN_STR,       /* Link contains a string, u.u_s is valid.  */
   M4__CHAIN_FUNC,      /* Link contains builtin token, u.builtin is valid.  */
-  M4__CHAIN_ARGV       /* Link contains a $@ reference, u.u_a is valid.  */
+  M4__CHAIN_ARGV,      /* Link contains a $@ reference, u.u_a is valid.  */
+  M4__CHAIN_LOC                /* Link contains m4wrap location, u.u_l is 
valid.  */
 };
 
 /* Composite symbols are built of a linked list of chain objects.  */
@@ -240,6 +240,11 @@ struct m4__symbol_chain
       bool_bitfield has_func : 1;      /* True if argv includes func.  */
       const m4_string_pair *quotes;    /* NULL for $*, quotes for 
address@hidden  */
     } u_a;                     /* M4__CHAIN_ARGV.  */
+    struct
+    {
+      const char *file;        /* File where subsequent links originate.  */
+      int line;                /* Line where subsequent links originate.  */
+    } u_l;                     /* M4__CHAIN_LOC.  */
   } u;
 };
 
diff --git a/m4/macro.c b/m4/macro.c
index d03f551..6d1976d 100644
--- a/m4/macro.c
+++ b/m4/macro.c
@@ -1670,6 +1670,74 @@ m4_push_args (m4 *context, m4_obstack *obs, 
m4_macro_args *argv, bool skip,
     arg_mark (argv);
 }
 
+/* Push arguments from ARGV onto the wrap stack for later rescanning.
+   If GNU extensions are disabled, only the first argument is pushed;
+   otherwise, all arguments are pushed and separated with a space.  */
+void
+m4_wrap_args (m4 *context, m4_macro_args *argv)
+{
+  size_t i;
+  m4_obstack *obs;
+  m4_symbol_value *value;
+  m4__symbol_chain *chain;
+  size_t limit = m4_get_posixly_correct_opt (context) ? 2 : argv->argc;
+
+  if (limit == 2 && m4_arg_empty (argv, 1))
+    return;
+
+  obs = m4_push_wrapup_init (context);
+  for (i = 1; i < limit; i++)
+    {
+      if (i != 1)
+       obstack_1grow (obs, ' ');
+      value = m4_arg_symbol (argv, i);
+      switch (value->type)
+       {
+       case M4_SYMBOL_TEXT:
+         obstack_grow (obs, m4_get_symbol_value_text (value),
+                       m4_get_symbol_value_len (value));
+         break;
+       case M4_SYMBOL_FUNC:
+         /* TODO allow builtins.  */
+         assert (false);
+         break;
+       case M4_SYMBOL_COMP:
+         chain = value->u.u_c.chain;
+         while (chain)
+           {
+             switch (chain->type)
+               {
+               case M4__CHAIN_STR:
+                 obstack_grow (obs, chain->u.u_s.str, chain->u.u_s.len);
+                 break;
+               case M4__CHAIN_FUNC:
+                 /* TODO allow builtins.  */
+                 assert (false);
+                 break;
+               case M4__CHAIN_ARGV:
+                 m4_arg_print (context, obs, chain->u.u_a.argv,
+                               chain->u.u_a.index,
+                               m4__quote_cache (M4SYNTAX, NULL,
+                                                chain->quote_age,
+                                                chain->u.u_a.quotes),
+                               chain->u.u_a.flatten, NULL, NULL, false,
+                               false);
+                 break;
+               default:
+                 assert (!"m4_wrap_args");
+                 abort ();
+               }
+             chain = chain->next;
+           }
+         break;
+       default:
+         assert (!"m4_wrap_args");
+         abort ();
+       }
+    }
+  m4_push_wrapup_finish ();
+}
+
 
 /* Define these last, so that earlier uses can benefit from the macros
    in m4private.h.  */
diff --git a/modules/m4.c b/modules/m4.c
index 359839b..02ac090 100644
--- a/modules/m4.c
+++ b/modules/m4.c
@@ -833,13 +833,7 @@ M4BUILTIN_HANDLER (m4exit)
    version only the first.  */
 M4BUILTIN_HANDLER (m4wrap)
 {
-  obs = m4_push_wrapup_init (context);
-  if (m4_get_posixly_correct_opt (context))
-    obstack_grow (obs, M4ARG (1), M4ARGLEN (1));
-  else
-    /* TODO allow pushing builtins.  */
-    m4_arg_print (context, obs, argv, 1, NULL, true, " ", NULL, false, false);
-  m4_push_wrapup_finish ();
+  m4_wrap_args (context, argv);
 }
 
 /* Enable tracing of all specified macros, or all, if none is specified.
diff --git a/tests/builtins.at b/tests/builtins.at
index 08c881b..34143a1 100644
--- a/tests/builtins.at
+++ b/tests/builtins.at
@@ -1227,8 +1227,8 @@ No. 33: The End.
 AT_CHECK_M4([wrap.m4], 0,
 [[
 No. 33: The End.
-Wrapper no. 2
 Wrapper no. 1
+Wrapper no. 2
 Wrapper no. 3
 Wrapper no. 4
 ]])


hooks/post-receive
--
GNU M4 source repository




reply via email to

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