[Top][All Lists]
[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
- faster m4_divert*,m4_cond,
Eric Blake <=