autoconf-patches
[Top][All Lists]
Advanced

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

Re: [PATCH] Rewrite handling of diversion and expansion stacks


From: Eric Blake
Subject: Re: [PATCH] Rewrite handling of diversion and expansion stacks
Date: Thu, 30 Oct 2008 21:14:53 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.17) Gecko/20080914 Thunderbird/2.0.0.17 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 10/30/2008 8:51 PM:
> Taking all three patches together, I even see a slight speedup on
> coreutils, from 9.709s to 9.548s.  Any comments before I apply?

Such as, where's the patch?

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkkKeC0ACgkQ84KuGfSFAYAKVQCdH83Lh0XhRWHWA5Eg2HE2qoO9
EjMAoI3frEg7X1A20aAUPXQBDtWQO2GV
=XXj+
-----END PGP SIGNATURE-----
>From 8832e7efae09f8a15964170c70ed2e1ed2c092f3 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 30 Oct 2008 12:16:15 -0600
Subject: [PATCH] Simplify expansion stack handling.

* lib/m4sugar/m4sugar.m4 (m4_expansion_stack): Use fewer macros;
always output 'top level'.
(m4_expansion_stack_push): Format string here, rather than in
caller.
(m4_warn, _m4_defun_pro, m4_expansion_stack_dump): Update
callers.
* tests/m4sugar.at (m4@&address@hidden): New test.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog              |   11 +++++++++++
 lib/m4sugar/m4sugar.m4 |   36 +++++++++++++++++-------------------
 tests/m4sugar.at       |   24 ++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 457d711..d357ff0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2008-10-30  Eric Blake  <address@hidden>
 
+       Simplify expansion stack handling.
+       * lib/m4sugar/m4sugar.m4 (m4_expansion_stack): Use fewer macros;
+       always output 'top level'.
+       (m4_expansion_stack_push): Format string here, rather than in
+       caller.
+       (m4_warn, _m4_defun_pro, m4_expansion_stack_dump): Update
+       callers.
+       * tests/m4sugar.at (m4@&address@hidden): New test.
+
+2008-10-30  Eric Blake  <address@hidden>
+
        Fix LINENO testsuite failure.
        * tests/m4sh.at (AT_DATA_LINENO): Use AS_LINENO_PREPARE, not
        undocumented _AS_PREPARE, and move unset earlier in script.
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index 85d36d0..7c1d74b 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -259,8 +259,7 @@ m4_define([_m4_warn], [])
 # Report a MESSAGE to the user if the CATEGORY of warnings is enabled.
 m4_define([m4_warn],
 [_m4_warn([$1], [$2],
-m4_ifdef([_m4_expansion_stack],
-        [m4_expansion_stack[]m4_location[: the top level]]))])
+m4_ifdef([_m4_expansion_stack], [m4_expansion_stack]))])
 
 
 
@@ -1507,7 +1506,7 @@ m4_define([m4_undivert],
 # You should keep the definitions of _m4_defun_pro, _m4_defun_epi, and
 # m4_require at hand to follow the steps.
 #
-# This implements tries not to assume that the current diversion is
+# This implementation tries not to assume that the current diversion is
 # BODY, so as soon as a macro (m4_defun'd) is expanded, we first
 # record the current diversion under the name _m4_divert_dump (denoted
 # DUMP below for short).  This introduces an important difference with
@@ -1614,17 +1613,20 @@ m4_define([m4_undivert],
 
 # m4_expansion_stack
 # ------------------
-# Expands to the entire contents of the expansion stack, if not empty,
-# with a newline at its end.
+# Expands to the entire contents of the expansion stack.  The caller
+# must supply a trailing newline.  This macro always prints a
+# location; check whether _m4_expansion_stack is defined to filter out
+# the case when no defun'd macro is in force.
 m4_define([m4_expansion_stack],
-[m4_ifdef([_m4_expansion_stack],
-         [m4_stack_foreach_lifo([_m4_expansion_stack], [m4_n])])])
+[m4_stack_foreach_sep_lifo([_m4_expansion_stack], [], [
+])m4_location[: the top level]])
 
-# m4_expansion_stack_push(TEXT)
-# -----------------------------
-# Form an entry of the expansion stack and push it.
+# m4_expansion_stack_push(MACRO)
+# ------------------------------
+# Form an entry of the expansion stack on entry to MACRO and push it.
 m4_define([m4_expansion_stack_push],
-[m4_pushdef([_m4_expansion_stack], [[$1]])])
+[m4_pushdef([_m4_expansion_stack],
+_m4_defn([m4_location($1)])[: $1 is expanded from...])])
 
 
 # m4_expansion_stack_pop
