]> git.saurik.com Git - bison.git/blobdiff - data/m4sugar/m4sugar.m4
Simplify yysyntax_error_ use.
[bison.git] / data / m4sugar / m4sugar.m4
index 4fa54b39a9da58f49649ec89589dd54047b4caac..6fbd34315d2decb5912ac3a3e2aba6942dbb5174 100644 (file)
@@ -149,7 +149,7 @@ m4_undefine([maketemp])],
 [m4_rename_m4([maketemp])
 m4_copy([m4_maketemp], [m4_mkstemp])])
 m4_rename([patsubst], [m4_bpatsubst])
-m4_undefine([popdef])
+m4_rename_m4([popdef])
 m4_rename_m4([pushdef])
 m4_rename([regexp], [m4_bregexp])
 m4_rename_m4([shift])
@@ -232,7 +232,7 @@ m4_define([_m4_warn], [])
 m4_define([m4_warn],
 [_m4_warn([$1], [$2],
 m4_ifdef([m4_expansion_stack],
-        [m4_defn([m4_expansion_stack])
+        [_m4_defn([m4_expansion_stack])
 m4_location[: the top level]]))dnl
 ])
 
@@ -333,7 +333,7 @@ m4_define([m4_ifvaln],
 # expand IF-FALSE, otherwise IF-TRUE.
 m4_define([m4_ifset],
 [m4_ifdef([$1],
-         [m4_ifval(m4_defn([$1]), [$2], [$3])],
+         [m4_ifval(_m4_defn([$1]), [$2], [$3])],
          [$3])])
 
 
@@ -361,12 +361,14 @@ m4_define([m4_ifndef],
 # }.
 # 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, [],
        [$#], 2, [$2],
        [$1], [$2], [$3],
-       [$0([$1], m4_shiftn(3, $@))])])
+       [$0([$1], m4_shift3($@))])])
 
 
 # m4_bmatch(SWITCH, RE1, VAL1, RE2, VAL2, ..., DEFAULT)
@@ -384,11 +386,13 @@ m4_define([m4_case],
 #
 # 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])],
        [$#], 2, [$2],
-       [m4_if(m4_bregexp([$1], [$2]), -1, [$0([$1], m4_shiftn(3, $@))],
+       [m4_if(m4_bregexp([$1], [$2]), -1, [$0([$1], m4_shift3($@))],
              [$3])])])
 
 
@@ -402,28 +406,61 @@ m4_define([m4_cdr],
        [$#], 1, [],
        [m4_dquote(m4_shift($@))])])
 
