autoconf-patches
[Top][All Lists]
Advanced

[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.





reply via email to

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