@@ -1636,11 +1638,9 @@ m4_define([m4_expansion_stack_pop],
 
 # m4_expansion_stack_dump
 # -----------------------
-# Dump the expansion stack.
+# Dump the expansion stack to stderr.
 m4_define([m4_expansion_stack_dump],
-[m4_ifdef([_m4_expansion_stack],
-         [m4_errprint(m4_expansion_stack)])dnl
-m4_errprintn(m4_location[: the top level])])
+[m4_errprintn(m4_expansion_stack)])
 
 
 # _m4_divert(GROW)
@@ -1669,10 +1669,8 @@ m4_define([_m4_divert(GROW)],       10000)
 # This is called frequently, so minimize the number of macro invocations
 # by avoiding dnl and m4_defn overhead.
 m4_define([_m4_defun_pro],
-m4_do([[m4_ifdef([_m4_expansion_stack], [], [_m4_defun_pro_outer[]])]],
-      [[m4_expansion_stack_push(_m4_defn(
-         [m4_location($1)])[: $1 is expanded from...])]],
-      [[m4_pushdef([_m4_expanding($1)])]]))
+[m4_ifdef([_m4_expansion_stack], [], [_m4_defun_pro_outer[]])]dnl
+[m4_expansion_stack_push([$1])m4_pushdef([_m4_expanding($1)])])
 
 m4_define([_m4_defun_pro_outer],
 [m4_define([_m4_divert_dump],
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index 550d085..d8554b5 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -243,6 +243,30 @@ script.4s:6: the top level
 AT_CLEANUP
 
 
+## -------------------- ##
+## m4_expansion_stack.  ##
+## -------------------- ##
+
+AT_SETUP([m4@&address@hidden)
+
+AT_CHECK_M4SUGAR_TEXT([[1.m4_expansion_stack
+m4_defun([a], [b])dnl
+m4_define([c], [d])dnl
+m4_defun([d], [2.m4_expansion_stack])dnl
+m4_defun([b], [c])dnl
+a
+3.m4_ifdef([_m4_expansion_stack], [m4_expansion_stack])
+]], [[1.script.4s:3: the top level
+2.script.4s:6: d is expanded from...
+script.4s:7: b is expanded from...
+script.4s:4: a is expanded from...
+script.4s:8: the top level
+3.
+]])
+
+AT_CLEANUP
+
+
 ## --------------------------- ##
 ## m4_require: error message.  ##
 ## --------------------------- ##
-- 
1.6.0.2


>From 734ea188a052625615062b73aab1f5f0b8265655 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 30 Oct 2008 15:32:56 -0600
Subject: [PATCH] Simplify diversion stack handling.

* lib/m4sugar/m4sugar.m4 (m4_divert_stack): Use fewer macros, and
avoid extra newlines.
(m4_divert_stack_push): Compute location here, rather than caller.
(m4_divert_push): Update caller.
(m4_divert): Likewise, and also adjust current diversion name.
(m4_divert_pop): Simplify rule that diversion stack must never go
empty.
(_m4_require_call): Bypass diversion stack when collecting
required macro text.
(m4_init): Set current diversion without requiring m4_init.
* lib/m4sugar/m4sh.m4 (AS_INIT): Avoid too many pops.
* lib/autotest/general.m4 (AT_INIT): Likewise.
* lib/autoconf/general.m4 (_AC_INIT_DEFAULTS): Schedule wrapped
text to run prior to m4sugar cleanup.
* doc/autoconf.texi (Text processing Macros) <m4_newline>: Mention
optional argument.
(Conditional constructs) <m4_ifvaln, m4_n>: Mention use of dnl.
* NEWS: Undo blurb about m4_divert.
* tests/m4sugar.at (m4@&address@hidden): New test.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog               |   21 ++++++++++++++
 NEWS                    |    2 -
 doc/autoconf.texi       |    8 +++--
 lib/autoconf/general.m4 |    2 +-
 lib/autotest/general.m4 |    3 +-
 lib/m4sugar/m4sh.m4     |    7 ++---
 lib/m4sugar/m4sugar.m4  |   51 ++++++++++++++++++++---------------
 tests/m4sugar.at        |   68 +++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 128 insertions(+), 34 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d357ff0..3a46f64 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
 2008-10-30  Eric Blake  <address@hidden>
 
+       Simplify diversion stack handling.
+       * lib/m4sugar/m4sugar.m4 (m4_divert_stack): Use fewer macros, and
+       avoid extra newlines.
+       (m4_divert_stack_push): Compute location here, rather than caller.
+       (m4_divert_push): Update caller.
+       (m4_divert): Likewise, and also adjust current diversion name.
+       (m4_divert_pop): Simplify rule that diversion stack must never go
+       empty.
+       (_m4_require_call): Bypass diversion stack when collecting
+       required macro text.
+       (m4_init): Set current diversion without requiring m4_init.
+       * lib/m4sugar/m4sh.m4 (AS_INIT): Avoid too many pops.
+       * lib/autotest/general.m4 (AT_INIT): Likewise.
+       * lib/autoconf/general.m4 (_AC_INIT_DEFAULTS): Schedule wrapped
+       text to run prior to m4sugar cleanup.
+       * doc/autoconf.texi (Text processing Macros) <m4_newline>: Mention
+       optional argument.
+       (Conditional constructs) <m4_ifvaln, m4_n>: Mention use of dnl.
+       * NEWS: Undo blurb about m4_divert.
+       * tests/m4sugar.at (m4@&address@hidden): New test.
+
        Simplify expansion stack handling.
        * lib/m4sugar/m4sugar.m4 (m4_expansion_stack): Use fewer macros;
        always output 'top level'.
diff --git a/NEWS b/NEWS
index d07c143..e22559f 100644
--- a/NEWS
+++ b/NEWS
@@ -12,8 +12,6 @@ GNU Autoconf NEWS - User visible changes.
 
 ** Configure scripts now use shell functions.
 
-** m4sugar requires m4_init in order to use m4_divert.
-
 ** The following documented m4sugar macros are new:
    m4_curry  m4_default_quoted  m4_map_args  m4_map_args_pair
    m4_set_map
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index f10eeae..a1b2390 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -10813,12 +10813,13 @@ Conditional constructs
 @defmac m4_ifvaln (@var{cond}, @ovar{if-true}, @ovar{if-false})
 @msindex{ifvaln}
 Similar to @code{m4_ifval}, except guarantee that a newline is present
-after any non-empty expansion.
+after any non-empty expansion.  Often followed by @code{dnl}.
 @end defmac
 
 @defmac m4_n (@var{text})
 @msindex{n}
 Expand to @var{text}, and add a newline if @var{text} is not empty.
+Often followed by @code{dnl}.
 @end defmac
 
 
@@ -11421,9 +11422,10 @@ Text processing Macros
 efficient to use @code{m4_dquote}.
 @end defmac
 
address@hidden m4_newline
address@hidden m4_newline (@ovar{text})
 @msindex{newline}
-This macro was introduced in Autoconf 2.62, and expands to a newline.
+This macro was introduced in Autoconf 2.62, and expands to a newline,
+followed by any @var{text}.
 It is primarily useful for maintaining macro formatting, and ensuring
 that M4 does not discard leading whitespace during argument collection.
 @end defmac
diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index ccaf340..c990c05 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -433,7 +433,7 @@ AC_SUBST([PACKAGE_BUGREPORT],
         [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])])dnl
 
 m4_divert_pop([DEFAULTS])dnl
-m4_wrap([m4_divert_text([DEFAULTS],
+m4_wrap_lifo([m4_divert_text([DEFAULTS],
 [ac_subst_vars='m4_set_dump([_AC_SUBST_VARS], m4_newline)'
 ac_subst_files='m4_ifdef([_AC_SUBST_FILES], [m4_defn([_AC_SUBST_FILES])])'
 ac_user_opts='
diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4
index 03d3902..68f75d8 100644
--- a/lib/autotest/general.m4
+++ b/lib/autotest/general.m4
@@ -1423,8 +1423,7 @@ m4_divert_pop([TESTS])dnl
 dnl End of AT_INIT: divert to KILL, only test groups are to be
 dnl output, the rest is ignored.  Current diversion is BODY, inherited
 dnl from M4sh.
-m4_divert_pop([BODY])
-m4_divert_push([KILL])
+m4_divert([KILL])
 ])# AT_INIT
 
 
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 1a61729..a506ef0 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -235,8 +235,8 @@ dnl Remove any tests from suggested that are also required
             as_shell=$as_dir/$as_base
             AS_IF([{ test -f "$as_shell" || test -f "$as_shell.exe"; } &&
                    _AS_RUN(["$as_required"], ["$as_shell"])],
-                  [CONFIG_SHELL=$as_shell as_have_required=yes
-                  m4_set_empty([_AS_DETECT_SUGGESTED_BODY], [break 2],
+                  [CONFIG_SHELL=$as_shell as_have_required=yes
+                  m4_set_empty([_AS_DETECT_SUGGESTED_BODY], [break 2],
                     [AS_IF([_AS_RUN(["$as_suggested"], ["$as_shell"])],
                            [break 2])])])
           done;;
@@ -1906,8 +1906,7 @@ m4_divert_text([M4SH-SANITIZE], [_AS_SHELL_SANITIZE])
 m4_divert_text([M4SH-INIT-FN], [m4_text_box([M4sh Shell Functions.])])
 
 # Let's go!
-m4_divert_pop([KILL])[]dnl
-m4_divert_push([BODY])
+m4_divert([BODY])dnl
 m4_text_box([Main body of script.])
 _AS_DETECT_REQUIRED([_AS_SHELL_FN_WORK])dnl
 AS_REQUIRE([_AS_UNSET_PREPARE], [], [M4SH-INIT-FN])dnl
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index 7c1d74b..0707996 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -1259,16 +1259,19 @@ m4_define([_m4_divert()],                0)
 
 # m4_divert_stack
 # ------------------
-# Print m4_divert_stack with newline prepended, if it's nonempty.
+# Print the diversion stack, if it's nonempty.  The caller is
+# responsible for any leading or trailing newline.
 m4_define([m4_divert_stack],
-[m4_stack_foreach_lifo([_m4_divert_stack], [m4_newline])])
+[m4_stack_foreach_sep_lifo([_m4_divert_stack], [], [], [
+])])
 
 
-# m4_divert_stack_push(LOCATION, MACRO-NAME, DIVERSION-NAME)
-# -----------------------------------------------------------
-# Form an entry of the diversion stack and push it.
+# m4_divert_stack_push(MACRO-NAME, DIVERSION-NAME)
+# ------------------------------------------------
+# Form an entry of the diversion stack from caller MACRO-NAME and
+# entering DIVERSION-NAME and push it.
 m4_define([m4_divert_stack_push],
-[m4_pushdef([_m4_divert_stack], [[$1: $2: $3]])])
+[m4_pushdef([_m4_divert_stack], m4_location[: $1: $2])])
 
 
 # m4_divert(DIVERSION-NAME)
@@ -1276,7 +1279,8 @@ m4_define([m4_divert_stack_push],
 # Change the diversion stream to DIVERSION-NAME.
 m4_define([m4_divert],
 [m4_popdef([_m4_divert_stack])]dnl
-[m4_divert_stack_push(m4_location, [$0], [$1])]dnl
+[m4_define([_m4_divert_diversion], [$1])]dnl
+[m4_divert_stack_push([$0], [$1])]dnl
 [m4_builtin([divert], _m4_divert([$1]))])
 
 
@@ -1284,7 +1288,7 @@ m4_define([m4_divert],
 # ------------------------------
 # Change the diversion stream to DIVERSION-NAME, while stacking old values.
 m4_define([m4_divert_push],
-[m4_divert_stack_push(m4_location, [$0], [$1])]dnl
+[m4_divert_stack_push([$0], [$1])]dnl
 [m4_pushdef([_m4_divert_diversion], [$1])]dnl
 [m4_builtin([divert], _m4_divert([$1]))])
 
@@ -1295,16 +1299,14 @@ m4_define([m4_divert_push],
 # If specified, verify we left DIVERSION-NAME.
 # When we pop the last value from the stack, we divert to -1.
 m4_define([m4_divert_pop],
-[m4_ifndef([_m4_divert_diversion],
-          [m4_fatal([too many m4_divert_pop])])]dnl
 [m4_if([$1], [], [],
        [$1], _m4_defn([_m4_divert_diversion]), [],
-       [m4_fatal([$0($1): diversion mismatch: ]m4_divert_stack)])]dnl
+       [m4_fatal([$0($1): diversion mismatch:
+]m4_divert_stack)])]dnl
 [_m4_popdef([_m4_divert_stack], [_m4_divert_diversion])]dnl
-[m4_builtin([divert],
-           m4_ifdef([_m4_divert_diversion],
-                    [_m4_divert(_m4_defn([_m4_divert_diversion]))],
-                    -1))])
+[m4_ifdef([_m4_divert_diversion], [],
+          [m4_fatal([too many m4_divert_pop])])]dnl
+[m4_builtin([divert], _m4_divert(_m4_defn([_m4_divert_diversion])))])
 
 
 # m4_divert_text(DIVERSION-NAME, CONTENT)
@@ -1850,8 +1852,8 @@ m4_provide_if([$1],
              [],
              [m4_warn([syntax],
                       [$1 is m4_require'd but not m4_defun'd])])]],
-      [[m4_divert($3)]],
-      [[m4_undivert(_m4_divert_grow)]],
+      [[m4_builtin([divert], _m4_divert($3))]],
+      [[m4_builtin([undivert], _m4_divert_grow)]],
       [[m4_divert_pop(_m4_divert_grow)]],
       [[m4_define([_m4_divert_grow], m4_incr(_m4_divert_grow))]]))
 
@@ -2944,6 +2946,8 @@ m4_if(m4_sysval, [0], [],
 ## 17. Setting M4sugar up.  ##
 ## ------------------------ ##
 
+# _m4_divert_diversion should be defined.
+m4_divert_push([KILL])
 
 # m4_init
 # -------
@@ -2969,11 +2973,14 @@ m4_define([m4_popdef], _m4_defn([m4_popdef]))
 m4_define([m4_undefine], _m4_defn([m4_undefine]))],
 [m4_builtin([include], [m4sugar/foreach.m4])])
 
-# _m4_divert_diversion should be defined:
-m4_divert_push([KILL])
+# Rewrite the first entry of the diversion stack.
+m4_divert([KILL])
 
 # Check the divert push/pop perfect balance.
-m4_wrap([m4_divert_pop([])
-        m4_ifdef([_m4_divert_diversion],
-          [m4_fatal([$0: unbalanced m4_divert_push:]m4_divert_stack)])[]])
+# Some users are prone to also use m4_wrap to register last-minute
+# m4_divert_text; so after our diversion cleanups, we restore
+# KILL as the bottom of the diversion stack.
+m4_wrap([m4_popdef([_m4_divert_diversion])m4_ifdef(
+  [_m4_divert_diversion], [m4_fatal([$0: unbalanced m4_divert_push:
+]m4_divert_stack)])_m4_popdef([_m4_divert_stack])m4_divert_push([KILL])])
 ])
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index d8554b5..8034ced 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -243,6 +243,74 @@ script.4s:6: the top level
 AT_CLEANUP
 
 