-
-# m4_map(MACRO, LIST)
-# -------------------
-# Invoke MACRO($1), MACRO($2) etc. where $1, $2... are the elements
-# of LIST (which can be lists themselves, for multiple arguments MACROs).
-m4_define([m4_fst], [$1])
-m4_define([m4_map],
-[m4_if([$2], [[]], [],
-       [_m4_map([$1], [$2])])])
-m4_define([_m4_map],
-[m4_ifval([$2],
-         [$1(m4_fst($2))[]_m4_map([$1], m4_cdr($2))])])
-
-
-# m4_map_sep(MACRO, SEPARATOR, LIST)
-# ----------------------------------
-# Invoke MACRO($1), SEPARATOR, MACRO($2), ..., MACRO($N) where $1, $2... $N
-# are the elements of LIST (which can be lists themselves, for multiple
-# arguments MACROs).
-m4_define([m4_map_sep],
-[m4_if([$3], [[]], [],
-       [$1(m4_fst($3))[]_m4_map([$2[]$1], m4_cdr($3))])])
+# _m4_cdr(LIST)
+# -------------
+# Like m4_cdr, except include a leading comma unless only one element
+# remains.  Why?  Because comparing a large list against [] is more
+# expensive in expansion time than comparing the number of arguments; so
+# _m4_cdr can be used to reduce the number of arguments when it is time
+# to end recursion.
+m4_define([_m4_cdr],
+[m4_if([$#], 1, [],
+       [, m4_dquote(m4_shift($@))])])
+
+
+
+# m4_cond(TEST1, VAL1, IF-VAL1, TEST2, VAL2, IF-VAL2, ..., [DEFAULT])
+# -------------------------------------------------------------------
+# Similar to m4_if, except that each TEST is expanded when encountered.
+# If the expansion of TESTn matches the string VALn, the result is IF-VALn.
+# The result is DEFAULT if no tests passed.  This macro allows
+# short-circuiting of expensive tests, where it pays to arrange quick
+# filter tests to run first.
+#
+# For an example, consider a previous implementation of _AS_QUOTE_IFELSE:
+#
+#    m4_if(m4_index([$1], [\]), [-1], [$2],
+#          m4_eval(m4_index([$1], [\\]) >= 0), [1], [$2],
+#          m4_eval(m4_index([$1], [\$]) >= 0), [1], [$2],
+#          m4_eval(m4_index([$1], [\`]) >= 0), [1], [$3],
+#          m4_eval(m4_index([$1], [\"]) >= 0), [1], [$3],
+#          [$2])
+#
+# Here, m4_index is computed 5 times, and m4_eval 4, even if $1 contains
+# no backslash.  It is more efficient to do:
+#
+#    m4_cond([m4_index([$1], [\])], [-1], [$2],
+#            [m4_eval(m4_index([$1], [\\]) >= 0)], [1], [$2],
+#            [m4_eval(m4_index([$1], [\$]) >= 0)], [1], [$2],
+#            [m4_eval(m4_index([$1], [\`]) >= 0)], [1], [$3],
+#            [m4_eval(m4_index([$1], [\"]) >= 0)], [1], [$3],
+#            [$2])
+#
+# 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_eval([$# % 3]), [2], [m4_fatal([$0: missing an argument])],
+       [_$0($@)])])
+
+m4_define([_m4_cond],
+[m4_if(($1), [($2)], [$3],
+       [$#], [3], [],
+       [$#], [4], [$4],
+       [$0(m4_shift3($@))])])
 
 
 ## ---------------------------------------- ##
@@ -445,24 +482,21 @@ m4_define([m4_map_sep],
 # I would have liked to name this macro `m4_bpatsubst', unfortunately,
 # due to quotation problems, I need to double quote $1 below, therefore
 # the anchors are broken :(  I can't let users be trapped by that.
+#
+# 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])],
-       [$#], 2, [m4_builtin([patsubst], $@)],
+       [$#], 2, [m4_unquote(m4_builtin([patsubst], [[$1]], [$2]))],
+       [$#], 3, [m4_unquote(m4_builtin([patsubst], [[$1]], [$2], [$3]))],
+       [_$0($@m4_if(m4_eval($# & 1), 0, [,]))])])
+m4_define([_m4_bpatsubsts],
+[m4_if([$#], 2, [$1],
        [$0(m4_builtin([patsubst], [[$1]], [$2], [$3]),
-          m4_shiftn(3, $@))])])
-
-
-
-# m4_do(STRING, ...)
-# ------------------
-# This macro invokes all its arguments (in sequence, of course).  It is
-# useful for making your macros more structured and readable by dropping
-# unnecessary dnl's and have the macros indented properly.
-m4_define([m4_do],
-[m4_if($#, 0, [],
-       $#, 1, [$1],
-       [$1[]m4_do(m4_shift($@))])])
+          m4_shift3($@))])])
 
 
 # m4_define_default(MACRO, VALUE)
@@ -475,27 +509,45 @@ m4_define([m4_define_default],
 # m4_default(EXP1, EXP2)
 # ----------------------
 # Returns EXP1 if non empty, otherwise EXP2.
+#
+# This macro is called on hot paths, so inline the contents of m4_ifval,
+# for one less round of expansion.
 m4_define([m4_default],
-[m4_ifval([$1], [$1], [$2])])
+[m4_if([$1], [], [$2], [$1])])
 
 
 # m4_defn(NAME)
 # -------------
-# Unlike to the original, don't tolerate popping something which is
-# undefined.
+# Like the original, except guarantee a warning when using something which is
+# undefined (unlike M4 1.4.x).  This replacement is not a full-featured
+# replacement: if any of the defined macros contain unbalanced quoting, but
+# when pasted together result in a well-quoted string, then only native m4
+# support is able to get it correct.  But that's where quadrigraphs come in
+# handy, if you really need unbalanced quotes inside your macros.
+#
+# 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 (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_define([m4_defn],
-[m4_ifndef([$1],
-          [m4_fatal([$0: undefined macro: $1])])dnl
-m4_builtin([defn], $@)])
+[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_dumpdefs_up(NAME)
 # ---------------------
 m4_define([_m4_dumpdefs_up],
 [m4_ifdef([$1],
-         [m4_pushdef([_m4_dumpdefs], m4_defn([$1]))dnl
+         [m4_pushdef([_m4_dumpdefs], _m4_defn([$1]))dnl
 m4_dumpdef([$1])dnl
-m4_popdef([$1])dnl
+_m4_popdef([$1])dnl
 _m4_dumpdefs_up([$1])])])
 
 
@@ -503,8 +555,8 @@ _m4_dumpdefs_up([$1])])])
 # -----------------------
 m4_define([_m4_dumpdefs_down],
 [m4_ifdef([_m4_dumpdefs],
-         [m4_pushdef([$1], m4_defn([_m4_dumpdefs]))dnl
-m4_popdef([_m4_dumpdefs])dnl
+         [m4_pushdef([$1], _m4_defn([_m4_dumpdefs]))dnl
+_m4_popdef([_m4_dumpdefs])dnl
 _m4_dumpdefs_down([$1])])])
 
 
@@ -519,80 +571,98 @@ _m4_dumpdefs_down([$1])])
 
 # m4_popdef(NAME)
 # ---------------
-# Unlike to the original, don't tolerate popping something which is
-# undefined.
-m4_define([m4_popdef],
-[m4_ifndef([$1],
-          [m4_fatal([$0: undefined macro: $1])])dnl
-m4_builtin([popdef], $@)])
-
-
-# m4_quote(ARGS)
-# --------------
-# Return ARGS as a single arguments.
+# Like the original, except guarantee a warning when using something which is
+# undefined (unlike M4 1.4.x).
 #
-# It is important to realize the difference between `m4_quote(exp)' and
-# `[exp]': in the first case you obtain the quoted *result* of the
-# expansion of EXP, while in the latter you just obtain the string
-# `exp'.
-m4_define([m4_quote],  [[$*]])
-m4_define([m4_dquote],  [[$@]])
-
-
-# m4_noquote(STRING)
-# ------------------
-# Return the result of ignoring all quotes in STRING and invoking the
-# macros it contains.  Amongst other things, this is useful for enabling
-# macro invocations inside strings with [] blocks (for instance regexps
-# and help-strings).  On the other hand, since all quotes are disabled,
-# any macro expanded during this time that relies on nested [] quoting
-# will likely crash and burn.  This macro is seldom useful; consider
-# m4_unquote or m4_expand instead.
-m4_define([m4_noquote],
-[m4_changequote(-=<{,}>=-)$1-=<{}>=-m4_changequote([,])])
+# 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 (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_define([m4_popdef],
+[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_shiftn(N, ...)
 # -----------------
 # Returns ... shifted N times.  Useful for recursive "varargs" constructs.
+#
+# Autoconf does not use this macro, because it is inherently slower than
+# calling the common cases of m4_shift2 or m4_shift3 directly.  But it
+# might as well be fast for other clients, such as Libtool.  One way to
+# do this is to expand $@ only once in _m4_shiftn (otherwise, for long
+# lists, the expansion of m4_if takes twice as much memory as what the
+# list itself occupies, only to throw away the unused branch).  The end
+# result is strictly equivalent to
+#   m4_if([$1], 1, [m4_shift(,m4_shift(m4_shift($@)))],
+#         [_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(($1 >= 0) && ($# > $1))dnl
-_m4_shiftn($@)])
+[m4_assert(0 < $1 && $1 < $#)_$0($@)])
 
 m4_define([_m4_shiftn],
-[m4_if([$1], 0,
-       [m4_shift($@)],
-       [_m4_shiftn(m4_eval([$1]-1), m4_shift(m4_shift($@)))])])
+[m4_if([$1], 1, [m4_shift(],
+       [$0(m4_decr([$1])]), m4_shift(m4_shift($@)))])
+
+# m4_shift2(...)
+# m4_shift3(...)
+# -----------------
+# Returns ... shifted twice, and three times.  Faster than m4_shiftn.
+m4_define([m4_shift2], [m4_shift(m4_shift($@))])
+m4_define([m4_shift3], [m4_shift(m4_shift(m4_shift($@)))])
+
+# _m4_shift2(...)
+# _m4_shift3(...)
+# ---------------
+# Like m4_shift2 or m4_shift3, except include a leading comma unless shifting
+# consumes all arguments.  Why?  Because in recursion, it is nice to
+# distinguish between 1 element left and 0 elements left, based on how many
+# arguments this shift expands to.
+m4_define([_m4_shift2],
+[m4_if([$#], [2], [],
+       [, m4_shift(m4_shift($@))])])
+m4_define([_m4_shift3],
+[m4_if([$#], [3], [],
+       [, m4_shift(m4_shift(m4_shift($@)))])])
 
 
 # m4_undefine(NAME)
 # -----------------
-# Unlike to the original, don't tolerate undefining something which is
-# undefined.
+# Like the original, except guarantee a warning when using something which is
+# undefined (unlike M4 1.4.x).
+#
+# 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 (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_define([m4_undefine],
-[m4_ifndef([$1],
-          [m4_fatal([$0: undefined macro: $1])])dnl
-m4_builtin([undefine], $@)])
-
-
-# m4_unquote(ARGS)
-# ----------------
-# Remove one layer of quotes from each ARG, performing one level of
-# expansion.  For one argument, m4_unquote([arg]) is more efficient than
-# m4_do([arg]), but for multiple arguments, the difference is that
-# m4_unquote separates arguments with commas while m4_do concatenates.
-m4_define([m4_unquote], [$*])
+[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_wrap(PRE, POST)
 # -------------------
 # Helper macro for m4_wrap and m4_wrap_lifo.  Allows nested calls to
-# m4_wrap within wrapped text.
-# Skip m4_defn and m4_popdef for speed.
+# m4_wrap within wrapped text.  Use _m4_defn and _m4_popdef for speed.
 m4_define([_m4_wrap],
 [m4_ifdef([$0_text],
-         [m4_define([$0_text], [$1]m4_builtin([defn], [$0_text])[$2])],
-         [m4_builtin([m4wrap], [m4_unquote(m4_builtin([defn],
-  [$0_text])m4_builtin([popdef], [$0_text]))])m4_define([$0_text], [$1$2])])])
+         [m4_define([$0_text], [$1]_m4_defn([$0_text])[$2])],
+         [m4_builtin([m4wrap], [m4_unquote(
+  _m4_defn([$0_text])_m4_popdef([$0_text]))])m4_define([$0_text], [$1$2])])])
 
 # m4_wrap(TEXT)
 # -------------
@@ -610,6 +680,173 @@ m4_define([m4_wrap],
 m4_define([m4_wrap_lifo],
 [_m4_wrap([$1[]])])
 
+## ------------------------- ##
+## 7. Quoting manipulation.  ##
+## ------------------------- ##
+
+
+# m4_apply(MACRO, LIST)
+# ---------------------
+# Invoke MACRO, with arguments provided from the quoted list of
+# comma-separated quoted arguments.  If LIST is empty, invoke MACRO
+# without arguments.  The expansion will not be concatenated with
+# subsequent text.
+m4_define([m4_apply],
+[m4_if([$2], [], [$1], [$1($2)])[]])
+
+# _m4_apply(MACRO, LIST)
+# ----------------------
+# Like m4_apply, except do nothing if LIST is empty.
+m4_define([_m4_apply],
+[m4_if([$2], [], [], [$1($2)[]])])
+
+
+# m4_count(ARGS)
+# --------------
+# Return a count of how many ARGS are present.
+m4_define([m4_count], [$#])
+
+
+# m4_do(STRING, ...)
+# ------------------
+# This macro invokes all its arguments (in sequence, of course).  It is
+# 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[]],
+       [$1[]$0(m4_shift($@))])])
+
+
+# m4_dquote(ARGS)
+# ---------------
+# Return ARGS as a quoted list of quoted arguments.
+m4_define([m4_dquote],  [[$@]])
+
+
+# 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]]],
+       [[[$1]],$0(m4_shift($@))])])
+
+
+# m4_echo(ARGS)
+# -------------
+# Return the ARGS, with the same level of quoting.  Whitespace after
+# unquoted commas are consumed.
+m4_define([m4_echo], [$@])
+
+
+# m4_expand(ARG)
+# --------------
+# Return the expansion of ARG as a single string.  Unlike m4_quote($1), this
+# correctly preserves whitespace following single-quoted commas that appeared
+# within ARG.
+#
+#   m4_define([active], [ACT, IVE])
+#   m4_define([active2], [[ACT, IVE]])
+#   m4_quote(active, active2)
+#   => ACT,IVE,ACT, IVE
+#   m4_expand([active, active2])
+#   => ACT, IVE, ACT, IVE
+#
+# Unfortunately, due to limitations in m4, ARG must expand to something
+# with balanced quotes (use quadrigraphs to get around this).  The input
+# is not likely to have unbalanced -=<{(/)}>=- quotes, and it is possible
+# to have unbalanced (), provided it was specified with proper [] quotes.
+#
+# Exploit that extra () will group unquoted commas and the following
+# whitespace, then convert () to [].  m4_bpatsubst can't handle newlines
+# inside $1, and m4_substr strips quoting.  So we (ab)use m4_changequote.
+m4_define([m4_expand], [_$0(-=<{($1)}>=-)])
+m4_define([_m4_expand],
+[m4_changequote([-=<{(], [)}>=-])$1m4_changequote([, ])])
+
+
+# m4_ignore(ARGS)
+# ---------------
+# Expands to nothing.  Useful for conditionally ignoring an arbitrary
+# number of arguments (see _m4_list_cmp for an example).
+m4_define([m4_ignore])
+
+
+# m4_make_list(ARGS)
+# ------------------
+# Similar to m4_dquote, this creates a quoted list of quoted ARGS.  This
+# version is less efficient than m4_dquote, but separates each argument
+# with a comma and newline, rather than just comma, for readability.
+# When developing an m4sugar algorithm, you could temporarily use
+#   m4_pushdef([m4_dquote],m4_defn([m4_make_list]))
+# around your code to make debugging easier.
+m4_define([m4_make_list], [m4_join([,
+], m4_dquote_elt($@))])
+
+
+# m4_noquote(STRING)
+# ------------------
+# Return the result of ignoring all quotes in STRING and invoking the
+# macros it contains.  Amongst other things, this is useful for enabling
+# macro invocations inside strings with [] blocks (for instance regexps
+# and help-strings).  On the other hand, since all quotes are disabled,
+# any macro expanded during this time that relies on nested [] quoting
+# will likely crash and burn.  This macro is seldom useful; consider
+# m4_unquote or m4_expand instead.
+m4_define([m4_noquote],
+[m4_changequote([-=<{(],[)}>=-])$1-=<{()}>=-m4_changequote([,])])
+
+
+# m4_quote(ARGS)
+# --------------
+# Return ARGS as a single argument.  Any whitespace after unquoted commas
+# is stripped.  There is always output, even when there were no arguments.
+#
+# It is important to realize the difference between `m4_quote(exp)' and
+# `[exp]': in the first case you obtain the quoted *result* of the
+# expansion of EXP, while in the latter you just obtain the string
+# `exp'.
+m4_define([m4_quote],  [[$*]])
+
+
+# _m4_quote(ARGS)
+# ---------------
+# Like m4_quote, except that when there are no arguments, there is no
+# output.  For conditional scenarios (such as passing _m4_quote as the
+# macro name in m4_mapall), this feature can be used to distinguish between
+# one argument of the empty string vs. no arguments.  However, in the
+# normal case with arguments present, this is less efficient than m4_quote.
+m4_define([_m4_quote],
+[m4_if([$#], [0], [], [[$*]])])
+
+
+# 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_unquote(ARGS)
+# ----------------
+# Remove one layer of quotes from each ARG, performing one level of
+# expansion.  For one argument, m4_unquote([arg]) is more efficient than
+# m4_do([arg]), but for multiple arguments, the difference is that
+# m4_unquote separates arguments with commas while m4_do concatenates.
+# Follow this macro with [] if concatenation with subsequent text is
+# undesired.
+m4_define([m4_unquote], [$*])
+
+
 ## -------------------------- ##
 ## 8. Implementing m4 loops.  ##
 ## -------------------------- ##
@@ -618,26 +855,36 @@ m4_define([m4_wrap_lifo],
 # m4_for(VARIABLE, FIRST, LAST, [STEP = +/-1], EXPRESSION)
 # --------------------------------------------------------
 # Expand EXPRESSION defining VARIABLE to FROM, FROM + 1, ..., TO with
-# increments of STEP.
-# Both limits are included, and bounds are checked for consistency.
+# increments of STEP.  Both limits are included, and bounds are
+# checked for consistency.  The algorithm is robust to indirect
+# VARIABLE names.  Changing VARIABLE inside EXPRESSION will not impact
+# the number of iterations.
+#
+# Uses _m4_defn for speed, and avoid dnl in the macro body.
 m4_define([m4_for],
-[m4_case(m4_sign(m4_eval($3 - $2)),
-        1, [m4_assert(m4_sign(m4_default($4, 1)) == 1)],
-       -1, [m4_assert(m4_sign(m4_default($4, -1)) == -1)])dnl
-m4_pushdef([$1], [$2])dnl
-m4_if(m4_eval([$3 > $2]), 1,
-      [_m4_for([$1], [$3], m4_default([$4], 1), [$5])],
-      [_m4_for([$1], [$3], m4_default([$4], -1), [$5])])dnl
-m4_popdef([$1])])
-
-
-# _m4_for(VARIABLE, FIRST, LAST, STEP, EXPRESSION)
+[m4_pushdef([$1], m4_eval([$2]))]dnl
+[m4_cond([m4_eval(([$3]) > ([$2]))], 1,
+          [m4_pushdef([_m4_step], m4_eval(m4_default([$4],
+             1)))m4_assert(_m4_step > 0)_$0([$1], _m4_defn([$1]),
+  m4_eval((([$3]) - ([$2])) / _m4_step * _m4_step + ([$2])),
+  _m4_step, [$5])],
+        [m4_eval(([$3]) < ([$2]))], 1,
+          [m4_pushdef([_m4_step], m4_eval(m4_default([$4],
+             -1)))m4_assert(_m4_step < 0)_$0([$1], _m4_defn([$1]),
+  m4_eval((([$2]) - ([$3])) / -(_m4_step) * _m4_step + ([$2])),
+  _m4_step, [$5])],
+        [m4_pushdef([_m4_step])$5])[]]dnl
+[m4_popdef([_m4_step], [$1])])
+
+
+# _m4_for(VARIABLE, COUNT, LAST, STEP, EXPRESSION)
 # ------------------------------------------------
-# Core of the loop, no consistency checks.
+# Core of the loop, no consistency checks, all arguments are plain
+# numbers.  Define VARIABLE to COUNT, expand EXPRESSION, then alter
+# COUNT by STEP and iterate if COUNT is not LAST.
 m4_define([_m4_for],
-[$4[]dnl
-m4_if($1, [$2], [],
-      [m4_define([$1], m4_eval($1+[$3]))_m4_for([$1], [$2], [$3], [$4])])])
+[m4_define([$1], [$2])$5[]m4_if([$2], [$3], [],
+      [$0([$1], m4_eval([$2 + $4]), [$3], [$4], [$5])])])
 
 
 # Implementing `foreach' loops in m4 is much more tricky than it may
@@ -717,7 +964,9 @@ m4_if($1, [$2], [],
 # Hence the design below.
 #
 # The M4 manual now includes a chapter devoted to this issue, with
-# the lessons learned from m4sugar.
+# the lessons learned from m4sugar.  And still, this design is only
+# optimal for M4 1.6; see foreach.m4 for yet more comments on why
+# M4 1.4.x uses yet another implementation.
 
 
 # m4_foreach(VARIABLE, LIST, EXPRESSION)
@@ -738,13 +987,23 @@ m4_if($1, [$2], [],
 #
 #      | m4_foreach(Var, [[[active]], [[active]]], [-Var-])
 #     => -active--active-
+#
+# This macro is called frequently, so avoid extra expansions such as
+# m4_ifval and dnl.  Also, since $2 might be quite large, try to use it
+# as little as possible in _m4_foreach; each extra use requires that much
+# more memory for expansion.  So, rather than directly compare $2 against
+# [] 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_pushdef([$1])_m4_foreach($@)m4_popdef([$1])])
+[m4_if([$2], [], [],
+       [m4_pushdef([$1])_$0([$1], [$3], [], $2)m4_popdef([$1])])])
 
 m4_define([_m4_foreach],
-[m4_ifval([$2],
-         [m4_define([$1], m4_car($2))$3[]dnl
-_m4_foreach([$1], m4_cdr($2), [$3])])])
+[m4_if([$#], [3], [],
+       [m4_define([$1], [$4])$2[]$0([$1], [$2], m4_shift3($@))])])
 
 
 # m4_foreach_w(VARIABLE, LIST, EXPRESSION)
@@ -759,9 +1018,110 @@ _m4_foreach([$1], m4_cdr($2), [$3])])])
 #    => -active--b--active-end
 #
 m4_define([m4_foreach_w],
-[m4_foreach([$1], m4_split(m4_normalize([$2])), [$3])])
+[m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])])
 
 
+# m4_map(MACRO, LIST)
+# m4_mapall(MACRO, LIST)
+# ----------------------
+# Invoke MACRO($1), MACRO($2) etc. where $1, $2... are the elements of
+# LIST.  $1, $2... must in turn be lists, appropriate for m4_apply.
+# If LIST contains an empty sublist, m4_map skips the expansion of
+# MACRO, while m4_mapall expands MACRO with no arguments.
+#
+# Since LIST may be quite large, we want to minimize how often it
+# appears in the expansion.  Rather than use m4_car/m4_cdr iteration,
+# we unbox the list, ignore the second argument, and use m4_shift2 to
+# detect the end of recursion.  The mismatch in () is intentional; see
+# _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_mapall],
+[m4_if([$2], [], [],
+       [_m4_map([m4_apply([$1]], [], $2)])])
+
+
+# m4_map_sep(MACRO, SEPARATOR, LIST)
+# m4_mapall_sep(MACRO, SEPARATOR, LIST)
+# -------------------------------------
+# Invoke MACRO($1), SEPARATOR, MACRO($2), ..., MACRO($N) where $1,
+# $2... $N are the elements of LIST, and are in turn lists appropriate
+# for m4_apply.  SEPARATOR is expanded, in order to allow the creation
+# of a list of arguments by using a single-quoted comma as the
+# separator.  For each empty sublist, m4_map_sep skips the expansion
+# of MACRO and SEPARATOR, while m4_mapall_sep expands MACRO with no
+# arguments.
+#
+# For m4_mapall_sep, merely expand the first iteration without the
+# 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.
+m4_define([m4_map_sep],
+[m4_pushdef([m4_Sep], [m4_define([m4_Sep], _m4_defn([m4_unquote]))])]dnl
+[_m4_map([_m4_apply([m4_Sep([$2])[]$1]], [], $3)m4_popdef([m4_Sep])])
+
+m4_define([m4_mapall_sep],
+[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, ...)
+# --------------------------------------
+# Common implementation for all four m4_map variants.  The mismatch in
+# the number of () is intentional.  PREFIX must supply a form of
+# m4_apply, the open `(', and the MACRO to be applied.  Each iteration
+# 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_transform(EXPRESSION, ARG...)
+# --------------------------------
+# 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], [],
+       [$#], [2], [$1([$2])[]],
+       [$1([$2])[]$0([$1], m4_shift2($@))])])
+
+
+# m4_transform_pair(EXPRESSION, [END-EXPR = EXPRESSION], ARG...)
+# --------------------------------------------------------------
+# Perform a pairwise grouping of consecutive ARGs, by expanding
+# EXPRESSION([ARG1], [ARG2]).  If there are an odd number of ARGs, the
+# final argument is expanded with END-EXPR([ARGn]).
+#
+# For example:
+#   m4_define([show], [($*)m4_newline])dnl
+#   m4_transform_pair([show], [], [a], [b], [c], [d], [e])dnl
+#   => (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])],
+       [$#], [2], [],
+       [$#], [3], [m4_default([$2], [$1])([$3])[]],
+       [$#], [4], [$1([$3], [$4])[]],
+       [$1([$3], [$4])[]$0([$1], [$2], m4_shift(m4_shift3($@)))])])
+
 
 ## --------------------------- ##
 ## 9. More diversion support.  ##
