[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Multi-Line Definitions
From: |
Eric Blake-1 |
Subject: |
Re: Multi-Line Definitions |
Date: |
Thu, 4 Oct 2007 09:03:49 -0700 (PDT) |
> Of the above list, the first line which doesn't represent multi-character
> replacement or true regex pattern searching is
> 98 p:y:{.}
> (from m4_text_box); the returns for fixing this, or any other
> low-frequency pattern, to avoid regexes is probably too small to be worth
> the effort. I don't see any more obvious speed improvements on the
> autoconf side of things
Looks like I lied. This shaves another second off of building
coreutils' configure on my machine, by dropping another 2000 regex
from this crowd:
> 1163 p:n:{\\
> 1163 p:y:{^. ?\(.*\) .$}
> 1164 }
> 2324 p:y:{[ ]+}
We were being rather redundant with the [\t ]+ regex - m4_foreach_w
was splitting strings on the very pattern that it had just stripped,
not to mention that once stripped, an m4_index becomes sufficient
to check for a one-element list. Also, `` and '' are both valid in
shell code (although the latter is more common), so m4sugar should
pick a slightly less-likely alternate quote (I chose the same string
as in m4_noquote).
Oh, and I decided to add a test case, since I nearly botched
m4_split([abcde], [[bd]]) on my first try.
Note that I did _not_ try to fix the case of the empty delimiter (ie.
splitting a string into its characters); both before and after my
patch the quote characters are mistakenly matched, violating any
promises of quote safety. A correct fix would require not overquoting
$1 to begin with, plus a second use of changequote to make the
third argument to patsubst contain inverted quotes (see my recent
m4 patch for an idea of what is needed:
http://lists.gnu.org/archive/html/m4-patches/2007-10/msg00000.html).
Fortunately, I'm not too worried about the likelihood of this use case:
m4_define([b], [oops])m4_split([abc], [\(\)])
=> [], [-], [=], [<], [{], [a], [oops], [c], [}], [>], [=], [-], []
2007-10-04 Eric Blake <address@hidden>
One more round of m4_foreach_w speedups.
* lib/m4sugar/m4sugar.m4 (m4_flatten): Only use regex if newline
is present.
(_m4_split): Avoid useless expansions inside definition. Move
argument defaulting...
(m4_split): ...here. Change alternate quote to something less
likely to appear in $1. Also, special case space as regexp...
(m4_foreach_w): ...to avoid regexp on single-term list.
(m4_default, m4_defn, m4_popdef, m4_undefine, _m4_foreach): Avoid
useless expansions inside definition.
* tests/m4sugar.at (m4@&address@hidden): Add tests.
From: Eric Blake <address@hidden>
Date: Thu, 4 Oct 2007 09:43:59 -0600
Subject: [PATCH] One more round of m4_foreach_w speedups.
* lib/m4sugar/m4sugar.m4 (m4_flatten): Only use regex if newline
is present.
(_m4_split): Avoid useless expansions inside definition. Move
argument defaulting...
(m4_split): ...here. Change alternate quote to something less
likely to appear in $1. Also, special case space as regexp...
(m4_foreach_w): ...to avoid regexp on single-term list.
(m4_default, m4_defn, m4_popdef, m4_undefine, _m4_foreach): Avoid
useless expansions inside definition.
* tests/m4sugar.at (m4@&address@hidden): Add tests.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 12 +++++++
lib/m4sugar/m4sugar.m4 | 84
++++++++++++++++++++++++++++++-----------------
tests/m4sugar.at | 42 ++++++++++++++++++++++++
3 files changed, 107 insertions(+), 31 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index b98cf3e..8afa5e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2007-10-04 Eric Blake <address@hidden>
+ One more round of m4_foreach_w speedups.
+ * lib/m4sugar/m4sugar.m4 (m4_flatten): Only use regex if newline
+ is present.
+ (_m4_split): Avoid useless expansions inside definition. Move
+ argument defaulting...
+ (m4_split): ...here. Change alternate quote to something less
+ likely to appear in $1. Also, special case space as regexp...
+ (m4_foreach_w): ...to avoid regexp on single-term list.
+ (m4_default, m4_defn, m4_popdef, m4_undefine, _m4_foreach): Avoid
+ useless expansions inside definition.
+ * tests/m4sugar.at (m4@&address@hidden): Add tests.
+
Speed up building testsuites.
* lib/autotest/general.m4 (AT_LINE): Only use regex when file
changed since last time. Use simpler regex.
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index 5317617..d9cf142 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -477,18 +477,24 @@ 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)
# -------------
# Like the original, except don't tolerate popping something which is
-# undefined.
+# undefined, and only support one argument.
+#
+# This macro is called frequently, so minimize the amount of additional
+# expansions by skipping m4_ifndef.
m4_define([m4_defn],
-[m4_ifndef([$1],
- [m4_fatal([$0: undefined macro: $1])])dnl
-m4_builtin([defn], $@)])
+[m4_ifdef([$1], [],
+ [m4_fatal([$0: undefined macro: $1])])]dnl
+[m4_builtin([defn], $@)])
# _m4_dumpdefs_up(NAME)
@@ -522,11 +528,14 @@ _m4_dumpdefs_down([$1])])
# m4_popdef(NAME)
# ---------------
# Like the original, except don't tolerate popping something which is
-# undefined.
+# undefined, and only support one argument.
+#
+# This macro is called frequently, so minimize the amount of additional
+# expansions by skipping m4_ifndef.
m4_define([m4_popdef],
-[m4_ifndef([$1],
- [m4_fatal([$0: undefined macro: $1])])dnl
-m4_builtin([popdef], $@)])
+[m4_ifdef([$1], [],
+ [m4_fatal([$0: undefined macro: $1])])]dnl
+[m4_builtin([popdef], $@)])
# m4_quote(ARGS)
@@ -579,11 +588,14 @@ m4_define([m4_shift3],
[m4_shift(m4_shift(m4_shift($@)))])
# m4_undefine(NAME)
# -----------------
# Like the original, except don't tolerate undefining something which is
-# undefined.
+# undefined, and only support one argument.
+#
+# This macro is called frequently, so minimize the amount of additional
+# expansions by skipping m4_ifndef.
m4_define([m4_undefine],
-[m4_ifndef([$1],
- [m4_fatal([$0: undefined macro: $1])])dnl
-m4_builtin([undefine], $@)])
+[m4_ifdef([$1], [],
+ [m4_fatal([$0: undefined macro: $1])])]dnl
+[m4_builtin([undefine], $@)])
## -------------------------- ##
@@ -724,13 +736,15 @@ m4_if(m4_defn([$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.
m4_define([m4_foreach],
-[m4_pushdef([$1])_m4_foreach($@)m4_popdef([$1])])
+[m4_pushdef([$1])_$0($@)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([$2], [], [],
+ [m4_define([$1], m4_car($2))$3[]$0([$1], m4_cdr($2), [$3])])])
# m4_foreach_w(VARIABLE, LIST, EXPRESSION)
@@ -745,7 +759,7 @@ _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])])
@@ -1488,28 +1502,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([, ])])
@@ -1523,10 +1541,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)
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index 5aff0c9..81e7919 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -40,7 +40,10 @@ AT_CHECK_M4SUGAR([-o-],, [$2], [$3])
# - m4_require
# uses warn/error code.
#
+# - m4_split
+#
# - m4_text_wrap
+# uses m4_split code.
## --------- ##
## m4_warn. ##
@@ -140,6 +143,45 @@ autom4te: m4 failed with exit status: 1
AT_CLEANUP
+## ---------- ##
+## m4_split. ##
+## ---------- ##
+
+AT_SETUP([m4@&address@hidden)
+
+AT_CHECK_M4SUGAR_TEXT(
+[[m4_define([active], [ACT, IVE])m4_define([bd], [oops])
+m4_split
+m4_split([[]])
+m4_split([ ])
+m4_split([active])
+m4_split([ active active ])end
+m4_split([ ], [ ])
+m4_split([active], [ ])
+m4_split([ active active ], [ ])end
+m4_split([abcde], [bd])
+m4_split([abcde], [[bd]])
+m4_split([foo=`` bar=''])
+m4_split([foo='' bar=``])
+]],
+[[
+
+[[]]
+[], []
+[active]
+[], [active], [active], []end
+[], []
+[active]
+[], [active active], []end
+[abcde]
+[a], [c], [e]
+[foo=``], [bar='']
+[foo=''], [bar=``]
+]])
+
+AT_CLEANUP
+
+
## -------------- ##
## m4_text_wrap. ##
## -------------- ##
--
1.5.3.2
--
View this message in context:
http://www.nabble.com/Re%3A-Multi-Line-Definitions-tf4476595.html#a13043219
Sent from the Gnu - Autoconf - Patches mailing list archive at Nabble.com.