+## ----------------- ##
+## m4_divert_stack.  ##
+## ----------------- ##
+
+AT_SETUP([m4@&address@hidden)
+
+AT_CHECK_M4SUGAR_TEXT([[1.m4_divert_stack
+m4_divert_push([10])2.m4_divert_stack
+m4_divert_text([20], [3.m4_divert_stack])dnl
+m4_divert([30])4.m4_divert_stack
+m4_divert_pop([30])dnl
+5.m4_undivert([20])
+6.m4_undivert([30])
+m4_pattern_allow([^m4_divert])dnl
+]], [[1.script.4s:2: m4@&address@hidden: 0
+script.4s:1: m4@&address@hidden: KILL
+5.3.script.4s:5: m4@&address@hidden: 20
+script.4s:4: m4@&address@hidden: 10
+script.4s:2: m4@&address@hidden: 0
+script.4s:1: m4@&address@hidden: KILL
+
+6.4.script.4s:6: m4@&address@hidden: 30
+script.4s:2: m4@&address@hidden: 0
+script.4s:1: m4@&address@hidden: KILL
+
+2.script.4s:4: m4@&address@hidden: 10
+script.4s:2: m4@&address@hidden: 0
+script.4s:1: m4@&address@hidden: KILL
+]])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_divert_pop
+]])
+AT_CHECK_M4SUGAR([-o-], [1], [],
+[[script.4s:1: error: too many m4@&address@hidden
+script.4s:1: the top level
+autom4te: m4 failed with exit status: 1
+]])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_divert_push([1])
+m4_divert_pop([2])
+]])
+AT_CHECK_M4SUGAR([-o-], [1], [],
+[[script.4s:3: error: m4@&address@hidden(2): diversion mismatch:
+script.4s:2: m4@&address@hidden: 1
+script.4s:1: m4@&address@hidden: KILL
+script.4s:3: the top level
+autom4te: m4 failed with exit status: 1
+]])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_divert([1])
+m4_init
+m4_divert_push([2])
+]])
+AT_CHECK_M4SUGAR([-o-], [1], [],
+[[script.4s:2: error: m4@&address@hidden: unbalanced m4@&address@hidden:
+script.4s:3: m4@&address@hidden: 2
+script.4s:2: m4@&address@hidden: KILL
+script.4s:2: the top level
+autom4te: m4 failed with exit status: 1
+]])
+
+AT_CLEANUP
+
+
 ## -------------------- ##
 ## m4_expansion_stack.  ##
 ## -------------------- ##
