From: Eric Blake Date: Thu, 4 Oct 2007 15:43:59 +0000 (-0600) Subject: One more round of m4_foreach_w speedups. X-Git-Tag: v2.62~230 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=10fa310839dcdc56b1bfc4013bf279155df90122;p=thirdparty%2Fautoconf.git 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@&t@_split): Add tests. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index a2669a8b..5a37f4cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2007-10-04 Eric Blake + + 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@&t@_split): Add tests. + 2007-10-04 Paolo Bonzini Fix previous commit. diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index 5317617c..d9cf142a 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 5aff0c9d..81e7919e 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@&t@_split]) + +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. ## ## -------------- ##