@@ -780,32 +1140,33 @@ m4_define([_m4_divert],
 # KILL is only used to suppress output.
 m4_define([_m4_divert(KILL)],           -1)
 
+# The empty diversion name is a synonym for 0.
+m4_define([_m4_divert()],                0)
+
 
 # _m4_divert_n_stack
 # ------------------
 # Print m4_divert_stack with newline prepended, if it's nonempty.
 m4_define([_m4_divert_n_stack],
 [m4_ifdef([m4_divert_stack], [
-m4_defn([m4_divert_stack])])])
+_m4_defn([m4_divert_stack])])])
 
 
 # m4_divert(DIVERSION-NAME)
 # -------------------------
 # Change the diversion stream to DIVERSION-NAME.
 m4_define([m4_divert],
-[m4_define([m4_divert_stack], m4_location[: $0: $1]_m4_divert_n_stack)dnl
-m4_builtin([divert], _m4_divert([$1]))dnl
-])
+[m4_define([m4_divert_stack], m4_location[: $0: $1]_m4_divert_n_stack)]dnl
+[m4_builtin([divert], _m4_divert([$1]))])
 
 
 # m4_divert_push(DIVERSION-NAME)
 # ------------------------------
 # Change the diversion stream to DIVERSION-NAME, while stacking old values.
 m4_define([m4_divert_push],
-[m4_pushdef([m4_divert_stack], m4_location[: $0: $1]_m4_divert_n_stack)dnl
-m4_pushdef([_m4_divert_diversion], [$1])dnl
-m4_builtin([divert], _m4_divert([$1]))dnl
-])
+[m4_pushdef([m4_divert_stack], m4_location[: $0: $1]_m4_divert_n_stack)]dnl
+[m4_pushdef([_m4_divert_diversion], [$1])]dnl
+[m4_builtin([divert], _m4_divert([$1]))])
 
 
 # m4_divert_pop([DIVERSION-NAME])
@@ -815,17 +1176,15 @@ m4_builtin([divert], _m4_divert([$1]))dnl
 # 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_n_stack)])dnl
-m4_popdef([m4_divert_stack])dnl
-m4_popdef([_m4_divert_diversion])dnl
-m4_builtin([divert],
-          m4_ifdef([_m4_divert_diversion],
-                   [_m4_divert(m4_defn([_m4_divert_diversion]))],
-                   -1))dnl
-])
+          [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_n_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_divert_text(DIVERSION-NAME, CONTENT)
@@ -833,10 +1192,8 @@ m4_builtin([divert],
 # Output CONTENT into DIVERSION-NAME (which may be a number actually).
 # An end of line is appended for free to CONTENT.
 m4_define([m4_divert_text],
-[m4_divert_push([$1])dnl
-$2
-m4_divert_pop([$1])dnl
-])
+[m4_divert_push([$1])$2
+m4_divert_pop([$1])])
 
 
 # m4_divert_once(DIVERSION-NAME, CONTENT)
@@ -1138,7 +1495,7 @@ m4_define([m4_undivert],
 m4_define([m4_expansion_stack_push],
 [m4_pushdef([m4_expansion_stack],
            [$1]m4_ifdef([m4_expansion_stack], [
-m4_defn([m4_expansion_stack])]))])
+_m4_defn([m4_expansion_stack])]))])
 
 
 # m4_expansion_stack_pop
