m4-commit
[Top][All Lists]
Advanced

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

[SCM] GNU M4 source repository branch, branch-1_4, updated. branch-cvs-r


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, branch-1_4, updated. branch-cvs-readonly-21-gac88455
Date: Sun, 25 Nov 2007 00:28:04 +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=ac8845562f0066ef07d74a1f5b0e749eceb19b89

The branch, branch-1_4 has been updated
       via  ac8845562f0066ef07d74a1f5b0e749eceb19b89 (commit)
      from  9de0b8950ca83762363605805c40f8f8614acbc8 (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 ac8845562f0066ef07d74a1f5b0e749eceb19b89
Author: Eric Blake <address@hidden>
Date:   Fri Oct 19 07:43:34 2007 -0600

    Stage 1: convert token_data** into new object.
    
    * m4/gnulib-cache.m4: Import flexmember module.
    * src/m4.h (struct macro_arguments, struct token_chain): New
    structs.
    (builtin_func): Alter signature.
    (token_data): Add new TOKEN_COMP alternative.
    * src/builtin.c: All builtins changed.
    (ARG, dump_args, define_macro, expand_user_macro): Update to use
    struct.
    * src/debug.c (trace_pre, trace_post): Likewise.
    * src/format.c (ARG_INT, ARG_LONG, ARG_STR, ARG_DOUBLE, format):
    Likewise.
    * src/macro.c (collect_arguments): Build new struct.
    (call_macro, expand_macro): Update to use new struct.
    
    (cherry picked from commit 44f5da7de32ac8f71f26d9e441316fa563db30d6)
    
    Signed-off-by: Eric Blake <address@hidden>

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

Summary of changes:
 ChangeLog          |   17 +++++
 m4/gnulib-cache.m4 |    4 +-
 src/builtin.c      |  201 ++++++++++++++++++++++++++++++----------------------
 src/debug.c        |   10 ++--
 src/format.c       |   45 +++++-------
 src/m4.h           |   71 ++++++++++++++-----
 src/macro.c        |   51 ++++++++------
 7 files changed, 243 insertions(+), 156 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9bbf726..14deb9f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2007-11-24  Eric Blake  <address@hidden>
+
+       Stage 1: convert token_data** into new object.
+       * m4/gnulib-cache.m4: Import flexmember module.
+       * src/m4.h (struct macro_arguments, struct token_chain): New
+       structs.
+       (builtin_func): Alter signature.
+       (token_data): Add new TOKEN_COMP alternative.
+       * src/builtin.c: All builtins changed.
+       (ARG, dump_args, define_macro, expand_user_macro): Update to use
+       struct.
+       * src/debug.c (trace_pre, trace_post): Likewise.
+       * src/format.c (ARG_INT, ARG_LONG, ARG_STR, ARG_DOUBLE, format):
+       Likewise.
+       * src/macro.c (collect_arguments): Build new struct.
+       (call_macro, expand_macro): Update to use new struct.
+
 2007-11-22  Eric Blake  <address@hidden>
 
        More error messages tied to macro names.
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index 4d1727d..a89650c 100644
--- a/m4/gnulib-cache.m4
+++ b/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=libm4 
--source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests 
--no-libtool --macro-prefix=M4 assert avltree-oset binary-io clean-temp cloexec 
close-stream closein config-h error fdl fflush fopen-safer free fseeko gendocs 
getopt gnupload gpl-3.0 mkstemp obstack regex stdbool stdint stdlib-safer 
strtol unlocked-io verror version-etc version-etc-fsf xalloc xprintf 
xvasprintf-posix
+#   gnulib-tool --import --dir=. --local-dir=local --lib=libm4 
--source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests 
--no-libtool --macro-prefix=M4 assert avltree-oset binary-io clean-temp cloexec 
close-stream closein config-h error fdl fflush flexmember fopen-safer free 
fseeko gendocs getopt gnupload gpl-3.0 mkstemp obstack regex stdbool stdint 
stdlib-safer strtol unlocked-io verror version-etc version-etc-fsf xalloc 
xprintf xvasprintf-posix
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([local])
-gl_MODULES([assert avltree-oset binary-io clean-temp cloexec close-stream 
closein config-h error fdl fflush fopen-safer free fseeko gendocs getopt 
gnupload gpl-3.0 mkstemp obstack regex stdbool stdint stdlib-safer strtol 
unlocked-io verror version-etc version-etc-fsf xalloc xprintf xvasprintf-posix])
+gl_MODULES([assert avltree-oset binary-io clean-temp cloexec close-stream 
closein config-h error fdl fflush flexmember fopen-safer free fseeko gendocs 
getopt gnupload gpl-3.0 mkstemp obstack regex stdbool stdint stdlib-safer 
strtol unlocked-io verror version-etc version-etc-fsf xalloc xprintf 
xvasprintf-posix])
 gl_AVOID([])
 gl_SOURCE_BASE([lib])
 gl_M4_BASE([m4])
diff --git a/src/builtin.c b/src/builtin.c
index cc4e469..eb66465 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -30,14 +30,16 @@
 # include <sys/wait.h>
 #endif
 
-#define ARG(i) (argc > (i) ? TOKEN_DATA_TEXT (argv[i]) : "")
+#define ARG(i)                                                         \
+  ((i) == 0 ? argv->argv0                                              \
+   : argv->argc > (i) ? TOKEN_DATA_TEXT (argv->array[(i) - 1]) : "")
 
 /* Initialization of builtin and predefined macros.  The table
    "builtin_tab" is both used for initialization, and by the "builtin"
    builtin.  */
 
 #define DECLARE(name) \
-  static void name (struct obstack *, int, token_data **)
+  static void name (struct obstack *, int, macro_arguments *)
 
 DECLARE (m4___file__);
 DECLARE (m4___line__);
@@ -602,16 +604,19 @@ shipout_int (struct obstack *obs, int val)
 `----------------------------------------------------------------------*/
 
 static void
-dump_args (struct obstack *obs, int argc, token_data **argv,
+dump_args (struct obstack *obs, int start, macro_arguments *argv,
           const char *sep, bool quoted)
 {
   int i;
+  bool dump_sep = false;
   size_t len = strlen (sep);
 
-  for (i = 1; i < argc; i++)
+  for (i = start; i < argv->argc; i++)
     {
-      if (i > 1)
+      if (dump_sep)
        obstack_grow (obs, sep, len);
+      else
+       dump_sep = true;
       if (quoted)
        obstack_grow (obs, lquote.string, lquote.length);
       obstack_grow (obs, ARG (i), strlen (ARG (i)));
@@ -623,14 +628,15 @@ dump_args (struct obstack *obs, int argc, token_data 
**argv,
 /* The rest of this file is code for builtins and expansion of user
    defined macros.  All the functions for builtins have a prototype as:
 
-       void m4_MACRONAME (struct obstack *obs, int argc, char *argv[]);
+     void m4_MACRONAME (struct obstack *obs, int argc, macro_arguments *argv);
 
-   The function are expected to leave their expansion on the obstack OBS,
-   as an unfinished object.  ARGV is a table of ARGC pointers to the
-   individual arguments to the macro.  Please note that in general
-   argv[argc] != NULL.  */
+   The functions are expected to leave their expansion on the obstack OBS,
+   as an unfinished object.  ARGV is an object representing ARGC pointers
+   to the individual arguments to the macro; the object may be compressed
+   due to references to $@ expansions, so accessors should be used.  Please
+   note that in general argv[argc] != NULL.  */
 
-/* The first section are macros for definining, undefining, examining,
+/* The first section are macros for defining, undefining, examining,
    changing, ... other macros.  */
 
 /*-------------------------------------------------------------------------.
@@ -641,7 +647,7 @@ dump_args (struct obstack *obs, int argc, token_data **argv,
 `-------------------------------------------------------------------------*/
 
 static void
-define_macro (int argc, token_data **argv, symbol_lookup mode)
+define_macro (int argc, macro_arguments *argv, symbol_lookup mode)
 {
   const builtin *bp;
   const char *me = ARG (0);
@@ -649,7 +655,7 @@ define_macro (int argc, token_data **argv, symbol_lookup 
mode)
   if (bad_argc (me, argc, 1, 2))
     return;
 
-  if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
+  if (TOKEN_DATA_TYPE (argv->array[0]) != TOKEN_TEXT)
     {
       m4_warn (0, me, _("invalid macro name ignored"));
       return;
@@ -661,14 +667,14 @@ define_macro (int argc, token_data **argv, symbol_lookup 
mode)
       return;
     }
 
-  switch (TOKEN_DATA_TYPE (argv[2]))
+  switch (TOKEN_DATA_TYPE (argv->array[1]))
     {
     case TOKEN_TEXT:
       define_user_macro (ARG (1), ARG (2), mode);
       break;
 
     case TOKEN_FUNC:
-      bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[2]));
+      bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv->array[1]));
       if (bp == NULL)
        return;
       else
