From: Eric Blake Date: Tue, 4 Nov 2008 00:17:38 +0000 (-0700) Subject: Add m4_map_args_sep, undocumented for now. X-Git-Tag: v2.63b~139 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1329287eb793d45ae2375414c0ec2fc17b10871d;p=thirdparty%2Fautoconf.git Add m4_map_args_sep, undocumented for now. * lib/m4sugar/m4sugar.m4 (m4_map_args_sep): New macro. (_m4_map): Change API to cover more of m4_map*. * lib/m4sugar/foreach.m4 (_m4_map): Adjust to new API. (m4_map_args): Delete. * tests/m4sugar.at (m4@&t@_map_args and m4@&t@_curry): Enhance test. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 2cbc291a5..c8597fd7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2008-11-04 Eric Blake + Add m4_map_args_sep, undocumented for now. + * lib/m4sugar/m4sugar.m4 (m4_map_args_sep): New macro. + (_m4_map): Change API to cover more of m4_map*. + * lib/m4sugar/foreach.m4 (_m4_map): Adjust to new API. + (m4_map_args): Delete. + * tests/m4sugar.at (m4@&t@_map_args and m4@&t@_curry): Enhance + test. + Improve m4_for performance. * lib/m4sugar/m4sugar.m4 (_m4_for): Alter API to make it easier to avoid m4_define by some clients. diff --git a/lib/m4sugar/foreach.m4 b/lib/m4sugar/foreach.m4 index cb0821283..29c1a2813 100644 --- a/lib/m4sugar/foreach.m4 +++ b/lib/m4sugar/foreach.m4 @@ -264,38 +264,22 @@ m4_define([m4_reverse], [[, ]m4_dquote($], [)])[_m4_popdef([_m4_r])])_m4_r($@)])]) -# m4_map(MACRO, LIST) -# ------------------- -# Invoke MACRO($1), MACRO($2) etc. where $1, $2... are the elements -# of LIST. $1, $2... must in turn be lists, appropriate for m4_apply. +# _m4_map(PRE, POST, IGNORED, LIST) +# --------------------------------- +# Form the common basis of the m4_map macros. For each element of +# LIST, expand PRE[element]POST[]. The IGNORED argument makes +# recursion easier, and must be supplied rather than implicit. # -# m4_map/m4_map_sep only execute once; the speedup comes in fixing -# _m4_map. The mismatch in () is intentional, since $1 supplies the -# opening `(' (but it sure looks odd!). Build the temporary _m4_m: -# $1, [$3])$1, [$4])...$1, [$m])_m4_popdef([_m4_m]) +# m4_map{,all,_args}{,_sep} each only execute once; the speedup comes +# in fixing _m4_map. Build the temporary _m4_m: +# $1[$4]$2[]$1[$5]$2[]...$1[$m]$2[]_m4_popdef([_m4_m]) m4_define([_m4_map], -[m4_if([$#], [2], [], - [m4_pushdef([_m4_m], _m4_for([3], [$#], [1], - [$0_([1],], [)])[_m4_popdef([_m4_m])])_m4_m($@)])]) +[m4_if([$#], [3], [], + [m4_pushdef([_m4_m], _m4_for([4], [$#], [1], + [$0_([1], [2],], [)])[_m4_popdef([_m4_m])])_m4_m($@)])]) m4_define([_m4_map_], -[[$$1, [$$2])]]) - -# m4_map_args(EXPRESSION, ARG...) -# ------------------------------- -# Expand EXPRESSION([ARG]) for each argument. More efficient than -# m4_foreach([var], [ARG...], [EXPRESSION(m4_defn([var]))]) -# -# Invoke the temporary macro _m4_map_args, defined as: -# $1([$2])[]$1([$3])[]...$1([$m])[]_m4_popdef([_m4_map_args]) -m4_define([m4_map_args], -[m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])], - [$#], [1], [], - [m4_pushdef([_$0], _m4_for([2], [$#], [1], - [_$0_([1],], [)])[_m4_popdef([_$0])])_$0($@)])]) - -m4_define([_m4_map_args_], -[[$$1([$$2])[]]]) +[[$$1[$$3]$$2[]]]) # m4_map_args_pair(EXPRESSION, [END-EXPR = EXPRESSION], ARG...) # ------------------------------------------------------------- diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index f8661126b..ded4edcba 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -1079,6 +1079,17 @@ m4_define([m4_foreach_w], [m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])]) +# _m4_map(PRE, POST, IGNORED, LIST) +# --------------------------------- +# Form the common basis of the m4_map macros. For each element of +# LIST, expand PRE[element]POST[]. The IGNORED argument makes +# recursion easier, and must be supplied rather than implicit. +# +# Please keep foreach.m4 in sync with any adjustments made here. +m4_define([_m4_map], +[m4_if([$#], [3], [], + [$1[$4]$2[]$0([$1], [$2], m4_shift3($@))])]) + # m4_map(MACRO, LIST) # m4_mapall(MACRO, LIST) # ---------------------- @@ -1089,19 +1100,15 @@ m4_define([m4_foreach_w], # # Since LIST may be quite large, we want to minimize how often it # appears in the expansion. Rather than use m4_car/m4_cdr iteration, -# we unbox the list, ignore the second argument, and use m4_shift2 to -# detect the end of recursion. The mismatch in () is intentional; see -# _m4_map. For m4_map, an empty list behaves like an empty sublist -# and gets ignored; for m4_mapall, we must special-case the empty -# list. -# -# Please keep foreach.m4 in sync with any adjustments made here. +# we unbox the list, and use _m4_map for iteration. For m4_map, an +# empty list behaves like an empty sublist and gets ignored; for +# m4_mapall, we must special-case the empty list. m4_define([m4_map], -[_m4_map([_m4_apply([$1]], [], $2)]) +[_m4_map([_m4_apply([$1],], [)], [], $2)]) m4_define([m4_mapall], [m4_if([$2], [], [], - [_m4_map([m4_apply([$1]], [], $2)])]) + [_m4_map([m4_apply([$1],], [)], [], $2)])]) # m4_map_sep(MACRO, SEPARATOR, LIST) @@ -1123,39 +1130,24 @@ m4_define([m4_mapall], # helper macro and use that as the separator instead. m4_define([m4_map_sep], [m4_pushdef([m4_Sep], [m4_define([m4_Sep], _m4_defn([m4_unquote]))])]dnl -[_m4_map([_m4_apply([m4_Sep([$2])[]$1]], [], $3)m4_popdef([m4_Sep])]) +[_m4_map([_m4_apply([m4_Sep([$2])[]$1],], [)], [], $3)m4_popdef([m4_Sep])]) m4_define([m4_mapall_sep], [m4_if([$3], [], [], [_$0([$1], [$2], $3)])]) m4_define([_m4_mapall_sep], -[m4_apply([$1], [$3])_m4_map([m4_apply([$2[]$1]], m4_shift2($@))]) - -# _m4_map(PREFIX, IGNORED, SUBLIST, ...) -# -------------------------------------- -# Common implementation for all four m4_map variants. The mismatch in -# the number of () is intentional. PREFIX must supply a form of -# m4_apply, the open `(', and the MACRO to be applied. Each iteration -# then appends `,', the current SUBLIST and the closing `)', then -# recurses to the next SUBLIST. IGNORED is an aid to ending recursion -# efficiently. -# -# Please keep foreach.m4 in sync with any adjustments made here. -m4_define([_m4_map], -[m4_if([$#], [2], [], - [$1, [$3])$0([$1], m4_shift2($@))])]) +[m4_apply([$1], [$3])_m4_map([m4_apply([$2[]$1],], [)], m4_shift2($@))]) # m4_map_args(EXPRESSION, ARG...) # ------------------------------- # Expand EXPRESSION([ARG]) for each argument. More efficient than -# m4_foreach([var], [ARG...], [EXPRESSION(m4_defn([var]))]) -# -# Please keep foreach.m4 in sync with any adjustments made here. +# m4_foreach([var], [ARG...], [EXPRESSION(m4_defn([var]))]) +# Shorthand for m4_map_args_sep([EXPRESSION(], [)], [], ARG...). m4_define([m4_map_args], [m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])], [$#], [1], [], [$#], [2], [$1([$2])[]], - [$1([$2])[]$0([$1], m4_shift2($@))])]) + [_m4_map([$1(], [)], $@)])]) # m4_map_args_pair(EXPRESSION, [END-EXPR = EXPRESSION], ARG...) @@ -1181,6 +1173,18 @@ m4_define([m4_map_args_pair], [$1([$3], [$4])[]$0([$1], [$2], m4_shift(m4_shift3($@)))])]) +# m4_map_args_sep(PRE, POST, SEP, ARG...) +# --------------------------------------- +# Expand PRE[ARG]POST for each argument, with SEP between arguments. +m4_define([m4_map_args_sep], +[m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])], + [$#], [1], [], + [$#], [2], [], + [$#], [3], [], + [$#], [4], [$1[$4]$2[]], + [$1[$4]$2[]_m4_map([$3[]$1], [$2], m4_shift3($@))])]) + + # m4_stack_foreach(MACRO, FUNC) # m4_stack_foreach_lifo(MACRO, FUNC) # ---------------------------------- diff --git a/tests/m4sugar.at b/tests/m4sugar.at index 70bb24b3a..c8b22eb68 100644 --- a/tests/m4sugar.at +++ b/tests/m4sugar.at @@ -1091,12 +1091,13 @@ hi AT_CLEANUP -## ---------------------------------- ## -## m4_map_args{,_pair} and m4_curry. ## -## ---------------------------------- ## +## --------------------------------------- ## +## m4_map_args{,_sep,_pair} and m4_curry. ## +## --------------------------------------- ## AT_SETUP([m4@&t@_map_args and m4@&t@_curry]) -AT_KEYWORDS([m4@&t@_map_args_pair m4@&t@_reverse]) +AT_KEYWORDS([m4@&t@_map_args_sep m4@&t@_map_args_pair m4@&t@_reverse +m4@&t@_map]) dnl First, make sure we can curry in isolation. AT_CHECK_M4SUGAR_TEXT( @@ -1125,6 +1126,8 @@ m4_map_args_pair([, m4_reverse], [, m4_dquote], [1]) m4_map_args_pair([, m4_reverse], [, m4_dquote], [1], [2]) m4_map_args_pair([, m4_reverse], [, m4_dquote], [1], [2], [3]) m4_map_args_pair([, m4_reverse], [, m4_dquote], [1], [2], [3], [4]) +m4_map_args_sep([<], [>], [:], [1], [2], [3]) +m4_map_args_sep([m4_echo(], [)], [ ], [plain], [active]) ]], [[ plain active @@ -1138,6 +1141,8 @@ plainACTIVE , 2, 1 , 2, 1, [3] , 2, 1, 4, 3 +<1>:<2>:<3> +plain active ]]) dnl Finally, put the two concepts together, to show the real power of the API.