]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Add m4_reverse, and improve m4_list_cmp.
authorEric Blake <ebb9@byu.net>
Tue, 29 Jul 2008 13:12:26 +0000 (07:12 -0600)
committerEric Blake <ebb9@byu.net>
Tue, 29 Jul 2008 13:12:26 +0000 (07:12 -0600)
* lib/m4sugar/m4sugar.m4 (m4_reverse): New macro.
(m4_list_cmp): Rewrite to give linear behavior with M4 1.6 on an
m4_reverse'd list.
* lib/m4sugar/foreach.m4 (m4_reverse): Add the M4 1.4.x
counterpart.
* tests/m4sugar.at (recursion): Test it.
* doc/autoconf.texi (Evaluation Macros) <m4_reverse>: Document
it.
(Text processing Macros) <m4_append>: Cross-reference to m4_set.
* NEWS: Mention new macro.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
NEWS
doc/autoconf.texi
lib/m4sugar/foreach.m4
lib/m4sugar/m4sugar.m4
tests/m4sugar.at

index 1a58651b41e0baf5599ca12a1fcff77164851b15..7019f3717cb5f573fbf365b05f6b5f0c4469dc8c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-07-29  Eric Blake  <ebb9@byu.net>
+
+       Add m4_reverse, and improve m4_list_cmp.
+       * lib/m4sugar/m4sugar.m4 (m4_reverse): New macro.
+       (m4_list_cmp): Rewrite to give linear behavior with M4 1.6 on an
+       m4_reverse'd list.
+       * lib/m4sugar/foreach.m4 (m4_reverse): Add the M4 1.4.x
+       counterpart.
+       * tests/m4sugar.at (recursion): Test it.
+       * doc/autoconf.texi (Evaluation Macros) <m4_reverse>: Document
+       it.
+       (Text processing Macros) <m4_append>: Cross-reference to m4_set.
+       * NEWS: Mention new macro.
+
 2008-07-28  Eric Blake  <ebb9@byu.net>
 
        Avoid _m4_shiftn for m4 1.6 speedup.
diff --git a/NEWS b/NEWS
index e7d1d1c0e9f2babac47544acb07ae6fcaf1f8674..9737c34894411bca5ae76c4c17c5e9f017d57ef7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -20,7 +20,7 @@ GNU Autoconf NEWS - User visible changes.
    allowing the output of unbalanced parantheses in more contexts.
 
 ** The following m4sugar macros are new:
-   m4_joinall  m4_set_add  m4_set_add_all  m4_set_contains
+   m4_joinall  m4_reverse  m4_set_add  m4_set_add_all  m4_set_contains
    m4_set_contents  m4_set_delete  m4_set_difference  m4_set_dump
    m4_set_empty  m4_set_foreach  m4_set_intersection  m4_set_list
    m4_set_listc  m4_set_remove  m4_set_size  m4_set_union
index 6ac8449d690bef8c3d8a2dd292b4d238d7e00f49..b3b416c88a3534b2ea0b9ab14a874111d47416bf 100644 (file)
@@ -10997,6 +10997,19 @@ quotes.  This effectively collapses multiple arguments into one,
 although it loses whitespace after unquoted commas in the process.
 @end defmac
 
+@defmac m4_reverse (@var{arg}, @dots{})
+@msindex{reverse}
+Outputs each argument with the same level of quoting, but in reverse
+order, and with space following each comma for readability.
+
+@example
+m4_define([active], [ACT,IVE])
+@result{}
+m4_reverse(active, [active])
+@result{}active, IVE, ACT
+@end example
+@end defmac
+
 @defmac m4_unquote (@var{arg}, @dots{})
 @msindex{unquote}
 This macro was introduced in Autoconf 2.62.  Expand each argument,
@@ -11082,7 +11095,8 @@ Note that @code{m4_append} can scale linearly in the length of the final
 string, depending on the quality of the underlying M4 implementation,
 while @code{m4_append_uniq} has an inherent quadratic scaling factor.
 If an algorithm can tolerate duplicates in the final string, use the
-former for speed.
+former for speed.  If duplicates must be avoided, consider using
+@code{m4_set_add} instead (@pxref{Set manipulation Macros}).
 
 @example
 m4_define([active], [ACTIVE])dnl