-- 
1.6.0.2


>From a424bd9500ae2a845de3216e6ac0d804509f6513 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 30 Oct 2008 15:51:26 -0600
Subject: [PATCH] Support multiple undiverts and dumpdefs at once.

* lib/m4sugar/m4sugar.m4 (m4_dumpdefs, m4_undivert): Allow extra
arguments.
* doc/autoconf.texi (Redefined M4 Macros) <m4_dumpdef>,
<m4_undivert>: Document argument list change.
* tests/m4sugar.at (m4@&address@hidden, m4@&address@hidden): Test
them.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog              |    8 ++++++++
 doc/autoconf.texi      |   10 +++++-----
 lib/m4sugar/m4sugar.m4 |   24 +++++++++++++++---------
 tests/m4sugar.at       |   11 +++++------
 4 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3a46f64..35a093c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2008-10-30  Eric Blake  <address@hidden>
 
+       Support multiple undiverts and dumpdefs at once.
+       * lib/m4sugar/m4sugar.m4 (m4_dumpdefs, m4_undivert): Allow extra
+       arguments.
+       * doc/autoconf.texi (Redefined M4 Macros) <m4_dumpdef>,
+       <m4_undivert>: Document argument list change.
+       * tests/m4sugar.at (m4@&address@hidden, m4@&address@hidden): Test
+       them.
+
        Simplify diversion stack handling.
        * lib/m4sugar/m4sugar.m4 (m4_divert_stack): Use fewer macros, and
        avoid extra newlines.
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index a1b2390..02f32b2 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -10408,14 +10408,14 @@ Redefined M4 Macros
 @end defmac
 
 @defmac m4_dumpdef (@address@hidden)