@@ -1152,7 +1509,7 @@ m4_define([m4_expansion_stack_pop],
 # Dump the expansion stack.
 m4_define([m4_expansion_stack_dump],
 [m4_ifdef([m4_expansion_stack],
-         [m4_errprintn(m4_defn([m4_expansion_stack]))])dnl
+         [m4_errprintn(_m4_defn([m4_expansion_stack]))])dnl
 m4_errprintn(m4_location[: the top level])])
 
 
@@ -1178,33 +1535,33 @@ m4_define([_m4_divert(GROW)],       10000)
 # _m4_defun_pro(MACRO-NAME)
 # -------------------------
 # The prologue for Autoconf macros.
+#
+# This is called frequently, so minimize the number of macro invocations
+# by avoiding dnl and m4_defn overhead.
 m4_define([_m4_defun_pro],
-[m4_ifndef([m4_expansion_stack], [_m4_defun_pro_outer[]])dnl
-m4_expansion_stack_push(m4_defn([m4_location($1)])[: $1 is expanded from...])dnl
-m4_pushdef([_m4_expanding($1)])dnl
-])
+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_define([_m4_defun_pro_outer],
-[m4_copy([_m4_divert_diversion], [_m4_divert_dump])dnl
-m4_divert_push([GROW])dnl
-])
+[m4_copy([_m4_divert_diversion], [_m4_divert_dump])m4_divert_push([GROW])])
 
 # _m4_defun_epi(MACRO-NAME)
 # -------------------------
 # The Epilogue for Autoconf macros.  MACRO-NAME only helps tracing
 # the PRO/EPI pairs.
+#
+# This is called frequently, so minimize the number of macro invocations
+# by avoiding dnl and m4_popdef overhead.
 m4_define([_m4_defun_epi],
-[m4_popdef([_m4_expanding($1)])dnl
-m4_expansion_stack_pop()dnl
-m4_ifndef([m4_expansion_stack], [_m4_defun_epi_outer[]])dnl
-m4_provide([$1])dnl
-])
+m4_do([[_m4_popdef([_m4_expanding($1)])]],
+      [[m4_expansion_stack_pop()]],
+      [[m4_ifdef([m4_expansion_stack], [], [_m4_defun_epi_outer[]])]],
+      [[m4_provide([$1])]]))
 
 m4_define([_m4_defun_epi_outer],
-[m4_undefine([_m4_divert_dump])dnl
-m4_divert_pop([GROW])dnl
-m4_undivert([GROW])dnl
-])
+[_m4_undefine([_m4_divert_dump])m4_divert_pop([GROW])m4_undivert([GROW])])
 
 
 # m4_defun(NAME, EXPANSION)
