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


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, master, updated. cvs-readonly-20-g14b2ffb
Date: Sun, 25 Nov 2007 00:27:41 +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=14b2ffbb82eb22cd36b1703a5501ee87ea51c45c

The branch, master has been updated
       via  14b2ffbb82eb22cd36b1703a5501ee87ea51c45c (commit)
       via  32ab6f9f819643ec7187bf1680d582eb8f131774 (commit)
      from  b6c03a0e43954549ed8724b770648678d6cf4edb (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 14b2ffbb82eb22cd36b1703a5501ee87ea51c45c
Author: Eric Blake <address@hidden>
Date:   Sat Nov 24 16:23:47 2007 -0700

    Stage 1: convert m4_symbol_value** into new object.
    
    * ltdl/m4/gnulib-cache.m4: Import flexmember module.
    * m4/m4module.h (m4_macro_args): New type, will be opaque to
    modules later.
    (m4_builtin_func, M4BUILTIN, M4BUILTIN_HANDLER, m4_dump_args)
    (m4_macro_call): Alter signature to use m4_macro_args object.
    (M4ARG): Redefine to access new struct.
    * m4/m4private.h (M4_SYMBOL_COMP): New enumerator.
    (struct m4_symbol_chain): New type.
    (struct m4_symbol_value): Add chain alternative.
    * m4/macro.c (collect_arguments): Build new struct.
    (expand_macro, m4_macro_call, process_macro, trace_pre)
    (trace_post): Adjust implementation to use it.
    * m4/utility.c (m4_dump_args): Likewise.
    * modules/gnu.c (builtin, indir): Likewise.
    * modules/format.c (format): Likewise.
    * modules/m4.h (m4_dump_symbols_func): Likewise.
    * modules/m4.c (m4_dump_symbols, define, pushdef, defn, ifelse)
    (shift, include, errprint, m4wrap): Likewise.
    * modules/evalparse.c (m4_evaluate): Likewise.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 32ab6f9f819643ec7187bf1680d582eb8f131774
Author: Eric Blake <address@hidden>
Date:   Sat Nov 24 07:04:18 2007 -0700

    Pass only macro name to utility functions.
    
    * m4/m4module.h (m4_bad_argc, m4_numeric_arg): Adjust signature.
    * m4/utility.c (m4_bad_argc, m4_numeric_arg): Adjust
    implementation.
    * m4/macro.c (m4_macro_call): Adjust callers.
    * modules/gnu.c (builtin, debuglen): Likewise.
    * modules/m4.c (ifelse, incr, decr, divert, undivert, m4exit)
    (substr): Likewise.
    * modules/evalparse.c (m4_evaluate): Likewise.
    * modules/stdlib.c (setenv, getpwuid, srand): Likewise.
    * modules/time.c (ctime, gmtime, localtime, mktime, strftime):
    Likewise.
    
    Signed-off-by: Eric Blake <address@hidden>

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

Summary of changes:
 ChangeLog               |   36 +++++++++++++++++
 ltdl/m4/gnulib-cache.m4 |    4 +-
 m4/m4module.h           |   76 +++++++++++++++++++++++-------------
 m4/m4private.h          |   30 +++++++++++---
 m4/macro.c              |   97 ++++++++++++++++++++++++----------------------
 m4/utility.c            |   54 +++++++++++++------------
 modules/evalparse.c     |   36 +++++++++---------
 modules/format.c        |   52 ++++++++++++-------------
 modules/gnu.c           |   68 ++++++++++++++++++++++-----------
 modules/m4.c            |   69 ++++++++++++++++++---------------
 modules/m4.h            |    2 +-
 modules/stdlib.c        |    6 +-
 modules/time.c          |   23 ++++++-----
 13 files changed, 330 insertions(+), 223 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0b02b24..2fbe4ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2007-11-24  Eric Blake  <address@hidden>
+
+       Stage 1: convert m4_symbol_value** into new object.
+       * ltdl/m4/gnulib-cache.m4: Import flexmember module.
+       * m4/m4module.h (m4_macro_args): New type, will be opaque to
+       modules later.
+       (m4_builtin_func, M4BUILTIN, M4BUILTIN_HANDLER, m4_dump_args)
+       (m4_macro_call): Alter signature to use m4_macro_args object.
+       (M4ARG): Redefine to access new struct.
+       * m4/m4private.h (M4_SYMBOL_COMP): New enumerator.
+       (struct m4_symbol_chain): New type.
+       (struct m4_symbol_value): Add chain alternative.
+       * m4/macro.c (collect_arguments): Build new struct.
+       (expand_macro, m4_macro_call, process_macro, trace_pre)
+       (trace_post): Adjust implementation to use it.
+       * m4/utility.c (m4_dump_args): Likewise.
+       * modules/gnu.c (builtin, indir): Likewise.
+       * modules/format.c (format): Likewise.
+       * modules/m4.h (m4_dump_symbols_func): Likewise.
+       * modules/m4.c (m4_dump_symbols, define, pushdef, defn, ifelse)
+       (shift, include, errprint, m4wrap): Likewise.
+       * modules/evalparse.c (m4_evaluate): Likewise.
+
+       Pass only macro name to utility functions.
+       * m4/m4module.h (m4_bad_argc, m4_numeric_arg): Adjust signature.
+       * m4/utility.c (m4_bad_argc, m4_numeric_arg): Adjust
+       implementation.
+       * m4/macro.c (m4_macro_call): Adjust callers.
+       * modules/gnu.c (builtin, debuglen): Likewise.
+       * modules/m4.c (ifelse, incr, decr, divert, undivert, m4exit)
+       (substr): Likewise.
+       * modules/evalparse.c (m4_evaluate): Likewise.
+       * modules/stdlib.c (setenv, getpwuid, srand): Likewise.
+       * modules/time.c (ctime, gmtime, localtime, mktime, strftime):
+       Likewise.
+
 2007-11-23  Eric Blake  <address@hidden>
 
        Add macro name to debugfile messages.
diff --git a/ltdl/m4/gnulib-cache.m4 b/ltdl/m4/gnulib-cache.m4
index 9c17a78..1eefbd5 100644
--- a/ltdl/m4/gnulib-cache.m4
+++ b/ltdl/m4/gnulib-cache.m4
@@ -15,11 +15,11 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --local-dir=local --lib=libgnu 
--source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --aux-dir=build-aux 
--with-tests --libtool --macro-prefix=M4 assert autobuild avltree-oset 
binary-io clean-temp cloexec close-stream closein config-h configmake dirname 
error exit fdl fflush filenamecat fopen-safer free fseeko gendocs gettext 
gnupload gpl-3.0 mkstemp obstack progname regex regexprops-generic 
sprintf-posix stdbool stdlib-safer strnlen strtol tempname unlocked-io verror 
xalloc xalloc-die xprintf-posix xstrndup xvasprintf-posix
+#   gnulib-tool --import --dir=. --local-dir=local --lib=libgnu 
--source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --aux-dir=build-aux 
--with-tests --libtool --macro-prefix=M4 assert autobuild avltree-oset 
binary-io clean-temp cloexec close-stream closein config-h configmake dirname 
error exit fdl fflush filenamecat flexmember fopen-safer free fseeko gendocs 
gettext gnupload gpl-3.0 mkstemp obstack progname regex regexprops-generic 
sprintf-posix stdbool stdlib-safer strnlen strtol tempname unlocked-io verror 
xalloc xalloc-die xprintf-posix xstrndup xvasprintf-posix
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([local])
-gl_MODULES([assert autobuild avltree-oset binary-io clean-temp cloexec 
close-stream closein config-h configmake dirname error exit fdl fflush 
filenamecat fopen-safer free fseeko gendocs gettext gnupload gpl-3.0 mkstemp 
obstack progname regex regexprops-generic sprintf-posix stdbool stdlib-safer 
strnlen strtol tempname unlocked-io verror xalloc xalloc-die xprintf-posix 
xstrndup xvasprintf-posix])
+gl_MODULES([assert autobuild avltree-oset binary-io clean-temp cloexec 
close-stream closein config-h configmake dirname error exit fdl fflush 
filenamecat flexmember fopen-safer free fseeko gendocs gettext gnupload gpl-3.0 
mkstemp obstack progname regex regexprops-generic sprintf-posix stdbool 
stdlib-safer strnlen strtol tempname unlocked-io verror xalloc xalloc-die 
xprintf-posix xstrndup xvasprintf-posix])
 gl_AVOID([])
 gl_SOURCE_BASE([gnu])
 gl_M4_BASE([ltdl/m4])
diff --git a/m4/m4module.h b/m4/m4module.h
index 8b59e15..3f60cba 100644
--- a/m4/m4module.h
+++ b/m4/m4module.h
@@ -37,10 +37,11 @@ typedef struct m4_macro             m4_macro;
 typedef struct m4_symbol_value m4_symbol_value;
 typedef struct m4_input_block  m4_input_block;
 typedef struct m4_module       m4_module;
+typedef struct m4_macro_args   m4_macro_args;
 
 typedef struct obstack         m4_obstack;
 
-typedef void   m4_builtin_func  (m4 *, m4_obstack *, int, m4_symbol_value **);
+typedef void   m4_builtin_func  (m4 *, m4_obstack *, int, m4_macro_args *);
 
 /* The value of m4_builtin flags is built from these:  */
 enum {
@@ -75,38 +76,58 @@ struct m4_macro
   const char *value;
 };
 
+/* FIXME - make this struct opaque.  */
+struct m4_macro_args
+{
+  /* One more than the highest actual argument.  May be larger than
+     arraylen since the array can refer to multiple arguments via a
+     single $@ reference.  */
+  unsigned int argc;
+  /* False unless the macro expansion refers to $@; determines whether
+     this object can be freed at end of macro expansion or must wait
+     until all references have been rescanned.  */
+  bool inuse;
+  const char *argv0; /* The macro name being expanded.  */
+  size_t arraylen; /* True length of allocated elements in array.  */
+  /* Used as a variable-length array, storing information about each
+     argument.  */
+  m4_symbol_value *array[FLEXIBLE_ARRAY_MEMBER];
+};
+
 
-#define M4BUILTIN(name)                                        \
-  static void CONC(builtin_, name)                             \
-   (m4 *context, m4_obstack *obs, int argc, m4_symbol_value **argv);
+#define M4BUILTIN(name)                                                        
\
+  static void CONC (builtin_, name)                                    \
+   (m4 *context, m4_obstack *obs, int argc, m4_macro_args *argv);
 
-#define M4BUILTIN_HANDLER(name)                                \
-  static void CONC(builtin_, name)                             \
-   (m4 *context, m4_obstack *obs, int argc, m4_symbol_value **argv)
+#define M4BUILTIN_HANDLER(name)                                                
\
+  static void CONC (builtin_, name)                                    \
+   (m4 *context, m4_obstack *obs, int argc, m4_macro_args *argv)
 
-#define M4INIT_HANDLER(name)                                   \
-  void CONC(name, CONC(_LTX_, m4_init_module))                 \
-       (m4 *context, m4_module *module, m4_obstack *obs);      \
-  void CONC(name, CONC(_LTX_, m4_init_module))                 \
+#define M4INIT_HANDLER(name)                                           \
+  void CONC (name, CONC (_LTX_, m4_init_module))                       \
+       (m4 *context, m4_module *module, m4_obstack *obs);              \
+  void CONC (name, CONC (_LTX_, m4_init_module))                       \
        (m4 *context, m4_module *module, m4_obstack *obs)
 
-#define M4FINISH_HANDLER(name)                                 \
-  void CONC(name, CONC(_LTX_, m4_finish_module))               \
-       (m4 *context, m4_module *module, m4_obstack *obs);      \
-  void CONC(name, CONC(_LTX_, m4_finish_module))               \
+#define M4FINISH_HANDLER(name)                                         \
+  void CONC (name, CONC (_LTX_, m4_finish_module))                     \
+       (m4 *context, m4_module *module, m4_obstack *obs);              \
+  void CONC (name, CONC (_LTX_, m4_finish_module))                     \
        (m4 *context, m4_module *module, m4_obstack *obs)
 
-#define M4_MODULE_IMPORT(M, S)                                 \
-  CONC(S, _func) *S = (CONC(S, _func) *)                       \
-       m4_module_import (context, STR(M), STR(S), obs)
+#define M4_MODULE_IMPORT(M, S)                                         \
+  CONC (S, _func) *S = (CONC (S, _func) *)                             \
+       m4_module_import (context, STR (M), STR (S), obs)
 
-#define M4ARG(i)       (argc > (i) ? m4_get_symbol_value_text (argv[i]) : "")
+#define M4ARG(i)                                                       \
+  ((i) == 0 ? argv->argv0                                              \
+   : argv->argc > (i) ? m4_get_symbol_value_text (argv->array[(i) - 1]) : "")
 
-extern bool    m4_bad_argc        (m4 *, int, m4_symbol_value **,
+extern bool    m4_bad_argc        (m4 *, int, const char *,
                                    unsigned int, unsigned int, bool);
-extern bool    m4_numeric_arg     (m4 *, int, m4_symbol_value **, int, int *);
+extern bool    m4_numeric_arg     (m4 *, const char *, const char *, int *);
 extern void    m4_dump_args       (m4 *, m4_obstack *, int,
-                                   m4_symbol_value **, const char *, bool);
+                                   m4_macro_args *, const char *, bool);
 extern bool    m4_parse_truth_arg (m4 *, const char *, const char *, bool);
 
 /* Error handling.  */
@@ -164,14 +185,14 @@ extern void               m4_delete       (m4 *);
 
 
 #define M4FIELD(type, base, field)                                     \
-       extern type CONC(m4_get_, base) (m4 *context);                  \
-       extern type CONC(m4_set_, base) (m4 *context, type value);
+       extern type CONC (m4_get_, base) (m4 *context);                 \
+       extern type CONC (m4_set_, base) (m4 *context, type value);
 m4_context_field_table
 #undef M4FIELD
 
 #define M4OPT_BIT(bit, base)                                           \
-       extern bool CONC(m4_get_, base) (m4 *context);          \
-       extern bool CONC(m4_set_, base) (m4 *context, bool value);
+  extern bool CONC (m4_get_, base) (m4 *context);                      \
+  extern bool CONC (m4_set_, base) (m4 *context, bool value);
 m4_context_opt_bit_table
 #undef M4OPT_BIT
 
@@ -287,8 +308,7 @@ extern const m4_builtin     *m4_builtin_find_by_func 
(m4_module *,
 
 extern void       m4_macro_expand_input (m4 *);
 extern void       m4_macro_call         (m4 *, m4_symbol_value *,
-                                         m4_obstack *, int,
-                                         m4_symbol_value **);
+                                         m4_obstack *, int, m4_macro_args *);
 
 
 
diff --git a/m4/m4private.h b/m4/m4private.h
index b067254..63a9bc4 100644
--- a/m4/m4private.h
+++ b/m4/m4private.h
@@ -30,10 +30,11 @@
 typedef struct m4__search_path_info m4__search_path_info;
 
 typedef enum {
-  M4_SYMBOL_VOID, /* Traced but undefined.  */
-  M4_SYMBOL_TEXT, /* Plain text.  */
-  M4_SYMBOL_FUNC, /* Builtin function.  */
-  M4_SYMBOL_PLACEHOLDER /* Placeholder for unknown builtin during -R.  */
+  M4_SYMBOL_VOID,              /* Traced but undefined, u is invalid.  */
+  M4_SYMBOL_TEXT,              /* Plain text, u.u_t is valid.  */
+  M4_SYMBOL_FUNC,              /* Builtin function, u.func is valid.  */
+  M4_SYMBOL_PLACEHOLDER,       /* Placeholder for unknown builtin from -R.  */
+  M4_SYMBOL_COMP               /* Composite symbol, u.chain is valid.  */
 } m4__symbol_type;
 
 #define BIT_TEST(flags, bit)   (((flags) & (bit)) == (bit))
@@ -171,13 +172,27 @@ extern m4_module *  m4__module_find (const char *name);
 
 /* --- SYMBOL TABLE MANAGEMENT --- */
 
+typedef struct m4_symbol_chain m4_symbol_chain;
+
 struct m4_symbol
 {
   bool         traced;
   m4_symbol_value *    value;
 };
 
-struct m4_symbol_value {
+/* Composite symbols are built of a linked list of chain objects.  */
+struct m4_symbol_chain
+{
+  m4_symbol_chain *next;/* Pointer to next link of chain.  */
+  char *str;           /* NUL-terminated string if text, else NULL.  */
+  m4_macro_args *argv; /* Reference to earlier address@hidden  */
+  unsigned int index;  /* Index within argv to start reading from.  */
+};
+
+/* A symbol value is used both for values associated with a macro
+   name, and for arguments to a macro invocation.  */
+struct m4_symbol_value
+{
   m4_symbol_value *    next;
   m4_module *          module;
   unsigned int         flags;
@@ -189,8 +204,9 @@ struct m4_symbol_value {
 
   m4__symbol_type      type;
   union {
-    const char *       text; /* Valid when type is TEXT, PLACEHOLDER.  */
-    const m4_builtin * builtin; /* Valid when type is FUNC.  */
+    const char *       text;   /* Valid when type is TEXT, PLACEHOLDER.  */
+    const m4_builtin * builtin;/* Valid when type is FUNC.  */
+    m4_symbol_chain *  chain;  /* Valid when type is COMP.  */
   } u;
 };
 
diff --git a/m4/macro.c b/m4/macro.c
index ffe55f7..c4ba1af 100644
--- a/m4/macro.c
+++ b/m4/macro.c
@@ -29,22 +29,23 @@
 
 #include "intprops.h"
 
-static void    collect_arguments (m4 *, const char *, m4_symbol *,
-                                 m4_obstack *, m4_obstack *);
+static m4_macro_args *collect_arguments (m4 *, const char *, m4_symbol *,
+                                        m4_obstack *, unsigned int,
+                                        m4_obstack *);
 static void    expand_macro      (m4 *, const char *, m4_symbol *);
 static void    expand_token      (m4 *, m4_obstack *, m4__token_type,
                                  m4_symbol_value *, int);
 static bool    expand_argument   (m4 *, m4_obstack *, m4_symbol_value *,
                                  const char *);
 static void    process_macro    (m4 *, m4_symbol_value *, m4_obstack *, int,
-                                 m4_symbol_value **);
+                                 m4_macro_args *);
 
 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 **);
+                                 m4_macro_args *);
 static void    trace_post       (m4 *, const char *, size_t, int,
-                                 m4_symbol_value **, m4_input_block *, bool);
+                                 m4_macro_args *, m4_input_block *, bool);
 
 static void    trace_format     (m4 *, const char *, ...)
   M4_GNUC_PRINTF (2, 3);
