]> git.saurik.com Git - bison.git/commitdiff
Resync m4sugar from autoconf.
authorEric Blake <ebb9@byu.net>
Thu, 28 Aug 2008 02:44:41 +0000 (20:44 -0600)
committerEric Blake <ebb9@byu.net>
Thu, 28 Aug 2008 02:44:41 +0000 (20:44 -0600)
* data/m4sugar/m4sugar.m4 (m4_defn, m4_popdef, m4_undefine)
(m4_init): Adjust to latest m4.git changes.
(m4_mapall_sep, _m4_list_cmp, m4_version_compare): Reduce side
effects.
* data/m4sugar/foreach.m4 (_m4_shiftn): Fix off-by-one bug.
(_m4_list_cmp): Reduce side effects.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
data/m4sugar/foreach.m4
data/m4sugar/m4sugar.m4

index e146d19dcd3818095da01477e76915cbe542d161..247f00dae9b004c4b3c22c151366cec307979f1b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-08-27  Eric Blake  <ebb9@byu.net>
+
+       Resync m4sugar from autoconf.
+       * data/m4sugar/m4sugar.m4 (m4_defn, m4_popdef, m4_undefine)
+       (m4_init): Adjust to latest m4.git changes.
+       (m4_mapall_sep, _m4_list_cmp, m4_version_compare): Reduce side
+       effects.
+       * data/m4sugar/foreach.m4 (_m4_shiftn): Fix off-by-one bug.
+       (_m4_list_cmp): Reduce side effects.
+
 2008-08-27  Akim Demaille  <demaille@gostai.com>
 
        Check yyerrok in calc.at.
 2008-08-27  Akim Demaille  <demaille@gostai.com>
 
        Check yyerrok in calc.at.
index e54e30e8ce148614bdd4362c9d10048e85169354..cd4d1fc8023058b10f9e83366d29c58a4fd0e3e2 100644 (file)
@@ -74,6 +74,8 @@
 # are not future-proof.  Thus, this file is conditionally included as
 # part of m4_init(), only when it is detected that M4 probably has
 # quadratic behavior (ie. it lacks the macro __m4_version__).
 # are not future-proof.  Thus, this file is conditionally included as
 # part of m4_init(), only when it is detected that M4 probably has
 # quadratic behavior (ie. it lacks the macro __m4_version__).
+#
+# Please keep this file in sync with m4sugar.m4.
 
 # m4_foreach(VARIABLE, LIST, EXPRESSION)
 # --------------------------------------
 
 # m4_foreach(VARIABLE, LIST, EXPRESSION)
 # --------------------------------------
