autoconf-patches
[Top][All Lists]
Advanced

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

faster m4_divert*,m4_cond


From: Eric Blake
Subject: faster m4_divert*,m4_cond
Date: Wed, 6 Aug 2008 15:55:46 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

More m4sugar tweaks.  Autoconf relies heavily on diversions (think AC_REQUIRE), 
so we might as well avoid dnl inside those macros.  I didn't see much speedup 
on configure files, but it doesn't hurt.

Then, I finally figured out how to make m4_cond linear for m4 1.4.x, as well as 
making it use fewer macro expansions for m4 1.6.

>From f13b34330d230e35ae00129d6285f008c7927bc0 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 30 Jul 2008 14:45:42 -0600
Subject: [PATCH] Speed up diversion handling.

* lib/m4sugar/m4sugar.m4 (m4_divert, m4_divert_push)
(m4_divert_pop, m4_divert_text): Avoid dnl for fewer macro
expansions.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog              |    5 +++++
 lib/m4sugar/m4sugar.m4 |   38 ++++++++++++++++----------------------
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ed7a915..a00502b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2008-08-06  Eric Blake  <address@hidden>
 
+       Speed up diversion handling.
+       * lib/m4sugar/m4sugar.m4 (m4_divert, m4_divert_push)
+       (m4_divert_pop, m4_divert_text): Avoid dnl for fewer macro
+       expansions.
+
        AC_C_CHAR_UNSIGNED is not strictly necessary.
        * doc/autoconf.texi (C Compiler) <AC_C_CHAR_UNSIGNED>: Mention a
        portable alternative to this macro.
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index d864f18..e3677e7 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -1055,19 +1055,17 @@ _m4_defn([m4_divert_stack])])])
 # -------------------------
 # 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])
@@ -1077,17 +1075,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)
@@ -1095,10 +1091,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)
-- 
1.5.6.4


>From 5581ef456970a8749f1ee5a7415b94e2d8502d1b Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 30 Jul 2008 16:44:03 -0600
Subject: [PATCH] Add linear m4_cond for m4 1.4.x.

* lib/m4sugar/m4sugar.m4 (m4_cond): Split into...
(_m4_cond): ...this, for fewer macros per iteration.
* lib/m4sugar/foreach.m4 (_m4_cond): New implementation.
* tests/m4sugar.at (recursion): Test it.
* NEWS: Document the linear guarantee.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog              |    7 +++++++
 NEWS                   |    4 ++--
 lib/m4sugar/foreach.m4 |   24 +++++++++++++++++++++++-
 lib/m4sugar/m4sugar.m4 |   10 ++++++++--
 tests/m4sugar.at       |   13 ++++++++++---
 5 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a00502b..60b3ee5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2008-08-06  Eric Blake  <address@hidden>
 
+       Add linear m4_cond for m4 1.4.x.
+       * lib/m4sugar/m4sugar.m4 (m4_cond): Split into...
+       (_m4_cond): ...this, for fewer macros per iteration.
+       * lib/m4sugar/foreach.m4 (_m4_cond): New implementation.
+       * tests/m4sugar.at (recursion): Test it.
+       * NEWS: Document the linear guarantee.
+
        Speed up diversion handling.
        * lib/m4sugar/m4sugar.m4 (m4_divert, m4_divert_push)
        (m4_divert_pop, m4_divert_text): Avoid dnl for fewer macro
diff --git a/NEWS b/NEWS
index 30f0f4e..efd7f46 100644
--- a/NEWS
+++ b/NEWS
@@ -33,8 +33,8 @@ GNU Autoconf NEWS - User visible changes.
    previously had linear scaling with m4 1.6 but quadratic scaling
    when using m4 1.4.x.  All macros built on top of these also gain
    the scaling improvements.
-   m4_bpatsubsts  m4_case  m4_do  m4_dquote_elt  m4_foreach  m4_join
-   m4_list_cmp  m4_map  m4_map_sep  m4_max  m4_min  m4_shiftn
+   m4_bpatsubsts  m4_case  m4_cond  m4_do  m4_dquote_elt  m4_foreach
+   m4_join  m4_list_cmp  m4_map  m4_map_sep  m4_max  m4_min  m4_shiftn
 
 ** AT_KEYWORDS once again performs expansion on its argument, such that
    AT_KEYWORDS([m4_if([$1], [], [default])]) no longer complains about