@@ -126,11 +127,11 @@ expand_token (m4 *context, m4_obstack *obs,
          ++textp;
 
        symbol = m4_symbol_lookup (M4SYMTAB, textp);
-       assert (! symbol || ! m4_is_symbol_void (symbol));
+       assert (!symbol || !m4_is_symbol_void (symbol));
        if (symbol == NULL
            || (symbol->value->type == M4_SYMBOL_FUNC
                && BIT_TEST (SYMBOL_FLAGS (symbol), VALUE_BLIND_ARGS_BIT)
-               && ! m4__next_token_is_open (context)))
+               && !m4__next_token_is_open (context)))
          {
            m4_shipout_text (context, obs, text, strlen (text), line);
          }
@@ -248,7 +249,7 @@ expand_macro (m4 *context, const char *name, m4_symbol 
*symbol)
   char *argc_base = NULL;      /* Base of argc_stack on entry.  */
   unsigned int argc_size;      /* Size of argc_stack on entry.  */
   unsigned int argv_size;      /* Size of argv_stack on entry.  */
-  m4_symbol_value **argv;
+  m4_macro_args *argv;
   int argc;
   m4_obstack *expansion;
   m4_input_block *expanded;
@@ -297,15 +298,12 @@ recursion limit of %zu exceeded, use -L<N> to change it"),
   if (traced && m4_is_debug_bit (context, M4_DEBUG_TRACE_CALL))
     trace_prepre (context, name, my_call_id, value);
 