address@hidden m4_dumpdefs (@var{name})
address@hidden m4_dumpdefs (@address@hidden)
 @msindex{dumpdef}
 @msindex{dumpdefs}
 @code{m4_dumpdef} is like the M4 builtin, except that this version
 requires at least one argument, output always goes to standard error
 rather than the current debug file, and an error is issued if any
 @var{name} is undefined.  @code{m4_dumpdefs} is a convenience macro that
-takes exactly one @var{name}, and calls @code{m4_dumpdef} for all of the
+calls @code{m4_dumpdef} for all of the
 @code{m4_pushdef} stack of definitions, starting with the current, and
 silently does nothing if @var{name} is undefined.
 @end defmac
@@ -10476,10 +10476,10 @@ Redefined M4 Macros
 if you are not sure whether @var{macro} is defined.
 @end defmac
 
address@hidden m4_undivert (@var{diversion})
address@hidden m4_undivert (@address@hidden)
 @msindex{undivert}
-Unlike the M4 builtin, only one diversion can be undiverted per
-invocation.  Also, since the M4sugar diversion stack prefers named
+Unlike the M4 builtin, a @var{diversion} must be specified.
+Also, since the M4sugar diversion stack prefers named
 diversions, the use of @code{m4_undivert} to include files is risky.
 @xref{Diversion support}, for more details about the use of the
 diversion stack.
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index 0707996..1791d9d 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -611,16 +611,19 @@ m4_define([m4_dumpdef],
        [m4_map_args([$0], $@)])])
 
 