@@ -211,9 +213,9 @@ m4_bpatsubst(m4_dquote(_m4_defn([_m4_p])), [$$1], [$$2]))]])
 #   ,[$5],[$6],...,[$m]_m4_popdef([_m4_s])
 # before calling m4_shift(_m4_s($@)).
 m4_define([_m4_shiftn],
 #   ,[$5],[$6],...,[$m]_m4_popdef([_m4_s])
 # before calling m4_shift(_m4_s($@)).
 m4_define([_m4_shiftn],
-[m4_define([_m4_s],
+[m4_if(m4_incr([$1]), [$#], [], [m4_define([_m4_s],
           m4_pushdef([_m4_s])_m4_for([_m4_s], m4_eval([$1 + 2]), [$#], [1],
           m4_pushdef([_m4_s])_m4_for([_m4_s], m4_eval([$1 + 2]), [$#], [1],
-  [[,]m4_dquote([$]_m4_s)])[_m4_popdef([_m4_s])])m4_shift(_m4_s($@))])
+  [[,]m4_dquote([$]_m4_s)])[_m4_popdef([_m4_s])])m4_shift(_m4_s($@))])])
 
 # m4_do(STRING, ...)
 # ------------------
 
 # m4_do(STRING, ...)
 # ------------------
@@ -336,6 +338,8 @@ m4_define([m4_joinall],
 # -----------------
 # Compare the two lists of integer expressions A and B.
 #
 # -----------------
 # Compare the two lists of integer expressions A and B.
 #
+# m4_list_cmp takes care of any side effects; we only override
+# _m4_list_cmp_raw, where we can safely expand lists multiple times.
 # First, insert padding so that both lists are the same length; the
 # trailing +0 is necessary to handle a missing list.  Next, create a
 # temporary macro to perform pairwise comparisons until an inequality
 # First, insert padding so that both lists are the same length; the
 # trailing +0 is necessary to handle a missing list.  Next, create a
 # temporary macro to perform pairwise comparisons until an inequality
@@ -344,9 +348,9 @@ m4_define([m4_joinall],
 #         m4_eval([($2) != ($4)]), [1], [m4_cmp([$2], [$4])],
 #         [0]_m4_popdef([_m4_cmp], [_m4_size]))
 # then calls _m4_cmp([1+0], [0], [1], [2+0])
 #         m4_eval([($2) != ($4)]), [1], [m4_cmp([$2], [$4])],
 #         [0]_m4_popdef([_m4_cmp], [_m4_size]))
 # then calls _m4_cmp([1+0], [0], [1], [2+0])
-m4_define([m4_list_cmp],
-[m4_if([$1], [$2], 0,
-  [m4_pushdef([_m4_size])_$0($1+0_m4_list_pad(m4_count($1), m4_count($2)),
+m4_define([_m4_list_cmp_raw],
+[m4_if([$1], [$2], 0, [m4_pushdef(
+     [_m4_size])_m4_list_cmp($1+0_m4_list_pad(m4_count($1), m4_count($2)),
                             $2+0_m4_list_pad(m4_count($2), m4_count($1)))])])
 
 m4_define([_m4_list_pad],
                             $2+0_m4_list_pad(m4_count($2), m4_count($1)))])])
 
 m4_define([_m4_list_pad],
index b9ccd5b51690912b2086905370510e8a972cf5ee..6fbd34315d2decb5912ac3a3e2aba6942dbb5174 100644 (file)
@@ -361,6 +361,8 @@ m4_define([m4_ifndef],
 # }.
 # All the values are optional, and the macro is robust to active
 # symbols properly quoted.
 # }.
 # All the values are optional, and the macro is robust to active
 # symbols properly quoted.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_case],
 [m4_if([$#], 0, [],
        [$#], 1, [],
 m4_define([m4_case],
 [m4_if([$#], 0, [],
        [$#], 1, [],
@@ -384,6 +386,8 @@ m4_define([m4_case],
 #
 # All the values are optional, and the macro is robust to active symbols
 # properly quoted.
 #
 # All the values are optional, and the macro is robust to active symbols
 # properly quoted.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_bmatch],
 [m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
        [$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
 m4_define([m4_bmatch],
 [m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
        [$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
@@ -444,6 +448,8 @@ m4_define([_m4_cdr],
 #
 # In the common case of $1 with no backslash, only one m4_index expansion
 # occurs, and m4_eval is avoided altogether.
 #
 # In the common case of $1 with no backslash, only one m4_index expansion
 # occurs, and m4_eval is avoided altogether.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_cond],
 [m4_if([$#], [0], [m4_fatal([$0: cannot be called without arguments])],
        [$#], [1], [$1],
 m4_define([m4_cond],
 [m4_if([$#], [0], [m4_fatal([$0: cannot be called without arguments])],
        [$#], [1], [$1],
@@ -479,6 +485,8 @@ m4_define([_m4_cond],
 #
 # Recall that m4_shift3 always results in an argument.  Hence, we need
 # to distinguish between a final deletion vs. ending recursion.
 #
 # Recall that m4_shift3 always results in an argument.  Hence, we need
 # to distinguish between a final deletion vs. ending recursion.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_bpatsubsts],
 [m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
        [$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
 m4_define([m4_bpatsubsts],
 [m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
        [$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
@@ -519,19 +527,18 @@ m4_define([m4_default],
 #
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
 #
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
-# (added in M4 1.6), then let m4 do the job for us.
+# (added in M4 1.6), then let m4 do the job for us (see m4_init).
 #
 # _m4_defn is for internal use only - it bypasses the wrapper, so it
 # must only be used on one argument at a time, and only on macros
 # known to be defined.  Make sure this still works if the user renames
 # m4_defn but not _m4_defn.
 m4_copy([m4_defn], [_m4_defn])
 #
 # _m4_defn is for internal use only - it bypasses the wrapper, so it
 # must only be used on one argument at a time, and only on macros
 # known to be defined.  Make sure this still works if the user renames
 # m4_defn but not _m4_defn.
 m4_copy([m4_defn], [_m4_defn])
-m4_ifdef([__m4_version__], [],
-[m4_define([m4_defn],
+m4_define([m4_defn],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_defn([$1])],
                            [m4_fatal([$0: undefined macro: $1])])],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_defn([$1])],
                            [m4_fatal([$0: undefined macro: $1])])],
-       [m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])])
+       [m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])
 
 
 # _m4_dumpdefs_up(NAME)
 
 
 # _m4_dumpdefs_up(NAME)
@@ -569,18 +576,17 @@ _m4_dumpdefs_down([$1])])
 #
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
 #
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
-# (added in M4 1.6), then let m4 do the job for us.
+# (added in M4 1.6), then let m4 do the job for us (see m4_init).
 #
 # _m4_popdef is for internal use only - it bypasses the wrapper, so it
 # must only be used on macros known to be defined.  Make sure this
 # still works if the user renames m4_popdef but not _m4_popdef.
 m4_copy([m4_popdef], [_m4_popdef])
 #
 # _m4_popdef is for internal use only - it bypasses the wrapper, so it
 # must only be used on macros known to be defined.  Make sure this
 # still works if the user renames m4_popdef but not _m4_popdef.
 m4_copy([m4_popdef], [_m4_popdef])
-m4_ifdef([__m4_version__], [],
-[m4_define([m4_popdef],
+m4_define([m4_popdef],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_popdef([$1])],
                            [m4_fatal([$0: undefined macro: $1])])],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_popdef([$1])],
                            [m4_fatal([$0: undefined macro: $1])])],
-       [m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])])
+       [m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])
 
 
 # m4_shiftn(N, ...)
 
 
 # m4_shiftn(N, ...)
@@ -598,6 +604,8 @@ m4_ifdef([__m4_version__], [],
 #         [_m4_shiftn(m4_decr([$1]), m4_shift(m4_shift($@)))])
 # but with the final `m4_shift(m4_shift($@)))' shared between the two
 # paths.  The first leg uses a no-op m4_shift(,$@) to balance out the ().
 #         [_m4_shiftn(m4_decr([$1]), m4_shift(m4_shift($@)))])
 # but with the final `m4_shift(m4_shift($@)))' shared between the two
 # paths.  The first leg uses a no-op m4_shift(,$@) to balance out the ().
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_shiftn],
 [m4_assert(0 < $1 && $1 < $#)_$0($@)])
 
 m4_define([m4_shiftn],
 [m4_assert(0 < $1 && $1 < $#)_$0($@)])
 
@@ -634,18 +642,17 @@ m4_define([_m4_shift3],
 #
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
 #
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
-# (added in M4 1.6), then let m4 do the job for us.
+# (added in M4 1.6), then let m4 do the job for us (see m4_init).
 #
 # _m4_undefine is for internal use only - it bypasses the wrapper, so
 # it must only be used on macros known to be defined.  Make sure this
 # still works if the user renames m4_undefine but not _m4_undefine.
 m4_copy([m4_undefine], [_m4_undefine])
 #
 # _m4_undefine is for internal use only - it bypasses the wrapper, so
 # it must only be used on macros known to be defined.  Make sure this
 # still works if the user renames m4_undefine but not _m4_undefine.
 m4_copy([m4_undefine], [_m4_undefine])
-m4_ifdef([__m4_version__], [],
-[m4_define([m4_undefine],
+m4_define([m4_undefine],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_undefine([$1])],
                            [m4_fatal([$0: undefined macro: $1])])],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_undefine([$1])],
                            [m4_fatal([$0: undefined macro: $1])])],
-       [m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])])
+       [m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])
 
 # _m4_wrap(PRE, POST)
 # -------------------
 
 # _m4_wrap(PRE, POST)
 # -------------------
@@ -706,6 +713,8 @@ m4_define([m4_count], [$#])
 # useful for making your macros more structured and readable by dropping
 # unnecessary dnl's and have the macros indented properly.  No concatenation
 # occurs after a STRING; use m4_unquote(m4_join(,STRING)) for that.
 # useful for making your macros more structured and readable by dropping
 # unnecessary dnl's and have the macros indented properly.  No concatenation
 # occurs after a STRING; use m4_unquote(m4_join(,STRING)) for that.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_do],
 [m4_if([$#], 0, [],
        [$#], 1, [$1[]],
 m4_define([m4_do],
 [m4_if([$#], 0, [],
        [$#], 1, [$1[]],
@@ -721,6 +730,8 @@ m4_define([m4_dquote],  [[$@]])
 # m4_dquote_elt(ARGS)
 # -------------------
 # Return ARGS as an unquoted list of double-quoted arguments.
 # m4_dquote_elt(ARGS)
 # -------------------
 # Return ARGS as an unquoted list of double-quoted arguments.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_dquote_elt],
 [m4_if([$#], [0], [],
        [$#], [1], [[[$1]]],
 m4_define([m4_dquote_elt],
 [m4_if([$#], [0], [],
        [$#], [1], [[[$1]]],
@@ -818,6 +829,8 @@ m4_define([_m4_quote],
 # m4_reverse(ARGS)
 # ----------------
 # Output ARGS in reverse order.
 # m4_reverse(ARGS)
 # ----------------
 # Output ARGS in reverse order.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_reverse],
 [m4_if([$#], [0], [], [$#], [1], [[$1]],
        [$0(m4_shift($@)), [$1]])])
 m4_define([m4_reverse],
 [m4_if([$#], [0], [], [$#], [1], [[$1]],
        [$0(m4_shift($@)), [$1]])])
@@ -982,6 +995,8 @@ m4_define([_m4_for],
 # [] and use m4_car/m4_cdr for recursion, we instead unbox the list (which
 # requires swapping the argument order in the helper), insert an ignored
 # third argument, and use m4_shift3 to detect when recursion is complete.
 # [] and use m4_car/m4_cdr for recursion, we instead unbox the list (which
 # requires swapping the argument order in the helper), insert an ignored
 # third argument, and use m4_shift3 to detect when recursion is complete.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_foreach],
 [m4_if([$2], [], [],
        [m4_pushdef([$1])_$0([$1], [$3], [], $2)m4_popdef([$1])])])
 m4_define([m4_foreach],
 [m4_if([$2], [], [],
        [m4_pushdef([$1])_$0([$1], [$3], [], $2)m4_popdef([$1])])])
@@ -1021,6 +1036,8 @@ m4_define([m4_foreach_w],
 # _m4_map.  For m4_map, an empty list behaves like an empty sublist
 # and gets ignored; for m4_mapall, we must special-case the empty
 # list.
 # _m4_map.  For m4_map, an empty list behaves like an empty sublist
 # and gets ignored; for m4_mapall, we must special-case the empty
 # list.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_map],
 [_m4_map([_m4_apply([$1]], [], $2)])
 
 m4_define([m4_map],
 [_m4_map([_m4_apply([$1]], [], $2)])
 
@@ -1041,7 +1058,8 @@ m4_define([m4_mapall],
 # arguments.
 #
 # For m4_mapall_sep, merely expand the first iteration without the
 # arguments.
 #
 # For m4_mapall_sep, merely expand the first iteration without the
-# separator, then include separator as part of subsequent recursion.
+# separator, then include separator as part of subsequent recursion;
+# but avoid extra expansion of LIST's side-effects via a helper macro.
 # For m4_map_sep, things are trickier - we don't know if the first
 # list element is an empty sublist, so we must define a self-modifying
 # helper macro and use that as the separator instead.
 # For m4_map_sep, things are trickier - we don't know if the first
 # list element is an empty sublist, so we must define a self-modifying
 # helper macro and use that as the separator instead.
@@ -1050,8 +1068,10 @@ m4_define([m4_map_sep],
 [_m4_map([_m4_apply([m4_Sep([$2])[]$1]], [], $3)m4_popdef([m4_Sep])])
 
 m4_define([m4_mapall_sep],
 [_m4_map([_m4_apply([m4_Sep([$2])[]$1]], [], $3)m4_popdef([m4_Sep])])
 
 m4_define([m4_mapall_sep],
-[m4_if([$3], [], [],
-       [m4_apply([$1], m4_car($3))_m4_map([m4_apply([$2[]$1]], $3)])])
+[m4_if([$3], [], [], [_$0([$1], [$2], $3)])])
+
+m4_define([_m4_mapall_sep],
+[m4_apply([$1], [$3])_m4_map([m4_apply([$2[]$1]], m4_shift2($@))])
 
 # _m4_map(PREFIX, IGNORED, SUBLIST, ...)
 # --------------------------------------
 
 # _m4_map(PREFIX, IGNORED, SUBLIST, ...)
 # --------------------------------------
@@ -1061,6 +1081,8 @@ m4_define([m4_mapall_sep],
 # then appends `,', the current SUBLIST and the closing `)', then
 # recurses to the next SUBLIST.  IGNORED is an aid to ending recursion
 # efficiently.
 # then appends `,', the current SUBLIST and the closing `)', then
 # recurses to the next SUBLIST.  IGNORED is an aid to ending recursion
 # efficiently.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([_m4_map],
 [m4_if([$#], [2], [],
        [$1, [$3])$0([$1], m4_shift2($@))])])
 m4_define([_m4_map],
 [m4_if([$#], [2], [],
        [$1, [$3])$0([$1], m4_shift2($@))])])
@@ -1069,6 +1091,8 @@ m4_define([_m4_map],
 # --------------------------------
 # Expand EXPRESSION([ARG]) for each argument.  More efficient than
 # m4_foreach([var], [ARG...], [EXPRESSION(m4_defn([var]))])
 # --------------------------------
 # Expand EXPRESSION([ARG]) for each argument.  More efficient than
 # m4_foreach([var], [ARG...], [EXPRESSION(m4_defn([var]))])
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_transform],
 [m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
        [$#], [1], [],
 m4_define([m4_transform],
 [m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
        [$#], [1], [],
@@ -1088,6 +1112,8 @@ m4_define([m4_transform],
 #   => (a,b)
 #   => (c,d)
 #   => (e)
 #   => (a,b)
 #   => (c,d)
 #   => (e)
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_transform_pair],
 [m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
        [$#], [1], [m4_fatal([$0: too few arguments: $#: $1])],
 m4_define([m4_transform_pair],
 [m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
        [$#], [1], [m4_fatal([$0: too few arguments: $#: $1])],
@@ -1947,6 +1973,8 @@ m4_define([m4_normalize],
 # elements, and outputs them following a separator.  The final trick to
 # note is that we decide between recursing with $0 or _$0 based on the
 # nested m4_if ending with `_'.
 # elements, and outputs them following a separator.  The final trick to
 # note is that we decide between recursing with $0 or _$0 based on the
 # nested m4_if ending with `_'.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_join],
 [m4_if([$#], [1], [],
        [$#], [2], [[$2]],
 m4_define([m4_join],
 [m4_if([$#], [1], [],
        [$#], [2], [[$2]],
@@ -1959,6 +1987,8 @@ m4_define([_m4_join],
 # ------------------------------
 # Produce ARG1SEPARG2...SEPARGn.  An empty ARG results in back-to-back SEP.
 # No expansion is performed on SEP or ARGs.
 # ------------------------------
 # Produce ARG1SEPARG2...SEPARGn.  An empty ARG results in back-to-back SEP.
 # No expansion is performed on SEP or ARGs.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_joinall], [[$2]_$0([$1], m4_shift($@))])
 m4_define([_m4_joinall],
 [m4_if([$#], [2], [], [[$1$3]$0([$1], m4_shift2($@))])])
 m4_define([m4_joinall], [[$2]_$0([$1], m4_shift($@))])
 m4_define([_m4_joinall],
 [m4_if([$#], [2], [], [[$1$3]$0([$1], m4_shift2($@))])])
@@ -2233,15 +2263,21 @@ m4_define([m4_cmp],
 # long lists, since less text is being expanded for deciding when to end
 # recursion.  The recursion is between a pair of macros that alternate
 # which list is trimmed by one element; this is more efficient than
 # long lists, since less text is being expanded for deciding when to end
 # recursion.  The recursion is between a pair of macros that alternate
 # which list is trimmed by one element; this is more efficient than
-# calling m4_cdr on both lists from a single macro.
+# calling m4_cdr on both lists from a single macro.  Guarantee exactly
+# one expansion of both lists' side effects.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_list_cmp],
 m4_define([m4_list_cmp],
+[_$0_raw(m4_dquote($1), m4_dquote($2))])
+
+m4_define([_m4_list_cmp_raw],
 [m4_if([$1], [$2], [0], [_m4_list_cmp_1([$1], $2)])])
 
 m4_define([_m4_list_cmp],
 [m4_if([$1], [], [0m4_ignore], [$2], [0], [m4_unquote], [$2m4_ignore])])
 
 m4_define([_m4_list_cmp_1],
 [m4_if([$1], [$2], [0], [_m4_list_cmp_1([$1], $2)])])
 
 m4_define([_m4_list_cmp],
 [m4_if([$1], [], [0m4_ignore], [$2], [0], [m4_unquote], [$2m4_ignore])])
 
 m4_define([_m4_list_cmp_1],
-[_m4_list_cmp_2([$2], m4_dquote(m4_shift2($@)), $1)])
+[_m4_list_cmp_2([$2], [m4_shift2($@)], $1)])
 
 m4_define([_m4_list_cmp_2],
 [_m4_list_cmp([$1$3], m4_cmp([$3+0], [$1+0]))(
 
 m4_define([_m4_list_cmp_2],
 [_m4_list_cmp([$1$3], m4_cmp([$3+0], [$1+0]))(
@@ -2256,6 +2292,8 @@ m4_define([_m4_list_cmp_2],
 # M4 1.4.x doesn't provide ?:.  Hence this huge m4_eval.  Avoid m4_eval
 # if both arguments are identical, but be aware of m4_max(0xa, 10) (hence
 # the use of <=, not just <, in the second multiply).
 # M4 1.4.x doesn't provide ?:.  Hence this huge m4_eval.  Avoid m4_eval
 # if both arguments are identical, but be aware of m4_max(0xa, 10) (hence
 # the use of <=, not just <, in the second multiply).
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_max],
 [m4_if([$#], [0], [m4_fatal([too few arguments to $0])],
        [$#], [1], [m4_eval([$1])],
 m4_define([m4_max],
 [m4_if([$#], [0], [m4_fatal([too few arguments to $0])],
        [$#], [1], [m4_eval([$1])],
@@ -2280,6 +2318,8 @@ m4_define([_m4_min],
 # ---------------------------------
 # Common recursion code for m4_max and m4_min.  METHOD must be _m4_max
 # or _m4_min, and there must be at least two arguments to combine.
 # ---------------------------------
 # Common recursion code for m4_max and m4_min.  METHOD must be _m4_max
 # or _m4_min, and there must be at least two arguments to combine.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([_m4_minmax],
 [m4_if([$#], [3], [$1([$2], [$3])],
        [$0([$1], $1([$2], [$3]), m4_shift3($@))])])
 m4_define([_m4_minmax],
 [m4_if([$#], [3], [$1([$2], [$3])],
        [$0([$1], $1([$2], [$3]), m4_shift3($@))])])
@@ -2333,8 +2373,11 @@ m4_dquote(m4_dquote(m4_defn([m4_cr_Letters])))[[+],
 #  -1 if VERSION-1 < VERSION-2
 #   0 if           =
 #   1 if           >
 #  -1 if VERSION-1 < VERSION-2
 #   0 if           =
 #   1 if           >
+#
+# Since _m4_version_unletter does not output side effects, we can
+# safely bypass the overhead of m4_version_cmp.
 m4_define([m4_version_compare],
 m4_define([m4_version_compare],
-[m4_list_cmp(_m4_version_unletter([$1]), _m4_version_unletter([$2]))])
+[_m4_list_cmp_raw(_m4_version_unletter([$1]), _m4_version_unletter([$2]))])
 
 
 # m4_PACKAGE_NAME
 
 
 # m4_PACKAGE_NAME
@@ -2436,6 +2479,8 @@ m4_define([m4_set_add],
 # not pruned.  The recursion helpers ignore their second argument, so
 # that we can use the faster m4_shift2 and 2 arguments, rather than
 # _m4_shift2 and one argument, as the signal to end recursion.
 # not pruned.  The recursion helpers ignore their second argument, so
 # that we can use the faster m4_shift2 and 2 arguments, rather than
 # _m4_shift2 and one argument, as the signal to end recursion.
+#
+# Please keep foreach.m4 in sync with any adjustments made here.
 m4_define([m4_set_add_all],
 [m4_define([_m4_set_size($1)], m4_eval(m4_set_size([$1])
   + m4_len(m4_ifdef([_m4_set_cleanup($1)], [_$0_check], [_$0])([$1], $@))))])
 m4_define([m4_set_add_all],
 [m4_define([_m4_set_size($1)], m4_eval(m4_set_size([$1])
   + m4_len(m4_ifdef([_m4_set_cleanup($1)], [_$0_check], [_$0])([$1], $@))))])
@@ -2721,12 +2766,18 @@ m4_pattern_forbid([^_?m4_])
 m4_pattern_forbid([^dnl$])
 
 # If __m4_version__ is defined, we assume that we are being run by M4
 m4_pattern_forbid([^dnl$])
 
 # If __m4_version__ is defined, we assume that we are being run by M4
-# 1.6 or newer, and thus that $@ recursion is linear; nothing further
-# needs to be done.  But if it is missing, we assume we are being run
-# by M4 1.4.x, that $@ recursion is quadratic, and that we need
-# foreach-based replacement macros.  Use the raw builtin to avoid
-# tripping up include tracing.
-m4_ifndef([__m4_version__], [m4_builtin([include], [m4sugar/foreach.m4])])
+# 1.6 or newer, and thus that $@ recursion is linear and debugmode(d)
+# is available for faster checks of dereferencing undefined macros.
+# But if it is missing, we assume we are being run by M4 1.4.x, that
+# $@ recursion is quadratic, and that we need foreach-based
+# replacement macros.  Use the raw builtin to avoid tripping up
+# include tracing.
+m4_ifdef([__m4_version__],
+[m4_debugmode([+d])
+m4_copy([_m4_defn], [m4_defn])
+m4_copy([_m4_popdef], [m4_popdef])
+m4_copy([_m4_undefine], [m4_undefine])],
+[m4_builtin([include], [m4sugar/foreach.m4])])
 
 # _m4_divert_diversion should be defined:
 m4_divert_push([KILL])
 
 # _m4_divert_diversion should be defined:
 m4_divert_push([KILL])