@@ -682,13 +688,13 @@ define_macro (int argc, token_data **argv, symbol_lookup 
mode)
 }
 
 static void
-m4_define (struct obstack *obs, int argc, token_data **argv)
+m4_define (struct obstack *obs, int argc, macro_arguments *argv)
 {
   define_macro (argc, argv, SYMBOL_INSERT);
 }
 
 static void
-m4_undefine (struct obstack *obs, int argc, token_data **argv)
+m4_undefine (struct obstack *obs, int argc, macro_arguments *argv)
 {
   int i;
   if (bad_argc (ARG (0), argc, 1, -1))
@@ -698,13 +704,13 @@ m4_undefine (struct obstack *obs, int argc, token_data 
**argv)
 }
 
 static void
-m4_pushdef (struct obstack *obs, int argc, token_data **argv)
+m4_pushdef (struct obstack *obs, int argc, macro_arguments *argv)
 {
-  define_macro (argc, argv,  SYMBOL_PUSHDEF);
+  define_macro (argc, argv, SYMBOL_PUSHDEF);
 }
 
 static void
-m4_popdef (struct obstack *obs, int argc, token_data **argv)
+m4_popdef (struct obstack *obs, int argc, macro_arguments *argv)
 {
   int i;
   if (bad_argc (ARG (0), argc, 1, -1))
@@ -718,7 +724,7 @@ m4_popdef (struct obstack *obs, int argc, token_data **argv)
 `---------------------*/
 
 static void
-m4_ifdef (struct obstack *obs, int argc, token_data **argv)
+m4_ifdef (struct obstack *obs, int argc, macro_arguments *argv)
 {
   symbol *s;
   const char *result;
@@ -739,10 +745,11 @@ m4_ifdef (struct obstack *obs, int argc, token_data 
**argv)
 }
 
 static void
-m4_ifelse (struct obstack *obs, int argc, token_data **argv)
+m4_ifelse (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *result;
   const char *me;
+  int index;
 
   if (argc == 2)
     return;
@@ -754,14 +761,14 @@ m4_ifelse (struct obstack *obs, int argc, token_data 
**argv)
     /* Diagnose excess arguments if 5, 8, 11, etc., actual arguments.  */
     bad_argc (me, argc, 0, argc - 2);
 
-  argv++;
+  index = 1;
   argc--;
 
   result = NULL;
   while (result == NULL)
 
-    if (strcmp (ARG (0), ARG (1)) == 0)
-      result = ARG (2);
+    if (strcmp (ARG (index), ARG (index + 1)) == 0)
+      result = ARG (index + 2);
 
     else
       switch (argc)
@@ -771,12 +778,12 @@ m4_ifelse (struct obstack *obs, int argc, token_data 
**argv)
 
        case 4:
        case 5:
-         result = ARG (3);
+         result = ARG (index + 3);
          break;
 
        default:
          argc -= 3;
-         argv += 3;
+         index += 3;
        }
 
   obstack_grow (obs, result, strlen (result));
@@ -826,7 +833,7 @@ dumpdef_cmp (const void *s1, const void *s2)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_dumpdef (struct obstack *obs, int argc, token_data **argv)
+m4_dumpdef (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   symbol *s;
@@ -900,7 +907,7 @@ m4_dumpdef (struct obstack *obs, int argc, token_data 
**argv)
 `---------------------------------------------------------------------*/
 
 static void
-m4_builtin (struct obstack *obs, int argc, token_data **argv)
+m4_builtin (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   const builtin *bp;
@@ -908,7 +915,7 @@ m4_builtin (struct obstack *obs, int argc, token_data 
**argv)
 
   if (bad_argc (me, argc, 1, -1))
     return;
-  if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
+  if (TOKEN_DATA_TYPE (argv->array[0]) != TOKEN_TEXT)
     {
       m4_warn (0, me, _("invalid macro name ignored"));
       return;
@@ -921,14 +928,25 @@ m4_builtin (struct obstack *obs, int argc, token_data 
**argv)
   else
     {
       int i;
+      /* TODO make use of $@ reference, instead of copying argv.  */
+      macro_arguments *new_argv = xmalloc (offsetof (macro_arguments, array)
+                                          + ((argc - 2)
+                                             * sizeof (token_data *)));
+      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 (token_data *));
       if (!bp->groks_macro_args)
        for (i = 2; i < argc; i++)
-         if (TOKEN_DATA_TYPE (argv[i]) != TOKEN_TEXT)
+         if (TOKEN_DATA_TYPE (new_argv->array[i - 2]) != TOKEN_TEXT)
            {
-             TOKEN_DATA_TYPE (argv[i]) = TOKEN_TEXT;
-             TOKEN_DATA_TEXT (argv[i]) = (char *) "";
+             TOKEN_DATA_TYPE (new_argv->array[i - 2]) = TOKEN_TEXT;
+             TOKEN_DATA_TEXT (new_argv->array[i - 2]) = (char *) "";
            }
-      bp->func (obs, argc - 1, argv + 1);
+      bp->func (obs, argc - 1, new_argv);
+      free (new_argv);
     }
 }
 
@@ -940,7 +958,7 @@ m4_builtin (struct obstack *obs, int argc, token_data 
**argv)
 `------------------------------------------------------------------------*/
 
 static void
-m4_indir (struct obstack *obs, int argc, token_data **argv)
+m4_indir (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   symbol *s;
@@ -948,7 +966,7 @@ m4_indir (struct obstack *obs, int argc, token_data **argv)
 
   if (bad_argc (me, argc, 1, -1))
     return;
-  if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
+  if (TOKEN_DATA_TYPE (argv->array[0]) != TOKEN_TEXT)
     {
       m4_warn (0, me, _("invalid macro name ignored"));
       return;
@@ -961,14 +979,25 @@ m4_indir (struct obstack *obs, int argc, token_data 
**argv)
   else
     {
       int i;
+      /* TODO make use of $@ reference, instead of copying argv.  */
+      macro_arguments *new_argv = xmalloc (offsetof (macro_arguments, array)
+                                          + ((argc - 2)
+                                             * sizeof (token_data *)));
+      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 (token_data *));
       if (!SYMBOL_MACRO_ARGS (s))
        for (i = 2; i < argc; i++)
-         if (TOKEN_DATA_TYPE (argv[i]) != TOKEN_TEXT)
+         if (TOKEN_DATA_TYPE (new_argv->array[i - 2]) != TOKEN_TEXT)
            {
-             TOKEN_DATA_TYPE (argv[i]) = TOKEN_TEXT;
-             TOKEN_DATA_TEXT (argv[i]) = (char *) "";
+             TOKEN_DATA_TYPE (new_argv->array[i - 2]) = TOKEN_TEXT;
+             TOKEN_DATA_TEXT (new_argv->array[i - 2]) = (char *) "";
            }
-      call_macro (s, argc - 1, argv + 1, obs);
+      call_macro (s, argc - 1, new_argv, obs);
+      free (new_argv);
     }
 }
 
@@ -979,7 +1008,7 @@ m4_indir (struct obstack *obs, int argc, token_data **argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_defn (struct obstack *obs, int argc, token_data **argv)
+m4_defn (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   symbol *s;
@@ -1060,7 +1089,7 @@ m4_defn (struct obstack *obs, int argc, token_data **argv)
 static int sysval;
 
 static void
-m4_syscmd (struct obstack *obs, int argc, token_data **argv)
+m4_syscmd (struct obstack *obs, int argc, macro_arguments *argv)
 {
   if (bad_argc (ARG (0), argc, 1, 1))
     {
@@ -1084,7 +1113,7 @@ m4_syscmd (struct obstack *obs, int argc, token_data 
**argv)
 }
 
 static void
-m4_esyscmd (struct obstack *obs, int argc, token_data **argv)
+m4_esyscmd (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   FILE *pin;
@@ -1114,7 +1143,7 @@ m4_esyscmd (struct obstack *obs, int argc, token_data 
**argv)
 }
 
 static void
-m4_sysval (struct obstack *obs, int argc, token_data **argv)
+m4_sysval (struct obstack *obs, int argc, macro_arguments *argv)
 {
   shipout_int (obs, (sysval == -1 ? 127
                     : (M4SYSVAL_EXITBITS (sysval)
@@ -1127,7 +1156,7 @@ m4_sysval (struct obstack *obs, int argc, token_data 
**argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_eval (struct obstack *obs, int argc, token_data **argv)
+m4_eval (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   int32_t value = 0;
@@ -1190,7 +1219,7 @@ m4_eval (struct obstack *obs, int argc, token_data **argv)
 }
 
 static void
-m4_incr (struct obstack *obs, int argc, token_data **argv)
+m4_incr (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   int value;
@@ -1205,7 +1234,7 @@ m4_incr (struct obstack *obs, int argc, token_data **argv)
 }
 
 static void
-m4_decr (struct obstack *obs, int argc, token_data **argv)
+m4_decr (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   int value;
@@ -1228,7 +1257,7 @@ m4_decr (struct obstack *obs, int argc, token_data **argv)
 `-----------------------------------------------------------------------*/
 
 static void
-m4_divert (struct obstack *obs, int argc, token_data **argv)
+m4_divert (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   int i = 0;
@@ -1245,7 +1274,7 @@ m4_divert (struct obstack *obs, int argc, token_data 
**argv)
 `-----------------------------------------------------*/
 
 static void
-m4_divnum (struct obstack *obs, int argc, token_data **argv)
+m4_divnum (struct obstack *obs, int argc, macro_arguments *argv)
 {
   bad_argc (ARG (0), argc, 0, 0);
   shipout_int (obs, current_diversion);
@@ -1259,7 +1288,7 @@ m4_divnum (struct obstack *obs, int argc, token_data 
**argv)
 `-----------------------------------------------------------------------*/
 
 static void
-m4_undivert (struct obstack *obs, int argc, token_data **argv)
+m4_undivert (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   int i;
@@ -1303,7 +1332,7 @@ m4_undivert (struct obstack *obs, int argc, token_data 
**argv)
 `------------------------------------------------------------------------*/
 
 static void
-m4_dnl (struct obstack *obs, int argc, token_data **argv)
+m4_dnl (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
 
@@ -1317,11 +1346,12 @@ m4_dnl (struct obstack *obs, int argc, token_data 
**argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_shift (struct obstack *obs, int argc, token_data **argv)
+m4_shift (struct obstack *obs, int argc, macro_arguments *argv)
 {
   if (bad_argc (ARG (0), argc, 1, -1))
     return;
-  dump_args (obs, argc - 1, argv + 1, ",", true);
+  /* TODO push a $@ reference.  */
+  dump_args (obs, 2, argv, ",", true);
 }
 
 /*--------------------------------------------------------------------------.
@@ -1329,13 +1359,13 @@ m4_shift (struct obstack *obs, int argc, token_data 
**argv)
 `--------------------------------------------------------------------------*/
 
 static void
-m4_changequote (struct obstack *obs, int argc, token_data **argv)
+m4_changequote (struct obstack *obs, int argc, macro_arguments *argv)
 {
   bad_argc (ARG (0), argc, 0, 2);
 
   /* Explicit NULL distinguishes between empty and missing argument.  */
   set_quotes ((argc >= 2) ? ARG (1) : NULL,
-            (argc >= 3) ? ARG (2) : NULL);
+             (argc >= 3) ? ARG (2) : NULL);
 }
 
 /*--------------------------------------------------------------------.
@@ -1344,7 +1374,7 @@ m4_changequote (struct obstack *obs, int argc, token_data 
**argv)
 `--------------------------------------------------------------------*/
 
 static void
-m4_changecom (struct obstack *obs, int argc, token_data **argv)
+m4_changecom (struct obstack *obs, int argc, macro_arguments *argv)
 {
   bad_argc (ARG (0), argc, 0, 2);
 
@@ -1361,7 +1391,7 @@ m4_changecom (struct obstack *obs, int argc, token_data 
**argv)
 `-----------------------------------------------------------------------*/
 
 static void
-m4_changeword (struct obstack *obs, int argc, token_data **argv)
+m4_changeword (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
 
@@ -1382,7 +1412,7 @@ m4_changeword (struct obstack *obs, int argc, token_data 
**argv)
 `-------------------------------------------------------------------------*/
 
 static void
-include (int argc, token_data **argv, bool silent)
+include (int argc, macro_arguments *argv, bool silent)
 {
   const char *me = ARG (0);
   FILE *fp;
@@ -1408,7 +1438,7 @@ include (int argc, token_data **argv, bool silent)
 `------------------------------------------------*/
 
 static void
-m4_include (struct obstack *obs, int argc, token_data **argv)
+m4_include (struct obstack *obs, int argc, macro_arguments *argv)
 {
   include (argc, argv, false);
 }
@@ -1418,7 +1448,7 @@ m4_include (struct obstack *obs, int argc, token_data 
**argv)
 `----------------------------------*/
 
 static void
-m4_sinclude (struct obstack *obs, int argc, token_data **argv)
+m4_sinclude (struct obstack *obs, int argc, macro_arguments *argv)
 {
   include (argc, argv, true);
 }
@@ -1462,7 +1492,7 @@ mkstemp_helper (struct obstack *obs, const char *me, 
const char *name)
 }
 
 static void
-m4_maketemp (struct obstack *obs, int argc, token_data **argv)
+m4_maketemp (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
 
@@ -1507,7 +1537,7 @@ m4_maketemp (struct obstack *obs, int argc, token_data 
**argv)
 }
 
 static void
-m4_mkstemp (struct obstack *obs, int argc, token_data **argv)
+m4_mkstemp (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
 
@@ -1521,11 +1551,11 @@ m4_mkstemp (struct obstack *obs, int argc, token_data 
**argv)
 `----------------------------------------*/
 
 static void
-m4_errprint (struct obstack *obs, int argc, token_data **argv)
+m4_errprint (struct obstack *obs, int argc, macro_arguments *argv)
 {
   if (bad_argc (ARG (0), argc, 1, -1))
     return;
-  dump_args (obs, argc, argv, " ", false);
+  dump_args (obs, 1, argv, " ", false);
   obstack_1grow (obs, '\0');
   debug_flush_files ();
   xfprintf (stderr, "%s", (char *) obstack_finish (obs));
@@ -1533,7 +1563,7 @@ m4_errprint (struct obstack *obs, int argc, token_data 
**argv)
 }
 
 static void
-m4___file__ (struct obstack *obs, int argc, token_data **argv)
+m4___file__ (struct obstack *obs, int argc, macro_arguments *argv)
 {
   bad_argc (ARG (0), argc, 0, 0);
   obstack_grow (obs, lquote.string, lquote.length);
@@ -1542,14 +1572,14 @@ m4___file__ (struct obstack *obs, int argc, token_data 
**argv)
 }
 
 static void
-m4___line__ (struct obstack *obs, int argc, token_data **argv)
+m4___line__ (struct obstack *obs, int argc, macro_arguments *argv)
 {
   bad_argc (ARG (0), argc, 0, 0);
   shipout_int (obs, current_line);
 }
 
 static void
-m4___program__ (struct obstack *obs, int argc, token_data **argv)
+m4___program__ (struct obstack *obs, int argc, macro_arguments *argv)
 {
   bad_argc (ARG (0), argc, 0, 0);
   obstack_grow (obs, lquote.string, lquote.length);
@@ -1567,7 +1597,7 @@ m4___program__ (struct obstack *obs, int argc, token_data 
**argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_m4exit (struct obstack *obs, int argc, token_data **argv)
+m4_m4exit (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   int exit_code = EXIT_SUCCESS;
@@ -1600,14 +1630,14 @@ m4_m4exit (struct obstack *obs, int argc, token_data 
**argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_m4wrap (struct obstack *obs, int argc, token_data **argv)
+m4_m4wrap (struct obstack *obs, int argc, macro_arguments *argv)
 {
   if (bad_argc (ARG (0), argc, 1, -1))
     return;
   if (no_gnu_extensions)
     obstack_grow (obs, ARG (1), strlen (ARG (1)));
   else
-    dump_args (obs, argc, argv, " ", false);
+    dump_args (obs, 1, argv, " ", false);
   obstack_1grow (obs, '\0');
   push_wrapup ((char *) obstack_finish (obs));
 }
@@ -1632,7 +1662,7 @@ set_trace (symbol *sym, void *data)
 }
 
 static void
-m4_traceon (struct obstack *obs, int argc, token_data **argv)
+m4_traceon (struct obstack *obs, int argc, macro_arguments *argv)
 {
   symbol *s;
   int i;
@@ -1652,7 +1682,7 @@ m4_traceon (struct obstack *obs, int argc, token_data 
**argv)
 `------------------------------------------------------------------------*/
 
 static void
-m4_traceoff (struct obstack *obs, int argc, token_data **argv)
+m4_traceoff (struct obstack *obs, int argc, macro_arguments *argv)
 {
   symbol *s;
   int i;
@@ -1675,7 +1705,7 @@ m4_traceoff (struct obstack *obs, int argc, token_data 
**argv)
 `----------------------------------------------------------------------*/
 
 static void
-m4_debugmode (struct obstack *obs, int argc, token_data **argv)
+m4_debugmode (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   const char *str = ARG (1);
@@ -1727,7 +1757,7 @@ m4_debugmode (struct obstack *obs, int argc, token_data 
**argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_debugfile (struct obstack *obs, int argc, token_data **argv)
+m4_debugfile (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
 
@@ -1748,7 +1778,7 @@ m4_debugfile (struct obstack *obs, int argc, token_data 
**argv)
 `---------------------------------------------*/
 
 static void
-m4_len (struct obstack *obs, int argc, token_data **argv)
+m4_len (struct obstack *obs, int argc, macro_arguments *argv)
 {
   if (bad_argc (ARG (0), argc, 1, 1))
     return;
@@ -1761,7 +1791,7 @@ m4_len (struct obstack *obs, int argc, token_data **argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_index (struct obstack *obs, int argc, token_data **argv)
+m4_index (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *haystack;
   const char *needle;
@@ -1801,7 +1831,7 @@ m4_index (struct obstack *obs, int argc, token_data 
**argv)
 `-------------------------------------------------------------------------*/
 
 static void
-m4_substr (struct obstack *obs, int argc, token_data **argv)
+m4_substr (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   int start = 0;
@@ -1885,7 +1915,7 @@ expand_ranges (const char *s, struct obstack *obs)
 `----------------------------------------------------------------------*/
 
 static void
-m4_translit (struct obstack *obs, int argc, token_data **argv)
+m4_translit (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *data;
   const char *from;
@@ -1950,7 +1980,7 @@ m4_translit (struct obstack *obs, int argc, token_data 
**argv)
 `--------------------------------------------------------------*/
 
 static void
-m4_format (struct obstack *obs, int argc, token_data **argv)
+m4_format (struct obstack *obs, int argc, macro_arguments *argv)
 {
   if (bad_argc (ARG (0), argc, 1, -1))
     return;
@@ -2047,7 +2077,7 @@ init_pattern_buffer (struct re_pattern_buffer *buf, 
struct re_registers *regs)
 `------------------------------------------------------------------*/
 
 static void
-m4_regexp (struct obstack *obs, int argc, token_data **argv)
+m4_regexp (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   const char *victim;          /* first argument */
@@ -2117,7 +2147,7 @@ m4_regexp (struct obstack *obs, int argc, token_data 
**argv)
 `------------------------------------------------------------------*/
 
 static void
-m4_patsubst (struct obstack *obs, int argc, token_data **argv)
+m4_patsubst (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const char *me = ARG (0);
   const char *victim;          /* first argument */
@@ -2222,7 +2252,7 @@ m4_patsubst (struct obstack *obs, int argc, token_data 
**argv)
 `--------------------------------------------------------------------*/
 
 void
-m4_placeholder (struct obstack *obs, int argc, token_data **argv)
+m4_placeholder (struct obstack *obs, int argc, macro_arguments *argv)
 {
   m4_warn (0, NULL, _("builtin `%s' requested by frozen file not found"),
           ARG (0));
@@ -2238,7 +2268,7 @@ m4_placeholder (struct obstack *obs, int argc, token_data 
**argv)
 
 void
 expand_user_macro (struct obstack *obs, symbol *sym,
-                  int argc, token_data **argv)
+                  int argc, macro_arguments *argv)
 {
   const char *text;
   int i;
@@ -2263,7 +2293,7 @@ expand_user_macro (struct obstack *obs, symbol *sym,
          else
            {
              for (i = 0; isdigit (to_uchar (*text)); text++)
-               i = i*10 + (*text - '0');
+               i = i * 10 + (*text - '0');
            }
          if (i < argc)
            obstack_grow (obs, ARG (i), strlen (ARG (i)));
@@ -2276,7 +2306,8 @@ expand_user_macro (struct obstack *obs, symbol *sym,
 
        case '*':               /* all arguments */
        case '@':               /* ... same, but quoted */
-         dump_args (obs, argc, argv, ",", *text == '@');
+         /* TODO push a $@ reference.  */
+         dump_args (obs, 1, argv, ",", *text == '@');
          text++;
          break;
 
diff --git a/src/debug.c b/src/debug.c
index c22a482..e5bd280 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -362,7 +362,7 @@ trace_prepre (const char *name, int id)
 `-----------------------------------------------------------------------*/
 
 void
-trace_pre (const char *name, int id, int argc, token_data **argv)
+trace_pre (const char *name, int id, int argc, macro_arguments *argv)
 {
   int i;
   const builtin *bp;
@@ -379,14 +379,14 @@ trace_pre (const char *name, int id, int argc, token_data 
**argv)
          if (i != 1)
            trace_format (", ");
 
-         switch (TOKEN_DATA_TYPE (argv[i]))
+         switch (TOKEN_DATA_TYPE (argv->array[i - 1]))
            {
            case TOKEN_TEXT:
-             trace_format ("%l%S%r", TOKEN_DATA_TEXT (argv[i]));
+             trace_format ("%l%S%r", TOKEN_DATA_TEXT (argv->array[i - 1]));
              break;
 
            case TOKEN_FUNC:
-             bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[i]));
+             bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv->array[i - 1]));
              if (bp == NULL)
                {
                  assert (!"trace_pre");
@@ -417,7 +417,7 @@ trace_pre (const char *name, int id, int argc, token_data 
**argv)
 `-------------------------------------------------------------------*/
 
 void
-trace_post (const char *name, int id, int argc, token_data **argv,
+trace_post (const char *name, int id, int argc, macro_arguments *argv,
            const char *expanded)
 {
   if (debug_level & DEBUG_TRACE_CALL)
diff --git a/src/format.c b/src/format.c
index 96ac562..4c2b60a 100644
--- a/src/format.c
+++ b/src/format.c
@@ -27,21 +27,17 @@
 /* Simple varargs substitute.  We assume int and unsigned int are the
    same size; likewise for long and unsigned long.  */
 
-#define ARG_INT(argc, argv) \
-       ((argc == 0) ? 0 : \
-        (--argc, argv++, atoi (TOKEN_DATA_TEXT (argv[-1]))))
+#define ARG_INT(i, argc, argv)                                         \
+       ((i == argc) ? 0 : atoi (TOKEN_DATA_TEXT (argv->array[i++ - 1])))
 
-#define ARG_LONG(argc, argv) \
-       ((argc == 0) ? 0 : \
-        (--argc, argv++, atol (TOKEN_DATA_TEXT (argv[-1]))))
+#define ARG_LONG(i, argc, argv)                                                
\
+       ((i == argc) ? 0L : atol (TOKEN_DATA_TEXT (argv->array[i++ - 1])))
 
-#define ARG_STR(argc, argv) \
-       ((argc == 0) ? "" : \
-        (--argc, argv++, TOKEN_DATA_TEXT (argv[-1])))
+#define ARG_STR(i, argc, argv)                                         \
+       ((i == argc) ? "" : TOKEN_DATA_TEXT (argv->array[i++ - 1]))
 
-#define ARG_DOUBLE(argc, argv) \
-       ((argc == 0) ? 0 : \
-        (--argc, argv++, atof (TOKEN_DATA_TEXT (argv[-1]))))
+#define ARG_DOUBLE(i, argc, argv)                                      \
+       ((i == argc) ? 0.0 : atof (TOKEN_DATA_TEXT (argv->array[i++ - 1])))
 
 
 /*------------------------------------------------------------------.
@@ -53,14 +49,15 @@
 `------------------------------------------------------------------*/
 
 void
-format (struct obstack *obs, int argc, token_data **argv)
+format (struct obstack *obs, int argc, macro_arguments *argv)
 {
-  const char *me = TOKEN_DATA_TEXT (argv[0]);
+  const char *me = argv->argv0;
   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 */
@@ -88,9 +85,7 @@ format (struct obstack *obs, int argc, token_data **argv)
   char *str;                   /* malloc'd buffer of formatted text */
   enum {CHAR, INT, LONG, DOUBLE, STR} datatype;
 
-  argv++;
-  argc--;
-  f = fmt = ARG_STR (argc, argv);
+  f = fmt = ARG_STR (index, argc, argv);
   memset (ok, 0, sizeof ok);
   for (;;)
     {
@@ -175,7 +170,7 @@ format (struct obstack *obs, int argc, token_data **argv)
       *p++ = '*';
       if (*fmt == '*')
        {
-         width = ARG_INT (argc, argv);
+         width = ARG_INT (index, argc, argv);
          fmt++;
        }
       else
@@ -195,7 +190,7 @@ format (struct obstack *obs, int argc, token_data **argv)
          ok['c'] = 0;
          if (*(++fmt) == '*')
            {
-             prec = ARG_INT (argc, argv);
+             prec = ARG_INT (index, argc, argv);
              ++fmt;
            }
          else
@@ -280,27 +275,27 @@ format (struct obstack *obs, int argc, token_data **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:
-         abort();
+         abort ();
        }
 
       /* NULL was returned on failure, such as invalid format string.
diff --git a/src/m4.h b/src/m4.h
index 4f1fa1f..94276e9 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -89,7 +89,8 @@ typedef struct string STRING;
 
 /* Those must come first.  */
 typedef struct token_data token_data;
-typedef void builtin_func (struct obstack *, int, token_data **);
+typedef struct macro_arguments macro_arguments;
+typedef void builtin_func (struct obstack *, int, macro_arguments *);
 
 /* Gnulib's stdbool doesn't work with bool bitfields.  For nicer
    debugging, use bool when we know it works, but use the more
@@ -103,14 +104,14 @@ typedef unsigned int bool_bitfield;
 /* Take advantage of GNU C compiler source level optimization hints,
    using portable macros.  */
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6)
-#  define M4_GNUC_ATTRIBUTE(args)      __attribute__(args)
+#  define M4_GNUC_ATTRIBUTE(args)      __attribute__ (args)
 #else
 #  define M4_GNUC_ATTRIBUTE(args)
 #endif  /* __GNUC__ */
 
-#define M4_GNUC_UNUSED         M4_GNUC_ATTRIBUTE((__unused__))
+#define M4_GNUC_UNUSED         M4_GNUC_ATTRIBUTE ((__unused__))
 #define M4_GNUC_PRINTF(fmt, arg)                       \
-  M4_GNUC_ATTRIBUTE((__format__ (__printf__, fmt, arg)))
+  M4_GNUC_ATTRIBUTE ((__format__ (__printf__, fmt, arg)))
 
 /* File: m4.c  --- global definitions.  */
 
@@ -132,12 +133,13 @@ extern const char *user_word_regexp;      /* -W */
 extern int retcode;
 extern const char *program_name;
 
-void m4_error (int, int, const char *, const char *, ...) M4_GNUC_PRINTF(4, 5);
+void m4_error (int, int, const char *, const char *, ...)
+  M4_GNUC_PRINTF (4, 5);
 void m4_error_at_line (int, int, const char *, int, const char *,
-                      const char *, ...) M4_GNUC_PRINTF(6, 7);
-void m4_warn (int, const char *, const char *, ...) M4_GNUC_PRINTF(3, 4);
+                      const char *, ...) M4_GNUC_PRINTF (6, 7);
+void m4_warn (int, const char *, const char *, ...) M4_GNUC_PRINTF (3, 4);
 void m4_warn_at_line (int, const char *, int, const char *,
-                     const char *, ...) M4_GNUC_PRINTF(5, 6);
+                     const char *, ...) M4_GNUC_PRINTF (5, 6);
 
 #ifdef USE_STACKOVF
 void setup_stackovf_trap (char *const *, char *const *,
@@ -235,11 +237,13 @@ bool debug_set_output (const char *, const char *);
 void debug_message_prefix (void);
 
 void trace_prepre (const char *, int);
-void trace_pre (const char *, int, int, token_data **);
-void trace_post (const char *, int, int, token_data **, const char *);
+void trace_pre (const char *, int, int, macro_arguments *);
+void trace_post (const char *, int, int, macro_arguments *, const char *);
 
 /* File: input.c  --- lexical definitions.  */
 
+typedef struct token_chain token_chain;
+
 /* Various different token types.  */
 enum token_type
 {
@@ -256,9 +260,19 @@ enum token_type
 /* The data for a token, a macro argument, and a macro definition.  */
 enum token_data_type
 {
-  TOKEN_VOID,
-  TOKEN_TEXT,
-  TOKEN_FUNC
+  TOKEN_VOID, /* Token still being constructed, u is invalid.  */
+  TOKEN_TEXT, /* Straight text, u.u_t is valid.  */
+  TOKEN_FUNC, /* Builtin function definition, u.func is valid.  */
+  TOKEN_COMP  /* Composite argument, u.chain is valid.  */
+};
+
+/* Composite tokens are built of a linked list of chains.  */
+struct token_chain
+{
+  token_chain *next; /* Pointer to next link of chain.  */
+  char *str; /* NUL-terminated string if text, else NULL.  */
+  macro_arguments *argv; /* Reference to earlier address@hidden  */
+  unsigned int index; /* Index within argv to start reading from.  */
 };
 
 struct token_data
@@ -275,10 +289,31 @@ struct token_data
        }
       u_t;
       builtin_func *func;
+
+      /* Composite text: a linked list of straight text and $@
+        placeholders.  */
+      token_chain *chain;
     }
   u;
 };
 
+struct macro_arguments
+{
+  /* Number of arguments owned by this object, 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 next byte read from file.  */
+  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.  */
+  token_data *array[FLEXIBLE_ARRAY_MEMBER];
+};
+
 #define TOKEN_DATA_TYPE(Td)            ((Td)->type)
 #define TOKEN_DATA_TEXT(Td)            ((Td)->u.u_t.text)
 #ifdef ENABLE_CHANGEWORD
@@ -358,7 +393,7 @@ struct symbol
   int pending_expansions;
 
   char *name;
-  token_data data;
+  token_data data;  /* Type should be only TOKEN_TEXT or TOKEN_FUNC.  */
 };
 
 #define SYMBOL_NEXT(S)         ((S)->next)
@@ -391,7 +426,7 @@ void hack_all_symbols (hack_symbol *, void *);
 extern int expansion_level;
 
 void expand_input (void);
-void call_macro (symbol *, int, token_data **, struct obstack *);
+void call_macro (symbol *, int, macro_arguments *, struct obstack *);
 
 /* File: builtin.c  --- builtins.  */
 
@@ -427,8 +462,8 @@ void set_macro_sequence (const char *);
 void free_regex (void);
 void define_user_macro (const char *, const char *, symbol_lookup);
 void undivert_all (void);
-void expand_user_macro (struct obstack *, symbol *, int, token_data **);
-void m4_placeholder (struct obstack *, int, token_data **);
+void expand_user_macro (struct obstack *, symbol *, int, macro_arguments *);
+void m4_placeholder (struct obstack *, int, macro_arguments *);
 void init_pattern_buffer (struct re_pattern_buffer *, struct re_registers *);
 const char *ntoa (int32_t, int);
 
@@ -448,7 +483,7 @@ bool evaluate (const char *, const char *, int32_t *);
 
 /* File: format.c  --- printf like formatting.  */
 
-void format (struct obstack *, int, token_data **);
+void format (struct obstack *, int, macro_arguments *);
 
 /* File: freeze.c --- frozen state files.  */
 
diff --git a/src/macro.c b/src/macro.c
index 8a678d4..d2f2cb7 100644
--- a/src/macro.c
+++ b/src/macro.c
@@ -241,19 +241,22 @@ expand_argument (struct obstack *obs, token_data *argp, 
const char *caller)
 | on the obstack ARGPTR.                                                  |
 `-------------------------------------------------------------------------*/
 
-static void
-collect_arguments (symbol *sym, struct obstack *argptr,
+static macro_arguments *
+collect_arguments (symbol *sym, struct obstack *argptr, unsigned argv_base,
                   struct obstack *arguments)
 {
   token_data td;
   token_data *tdp;
   bool more_args;
   bool groks_macro_args = SYMBOL_MACRO_ARGS (sym);
+  macro_arguments args;
+  macro_arguments *argv;
 
-  TOKEN_DATA_TYPE (&td) = TOKEN_TEXT;
-  TOKEN_DATA_TEXT (&td) = SYMBOL_NAME (sym);
-  tdp = (token_data *) obstack_copy (arguments, &td, sizeof td);
-  obstack_ptr_grow (argptr, tdp);
+  args.argc = 1;
+  args.inuse = false;
+  args.argv0 = SYMBOL_NAME (sym);
+  args.arraylen = 0;
+  obstack_grow (argptr, &args, offsetof (macro_arguments, array));
 
   if (peek_token () == TOKEN_OPEN)
     {
@@ -269,9 +272,15 @@ collect_arguments (symbol *sym, struct obstack *argptr,
            }
          tdp = (token_data *) obstack_copy (arguments, &td, sizeof td);
          obstack_ptr_grow (argptr, tdp);
+         args.arraylen++;
+         args.argc++;
        }
       while (more_args);
     }
+  argv = (macro_arguments *) ((char *) obstack_base (argptr) + argv_base);
+  argv->argc = args.argc;
+  argv->arraylen = args.arraylen;
+  return argv;
 }
 
 
@@ -285,13 +294,13 @@ collect_arguments (symbol *sym, struct obstack *argptr,
 `------------------------------------------------------------------------*/
 
 void
-call_macro (symbol *sym, int argc, token_data **argv,
-                struct obstack *expansion)
+call_macro (symbol *sym, int argc, macro_arguments *argv,
+           struct obstack *expansion)
 {
   switch (SYMBOL_TYPE (sym))
     {
     case TOKEN_FUNC:
-      (*SYMBOL_FUNC (sym)) (expansion, argc, argv);
+      SYMBOL_FUNC (sym) (expansion, argc, argv);
       break;
 
     case TOKEN_TEXT:
@@ -319,8 +328,8 @@ expand_macro (symbol *sym)
 {
   struct obstack arguments;    /* Alternate obstack if argc_stack is busy.  */
   unsigned argv_base;          /* Size of argv_stack on entry.  */
-  bool use_argc_stack = true;  /* Whether argc_stack is safe.  */
-  token_data **argv;
+  void *argc_start;            /* Start of argc_stack, else NULL if unsafe.  */
+  macro_arguments *argv;
   int argc;
   struct obstack *expansion;
   const char *expanded;
@@ -357,18 +366,17 @@ expand_macro (symbol *sym)
         outer invocation has an unfinished argument being
         collected.  */
       obstack_init (&arguments);
-      use_argc_stack = false;
+      argc_start = NULL;
     }
+  else
+    argc_start = obstack_finish (&argc_stack);
 
   if (traced && (debug_level & DEBUG_TRACE_CALL))
     trace_prepre (SYMBOL_NAME (sym), my_call_id);
 
-  collect_arguments (sym, &argv_stack,
-                    use_argc_stack ? &argc_stack : &arguments);
-
-  argc = ((obstack_object_size (&argv_stack) - argv_base)
-         / sizeof (token_data *));
-  argv = (token_data **) ((char *) obstack_base (&argv_stack) + argv_base);
+  argv = collect_arguments (sym, &argv_stack, argv_base,
+                           argc_start ? &argc_stack : &arguments);
+  argc = argv->argc;
 
   loc_close_file = current_file;
   loc_close_line = current_line;
@@ -394,9 +402,10 @@ expand_macro (symbol *sym)
   if (SYMBOL_DELETED (sym))
     free_symbol (sym);
 
-  if (use_argc_stack)
-    obstack_free (&argc_stack, argv[0]);
+  /* TODO pay attention to argv->inuse, in case someone is depending on 
address@hidden  */
+  if (argc_start)
+    obstack_free (&argc_stack, argc_start);
   else
     obstack_free (&arguments, NULL);
-  obstack_blank (&argv_stack, -argc * sizeof (token_data *));
+  obstack_blank (&argv_stack, argv_base - obstack_object_size (&argv_stack));
 }


hooks/post-receive
--
GNU M4 source repository




reply via email to

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