-# m4_dumpdefs(NAME)
-# -----------------
+# m4_dumpdefs(NAME...)
+# --------------------
 # Similar to `m4_dumpdef(NAME)', but if NAME was m4_pushdef'ed, display its
-# value stack (most recent displayed first).
+# value stack (most recent displayed first).  Also, this version silently
+# ignores undefined macros, rather than erroring out.
 #
 # This macro cheats, because it relies on the current definition of NAME
 # while the second argument of m4_stack_foreach_lifo is evaluated (which
 # would be undefined according to the API).
 m4_define([m4_dumpdefs],
-[m4_stack_foreach_lifo([$1], [m4_dumpdef([$1])m4_ignore])])
+[m4_if([$#], [0], [m4_fatal([$0: missing argument])],
+       [$#], [1], [m4_stack_foreach_lifo([$1], [m4_dumpdef([$1])m4_ignore])],
+       [m4_map_args([$0], $@)])])
 
 
 # m4_popdef(NAME)
@@ -1326,12 +1329,15 @@ m4_define([m4_divert_once],
 [m4_expand_once([m4_divert_text([$1], [$2])])])
 
 
-# m4_undivert(DIVERSION-NAME)
-# ---------------------------
-# Undivert DIVERSION-NAME.  Unlike the M4 version, this only takes a single
-# diversion identifier, and should not be used to undivert files.
+# m4_undivert(DIVERSION-NAME...)
+# ------------------------------
+# Undivert DIVERSION-NAME.  Unlike the M4 version, this requires at
+# least one DIVERSION-NAME; also, due to support for named diversions,
+# this should not be used to undivert files.
 m4_define([m4_undivert],
-[m4_builtin([undivert], _m4_divert([$1]))])
+[m4_if([$#], [0], [m4_fatal([$0: missing argument])],
+       [$#], [1], [m4_builtin([undivert], _m4_divert([$1]))],
+       [m4_map_args([$0], $@)])])
 
 
 ## --------------------------------------------- ##
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index 8034ced..70bb24b 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -181,8 +181,7 @@ AT_CHECK_M4SUGAR_TEXT([[m4_divert_push([KILL])
 m4_pushdef([a], [1])
 m4_pushdef([a], [2])
 m4_dumpdef([a])
-m4_dumpdefs([a])
-m4_dumpdefs([oops])
+m4_dumpdefs([oops], [a])
 m4_divert_pop([KILL])dnl
 ]], [],
 [[a:   [2]
@@ -248,14 +247,15 @@ AT_CLEANUP
 ## ----------------- ##
 
 AT_SETUP([m4@&address@hidden)
+AT_KEYWORDS([m4@&address@hidden m4@&address@hidden m4@&address@hidden
+m4@&address@hidden)
 
 AT_CHECK_M4SUGAR_TEXT([[1.m4_divert_stack
 m4_divert_push([10])2.m4_divert_stack
 m4_divert_text([20], [3.m4_divert_stack])dnl
 m4_divert([30])4.m4_divert_stack
 m4_divert_pop([30])dnl
-5.m4_undivert([20])
-6.m4_undivert([30])
+5.m4_undivert([20], [30])
 m4_pattern_allow([^m4_divert])dnl
 ]], [[1.script.4s:2: m4@&address@hidden: 0
 script.4s:1: m4@&address@hidden: KILL
@@ -263,8 +263,7 @@ script.4s:1: m4@&address@hidden: KILL
 script.4s:4: m4@&address@hidden: 10
 script.4s:2: m4@&address@hidden: 0
 script.4s:1: m4@&address@hidden: KILL
-
-6.4.script.4s:6: m4@&address@hidden: 30
+4.script.4s:6: m4@&address@hidden: 30
 script.4s:2: m4@&address@hidden: 0
 script.4s:1: m4@&address@hidden: KILL
 
-- 
1.6.0.2


reply via email to

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