@@ -1294,33 +1651,38 @@ m4_define([m4_before],
 #   such as `C' should dispatch the call to `AC_LANG_COMPILER(C)'.  But this
 #   `extension' prevents `AC_LANG_COMPILER' from having actual arguments that
 #   it passes to `AC_LANG_COMPILER(C)'.
+#
+# This is called frequently, so minimize the number of macro invocations
+# by avoiding dnl and other overhead on the common path.
 m4_define([m4_require],
-[m4_ifdef([_m4_expanding($1)],
-        [m4_fatal([$0: circular dependency of $1])])dnl
-m4_ifndef([_m4_divert_dump],
-         [m4_fatal([$0($1): cannot be used outside of an m4_defun'd macro])])dnl
-m4_provide_if([$1],
-             [],
-             [_m4_require_call([$1], [$2])])dnl
-])
-
-
-# _m4_require_call(BODY-TO-EXPAND)
-# --------------------------------
+m4_do([[m4_ifdef([_m4_expanding($1)],
+                [m4_fatal([$0: circular dependency of $1])])]],
+      [[m4_ifdef([_m4_divert_dump], [],
+                [m4_fatal([$0($1): cannot be used outside of an ]dnl
+m4_bmatch([$0], [^AC_], [[AC_DEFUN]], [[m4_defun]])['d macro])])]],
+      [[m4_provide_if([$1],
+                     [],
+                     [_m4_require_call([$1], [$2])])]]))
+
+
+# _m4_require_call(NAME-TO-CHECK, [BODY-TO-EXPAND = NAME-TO-CHECK])
+# -----------------------------------------------------------------
 # If m4_require decides to expand the body, it calls this macro.
+#
+# This is called frequently, so minimize the number of macro invocations
+# by avoiding dnl and other overhead on the common path.
 m4_define([_m4_require_call],
-[m4_define([_m4_divert_grow], m4_decr(_m4_divert_grow))dnl
-m4_divert_push(_m4_divert_grow)dnl
-m4_default([$2], [$1])
+m4_do([[m4_define([_m4_divert_grow], m4_decr(_m4_divert_grow))]],
+      [[m4_divert_push(_m4_divert_grow)]],
+      [[m4_default([$2], [$1])
 m4_provide_if([$1],
              [],
              [m4_warn([syntax],
-                      [$1 is m4_require'd but not m4_defun'd])])dnl
-m4_divert(m4_defn([_m4_divert_dump]))dnl
-m4_undivert(_m4_divert_grow)dnl
-m4_divert_pop(_m4_divert_grow)dnl
-m4_define([_m4_divert_grow], m4_incr(_m4_divert_grow))dnl
-])
+                      [$1 is m4_require'd but not m4_defun'd])])]],
+      [[m4_divert(_m4_defn([_m4_divert_dump]))]],
+      [[m4_undivert(_m4_divert_grow)]],
+      [[m4_divert_pop(_m4_divert_grow)]],
+      [[m4_define([_m4_divert_grow], m4_incr(_m4_divert_grow))]]))
 
 
 # _m4_divert_grow
@@ -1378,7 +1740,16 @@ m4_defn([m4_cr_LETTERS])dnl
 m4_define([m4_cr_digits], [0123456789])
 
 
-# m4_cr_symbols1 & m4_cr_symbols2
+# m4_cr_alnum
+# -----------
+m4_define([m4_cr_alnum],
+m4_defn([m4_cr_Letters])dnl
+m4_defn([m4_cr_digits])dnl
+)
+
+
+# m4_cr_symbols1
+# m4_cr_symbols2
 # -------------------------------
 m4_define([m4_cr_symbols1],
 m4_defn([m4_cr_Letters])dnl
@@ -1389,6 +1760,59 @@ m4_defn([m4_cr_symbols1])dnl
 m4_defn([m4_cr_digits])dnl
 )
 
+# m4_cr_all
+# ---------
+# The character range representing everything, with `-' as the last
+# character, since it is special to m4_translit.  Use with care, because
+# it contains characters special to M4 (fortunately, both ASCII and EBCDIC
+# have [] in order, so m4_defn([m4_cr_all]) remains a valid string).  It
+# also contains characters special to terminals, so it should never be
+# displayed in an error message.  Also, attempts to map [ and ] to other
+# characters via m4_translit must deal with the fact that m4_translit does
+# not add quotes to the output.
+#
+# It is mainly useful in generating inverted character range maps, for use
+# in places where m4_translit is faster than an equivalent m4_bpatsubst;
+# the regex `[^a-z]' is equivalent to:
+#  m4_translit(m4_dquote(m4_defn([m4_cr_all])), [a-z])
+m4_define([m4_cr_all],
+m4_translit(m4_dquote(m4_format(m4_dquote(m4_for(
+  ,1,255,,[[%c]]))m4_for([i],1,255,,[,i]))), [-])-)
+
+
+# _m4_define_cr_not(CATEGORY)
+# ---------------------------
+# Define m4_cr_not_CATEGORY as the inverse of m4_cr_CATEGORY.
+m4_define([_m4_define_cr_not],
+[m4_define([m4_cr_not_$1],
+          m4_translit(m4_dquote(m4_defn([m4_cr_all])),
+                      m4_defn([m4_cr_$1])))])
+
+
+# m4_cr_not_letters
+# m4_cr_not_LETTERS
+# m4_cr_not_Letters
+# m4_cr_not_digits
+# m4_cr_not_alnum
+# m4_cr_not_symbols1
+# m4_cr_not_symbols2
+# ------------------
+# Inverse character sets
+_m4_define_cr_not([letters])
+_m4_define_cr_not([LETTERS])
+_m4_define_cr_not([Letters])
+_m4_define_cr_not([digits])
+_m4_define_cr_not([alnum])
+_m4_define_cr_not([symbols1])
+_m4_define_cr_not([symbols2])
+
+
+# m4_newline
+# ----------
+# Expands to a newline.  Exists for formatting reasons.
+m4_define([m4_newline], [
+])
+
 
 # m4_re_escape(STRING)
 # --------------------
@@ -1420,11 +1844,15 @@ m4_defn([m4_re_string])dnl
 # m4_tolower(STRING)
 # m4_toupper(STRING)
 # ------------------
-# These macros lowercase and uppercase strings.
+# These macros convert STRING to lowercase or uppercase.
+#
+# Rather than expand the m4_defn each time, we inline them up front.
 m4_define([m4_tolower],
-[m4_translit([$1], m4_defn([m4_cr_LETTERS]), m4_defn([m4_cr_letters]))])
+[m4_translit([$1], ]m4_dquote(m4_defn([m4_cr_LETTERS]))[,
+                  ]m4_dquote(m4_defn([m4_cr_letters]))[)])
 m4_define([m4_toupper],
-[m4_translit([$1], m4_defn([m4_cr_letters]), m4_defn([m4_cr_LETTERS]))])
+[m4_translit([$1], ]m4_dquote(m4_defn([m4_cr_letters]))[,
+                  ]m4_dquote(m4_defn([m4_cr_LETTERS]))[)])
 
 
 # m4_split(STRING, [REGEXP])
@@ -1440,28 +1868,32 @@ m4_define([m4_toupper],
 #
 # Pay attention to the m4_changequotes.  When m4 reads the definition of
 # m4_split, it still has quotes set to [ and ].  Luckily, these are matched
-# in the macro body, so the definition is stored correctly.
+# in the macro body, so the definition is stored correctly.  Use the same
+# alternate quotes as m4_noquote; it must be unlikely to appear in $1.
 #
 # Also, notice that $1 is quoted twice, since we want the result to
 # be quoted.  Then you should understand that the argument of
-# patsubst is ``STRING'' (i.e., with additional `` and '').
+# patsubst is -=<{(STRING)}>=- (i.e., with additional -=<{( and )}>=-).
 #
 # This macro is safe on active symbols, i.e.:
 #   m4_define(active, ACTIVE)
 #   m4_split([active active ])end
 #   => [active], [active], []end
-
+#
+# Optimize on regex of ` ' (space), since m4_foreach_w already guarantees
+# that the list contains single space separators, and a common case is
+# splitting a single-element list.  This macro is called frequently,
+# so avoid unnecessary dnl inside the definition.
 m4_define([m4_split],
-[m4_ifval([$1], [_m4_split($@)])])
+[m4_if([$1], [], [],
+       [$2], [ ], [m4_if(m4_index([$1], [ ]), [-1], [[[$1]]], [_$0($@)])],
+       [$2], [], [_$0([$1], [[  ]+])],
+       [_$0($@)])])
 
 m4_define([_m4_split],
-[m4_changequote(``, '')dnl
-[dnl Can't use m4_default here instead of m4_if, because m4_default uses
-dnl [ and ] as quotes.
-m4_bpatsubst(````$1'''',
-            m4_if(``$2'',, ``[  ]+'', ``$2''),
-            ``], ['')]dnl
-m4_changequote([, ])])
+[m4_changequote([-=<{(],[)}>=-])]dnl
+[[m4_bpatsubst(-=<{(-=<{($1)}>=-)}>=-, -=<{($2)}>=-,
+              -=<{(], [)}>=-)]m4_changequote([, ])])
 
 
 
@@ -1475,10 +1907,14 @@ m4_changequote([, ])])
 #    act\
 #    ive])end
 #    => active activeend
+#
+# In m4, m4_bpatsubst is expensive, so first check for a newline.
 m4_define([m4_flatten],
-[m4_translit(m4_bpatsubst([[[$1]]], [\\
+[m4_if(m4_index([$1], [
+]), [-1], [[$1]],
+       [m4_translit(m4_bpatsubst([[[$1]]], [\\
 ]), [
-], [ ])])
+], [ ])])])
 
 
 # m4_strip(STRING)
@@ -1491,18 +1927,20 @@ m4_define([m4_flatten],
 #    m4_strip([  active <tab> <tab>active ])end
 #    => active activeend
 #
-# Because we want to preserve active symbols, STRING must be double-quoted.
+# First, notice that we guarantee trailing space.  Why?  Because regular
+# expressions are greedy, and `.* ?' would always group the space into the
+# .* portion.  The algorithm is simpler by avoiding `?' at the end.  The
+# algorithm correctly strips everything if STRING is just ` '.
 #
-# Then notice the 2 last patterns: they are in charge of removing the
+# Then notice the second pattern: it is in charge of removing the
 # leading/trailing spaces.  Why not just `[^ ]'?  Because they are
-# applied to doubly quoted strings, i.e. more or less [[STRING]].  So
-# if there is a leading space in STRING, then it is the *third*
-# character, since there are two leading `['; equally for the last pattern.
+# applied to over-quoted strings, i.e. more or less [STRING], due
+# to the limitations of m4_bpatsubsts.  So the leading space in STRING
+# is the *second* character; equally for the trailing space.
 m4_define([m4_strip],
-[m4_bpatsubsts([[$1]],
+[m4_bpatsubsts([$1 ],
               [[        ]+], [ ],
-              [^\(..\) ],    [\1],
-              [ \(..\)$],    [\1])])
+              [^. ?\(.*\) .$], [[[\1]]])])
 
 
 # m4_normalize(STRING)
@@ -1524,13 +1962,62 @@ m4_define([m4_normalize],
 
 # m4_join(SEP, ARG1, ARG2...)
 # ---------------------------
-# Produce ARG1SEPARG2...SEPARGn.
-m4_defun([m4_join],
-[m4_case([$#],
-        [1], [],
-        [2], [[$2]],
-        [[$2][$1]$0([$1], m4_shiftn(2, $@))])])
+# Produce ARG1SEPARG2...SEPARGn.  Avoid back-to-back SEP when a given ARG
+# is the empty string.  No expansion is performed on SEP or ARGs.
+#
+# Since the number of arguments to join can be arbitrarily long, we
+# want to avoid having more than one $@ in the macro definition;
+# otherwise, the expansion would require twice the memory of the already
+# long list.  Hence, m4_join merely looks for the first non-empty element,
+# and outputs just that element; while _m4_join looks for all non-empty
+# 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_if([$2], [], [], [[$2]_])$0([$1], m4_shift2($@))])])
+m4_define([_m4_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift2($@))])])
+
+# m4_joinall(SEP, ARG1, ARG2...)
+# ------------------------------
+# 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_combine([SEPARATOR], PREFIX-LIST, [INFIX], SUFFIX...)
+# --------------------------------------------------------
+# Produce the pairwise combination of every element in the quoted,
+# comma-separated PREFIX-LIST with every element from the SUFFIX arguments.
+# Each pair is joined with INFIX, and pairs are separated by SEPARATOR.
+# No expansion occurs on SEPARATOR, INFIX, or elements of either list.
+#
+# For example:
+#   m4_combine([, ], [[a], [b], [c]], [-], [1], [2], [3])
+#   => a-1, a-2, a-3, b-1, b-2, b-3, c-1, c-2, c-3
+#
+# In order to have the correct number of SEPARATORs, we use a temporary
+# variable that redefines itself after the first use.  We must use defn
+# rather than overquoting in case PREFIX or SUFFIX contains $1, but use
+# _m4_defn for speed.  Likewise, we compute the m4_shift3 only once,
+# rather than in each iteration of the outer m4_foreach.
+m4_define([m4_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([m4_Separator], [m4_define([m4_Separator],
+                                   _m4_defn([m4_echo]))])]]dnl
+[[m4_foreach([m4_Prefix], [$2],
+            [m4_foreach([m4_Suffix], ]m4_dquote(m4_dquote(m4_shift3($@)))[,
+       [m4_Separator([$1])[]_m4_defn([m4_Prefix])[$3]_m4_defn(
+                                                     [m4_Suffix])])])]]dnl
+[[_m4_popdef([m4_Separator])])])
 
 
 # m4_append(MACRO-NAME, STRING, [SEPARATOR])
@@ -1540,13 +2027,16 @@ m4_defun([m4_join],
 # in which case no SEPARATOR is added.  Be aware that the criterion is
 # `not being defined', and not `not being empty'.
 #
+# Note that neither STRING nor SEPARATOR are expanded here; rather, when
+# you expand MACRO-NAME, they will be expanded at that point in time.
+#
 # This macro is robust to active symbols.  It can be used to grow
 # strings.
 #
-#    | m4_define(active, ACTIVE)
-#    | m4_append([sentence], [This is an])
-#    | m4_append([sentence], [ active ])
-#    | m4_append([sentence], [symbol.])
+#    | m4_define(active, ACTIVE)dnl
+#    | m4_append([sentence], [This is an])dnl
+#    | m4_append([sentence], [ active ])dnl
+#    | m4_append([sentence], [symbol.])dnl
 #    | sentence
 #    | m4_undefine([active])dnl
 #    | sentence
@@ -1555,28 +2045,69 @@ m4_defun([m4_join],
 #
 # It can be used to define hooks.
 #
-#    | m4_define(active, ACTIVE)
-#    | m4_append([hooks], [m4_define([act1], [act2])])
-#    | m4_append([hooks], [m4_define([act2], [active])])
-#    | m4_undefine([active])
+#    | m4_define(active, ACTIVE)dnl
+#    | m4_append([hooks], [m4_define([act1], [act2])])dnl
+#    | m4_append([hooks], [m4_define([act2], [active])])dnl
+#    | m4_undefine([active])dnl
 #    | act1
 #    | hooks
 #    | act1
 #    => act1
 #    =>
 #    => active
+#
+# It can also be used to create lists, although this particular usage was
+# broken prior to autoconf 2.62.
+#    | m4_append([list], [one], [, ])dnl
+#    | m4_append([list], [two], [, ])dnl
+#    | m4_append([list], [three], [, ])dnl
+#    | list
+#    | m4_dquote(list)
+#    => one, two, three
+#    => [one],[two],[three]
+#
+# Note that m4_append can benefit from amortized O(n) m4 behavior, if
+# the underlying m4 implementation is smart enough to avoid copying existing
+# contents when enlarging a macro's definition into any pre-allocated storage
+# (m4 1.4.x unfortunately does not implement this optimization).  We do
+# not implement m4_prepend, since it is inherently O(n^2) (pre-allocated
+# storage only occurs at the end of a macro, so the existing contents must
+# always be moved).
+#
+# Use _m4_defn for speed.
 m4_define([m4_append],
-[m4_define([$1],
-          m4_ifdef([$1], [m4_defn([$1])$3])[$2])])
+[m4_define([$1], m4_ifdef([$1], [_m4_defn([$1])[$3]])[$2])])
 
-# m4_append_uniq(MACRO-NAME, STRING, [SEPARATOR])
-# -----------------------------------------------
-# As `m4_append', but append only if not yet present.
+
+# m4_append_uniq(MACRO-NAME, STRING, [SEPARATOR], [IF-UNIQ], [IF-DUP])
+# --------------------------------------------------------------------
+# Like `m4_append', but append only if not yet present.  Additionally,
+# expand IF-UNIQ if STRING was appended, or IF-DUP if STRING was already
+# present.  Also, warn if SEPARATOR is not empty and occurs within STRING,
+# as the algorithm no longer guarantees uniqueness.
+#
+# Note that while m4_append can be O(n) (depending on the quality of the
+# underlying M4 implementation), m4_append_uniq is inherently O(n^2)
+# because each append operation searches the entire string.
 m4_define([m4_append_uniq],
+[m4_ifval([$3], [m4_if(m4_index([$2], [$3]), [-1], [],
+                      [m4_warn([syntax],
+                               [$0: `$2' contains `$3'])])])_$0($@)])
+m4_define([_m4_append_uniq],
 [m4_ifdef([$1],
-         [m4_bmatch([$3]m4_defn([$1])[$3], m4_re_escape([$3$2$3]), [],
-                    [m4_append($@)])],
-         [m4_append($@)])])
+         [m4_if(m4_index([$3]_m4_defn([$1])[$3], [$3$2$3]), [-1],
+                [m4_append([$1], [$2], [$3])$4], [$5])],
+         [m4_define([$1], [$2])$4])])
+
+# m4_append_uniq_w(MACRO-NAME, STRINGS)
+# -------------------------------------
+# For each of the words in the whitespace separated list STRINGS, append
+# only the unique strings to the definition of MACRO-NAME.
+#
+# Use _m4_defn for speed.
+m4_define([m4_append_uniq_w],
+[m4_foreach_w([m4_Word], [$2],
+             [_m4_append_uniq([$1], _m4_defn([m4_Word]), [ ])])])
 
 
 # m4_text_wrap(STRING, [PREFIX], [FIRST-PREFIX], [WIDTH])
@@ -1587,6 +2118,9 @@ m4_define([m4_append_uniq],
 # if the length of FIRST-PREFIX is greater than that of PREFIX, then
 # FIRST-PREFIX will be left alone on the first line.
 #
+# No expansion occurs on the contents STRING, PREFIX, or FIRST-PREFIX,
+# although quadrigraphs are correctly recognized.
+#
 # Typical outputs are:
 #
 # m4_text_wrap([Short string */], [   ], [/* ], 20)
@@ -1612,56 +2146,78 @@ m4_define([m4_append_uniq],
 # we really want to bother with people trying each single corner
 # of a software?
 #
-# more important:
-# FIXME: handle quadrigraphs correctly, both in TEXT and in FIRST_PREFIX.
-#
-# This macro does not leave a trailing space behind the last word,
-# what complicates it a bit.  The algorithm is stupid simple: all the
-# words are preceded by m4_Separator which is defined to empty for the
-# first word, and then ` ' (single space) for all the others.
+# This macro does not leave a trailing space behind the last word of a line,
+# which complicates it a bit.  The algorithm is otherwise stupid and simple:
+# all the words are preceded by m4_Separator which is defined to empty for
+# the first word, and then ` ' (single space) for all the others.
+#
+# The algorithm uses a helper that uses $2 through $4 directly, rather than
+# using local variables, to avoid m4_defn overhead, or expansion swallowing
+# any $.  It also bypasses m4_popdef overhead with _m4_popdef since no user
+# macro expansion occurs in the meantime.  Also, the definition is written
+# with m4_do, to avoid time wasted on dnl during expansion (since this is
+# already a time-consuming macro).
 m4_define([m4_text_wrap],
-[m4_pushdef([m4_Prefix], [$2])dnl
-m4_pushdef([m4_Prefix1], m4_default([$3], [m4_Prefix]))dnl
-m4_pushdef([m4_Width], m4_default([$4], 79))dnl
-m4_pushdef([m4_Cursor], m4_len(m4_Prefix1))dnl
-m4_pushdef([m4_Separator], [])dnl
-m4_Prefix1[]dnl
-m4_if(m4_eval(m4_Cursor > m4_len(m4_Prefix)),
-      1, [m4_define([m4_Cursor], m4_len(m4_Prefix))
-m4_Prefix])[]dnl
-m4_foreach_w([m4_Word], [$1],
-[m4_define([m4_Cursor], m4_eval(m4_Cursor + m4_len(m4_defn([m4_Word])) + 1))dnl
-dnl New line if too long, else insert a space unless it is the first
-dnl of the words.
-m4_if(m4_eval(m4_Cursor > m4_Width),
-      1, [m4_define([m4_Cursor],
-                   m4_eval(m4_len(m4_Prefix) + m4_len(m4_defn([m4_Word])) + 1))]
-m4_Prefix,
-       [m4_Separator])[]dnl
-m4_defn([m4_Word])[]dnl
-m4_define([m4_Separator], [ ])])dnl
-m4_popdef([m4_Separator])dnl
-m4_popdef([m4_Cursor])dnl
-m4_popdef([m4_Width])dnl
-m4_popdef([m4_Prefix1])dnl
-m4_popdef([m4_Prefix])dnl
-])
+[_$0([$1], [$2], m4_if([$3], [], [[$2]], [[$3]]),
+     m4_if([$4], [], [79], [[$4]]))])
+m4_define([_m4_text_wrap],
+m4_do(dnl set up local variables, to avoid repeated calculations
+[[m4_pushdef([m4_Indent], m4_qlen([$2]))]],
+[[m4_pushdef([m4_Cursor], m4_qlen([$3]))]],
+[[m4_pushdef([m4_Separator], [m4_define([m4_Separator], [ ])])]],
+dnl expand the first prefix, then check its length vs. regular prefix
+dnl same length: nothing special
+dnl prefix1 longer: output on line by itself, and reset cursor
+dnl prefix1 shorter: pad to length of prefix, and reset cursor
+[[[$3]m4_cond([m4_Cursor], m4_Indent, [],
+             [m4_eval(m4_Cursor > m4_Indent)], [1], [
+[$2]m4_define([m4_Cursor], m4_Indent)],
+             [m4_format([%*s], m4_max([0],
+  m4_eval(m4_Indent - m4_Cursor)), [])m4_define([m4_Cursor], m4_Indent)])]],
+dnl now, for each word, compute the curser after the word is output, then
+dnl check if the cursor would exceed the wrap column
+dnl if so, reset cursor, and insert newline and prefix
+dnl if not, insert the separator (usually a space)
+dnl either way, insert the word
+[[m4_foreach_w([m4_Word], [$1],
+  [m4_define([m4_Cursor],
+            m4_eval(m4_Cursor + m4_qlen(_m4_defn([m4_Word]))
+                    + 1))m4_if(m4_eval(m4_Cursor > ([$4])),
+      [1], [m4_define([m4_Cursor],
+                     m4_eval(m4_Indent + m4_qlen(_m4_defn([m4_Word])) + 1))
+[$2]],
+      [m4_Separator[]])_m4_defn([m4_Word])])]],
+dnl finally, clean up the local variabls
+[[_m4_popdef([m4_Separator], [m4_Cursor], [m4_Indent])]]))
 
 
 # m4_text_box(MESSAGE, [FRAME-CHARACTER = `-'])
 # ---------------------------------------------
+# Turn MESSAGE into:
+#  ## ------- ##
+#  ## MESSAGE ##
+#  ## ------- ##
+# using FRAME-CHARACTER in the border.
 m4_define([m4_text_box],
-[@%:@@%:@ m4_bpatsubst([$1], [.], m4_if([$2], [], [[-]], [[$2]])) @%:@@%:@
+[m4_pushdef([m4_Border],
+           m4_translit(m4_format([%*s], m4_qlen(m4_expand([$1])), []),
+                       [ ], m4_if([$2], [], [[-]], [[$2]])))dnl
+@%:@@%:@ m4_Border @%:@@%:@
 @%:@@%:@ $1 @%:@@%:@
-@%:@@%:@ m4_bpatsubst([$1], [.], m4_if([$2], [], [[-]], [[$2]])) @%:@@%:@[]dnl
+@%:@@%:@ m4_Border @%:@@%:@_m4_popdef([m4_Border])dnl
 ])
 
 
 # m4_qlen(STRING)
 # ---------------
 # Expands to the length of STRING after autom4te converts all quadrigraphs.
+#
+# Avoid bpatsubsts for the common case of no quadrigraphs.
 m4_define([m4_qlen],
-[m4_len(m4_bpatsubsts([[$1]], [@\(<:\|:>\|S|\|%:\)@], [P], [@&t@]))])
+[m4_if(m4_index([$1], [@]), [-1], [m4_len([$1])],
+       [m4_len(m4_bpatsubst([[$1]],
+                           [@\(\(<:\|:>\|S|\|%:\|\{:\|:\}\)\(@\)\|&t@\)],
+                           [\3]))])])
 
 
 # m4_qdelta(STRING)
@@ -1677,16 +2233,6 @@ m4_define([m4_qdelta],
 ## 13. Number processing.  ##
 ## ----------------------- ##
 
-# m4_sign(A)
-# ----------
-#
-# The sign of the integer A.
-m4_define([m4_sign],
-[m4_bmatch([$1],
-          [^-], -1,
-          [^0+], 0,
-                 1)])
-
 # m4_cmp(A, B)
 # ------------
 # Compare two integer expressions.
@@ -1694,28 +2240,96 @@ m4_define([m4_sign],
 # A = B ->  0
 # A > B ->  1
 m4_define([m4_cmp],
-[m4_sign(m4_eval([$1 - $2]))])
+[m4_eval((([$1]) > ([$2])) - (([$1]) < ([$2])))])
 
 
 # m4_list_cmp(A, B)
 # -----------------
 #
-# Compare the two lists of integers A and B.  For instance:
-#   m4_list_cmp((1, 0),     (1))    ->  0
-#   m4_list_cmp((1, 0),     (1, 0)) ->  0
-#   m4_list_cmp((1, 2),     (1, 0)) ->  1
-#   m4_list_cmp((1, 2, 3),  (1, 2)) ->  1
-#   m4_list_cmp((1, 2, -3), (1, 2)) -> -1
-#   m4_list_cmp((1, 0),     (1, 2)) -> -1
-#   m4_list_cmp((1),        (1, 2)) -> -1
+# Compare the two lists of integer expressions A and B.  For instance:
+#   m4_list_cmp([1, 0],     [1])    ->  0
+#   m4_list_cmp([1, 0],     [1, 0]) ->  0
+#   m4_list_cmp([1, 2],     [1, 0]) ->  1
+#   m4_list_cmp([1, 2, 3],  [1, 2]) ->  1
+#   m4_list_cmp([1, 2, -3], [1, 2]) -> -1
+#   m4_list_cmp([1, 0],     [1, 2]) -> -1
+#   m4_list_cmp([1],        [1, 2]) -> -1
+#   m4_define([xa], [oops])dnl
+#   m4_list_cmp([[0xa]],    [5+5])  -> 0
+#
+# Rather than face the overhead of m4_case, we use a helper function whose
+# expansion includes the name of the macro to invoke on the tail, either
+# m4_ignore or m4_unquote.  This is particularly useful when comparing
+# 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.  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_if([$1$2], [()()], 0,
-       [$1], [()], [$0((0), [$2])],
-       [$2], [()], [$0([$1], (0))],
-       [m4_case(m4_cmp(m4_car$1, m4_car$2),
-               -1, -1,
-                1, 1,
-                0, [$0((m4_shift$1), (m4_shift$2))])])])
+[_$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_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_list_cmp_1(m4_dquote(m4_shift3($@)), $2)])])
+
+# m4_max(EXPR, ...)
+# m4_min(EXPR, ...)
+# -----------------
+# Return the decimal value of the maximum (or minimum) in a series of
+# integer expressions.
+#
+# 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])],
+       [$#$1], [2$2], [m4_eval([$1])],
+       [$#], [2], [_$0($@)],
+       [_m4_minmax([_$0], $@)])])
+
+m4_define([_m4_max],
+[m4_eval((([$1]) > ([$2])) * ([$1]) + (([$1]) <= ([$2])) * ([$2]))])
+
+m4_define([m4_min],
+[m4_if([$#], [0], [m4_fatal([too few arguments to $0])],
+       [$#], [1], [m4_eval([$1])],
+       [$#$1], [2$2], [m4_eval([$1])],
+       [$#], [2], [_$0($@)],
+       [_m4_minmax([_$0], $@)])])
+
+m4_define([_m4_min],
+[m4_eval((([$1]) < ([$2])) * ([$1]) + (([$1]) >= ([$2])) * ([$2]))])
+
+# _m4_minmax(METHOD, ARG1, ARG2...)
+# ---------------------------------
+# 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_sign(A)
+# ----------
+# The sign of the integer expression A.
+m4_define([m4_sign],
+[m4_eval((([$1]) > 0) - (([$1]) < 0))])
 
 
 
@@ -1726,23 +2340,31 @@ m4_define([m4_list_cmp],
 
 # m4_version_unletter(VERSION)
 # ----------------------------
-# Normalize beta version numbers with letters to numbers only for comparison.
+# Normalize beta version numbers with letters to numeric expressions, which
+# can then be handed to m4_eval for the purpose of comparison.
 #
 #   Nl -> (N+1).-1.(l#)
 #
-#i.e., 2.14a -> 2.15.-1.1, 2.14b -> 2.15.-1.2, etc.
-# This macro is absolutely not robust to active macro, it expects
-# reasonable version numbers and is valid up to `z', no double letters.
+# for example:
+#   [2.14a] -> [2.14+1.-1.[0r36:a]] -> 2.15.-1.10
+#   [2.14b] -> [2.15+1.-1.[0r36:b]] -> 2.15.-1.11
+#   [2.61aa.b] -> [2.61+1.-1.[0r36:aa],+1.-1.[0r36:b]] -> 2.62.-1.370.1.-1.11
+#
+# This macro expects reasonable version numbers, but can handle double
+# letters and does not expand any macros.  Original version strings can
+# use both `.' and `-' separators.
+#
+# Inline constant expansions, to avoid m4_defn overhead.
+# _m4_version_unletter is the real workhorse used by m4_version_compare,
+# but since [0r36:a] is less readable than 10, we provide a wrapper for
+# human use.
 m4_define([m4_version_unletter],
-[m4_translit(m4_bpatsubsts([$1],
-                          [\([0-9]+\)\([abcdefghi]\)],
-                            [m4_eval(\1 + 1).-1.\2],
-                          [\([0-9]+\)\([jklmnopqrs]\)],
-                            [m4_eval(\1 + 1).-1.1\2],
-                          [\([0-9]+\)\([tuvwxyz]\)],
-                            [m4_eval(\1 + 1).-1.2\2]),
-            [abcdefghijklmnopqrstuvwxyz],
-            [12345678901234567890123456])])
+[m4_map_sep([m4_eval], [.],
+           m4_dquote(m4_dquote_elt(m4_unquote(_$0([$1])))))])
+m4_define([_m4_version_unletter],
+[m4_bpatsubst(m4_translit([[[$1]]], [.-], [,,]),]dnl
+m4_dquote(m4_dquote(m4_defn([m4_cr_Letters])))[[+],
+             [+1,-1,[0r36:\&]])])
 
 
 # m4_version_compare(VERSION-1, VERSION-2)
@@ -1751,9 +2373,11 @@ m4_define([m4_version_unletter],
 #  -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_list_cmp((m4_split(m4_version_unletter([$1]), [\.])),
-            (m4_split(m4_version_unletter([$2]), [\.])))])
+[_m4_list_cmp_raw(_m4_version_unletter([$1]), _m4_version_unletter([$2]))])
 
 
 # m4_PACKAGE_NAME
@@ -1781,9 +2405,332 @@ m4_ifdef([m4_PACKAGE_VERSION],
 [[m4_fatal([m4sugar/version.m4 not found])]]))
 
 
+## ------------------ ##
+## 15. Set handling.  ##
+## ------------------ ##
+
+# Autoconf likes to create arbitrarily large sets; for example, as of
+# this writing, the configure.ac for coreutils tracks a set of more
+# than 400 AC_SUBST.  How do we track all of these set members,
+# without introducing duplicates?  We could use m4_append_uniq, with
+# the set NAME residing in the contents of the macro NAME.
+# Unfortunately, m4_append_uniq is quadratic for set creation, because
+# it costs O(n) to search the string for each of O(n) insertions; not
+# to mention that with m4 1.4.x, even using m4_append is slow, costing
+# O(n) rather than O(1) per insertion.  Other set operations, not used
+# by Autoconf but still possible by manipulation of the definition
+# tracked in macro NAME, include O(n) deletion of one element and O(n)
+# computation of set size.  Because the set is exposed to the user via
+# the definition of a single macro, we cannot cache any data about the
+# set without risking the cache being invalidated by the user
+# redefining NAME.
+#
+# Can we do better?  Yes, because m4 gives us an O(1) search function
+# for free: ifdef.  Additionally, even m4 1.4.x gives us an O(1)
+# insert operation for free: pushdef.  But to use these, we must
+# represent the set via a group of macros; to keep the set consistent,
+# we must hide the set so that the user can only manipulate it through
+# accessor macros.  The contents of the set are maintained through two
+# access points; _m4_set([name]) is a pushdef stack of values in the
+# set, useful for O(n) traversal of the set contents; while the
+# existence of _m4_set([name],value) with no particular value is
+# useful for O(1) querying of set membership.  And since the user
+# cannot externally manipulate the set, we are free to add additional
+# caching macros for other performance improvements.  Deletion can be
+# O(1) per element rather than O(n), by reworking the definition of
+# _m4_set([name],value) to be 0 or 1 based on current membership, and
+# adding _m4_set_cleanup(name) to defer the O(n) cleanup of
+# _m4_set([name]) until we have another reason to do an O(n)
+# traversal.  The existence of _m4_set_cleanup(name) can then be used
+# elsewhere to determine if we must dereference _m4_set([name],value),
+# or assume that definition implies set membership.  Finally, size can
+# be tracked in an O(1) fashion with _m4_set_size(name).
+#
+# The quoting in _m4_set([name],value) is chosen so that there is no
+# ambiguity with a set whose name contains a comma, and so that we can
+# supply the value via _m4_defn([_m4_set([name])]) without needing any
+# quote manipulation.
+
+# m4_set_add(SET, VALUE, [IF-UNIQ], [IF-DUP])
+# -------------------------------------------
+# Add VALUE as an element of SET.  Expand IF-UNIQ on the first
+# addition, and IF-DUP if it is already in the set.  Addition of one
+# element is O(1), such that overall set creation is O(n).
+#
+# We do not want to add a duplicate for a previously deleted but
+# unpruned element, but it is just as easy to check existence directly
+# as it is to query _m4_set_cleanup($1).
+m4_define([m4_set_add],
+[m4_ifdef([_m4_set([$1],$2)],
+         [m4_if(m4_indir([_m4_set([$1],$2)]), [0],
+                [m4_define([_m4_set([$1],$2)],
+                           [1])_m4_set_size([$1], [m4_incr])$3], [$4])],
+         [m4_define([_m4_set([$1],$2)],
+                    [1])m4_pushdef([_m4_set([$1])],
+                                   [$2])_m4_set_size([$1], [m4_incr])$3])])
+
+# m4_set_add_all(SET, VALUE...)
+# -----------------------------
+# Add each VALUE into SET.  This is O(n) in the number of VALUEs, and
+# can be faster than calling m4_set_add for each VALUE.
+#
+# Implement two recursion helpers; the check variant is slower but
+# handles the case where an element has previously been removed but
+# 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_if([$#], [2], [],
+       [m4_ifdef([_m4_set([$1],$3)], [],
+                [m4_define([_m4_set([$1],$3)], [1])m4_pushdef([_m4_set([$1])],
+          [$3])-])$0([$1], m4_shift2($@))])])
+
+m4_define([_m4_set_add_all_check],
+[m4_if([$#], [2], [],
+       [m4_set_add([$1], [$3])$0([$1], m4_shift2($@))])])
+
+# m4_set_contains(SET, VALUE, [IF-PRESENT], [IF-ABSENT])
+# ------------------------------------------------------
+# Expand IF-PRESENT if SET contains VALUE, otherwise expand IF-ABSENT.
+# This is always O(1).
+m4_define([m4_set_contains],
+[m4_ifdef([_m4_set_cleanup($1)],
+         [m4_if(m4_ifdef([_m4_set([$1],$2)],
+                   [m4_indir([_m4_set([$1],$2)])], [0]), [1], [$3], [$4])],
+         [m4_ifdef([_m4_set([$1],$2)], [$3], [$4])])])
+
+# m4_set_contents(SET, [SEP])
+# ---------------------------
+# Expand to a single string containing all the elements in SET,
+# separated by SEP, without modifying SET.  No provision is made for
+# disambiguating set elements that contain non-empty SEP as a
+# sub-string, or for recognizing a set that contains only the empty
+# string.  Order of the output is not guaranteed.  If any elements
+# have been previously removed from the set, this action will prune
+# the unused memory.  This is O(n) in the size of the set before
+# pruning.
+#
+# Use _m4_popdef for speed.  The existence of _m4_set_cleanup($1)
+# determines which version of _1 helper we use.
+m4_define([m4_set_contents],
+[m4_ifdef([_m4_set_cleanup($1)], [_$0_1c], [_$0_1])([$1])_$0_2([$1],
+    [_m4_defn([_m4_set_($1)])], [[$2]])])
+
+# _m4_set_contents_1(SET)
+# _m4_set_contents_1c(SET)
+# _m4_set_contents_2(SET, SEP, PREP)
+# ----------------------------------
+# Expand to a list of quoted elements currently in the set, separated
+# by SEP, and moving PREP in front of SEP on recursion.  To avoid
+# nesting limit restrictions, the algorithm must be broken into two
+# parts; _1 destructively copies the stack in reverse into
+# _m4_set_($1), producing no output; then _2 destructively copies
+# _m4_set_($1) back into the stack in reverse.  SEP is expanded while
+# _m4_set_($1) contains the current element, so a SEP containing
+# _m4_defn([_m4_set_($1)]) can produce output in the order the set was
+# created.  Behavior is undefined if SEP tries to recursively list or
+# modify SET in any way other than calling m4_set_remove on the
+# current element.  Use _1 if all entries in the stack are guaranteed
+# to be in the set, and _1c to prune removed entries.  Uses _m4_defn
+# and _m4_popdef for speed.
+m4_define([_m4_set_contents_1],
+[m4_ifdef([_m4_set([$1])], [m4_pushdef([_m4_set_($1)],
+    _m4_defn([_m4_set([$1])]))_m4_popdef([_m4_set([$1])])$0([$1])])])
+
+m4_define([_m4_set_contents_1c],
+[m4_ifdef([_m4_set([$1])],
+         [m4_set_contains([$1], _m4_defn([_m4_set([$1])]),
+                  [m4_pushdef([_m4_set_($1)], _m4_defn([_m4_set([$1])]))],
+                  [_m4_popdef([_m4_set([$1],]_m4_defn(
+      [_m4_set([$1])])[)])])_m4_popdef([_m4_set([$1])])$0([$1])],
+         [_m4_popdef([_m4_set_cleanup($1)])])])
+
+m4_define([_m4_set_contents_2],
+[m4_ifdef([_m4_set_($1)], [m4_pushdef([_m4_set([$1])],
+    _m4_defn([_m4_set_($1)]))$2[]_m4_popdef([_m4_set_($1)])$0([$1], [$3$2])])])
+
+# m4_set_delete(SET)
+# ------------------
+# Delete all elements in SET, and reclaim any memory occupied by the
+# set.  This is O(n) in the set size.
+#
+# Use _m4_defn and _m4_popdef for speed.
+m4_define([m4_set_delete],
+[m4_ifdef([_m4_set([$1])],
+         [_m4_popdef([_m4_set([$1],]_m4_defn([_m4_set([$1])])[)],
+                     [_m4_set([$1])])$0([$1])],
+         [m4_ifdef([_m4_set_cleanup($1)],
+                   [_m4_popdef([_m4_set_cleanup($1)])])m4_ifdef(
+                   [_m4_set_size($1)],
+                   [_m4_popdef([_m4_set_size($1)])])])])
+
+# m4_set_difference(SET1, SET2)
+# -----------------------------
+# Produce a LIST of quoted elements that occur in SET1 but not SET2.
+# Output a comma prior to any elements, to distinguish the empty
+# string from no elements.  This can be directly used as a series of
+# arguments, such as for m4_join, or wrapped inside quotes for use in
+# m4_foreach.  Order of the output is not guaranteed.
+#
+# Short-circuit the idempotence relation.  Use _m4_defn for speed.
+m4_define([m4_set_difference],
+[m4_if([$1], [$2], [],
+       [m4_set_foreach([$1], [_m4_element],
+                      [m4_set_contains([$2], _m4_defn([_m4_element]), [],
+                                       [,_m4_defn([_m4_element])])])])])
+
+# m4_set_dump(SET, [SEP])
+# -----------------------
+# Expand to a single string containing all the elements in SET,
+# separated by SEP, then delete SET.  In general, if you only need to
+# list the contents once, this is faster than m4_set_contents.  No
+# provision is made for disambiguating set elements that contain
+# non-empty SEP as a sub-string.  Order of the output is not
+# guaranteed.  This is O(n) in the size of the set before pruning.
+#
+# Use _m4_popdef for speed.  Use existence of _m4_set_cleanup($1) to
+# decide if more expensive recursion is needed.
+m4_define([m4_set_dump],
+[m4_ifdef([_m4_set_size($1)],
+         [_m4_popdef([_m4_set_size($1)])])m4_ifdef([_m4_set_cleanup($1)],
+    [_$0_check], [_$0])([$1], [], [$2])])
+
+# _m4_set_dump(SET, SEP, PREP)
+# _m4_set_dump_check(SET, SEP, PREP)
+# ----------------------------------
+# Print SEP and the current element, then delete the element and
+# recurse with empty SEP changed to PREP.  The check variant checks
+# whether the element has been previously removed.  Use _m4_defn and
+# _m4_popdef for speed.
+m4_define([_m4_set_dump],
+[m4_ifdef([_m4_set([$1])],
+         [[$2]_m4_defn([_m4_set([$1])])_m4_popdef([_m4_set([$1],]_m4_defn(
+               [_m4_set([$1])])[)], [_m4_set([$1])])$0([$1], [$2$3])])])
+
+m4_define([_m4_set_dump_check],
+[m4_ifdef([_m4_set([$1])],
+         [m4_set_contains([$1], _m4_defn([_m4_set([$1])]),
+                          [[$2]_m4_defn([_m4_set([$1])])])_m4_popdef(
+    [_m4_set([$1],]_m4_defn([_m4_set([$1])])[)],
+    [_m4_set([$1])])$0([$1], [$2$3])],
+         [_m4_popdef([_m4_set_cleanup($1)])])])
+
+# m4_set_empty(SET, [IF-EMPTY], [IF-ELEMENTS])
+# --------------------------------------------
+# Expand IF-EMPTY if SET has no elements, otherwise IF-ELEMENTS.
+m4_define([m4_set_empty],
+[m4_ifdef([_m4_set_size($1)],
+         [m4_if(m4_indir([_m4_set_size($1)]), [0], [$2], [$3])], [$2])])
+
+# m4_set_foreach(SET, VAR, ACTION)
+# --------------------------------
+# For each element of SET, define VAR to the element and expand
+# ACTION.  ACTION should not recursively list SET's contents, add
+# elements to SET, nor delete any element from SET except the one
+# currently in VAR.  The order that the elements are visited in is not
+# guaranteed.  This is faster than the corresponding m4_foreach([VAR],
+#   m4_indir([m4_dquote]m4_set_listc([SET])), [ACTION])
+m4_define([m4_set_foreach],
+[m4_pushdef([$2])m4_ifdef([_m4_set_cleanup($1)],
+    [_m4_set_contents_1c], [_m4_set_contents_1])([$1])_m4_set_contents_2([$1],
+       [m4_define([$2], _m4_defn([_m4_set_($1)]))$3[]])m4_popdef([$2])])
+
+# m4_set_intersection(SET1, SET2)
+# -------------------------------
+# Produce a LIST of quoted elements that occur in both SET1 or SET2.
+# Output a comma prior to any elements, to distinguish the empty
+# string from no elements.  This can be directly used as a series of
+# arguments, such as for m4_join, or wrapped inside quotes for use in
+# m4_foreach.  Order of the output is not guaranteed.
+#
+# Iterate over the smaller set, and short-circuit the idempotence
+# relation.  Use _m4_defn for speed.
+m4_define([m4_set_intersection],
+[m4_if([$1], [$2], [m4_set_listc([$1])],
+       m4_eval(m4_set_size([$2]) < m4_set_size([$1])), [1], [$0([$2], [$1])],
+       [m4_set_foreach([$1], [_m4_element],
+                      [m4_set_contains([$2], _m4_defn([_m4_element]),
+                                       [,_m4_defn([_m4_element])])])])])
+
+# m4_set_list(SET)
+# m4_set_listc(SET)
+# -----------------
+# Produce a LIST of quoted elements of SET.  This can be directly used
+# as a series of arguments, such as for m4_join or m4_set_add_all, or
+# wrapped inside quotes for use in m4_foreach or m4_map.  With
+# m4_set_list, there is no way to distinguish an empty set from a set
+# containing only the empty string; with m4_set_listc, a leading comma
+# is output if there are any elements.
+m4_define([m4_set_list],
+[m4_ifdef([_m4_set_cleanup($1)], [_m4_set_contents_1c],
+         [_m4_set_contents_1])([$1])_m4_set_contents_2([$1],
+              [_m4_defn([_m4_set_($1)])], [,])])
+
+m4_define([m4_set_listc],
+[m4_ifdef([_m4_set_cleanup($1)], [_m4_set_contents_1c],
+         [_m4_set_contents_1])([$1])_m4_set_contents_2([$1],
+              [,_m4_defn([_m4_set_($1)])])])
+
+# m4_set_remove(SET, VALUE, [IF-PRESENT], [IF-ABSENT])
+# ----------------------------------------------------
+# If VALUE is an element of SET, delete it and expand IF-PRESENT.
+# Otherwise expand IF-ABSENT.  Deleting a single value is O(1),
+# although it leaves memory occupied until the next O(n) traversal of
+# the set which will compact the set.
+#
+# Optimize if the element being removed is the most recently added,
+# since defining _m4_set_cleanup($1) slows down so many other macros.
+# In particular, this plays well with m4_set_foreach.
+m4_define([m4_set_remove],
+[m4_set_contains([$1], [$2], [_m4_set_size([$1],
+    [m4_decr])m4_if(_m4_defn([_m4_set([$1])]), [$2],
+                   [_m4_popdef([_m4_set([$1],$2)], [_m4_set([$1])])],
+                   [m4_define([_m4_set_cleanup($1)])m4_define(
+                     [_m4_set([$1],$2)], [0])])$3], [$4])])
+
+# m4_set_size(SET)
+# ----------------
+# Expand to the number of elements currently in SET.  This operation
+# is O(1), and thus more efficient than m4_count(m4_set_list([SET])).
+m4_define([m4_set_size],
+[m4_ifdef([_m4_set_size($1)], [m4_indir([_m4_set_size($1)])], [0])])
+
+# _m4_set_size(SET, ACTION)
+# -------------------------
+# ACTION must be either m4_incr or m4_decr, and the size of SET is
+# changed accordingly.  If the set is empty, ACTION must not be
+# m4_decr.
+m4_define([_m4_set_size],
+[m4_define([_m4_set_size($1)],
+          m4_ifdef([_m4_set_size($1)], [$2(m4_indir([_m4_set_size($1)]))],
+                   [1]))])
+
+# m4_set_union(SET1, SET2)
+# ------------------------
+# Produce a LIST of double quoted elements that occur in either SET1
+# or SET2, without duplicates.  Output a comma prior to any elements,
+# to distinguish the empty string from no elements.  This can be
+# directly used as a series of arguments, such as for m4_join, or
+# wrapped inside quotes for use in m4_foreach.  Order of the output is
+# not guaranteed.
+#
+# We can rely on the fact that m4_set_listc prunes SET1, so we don't
+# need to check _m4_set([$1],element) for 0.  Use _m4_defn for speed.
+# Short-circuit the idempotence relation.
+m4_define([m4_set_union],
+[m4_set_listc([$1])m4_if([$1], [$2], [], [m4_set_foreach([$2], [_m4_element],
+  [m4_ifdef([_m4_set([$1],]_m4_defn([_m4_element])[)], [],
+           [,_m4_defn([_m4_element])])])])])
+
 
 ## ------------------- ##
-## 15. File handling.  ##
+## 16. File handling.  ##
 ## ------------------- ##
 
 
@@ -1805,7 +2752,7 @@ m4_if(m4_sysval, [0], [],
 
 
 ## ------------------------ ##
-## 16. Setting M4sugar up.  ##
+## 17. Setting M4sugar up.  ##
 ## ------------------------ ##
 
 
@@ -1818,6 +2765,20 @@ m4_define([m4_init],
 m4_pattern_forbid([^_?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 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])