-  collect_arguments (context, name, symbol, &argv_stack, &argc_stack);
-
-  argc = ((obstack_object_size (&argv_stack) - argv_size)
-         / sizeof (m4_symbol_value *));
-  argv = (m4_symbol_value **) ((char *) obstack_base (&argv_stack)
-                              + argv_size);
+  argv = collect_arguments (context, name, symbol, &argv_stack, argv_size,
+                           &argc_stack);
+  argc = argv->argc;
   /* Calling collect_arguments invalidated name, but we copied it as
      argv[0].  */
-  name = m4_get_symbol_value_text (argv[0]);
+  name = argv->argv0;
 
   loc_close_file = m4_get_current_file (context);
   loc_close_line = m4_get_current_line (context);
@@ -331,32 +329,39 @@ recursion limit of %zu exceeded, use -L<N> to change it"),
   if (BIT_TEST (VALUE_FLAGS (value), VALUE_DELETED_BIT))
     m4_symbol_value_delete (value);
 
+  /* TODO - pay attention to argv->inuse.  */
   if (0 < argc_size)
     obstack_regrow (&argc_stack, argc_base, argc_size);
   else
-    obstack_free (&argc_stack, argv[0]);
-  obstack_blank (&argv_stack, -argc * sizeof (m4_symbol_value *));
+    obstack_free (&argc_stack, (void *) name);
+  obstack_blank (&argv_stack, argv_size - obstack_object_size (&argv_stack));
 }
 
-/* Collect all the arguments to a call of the macro SYMBOL (called NAME).
-   The arguments are stored on the obstack ARGUMENTS and a table of pointers
-   to the arguments on the obstack ARGPTR.  */
-static void
+/* Collect all the arguments to a call of the macro SYMBOL (called
+   NAME).  The arguments are stored on the obstack ARGUMENTS and a
+   table of pointers to the arguments on the obstack ARGPTR.  ARGPTR
+   is an incomplete object, currently occupying ARGV_BASE bytes.
+   Return the object describing all of the macro arguments.  */
+static m4_macro_args *
 collect_arguments (m4 *context, const char *name, m4_symbol *symbol,
-                  m4_obstack *argptr, m4_obstack *arguments)
+                  m4_obstack *argptr, unsigned argv_base,
+                  m4_obstack *arguments)
 {
   m4_symbol_value token;
   m4_symbol_value *tokenp;
   bool more_args;
   bool groks_macro_args;
+  m4_macro_args args;
+  m4_macro_args *argv;
 
   groks_macro_args = BIT_TEST (SYMBOL_FLAGS (symbol), VALUE_MACRO_ARGS_BIT);
 
-  tokenp = (m4_symbol_value *) obstack_alloc (arguments, sizeof *tokenp);
-  m4_set_symbol_value_text (tokenp, (char *) obstack_copy0 (arguments, name,
-                                                           strlen (name)));
-  name = m4_get_symbol_value_text (tokenp);
-  obstack_ptr_grow (argptr, tokenp);
+  args.argc = 1;
+  args.inuse = false;
+  args.argv0 = (char *) obstack_copy0 (arguments, name, strlen (name));
+  args.arraylen = 0;
+  obstack_grow (argptr, &args, offsetof (m4_macro_args, array));
+  name = args.argv0;
 
   if (m4__next_token_is_open (context))
     {
@@ -373,9 +378,15 @@ collect_arguments (m4 *context, const char *name, 
m4_symbol *symbol,
          tokenp = (m4_symbol_value *) obstack_copy (arguments, &token,
                                                     sizeof token);
          obstack_ptr_grow (argptr, tokenp);
+         args.arraylen++;
+         args.argc++;
        }
       while (more_args);
     }
+  argv = (m4_macro_args *) ((char *) obstack_base (argptr) + argv_base);
+  argv->argc = args.argc;
+  argv->arraylen = args.arraylen;
+  return argv;
 }
 
 