index 0b1d05c68bafc7eb10abc1b6d311ec647fd5b785..7cc435808ad3b93d38302b3c6e86a79f14e777e0 100644 (file)
@@ -154,6 +154,19 @@ m4_define([m4_do],
 m4_define([m4_dquote_elt],
 [m4_shift(m4_foreach([_m4_elt], [$@], [,m4_dquote(_m4_defn([_m4_elt]))]))])
 
+# m4_reverse(ARGS)
+# ----------------
+# Output ARGS in reverse order.
+#
+# Invoke _m4_r($@) with the temporary _m4_r built as
+#   [$m], [$m-1], ..., [$2], [$1]_m4_popdef([_m4_r])
+m4_define([m4_reverse],
+[m4_if([$#], [0], [], [$#], [1], [[$1]],
+[m4_define([_m4_r], m4_dquote([$$#])m4_pushdef([_m4_r],
+    m4_decr([$#]))_m4_for([_m4_r], [1], [-1],
+    [[, ]m4_dquote([$]_m4_r)])[_m4_popdef([_m4_r])])_m4_r($@)])])
+
+
 # m4_map(MACRO, LIST)
 # -------------------
 # Invoke MACRO($1), MACRO($2) etc. where $1, $2... are the elements
index 293e38eebf42c7b8e1b4634178294a5087016a7c..54439ce152b6e730d5a8ad4faca629fb4903917a 100644 (file)
@@ -802,6 +802,14 @@ m4_define([_m4_quote],
 [m4_if([$#], [0], [], [[$*]])])
 
 
+# m4_reverse(ARGS)
+# ----------------
+# Output ARGS in reverse order.
+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
@@ -2151,15 +2159,21 @@ m4_define([m4_cmp],
 # 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.
+# 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.
 m4_define([m4_list_cmp],
-[m4_if([$1$2], [], 0,
-       [$1], [], [$0(0, [$2])],
-       [$2], [], [$0([$1], 0)],
-       [$1], [$2], 0,
-       [_$0(m4_cmp(m4_car($1), m4_car($2)))([$0(m4_cdr($1), m4_cdr($2))])])])
+[m4_if([$1], [$2], [0], [_m4_list_cmp_1([$1], $2)])])
+
 m4_define([_m4_list_cmp],
-[m4_if([$1], 0, [m4_unquote], [$1m4_ignore])])
+[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, ...)
index d82675eb446207312ac26cd4780f72dcd3e06bc8..c69e37e64fedc56d61560bffacfdcf9ee7dc19d5 100644 (file)
@@ -757,7 +757,8 @@ AT_CLEANUP
 AT_SETUP([recursion])
 
 AT_KEYWORDS([m4@&t@_foreach m4@&t@_foreach_w m4@&t@_shiftn m4@&t@_dquote_elt
-m4@&t@_join m4@&t@_joinall m4@&t@_list_cmp m4@&t@_max m4@&t@_min])
+m4@&t@_join m4@&t@_joinall m4@&t@_list_cmp m4@&t@_max m4@&t@_min
+m4@&t@_reverse])
 
 dnl This test completes in a reasonable time if m4_foreach is linear,
 dnl but thrashes if it is quadratic.  If we are testing with m4 1.4.x,
@@ -776,7 +777,7 @@ m4_max(m4_min([1]m4_for([i], [2], [10000], [],
   [,i]))m4_for([i], [2], [10000], [], [,i]))
 m4_case([10000]m4_for([i], [1], [10000], [], [,i]),[end])
 m4_list_cmp(m4_dquote(1m4_for([i], [2], [10000], [], [,i])),
-            m4_dquote(1m4_for([i], [2], [10000], [], [,i]), [0]))
+  m4_dquote(m4_reverse(10000m4_for([i], [9999], [1], [], [,i])), [0]))
 m4_for([i], [1], [10000], [], [m4_define(i)])dnl
 m4_undefine(1m4_for([i], [2], [10000], [], [,i]))dnl
 m4_divert_pop(0)
@@ -813,7 +814,7 @@ m4_max(m4_min([1]m4_for([i], [2], [10000], [],
   [,i]))m4_for([i], [2], [10000], [], [,i]))
 m4_case([10000]m4_for([i], [1], [10000], [], [,i]),[end])
 m4_list_cmp(m4_dquote(1m4_for([i], [2], [10000], [], [,i])),
-            m4_dquote(1m4_for([i], [2], [10000], [], [,i]), [0]))
+  m4_dquote(m4_reverse(10000m4_for([i], [9999], [1], [], [,i])), [0]))
 m4_for([i], [1], [10000], [], [m4_define(i)])dnl
 m4_undefine(1m4_for([i], [2], [10000], [], [,i]))dnl
 m4_divert_pop(0)