diff --git a/lib/m4sugar/foreach.m4 b/lib/m4sugar/foreach.m4
index 3109a8f..78779c4 100644
--- a/lib/m4sugar/foreach.m4
+++ b/lib/m4sugar/foreach.m4
@@ -121,6 +121,29 @@ m4_define([m4_case],
 m4_define([_m4_case_],
 [[[$$1],[$$2],[$$3],]])
 
+# 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.
+#
+# m4_cond already guarantees either 3*n or 3*n + 1 arguments, 1 <= n.
+# We only have to speed up _m4_cond, by building the temporary _m4_c:
+#   m4_define([_m4_c], _m4_defn([m4_unquote]))_m4_c([m4_if(($1), [($2)],
+#   [$3[]m4_define([_m4_c])])])_m4_c([m4_if(($4), [($5)],
+#   [$6[]m4_define([_m4_c])])])..._m4_c([m4_if(($m-2), [($m-1)],
+#   [$m[]m4_define([_m4_c])])])_m4_c([$m+1]_m4_popdef([_m4_c]))
+m4_define([_m4_cond],
+[m4_define([_m4_c], m4_pushdef([_m4_c])[m4_define([_m4_c],
+  _m4_defn([m4_unquote]))]_m4_for([_m4_c], [2], m4_eval([$# / 3 * 3 - 1]), [3],
+  [$0_(m4_decr(_m4_c), _m4_c, m4_incr(_m4_c))])[_m4_c(]m4_dquote(
+  [$]m4_eval([$# / 3 * 3 + 1]))[_m4_popdef([_m4_c]))])_m4_c($@)])
+
+m4_define([_m4_cond_],
+[[_m4_c([m4_if(($$1), [($$2)], [$$3[]m4_define([_m4_c])])])]])
+
 # m4_bpatsubsts(STRING, RE1, SUBST1, RE2, SUBST2, ...)
 # ----------------------------------------------------
 # m4 equivalent of
@@ -147,7 +170,6 @@ m4_define([_m4_bpatsubsts_],
 [[m4_define([_m4_p],
 m4_bpatsubst(m4_dquote(_m4_defn([_m4_p])), [$$1], [$$2]))]])
 
-
 # m4_shiftn(N, ...)
 # -----------------
 # Returns ... shifted N times.  Useful for recursive "varargs" constructs.
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index e3677e7..8a0da4f 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -449,8 +449,14 @@ m4_define([_m4_cdr],
 m4_define([m4_cond],
 [m4_if([$#], [0], [m4_fatal([$0: cannot be called without arguments])],
        [$#], [1], [$1],
-       [$#], [2], [m4_fatal([$0: missing an argument])],
-       [m4_if($1, [$2], [$3], [$0(m4_shift3($@))])])])
+       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($@))])])
 
 
 ## ---------------------------------------- ##
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index 516881e..60910de 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -816,9 +816,9 @@ AT_CLEANUP
 
 AT_SETUP([recursion])
 
-AT_KEYWORDS([m4@&address@hidden m4@&address@hidden m4@&address@hidden 
m4@&address@hidden
-m4@&address@hidden m4@&address@hidden m4@&address@hidden m4@&address@hidden 
m4@&address@hidden
-m4@&address@hidden m4@&address@hidden m4@&address@hidden m4@&address@hidden 
m4@&address@hidden)
+AT_KEYWORDS([m4@&address@hidden m4@&address@hidden m4@&address@hidden 
m4@&address@hidden
+m4@&address@hidden m4@&address@hidden m4@&address@hidden m4@&address@hidden 
m4@&address@hidden
+m4@&address@hidden m4@&address@hidden m4@&address@hidden m4@&address@hidden 
m4@&address@hidden m4@&address@hidden)
 
 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,
@@ -843,6 +843,8 @@ m4_list_cmp([0m4_for([i], [1], [10000], [], [,0])], [0])
 m4_for([i], [1], [10000], [], [m4_define(i)])dnl
 m4_undefine(1m4_for([i], [2], [10000], [], [,i]))dnl
 m4_bpatsubsts([a1]m4_for([i], [1], [10000], [], [,i]), [a2], [A])
+m4_define([up], [m4_define([$1], m4_incr($1))$1])m4_define([j], 0)dnl
+m4_cond(m4_for([i], [1], [10000], [], [[up([j])], [9990], i,]) [oops]) j
 m4_divert_pop(0)
 ]])
 
@@ -856,6 +858,7 @@ end
 0
 0
 A
+9990 9990
 ]])
 
 AT_DATA_M4SUGAR([script.4s],
@@ -871,6 +874,7 @@ end
 0
 0
 A
+9990 9990
 m4_exit([0])])
 m4_init
 m4_divert_push(0)[]dnl
@@ -889,6 +893,8 @@ m4_list_cmp([0m4_for([i], [1], [10000], [], [,0])], [0])
 m4_for([i], [1], [10000], [], [m4_define(i)])dnl
 m4_undefine(1m4_for([i], [2], [10000], [], [,i]))dnl
 m4_bpatsubsts([a1]m4_for([i], [1], [10000], [], [,i]), [a2], [A])
+m4_define([up], [m4_define([$1], m4_incr($1))$1])m4_define([j], 0)dnl
+m4_cond(m4_for([i], [1], [10000], [], [[up([j])], [9990], i,]) [oops])
 m4_divert_pop(0)
 ]])
 
@@ -902,6 +908,7 @@ end
 0
 0
 A
+9990 9990
 ]])
 
 AT_CLEANUP
-- 
1.5.6.4







reply via email to

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