@@ -387,30 +398,24 @@ collect_arguments (m4 *context, const char *name, 
m4_symbol *symbol,
    the obstack EXPANSION.  Macro tracing is also handled here.  */
 void
 m4_macro_call (m4 *context, m4_symbol_value *value, m4_obstack *expansion,
-              int argc, m4_symbol_value **argv)
+              int argc, m4_macro_args *argv)
 {
-  if (m4_bad_argc (context, argc, argv,
+  if (m4_bad_argc (context, argc, argv->argv0,
                   VALUE_MIN_ARGS (value), VALUE_MAX_ARGS (value),
                   BIT_TEST (VALUE_FLAGS (value),
                             VALUE_SIDE_EFFECT_ARGS_BIT)))
     return;
   if (m4_is_symbol_value_text (value))
-    {
-      process_macro (context, value, expansion, argc, argv);
-    }
+    process_macro (context, value, expansion, argc, argv);
   else if (m4_is_symbol_value_func (value))
-    {
-      (*m4_get_symbol_value_func (value)) (context, expansion, argc, argv);
-    }
+    m4_get_symbol_value_func (value) (context, expansion, argc, argv);
   else if (m4_is_symbol_value_placeholder (value))
-    {
-      m4_warn (context, 0, M4ARG (0),
-              _("builtin `%s' requested by frozen file not found"),
-              m4_get_symbol_value_placeholder (value));
-    }
+    m4_warn (context, 0, M4ARG (0),
+            _("builtin `%s' requested by frozen file not found"),
+            m4_get_symbol_value_placeholder (value));
   else
     {
-      assert (!"INTERNAL ERROR: bad symbol type in call_macro ()");
+      assert (!"INTERNAL ERROR: bad symbol type in m4_macro_call ()");
       abort ();
     }
 }
@@ -422,7 +427,7 @@ m4_macro_call (m4 *context, m4_symbol_value *value, 
m4_obstack *expansion,
    as usual.  */
 static void
 process_macro (m4 *context, m4_symbol_value *value, m4_obstack *obs,
-              int argc, m4_symbol_value **argv)
+              int argc, m4_macro_args *argv)
 {
   const char *text;
   int i;
@@ -467,7 +472,7 @@ process_macro (m4 *context, m4_symbol_value *value, 
m4_obstack *obs,
 
        case '*':               /* all arguments */
        case '@':               /* ... same, but quoted */
-         m4_dump_args (context, obs, argc, argv, ",", *text == '@');
+         m4_dump_args (context, obs, 1, argv, ",", *text == '@');
          text++;
          break;
 
@@ -649,7 +654,7 @@ trace_prepre (m4 *context, const char *name, size_t id, 
m4_symbol_value *value)
    actually expanded.  Used from expand_macro ().  */
 static void
 trace_pre (m4 *context, const char *name, size_t id,
-          int argc, m4_symbol_value **argv)
+          int argc, m4_macro_args *argv)
 {
   int i;
 
@@ -670,7 +675,7 @@ trace_pre (m4 *context, const char *name, size_t id,
          if (i != 1)
            trace_format (context, ", ");
 
-         m4_symbol_value_print (argv[i], &context->trace_messages,
+         m4_symbol_value_print (argv->array[i - 1], &context->trace_messages,
                                 quote, lquote, rquote, arg_length, module);
        }
       trace_format (context, ")");
@@ -681,7 +686,7 @@ trace_pre (m4 *context, const char *name, size_t id,
    expand_macro ().  */
 static void
 trace_post (m4 *context, const char *name, size_t id,
-           int argc, m4_symbol_value **argv, m4_input_block *expanded,
+           int argc, m4_macro_args *argv, m4_input_block *expanded,
            bool trace_expansion)
 {
   if (trace_expansion)
diff --git a/m4/utility.c b/m4/utility.c
index 1839ea1..851da31 100644
--- a/m4/utility.c
+++ b/m4/utility.c
@@ -27,7 +27,7 @@
 #include "verror.h"
 #include "xvasprintf.h"
 
-static const char * skip_space (m4 *, const char *);
+static const char *skip_space (m4 *, const char *);
 
 
 
@@ -36,23 +36,23 @@ static const char * skip_space (m4 *, const char *);
    number of acceptable arguments, MAX is the 0-based maximum number
    or UINT_MAX if not applicable, and SIDE_EFFECT is true if the macro
    has side effects even if min is not satisfied.  ARGC is the 1-based
-   count of ARGV, where ARGV[0] is the name of the macro.  Return true
-   if the macro is guaranteed to expand to the empty string, false
-   otherwise.  */
+   count of supplied arguments, and CALLER is the name of the macro.
+   Return true if the macro is guaranteed to expand to the empty
+   string, false otherwise.  */
 bool
-m4_bad_argc (m4 *context, int argc, m4_symbol_value **argv,
-            unsigned int min, unsigned int max, bool side_effect)
+m4_bad_argc (m4 *context, int argc, const char *caller, unsigned int min,
+            unsigned int max, bool side_effect)
 {
   if (argc - 1 < min)
     {
-      m4_warn (context, 0, M4ARG (0), _("too few arguments: %d < %d"),
+      m4_warn (context, 0, caller, _("too few arguments: %d < %d"),
               argc - 1, min);
-      return ! side_effect;
+      return !side_effect;
     }
 
   if (argc - 1 > max)
     {
-      m4_warn (context, 0, M4ARG (0), _("extra arguments ignored: %d > %d"),
+      m4_warn (context, 0, caller, _("extra arguments ignored: %d > %d"),
               argc - 1, max);
     }
 
@@ -68,28 +68,26 @@ skip_space (m4 *context, const char *arg)
 }
 
 /* The function m4_numeric_arg () converts ARG to an int pointed to by
-   VALUEP. If the conversion fails, print error message for macro.
+   VALUEP. If the conversion fails, print error message for CALLER.
    Return true iff conversion succeeds.  */
 /* FIXME: Convert this to use gnulib's xstrtoimax, xstrtoumax.
    Otherwise, we are arbitrarily limiting integer values.  */
 bool
-m4_numeric_arg (m4 *context, int argc, m4_symbol_value **argv,
-               int arg, int *valuep)
+m4_numeric_arg (m4 *context, const char *caller, const char *arg, int *valuep)
 {
   char *endp;
 
-  if (*M4ARG (arg) == '\0')
+  if (*arg == '\0')
     {
       *valuep = 0;
-      m4_warn (context, 0, M4ARG (0), _("empty string treated as 0"));
+      m4_warn (context, 0, caller, _("empty string treated as 0"));
     }
   else
     {
-      *valuep = strtol (skip_space (context, M4ARG (arg)), &endp, 10);
+      *valuep = strtol (skip_space (context, arg), &endp, 10);
       if (*skip_space (context, endp) != 0)
        {
-         m4_warn (context, 0, M4ARG (0), _("non-numeric argument `%s'"),
-                  M4ARG (arg));
+         m4_warn (context, 0, caller, _("non-numeric argument `%s'"), arg);
          return false;
        }
     }
@@ -97,19 +95,23 @@ m4_numeric_arg (m4 *context, int argc, m4_symbol_value 
**argv,
 }
 
 
-/* Print ARGC arguments from the table ARGV to obstack OBS, separated by
-   SEP, and quoted by the current quotes, if QUOTED is true.  */
+/* Print arguments from the table ARGV to obstack OBS, starting at
+   index START, separated by SEP, and quoted by the current quotes, if
+   QUOTED is true.  */
 void
-m4_dump_args (m4 *context, m4_obstack *obs, int argc,
-             m4_symbol_value **argv, const char *sep, bool quoted)
+m4_dump_args (m4 *context, m4_obstack *obs, int start,
+             m4_macro_args *argv, const char *sep, bool quoted)
 {
   int i;
   size_t len = strlen (sep);
+  bool need_sep = false;
 
-  for (i = 1; i < argc; i++)
+  for (i = start; i < argv->argc; i++)
     {
-      if (i > 1)
+      if (need_sep)
        obstack_grow (obs, sep, len);
+      else
+       need_sep = true;
 
       m4_shipout_string (context, obs, M4ARG (i), 0, quoted);
     }
@@ -164,7 +166,7 @@ m4_verror_at_line (m4 *context, bool warn, int status, int 
errnum,
                  full ? full : format, args);
   free (full);
   if ((!warn || m4_get_fatal_warnings_opt (context))
-      && ! m4_get_exit_status (context))
+      && !m4_get_exit_status (context))
     m4_set_exit_status (context, EXIT_FAILURE);
 }
 
@@ -182,7 +184,7 @@ m4_error (m4 *context, int status, int errnum, const char 
*macro,
 {
   va_list args;
   int line = m4_get_current_line (context);
-  assert (m4_get_current_file (context) || ! line);
+  assert (m4_get_current_file (context) || !line);
   va_start (args, format);
   if (status == EXIT_SUCCESS && m4_get_warnings_exit_opt (context))
     status = EXIT_FAILURE;
@@ -228,7 +230,7 @@ m4_warn (m4 *context, int errnum, const char *macro, const 
char *format, ...)
       va_list args;
       int status = EXIT_SUCCESS;
       int line = m4_get_current_line (context);
-      assert (m4_get_current_file (context) || ! line);
+      assert (m4_get_current_file (context) || !line);
       va_start (args, format);
       if (m4_get_warnings_exit_opt (context))
        status = EXIT_FAILURE;
diff --git a/modules/evalparse.c b/modules/evalparse.c
index b4639b0..31e1e4b 100644
--- a/modules/evalparse.c
+++ b/modules/evalparse.c
@@ -885,40 +885,42 @@ simple_term (m4 *context, eval_token et, number *v1)
 
 /* Main entry point, called from "eval" and "mpeval" builtins.  */
 void
-m4_evaluate (m4 *context, m4_obstack *obs, int argc, m4_symbol_value **argv)
+m4_evaluate (m4 *context, m4_obstack *obs, int argc, m4_macro_args *argv)
 {
+  const char * me      = M4ARG (0);
+  const char * str     = M4ARG (1);
   int          radix   = 10;
   int          min     = 1;
   number       val;
   eval_token   et;
   eval_error   err     = NO_ERROR;
 
-  if (*M4ARG (2) && !m4_numeric_arg (context, argc, argv, 2, &radix))
+  if (*M4ARG (2) && !m4_numeric_arg (context, me, M4ARG (2), &radix))
     return;
 
   if (radix < 1 || radix > 36)
     {
-      m4_warn (context, 0, M4ARG (0), _("radix out of range: %d"), radix);
+      m4_warn (context, 0, me, _("radix out of range: %d"), radix);
       return;
     }
 
-  if (argc >= 4 && !m4_numeric_arg (context, argc, argv, 3, &min))
+  if (argc >= 4 && !m4_numeric_arg (context, me, M4ARG (3), &min))
     return;
 
   if (min < 0)
     {
-      m4_warn (context, 0, M4ARG (0), _("negative width: %d"), min);
+      m4_warn (context, 0, me, _("negative width: %d"), min);
       return;
     }
 
   numb_initialise ();
-  eval_init_lex (M4ARG (1));
+  eval_init_lex (str);
 
   numb_init (val);
   et = eval_lex (&val);
   if (et == EOTEXT)
     {
-      m4_warn (context, 0, M4ARG (0), _("empty string treated as zero"));
+      m4_warn (context, 0, me, _("empty string treated as zero"));
       numb_set (val, numb_ZERO);
     }
   else
@@ -939,42 +941,40 @@ m4_evaluate (m4 *context, m4_obstack *obs, int argc, 
m4_symbol_value **argv)
       break;
 
     case MISSING_RIGHT:
-      m4_warn (context, 0, M4ARG (0), _("missing right parenthesis: %s"),
-              M4ARG (1));
+      m4_warn (context, 0, me, _("missing right parenthesis: %s"), str);
       break;
 
     case MISSING_COLON:
-      m4_warn (context, 0, M4ARG (0), _("missing colon: %s"), M4ARG (1));
+      m4_warn (context, 0, me, _("missing colon: %s"), str);
       break;
 
     case SYNTAX_ERROR:
-      m4_warn (context, 0, M4ARG (0), _("bad expression: %s"), M4ARG (1));
+      m4_warn (context, 0, me, _("bad expression: %s"), str);
       break;
 
     case UNKNOWN_INPUT:
-      m4_warn (context, 0, M4ARG (0), _("bad input: %s"), M4ARG (1));
+      m4_warn (context, 0, me, _("bad input: %s"), str);
       break;
 
     case EXCESS_INPUT:
-      m4_warn (context, 0, M4ARG (0), _("excess input: %s"), M4ARG (1));
+      m4_warn (context, 0, me, _("excess input: %s"), str);
       break;
 
     case INVALID_OPERATOR:
       /* POSIX requires an error here, unless XCU ERN 137 is approved.  */
-      m4_error (context, 0, 0, M4ARG (0), _("invalid operator: %s"),
-               M4ARG (1));
+      m4_error (context, 0, 0, me, _("invalid operator: %s"), str);
       break;
 
     case DIVIDE_ZERO:
-      m4_warn (context, 0, M4ARG (0), _("divide by zero: %s"), M4ARG (1));
+      m4_warn (context, 0, me, _("divide by zero: %s"), str);
       break;
 
     case MODULO_ZERO:
-      m4_warn (context, 0, M4ARG (0), _("modulo by zero: %s"), M4ARG (1));
+      m4_warn (context, 0, me, _("modulo by zero: %s"), str);
       break;
 
     case NEGATIVE_EXPONENT:
-      m4_warn (context, 0, M4ARG (0), _("negative exponent: %s"), M4ARG (1));
+      m4_warn (context, 0, me, _("negative exponent: %s"), str);
       break;
 
     default:
diff --git a/modules/format.c b/modules/format.c
index 8e5f670..ced3924 100644
--- a/modules/format.c
+++ b/modules/format.c
@@ -30,21 +30,17 @@
    TODO - use xstrtoimax, not atoi, to catch overflow, non-numeric
    arguments, etc.  */
 
-#define ARG_INT(argc, argv) \
-       ((argc == 0) ? 0 : \
-        (--argc, argv++, atoi (M4ARG (-1))))
+#define ARG_INT(i, argc, argv)                 \
+  ((argc <= i++) ? 0 : atoi (M4ARG (i - 1)))
 
-#define ARG_LONG(argc, argv) \
-       ((argc == 0) ? 0 : \
-        (--argc, argv++, atol (M4ARG (-1))))
+#define ARG_LONG(i, argc, argv)                        \
+  ((argc <= i++) ? 0L : atol (M4ARG (i - 1)))
 
-#define ARG_STR(argc, argv) \
-       ((argc == 0) ? "" : \
-        (--argc, argv++, M4ARG (-1)))
+#define ARG_STR(i, argc, argv)                 \
+  ((argc <= i++) ? "" : M4ARG (i - 1))
 
-#define ARG_DOUBLE(argc, argv) \
-       ((argc == 0) ? 0 : \
-        (--argc, argv++, atof (M4ARG (-1))))
+#define ARG_DOUBLE(i, argc, argv)              \
+  ((argc <= i++) ? 0.0 : atof (M4ARG (i - 1)))
 
 
 /* The main formatting function.  Output is placed on the obstack OBS,
@@ -54,14 +50,15 @@
    format.  */
 
 static void
-format (m4 *context, m4_obstack *obs, int argc, m4_symbol_value **argv)
+format (m4 *context, m4_obstack *obs, int argc, m4_macro_args *argv)
 {
-  const char *name = ARG_STR (argc, argv);     /* macro name */
-  const char *f;                       /* format control string */
-  const char *fmt;                     /* position within f */
-  char fstart[] = "%'+- 0#*.*hhd";     /* current format spec */
-  char *p;                             /* position within fstart */
-  unsigned char c;                     /* a simple character */
+  const char *name = M4ARG (0);                /* Macro name.  */
+  const char *f;                       /* Format control string.  */
+  const char *fmt;                     /* Position within f.  */
+  char fstart[] = "%'+- 0#*.*hhd";     /* Current format spec.  */
+  char *p;                             /* Position within fstart.  */
+  unsigned char c;                     /* A simple character.  */
+  int index = 1;                       /* Index within argc used so far.  */
 
   /* Flags.  */
   char flags;                          /* flags to use in fstart */
@@ -89,7 +86,7 @@ format (m4 *context, m4_obstack *obs, int argc, 
m4_symbol_value **argv)
   char *str;                   /* malloc'd buffer of formatted text */
   enum {CHAR, INT, LONG, DOUBLE, STR} datatype;
 
-  f = fmt = ARG_STR (argc, argv);
+  f = fmt = ARG_STR (index, argc, argv);
   memset (ok, 0, sizeof ok);
   for (;;)
     {
@@ -174,7 +171,7 @@ format (m4 *context, m4_obstack *obs, int argc, 
m4_symbol_value **argv)
       *p++ = '*';
       if (*fmt == '*')
        {
-         width = ARG_INT (argc, argv);
+         width = ARG_INT (index, argc, argv);
          fmt++;
        }
       else
@@ -194,7 +191,7 @@ format (m4 *context, m4_obstack *obs, int argc, 
m4_symbol_value **argv)
          ok['c'] = 0;
          if (*(++fmt) == '*')
            {
-             prec = ARG_INT (argc, argv);
+             prec = ARG_INT (index, argc, argv);
              ++fmt;
            }
          else
@@ -279,23 +276,24 @@ format (m4 *context, m4_obstack *obs, int argc, 
m4_symbol_value **argv)
       switch (datatype)
        {
        case CHAR:
-         str = xasprintf (fstart, width, ARG_INT (argc, argv));
+         str = xasprintf (fstart, width, ARG_INT (index, argc, argv));
          break;
 
        case INT:
-         str = xasprintf (fstart, width, prec, ARG_INT (argc, argv));
+         str = xasprintf (fstart, width, prec, ARG_INT (index, argc, argv));
          break;
 
        case LONG:
-         str = xasprintf (fstart, width, prec, ARG_LONG (argc, argv));
+         str = xasprintf (fstart, width, prec, ARG_LONG (index, argc, argv));
          break;
 
        case DOUBLE:
-         str = xasprintf (fstart, width, prec, ARG_DOUBLE (argc, argv));
+         str = xasprintf (fstart, width, prec,
+                          ARG_DOUBLE (index, argc, argv));
          break;
 
        case STR:
-         str = xasprintf (fstart, width, prec, ARG_STR (argc, argv));
+         str = xasprintf (fstart, width, prec, ARG_STR (index, argc, argv));
          break;
 
        default:
diff --git a/modules/gnu.c b/modules/gnu.c
index 1aba84b..6fd6623 100644
--- a/modules/gnu.c
+++ b/modules/gnu.c
@@ -405,25 +405,26 @@ M4BUILTIN_HANDLER (__program__)
  **/
 M4BUILTIN_HANDLER (builtin)
 {
+  const char *me = M4ARG (0);
   const char *name;
   m4_symbol_value *value;
 
-  if (! m4_is_symbol_value_text (argv[1]))
+  if (!m4_is_symbol_value_text (argv->array[1 - 1]))
     {
-      if (m4_is_symbol_value_func (argv[1])
-         && m4_get_symbol_value_func (argv[1]) == builtin_builtin)
+      if (m4_is_symbol_value_func (argv->array[1 - 1])
+         && m4_get_symbol_value_func (argv->array[1 - 1]) == builtin_builtin)
        {
-         if (m4_bad_argc (context, argc, argv, 2, 2, false))
+         if (m4_bad_argc (context, argc, me, 2, 2, false))
            return;
-         if (! m4_is_symbol_value_text (argv[2]))
+         if (!m4_is_symbol_value_text (argv->array[2 - 1]))
            {
-             m4_warn (context, 0, M4ARG (0), _("invalid macro name ignored"));
+             m4_warn (context, 0, me, _("invalid macro name ignored"));
              return;
            }
          name = M4ARG (2);
          value = m4_builtin_find_by_name (NULL, name);
          if (value == NULL)
-           m4_warn (context, 0, M4ARG (0), _("undefined builtin `%s'"), name);
+           m4_warn (context, 0, me, _("undefined builtin `%s'"), name);
          else
            {
              m4_push_builtin (context, value);
@@ -431,27 +432,38 @@ M4BUILTIN_HANDLER (builtin)
            }
        }
       else
-       m4_warn (context, 0, M4ARG (0), _("invalid macro name ignored"));
+       m4_warn (context, 0, me, _("invalid macro name ignored"));
     }
   else
     {
       name = M4ARG (1);
       value = m4_builtin_find_by_name (NULL, name);
       if (value == NULL)
-       m4_warn (context, 0, M4ARG (0), _("undefined builtin `%s'"), name);
+       m4_warn (context, 0, me, _("undefined builtin `%s'"), name);
       else
        {
          const m4_builtin *bp = m4_get_symbol_value_builtin (value);
-         if (!m4_bad_argc (context, argc - 1, argv + 1,
+         if (!m4_bad_argc (context, argc - 1, name,
                            bp->min_args, bp->max_args,
                            (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
            {
              int i;
+             /* TODO - make use of $@ reference */
+             m4_macro_args *new_argv;
+             new_argv = xmalloc (offsetof (m4_macro_args, array)
+                                 + ((argc - 2) * sizeof (m4_symbol_value *)));
+             new_argv->argc = argc - 1;
+             new_argv->inuse = false;
+             new_argv->argv0 = name;
+             new_argv->arraylen = argc - 2;
+             memcpy (&new_argv->array[0], &argv->array[1],
+                     (argc - 2) * sizeof (m4_symbol_value *));
              if ((bp->flags & M4_BUILTIN_GROKS_MACRO) == 0)
                for (i = 2; i < argc; i++)
-                 if (! m4_is_symbol_value_text (argv[i]))
-                   m4_set_symbol_value_text (argv[i], "");
-             bp->func (context, obs, argc - 1, argv + 1);
+                 if (!m4_is_symbol_value_text (argv->array[i - 1]))
+                   m4_set_symbol_value_text (new_argv->array[i - 2], "");
+             bp->func (context, obs, argc - 1, new_argv);
+             free (new_argv);
            }
          free (value);
        }
@@ -559,7 +571,7 @@ M4BUILTIN_HANDLER (debugfile)
 M4BUILTIN_HANDLER (debuglen)
 {
   int i;
-  if (!m4_numeric_arg (context, argc, argv, 1, &i))
+  if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i))
     return;
   /* FIXME - make m4_numeric_arg more powerful - we want to accept
      suffixes, and limit the result to size_t.  */
@@ -666,24 +678,36 @@ M4BUILTIN_HANDLER (format)
  **/
 M4BUILTIN_HANDLER (indir)
 {
-  if (! m4_is_symbol_value_text (argv[1]))
-    m4_warn (context, 0, M4ARG (0), _("invalid macro name ignored"));
+  const char *me = M4ARG (0);
+  if (!m4_is_symbol_value_text (argv->array[1 - 1]))
+    m4_warn (context, 0, me, _("invalid macro name ignored"));
   else
     {
       const char *name = M4ARG (1);
       m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name);
 
       if (symbol == NULL)
-       m4_warn (context, 0, M4ARG (0), _("undefined macro `%s'"), name);
+       m4_warn (context, 0, me, _("undefined macro `%s'"), name);
       else
        {
          int i;
-         if (! m4_symbol_groks_macro (symbol))
+         /* TODO - make use of $@ reference */
+         m4_macro_args *new_argv;
+         new_argv = xmalloc (offsetof (m4_macro_args, array)
+                             + ((argc - 2) * sizeof (m4_symbol_value *)));
+         new_argv->argc = argc - 1;
+         new_argv->inuse = false;
+         new_argv->argv0 = name;
+         new_argv->arraylen = argc - 2;
+         memcpy (&new_argv->array[0], &argv->array[1],
+                 (argc - 2) * sizeof (m4_symbol_value *));
+         if (!m4_symbol_groks_macro (symbol))
            for (i = 2; i < argc; i++)
-             if (! m4_is_symbol_value_text (argv[i]))
-               m4_set_symbol_value_text (argv[i], "");
+             if (!m4_is_symbol_value_text (argv->array[i - 1]))
+               m4_set_symbol_value_text (new_argv->array[i - 2], "");
          m4_macro_call (context, m4_get_symbol_value (symbol), obs,
-                        argc - 1, argv + 1);
+                        argc - 1, new_argv);
+         free (new_argv);
        }
     }
 }
@@ -784,7 +808,7 @@ M4BUILTIN_HANDLER (regexp)
 
       /* The first case is the most difficult, because the empty string
         is a valid RESYNTAX, yet we want `regexp(aab, a*, )' to return
-        an empty string as per M4 1.4.x!  */
+        an empty string as per M4 1.4.x.  */
 
       if ((*replace == '\0') || (resyntax < 0))
        /* regexp(VICTIM, REGEXP, REPLACEMENT) */
diff --git a/modules/m4.c b/modules/m4.c
index ec2372a..7c0d8ed 100644
--- a/modules/m4.c
+++ b/modules/m4.c
@@ -50,7 +50,7 @@
 extern void m4_set_sysval    (int value);
 extern void m4_sysval_flush  (m4 *context, bool report);
 extern void m4_dump_symbols  (m4 *context, m4_dump_symbol_data *data, int argc,
-                             m4_symbol_value **argv, bool complain);
+                             m4_macro_args *argv, bool complain);
 extern const char *m4_expand_ranges (const char *s, m4_obstack *obs);
 extern void m4_make_temp     (m4 *context, m4_obstack *obs, const char *macro,
                              const char *name, bool dir);
@@ -102,7 +102,7 @@ extern void m4_make_temp     (m4 *context, m4_obstack *obs, 
const char *macro,
 typedef intmax_t number;
 typedef uintmax_t unumber;
 
-static void    include         (m4 *context, int argc, m4_symbol_value **argv,
+static void    include         (m4 *context, int argc, m4_macro_args *argv,
                                 bool silent);
 static int     dumpdef_cmp_CB  (const void *s1, const void *s2);
 static void *  dump_symbol_CB  (m4_symbol_table *ignored, const char *name,
@@ -113,7 +113,7 @@ static void numb_obstack    (m4_obstack *obs, number value,
 
 
 /* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros,  blind, side, min, max) M4BUILTIN(handler)
+#define BUILTIN(handler, macros,  blind, side, min, max) M4BUILTIN (handler)
   builtin_functions
 #undef BUILTIN
 
@@ -122,7 +122,7 @@ static void numb_obstack    (m4_obstack *obs, number value,
 m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)        \
-  { CONC(builtin_, handler), STR(handler),             \
+  { CONC (builtin_, handler), STR (handler),           \
     ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
      | (blind ? M4_BUILTIN_BLIND : 0)                  \
      | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
@@ -160,14 +160,14 @@ M4INIT_HANDLER (m4)
 
 M4BUILTIN_HANDLER (define)
 {
-  if (m4_is_symbol_value_text (argv[1]))
+  if (m4_is_symbol_value_text (argv->array[1 - 1]))
     {
       m4_symbol_value *value = m4_symbol_value_create ();
 
       if (argc == 2)
        m4_set_symbol_value_text (value, xstrdup (""));
       else
-       m4_symbol_value_copy (value, argv[2]);
+       m4_symbol_value_copy (value, argv->array[2 - 1]);
 
       m4_symbol_define (M4SYMTAB, M4ARG (1), value);
     }
@@ -191,14 +191,14 @@ M4BUILTIN_HANDLER (undefine)
 
 M4BUILTIN_HANDLER (pushdef)
 {
-  if (m4_is_symbol_value_text (argv[1]))
+  if (m4_is_symbol_value_text (argv->array[1 - 1]))
     {
       m4_symbol_value *value = m4_symbol_value_create ();
 
       if (argc == 2)
        m4_set_symbol_value_text (value, xstrdup (""));
       else
-       m4_symbol_value_copy (value, argv[2]);
+       m4_symbol_value_copy (value, argv->array[2 - 1]);
 
       m4_symbol_pushdef (M4SYMTAB, M4ARG (1), value);
     }
@@ -246,27 +246,29 @@ M4BUILTIN_HANDLER (ifdef)
 
 M4BUILTIN_HANDLER (ifelse)
 {
+  const char *me = M4ARG (0);
   const char *result;
+  int index;
 
   /* The valid ranges of argc for ifelse is discontinuous, we cannot
      rely on the regular mechanisms.  */
   if (argc == 2)
     return;
 
-  if (m4_bad_argc (context, argc, argv, 3, -1, false))
+  if (m4_bad_argc (context, argc, me, 3, -1, false))
     return;
   else if (argc % 3 == 0)
     /* Diagnose excess arguments if 5, 8, 11, etc., actual arguments.  */
-    m4_bad_argc (context, argc, argv, 0, argc - 2, false);
+    m4_bad_argc (context, argc, me, 0, argc - 2, false);
 
-  argv++;
+  index = 1;
   argc--;
 
   result = NULL;
   while (result == NULL)
 
-    if (strcmp (M4ARG (0), M4ARG (1)) == 0)
-      result = M4ARG (2);
+    if (strcmp (M4ARG (index), M4ARG (index + 1)) == 0)
+      result = M4ARG (index + 2);
 
     else
       switch (argc)
@@ -276,12 +278,12 @@ M4BUILTIN_HANDLER (ifelse)
 
        case 4:
        case 5:
-         result = M4ARG (3);
+         result = M4ARG (index + 3);
          break;
 
        default:
          argc -= 3;
-         argv += 3;
+         index += 3;
        }
 
   obstack_grow (obs, result, strlen (result));
@@ -326,7 +328,7 @@ dump_symbol_CB (m4_symbol_table *ignored, const char *name, 
m4_symbol *symbol,
    symbols, otherwise, only the specified symbols.  */
 void
 m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, int argc,
-                m4_symbol_value **argv, bool complain)
+                m4_macro_args *argv, bool complain)
 {
   assert (obstack_object_size (data->obs) == 0);
   data->size = obstack_room (data->obs) / sizeof (const char *);
@@ -393,15 +395,16 @@ M4BUILTIN_HANDLER (dumpdef)
    macro-definition token on the input stack.  */
 M4BUILTIN_HANDLER (defn)
 {
+  const char *me = M4ARG (0);
   int i;
 
   for (i = 1; i < argc; i++)
     {
-      const char *name = m4_get_symbol_value_text (argv[i]);
+      const char *name = M4ARG (i);
       m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name);
 
       if (!symbol)
-       m4_warn (context, 0, M4ARG (0), _("undefined macro `%s'"), name);
+       m4_warn (context, 0, me, _("undefined macro `%s'"), name);
       else if (m4_is_symbol_text (symbol))
        m4_shipout_string (context, obs, m4_get_symbol_text (symbol), 0, true);
       else if (m4_is_symbol_func (symbol))
@@ -549,7 +552,7 @@ M4BUILTIN_HANDLER (incr)
 {
   int value;
 
-  if (!m4_numeric_arg (context, argc, argv, 1, &value))
+  if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &value))
     return;
 
   m4_shipout_int (obs, value + 1);
@@ -559,7 +562,7 @@ M4BUILTIN_HANDLER (decr)
 {
   int value;
 
-  if (!m4_numeric_arg (context, argc, argv, 1, &value))
+  if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &value))
     return;
 
   m4_shipout_int (obs, value - 1);
@@ -576,7 +579,7 @@ M4BUILTIN_HANDLER (divert)
   int i = 0;
   const char *text;
 
-  if (argc >= 2 && !m4_numeric_arg (context, argc, argv, 1, &i))
+  if (argc >= 2 && !m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i))
     return;
 
   m4_make_diversion (context, i);
@@ -613,7 +616,7 @@ M4BUILTIN_HANDLER (undivert)
        if (*endp == '\0' && !isspace ((unsigned char) *str))
          m4_insert_diversion (context, diversion);
        else if (m4_get_posixly_correct_opt (context))
-         m4_numeric_arg (context, argc, argv, i, &diversion);
+         m4_numeric_arg (context, me, str, &diversion);
        else
          {
            FILE *fp = m4_path_search (context, str, NULL);
@@ -646,7 +649,7 @@ M4BUILTIN_HANDLER (dnl)
    output argument is quoted with the current quotes.  */
 M4BUILTIN_HANDLER (shift)
 {
-  m4_dump_args (context, obs, argc - 1, argv + 1, ",", true);
+  m4_dump_args (context, obs, 2, argv, ",", true);
 }
 
 /* Change the current quotes.  The function set_quotes () lives in
@@ -675,7 +678,7 @@ M4BUILTIN_HANDLER (changecom)
 /* Generic include function.  Include the file given by the first argument,
    if it exists.  Complain about inaccesible files iff SILENT is false.  */
 static void
-include (m4 *context, int argc, m4_symbol_value **argv, bool silent)
+include (m4 *context, int argc, m4_macro_args *argv, bool silent)
 {
   FILE *fp;
   char *name = NULL;
@@ -805,7 +808,7 @@ M4BUILTIN_HANDLER (mkstemp)
 M4BUILTIN_HANDLER (errprint)
 {
   assert (obstack_object_size (obs) == 0);
-  m4_dump_args (context, obs, argc, argv, " ", false);
+  m4_dump_args (context, obs, 1, argv, " ", false);
   obstack_1grow (obs, '\0');
   m4_sysval_flush (context, false);
   fputs ((char *) obstack_finish (obs), stderr);
@@ -825,7 +828,7 @@ M4BUILTIN_HANDLER (m4exit)
   int exit_code = EXIT_SUCCESS;
 
   /* Warn on bad arguments, but still exit.  */
-  if (argc >= 2 && !m4_numeric_arg (context, argc, argv, 1, &exit_code))
+  if (argc >= 2 && !m4_numeric_arg (context, me, M4ARG (1), &exit_code))
     exit_code = EXIT_FAILURE;
   if (exit_code < 0 || exit_code > 255)
     {
@@ -860,7 +863,7 @@ M4BUILTIN_HANDLER (m4wrap)
   if (m4_get_posixly_correct_opt (context))
     m4_shipout_string (context, obs, M4ARG (1), 0, false);
   else
-    m4_dump_args (context, obs, argc, argv, " ", false);
+    m4_dump_args (context, obs, 1, argv, " ", false);
   obstack_1grow (obs, '\0');
   m4_push_wrapup (context, obstack_finish (obs));
 }
@@ -934,21 +937,23 @@ M4BUILTIN_HANDLER (index)
    substring extends to the end of the first argument.  */
 M4BUILTIN_HANDLER (substr)
 {
+  const char *me = M4ARG (0);
+  const char *str = M4ARG (1);
   int start = 0;
   int length;
   int avail;
 
   if (argc <= 2)
     {
-      obstack_grow (obs, M4ARG (1), strlen (M4ARG (1)));
+      obstack_grow (obs, str, strlen (str));
       return;
     }
 
-  length = avail = strlen (M4ARG (1));
-  if (!m4_numeric_arg (context, argc, argv, 2, &start))
+  length = avail = strlen (str);
+  if (!m4_numeric_arg (context, me, M4ARG (2), &start))
     return;
 
-  if (argc >= 4 && !m4_numeric_arg (context, argc, argv, 3, &length))
+  if (argc >= 4 && !m4_numeric_arg (context, me, M4ARG (3), &length))
     return;
 
   if (start < 0 || length <= 0 || start >= avail)
@@ -956,7 +961,7 @@ M4BUILTIN_HANDLER (substr)
 
   if (start + length > avail)
     length = avail - start;
-  obstack_grow (obs, M4ARG (1) + start, length);
+  obstack_grow (obs, str + start, length);
 }
 
 
diff --git a/modules/m4.h b/modules/m4.h
index 5c14e25..4214aed 100644
--- a/modules/m4.h
+++ b/modules/m4.h
@@ -39,7 +39,7 @@ typedef struct
 typedef void m4_sysval_flush_func (m4 *context, bool report);
 typedef void m4_set_sysval_func (int value);
 typedef void m4_dump_symbols_func (m4 *context, m4_dump_symbol_data *data,
-                                  int argc, m4_symbol_value **argv,
+                                  int argc, m4_macro_args *argv,
                                   bool complain);
 typedef const char *m4_expand_ranges_func (const char *s, m4_obstack *obs);
 typedef void m4_make_temp_func (m4 *context, m4_obstack *obs,
diff --git a/modules/stdlib.c b/modules/stdlib.c
index 471ae17..62fdae7 100644
--- a/modules/stdlib.c
+++ b/modules/stdlib.c
@@ -110,7 +110,7 @@ M4BUILTIN_HANDLER (setenv)
   int overwrite = 1;
 
   if (argc >= 4)
-    if (!m4_numeric_arg (context, argc, argv, 3, &overwrite))
+    if (!m4_numeric_arg (context, M4ARG (0), M4ARG (3), &overwrite))
       return;
 
 #if HAVE_SETENV
@@ -209,7 +209,7 @@ M4BUILTIN_HANDLER (getpwuid)
   struct passwd *pw;
   int uid;
 
-  if (!m4_numeric_arg (context, argc, argv, 1, &uid))
+  if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &uid))
     return;
 
   pw = getpwuid (uid);
@@ -264,7 +264,7 @@ M4BUILTIN_HANDLER (srand)
     seed = time (0L) * getpid ();
   else
     {
-      if (!m4_numeric_arg (context, argc, argv, 1, &seed))
+      if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &seed))
        return;
     }
 
diff --git a/modules/time.c b/modules/time.c
index 62cff92..9807ae0 100644
--- a/modules/time.c
+++ b/modules/time.c
@@ -107,7 +107,7 @@ M4BUILTIN_HANDLER (ctime)
 
   if (argc == 2)
     {
-      m4_numeric_arg (context, argc, argv, 1, &i);
+      m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i);
       t = i;
     }
   else
@@ -155,7 +155,7 @@ M4BUILTIN_HANDLER (gmtime)
   time_t t;
   int i;
 
-  if (!m4_numeric_arg (context, argc, argv, 1, &i))
+  if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i))
     return;
 
   t = i;
@@ -170,7 +170,7 @@ M4BUILTIN_HANDLER (localtime)
   time_t t;
   int i;
 
-  if (!m4_numeric_arg (context, argc, argv, 1, &i))
+  if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i))
     return;
 
   t = i;
@@ -183,22 +183,23 @@ M4BUILTIN_HANDLER (localtime)
  **/
 M4BUILTIN_HANDLER (mktime)
 {
+  const char *me = M4ARG (0);
   struct tm tm;
   time_t t;
 
-  if (!m4_numeric_arg (context, argc, argv, 1, &tm.tm_sec))
+  if (!m4_numeric_arg (context, me, M4ARG (1), &tm.tm_sec))
     return;
-  if (!m4_numeric_arg (context, argc, argv, 2, &tm.tm_min))
+  if (!m4_numeric_arg (context, me, M4ARG (2), &tm.tm_min))
     return;
-  if (!m4_numeric_arg (context, argc, argv, 3, &tm.tm_hour))
+  if (!m4_numeric_arg (context, me, M4ARG (3), &tm.tm_hour))
     return;
-  if (!m4_numeric_arg (context, argc, argv, 4, &tm.tm_mday))
+  if (!m4_numeric_arg (context, me, M4ARG (4), &tm.tm_mday))
     return;
-  if (!m4_numeric_arg (context, argc, argv, 5, &tm.tm_mon))
+  if (!m4_numeric_arg (context, me, M4ARG (5), &tm.tm_mon))
     return;
-  if (!m4_numeric_arg (context, argc, argv, 6, &tm.tm_year))
+  if (!m4_numeric_arg (context, me, M4ARG (6), &tm.tm_year))
     return;
-  if (M4ARG (7) && !m4_numeric_arg (context, argc, argv, 7, &tm.tm_isdst))
+  if (M4ARG (7) && !m4_numeric_arg (context, me, M4ARG (7), &tm.tm_isdst))
     return;
 
   t = mktime (&tm);
@@ -218,7 +219,7 @@ M4BUILTIN_HANDLER (strftime)
   char *buf;
   int l;
 
-  if (!m4_numeric_arg (context, argc, argv, 2, &l))
+  if (!m4_numeric_arg (context, M4ARG (0), M4ARG (2), &l))
     return;
 
   t = l;


hooks/post-receive
--
GNU M4 source repository




reply via email to

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