From: Eric Blake Date: Fri, 15 Aug 2008 16:59:32 +0000 (-0600) Subject: Partial m4sugar merge from autoconf: m4_map. X-Git-Tag: v2.4~26 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/6bbb2ed5efc60128f52a542f0b8fb8337aa694fe Partial m4sugar merge from autoconf: m4_map. * data/m4sugar/m4sugar.m4 (m4_fst): Delete. (m4_map, m4_map_sep, _m4_map): Rewrite more efficiently. (m4_apply, _m4_apply, m4_mapall, m4_mapall_sep): New macros. * data/java.m4 (b4_token_enums): Use more efficient short-circuit for empty list. * data/c.m4 (b4_token_defines, b4_token_enums, b4_c_ansi_formals): Likewise. (b4_parse_param_for): Avoid m4_fst, now that autoconf no longer declares it. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index dd85885f..ffdc2b7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-08-15 Eric Blake + + Partial m4sugar merge from autoconf: m4_map. + * data/m4sugar/m4sugar.m4 (m4_fst): Delete. + (m4_map, m4_map_sep, _m4_map): Rewrite more efficiently. + (m4_apply, _m4_apply, m4_mapall, m4_mapall_sep): New macros. + * data/java.m4 (b4_token_enums): Use more efficient short-circuit + for empty list. + * data/c.m4 (b4_token_defines, b4_token_enums, b4_c_ansi_formals): + Likewise. + (b4_parse_param_for): Avoid m4_fst, now that autoconf no longer + declares it. + 2008-08-07 Joel E. Denny Keep .version and PACKAGE_VERSION in sync. diff --git a/data/c.m4 b/data/c.m4 index ced2b1e2..5d74e866 100644 --- a/data/c.m4 +++ b/data/c.m4 @@ -90,7 +90,7 @@ b4_parse_param) # the formal name to FORMAL, and evaluating the BODY. m4_define([b4_parse_param_for], [m4_foreach([$1_$2], m4_defn([b4_parse_param]), -[m4_pushdef([$1], m4_fst($1_$2))dnl +[m4_pushdef([$1], m4_unquote(m4_car($1_$2)))dnl m4_pushdef([$2], m4_shift($1_$2))dnl $3[]dnl m4_popdef([$2])dnl @@ -160,7 +160,7 @@ m4_define([b4_token_define], # ------------------------------------------------------- # Output the definition of the tokens (if there are) as #defines. m4_define([b4_token_defines], -[m4_if([$@], [[]], [], +[m4_if([$#$1], [1], [], [/* Tokens. */ m4_map([b4_token_define], [$@])]) ]) @@ -177,7 +177,7 @@ m4_define([b4_token_enum], # ----------------------------------------------------- # Output the definition of the tokens (if there are) as enums. m4_define([b4_token_enums], -[m4_if([$@], [[]], [], +[m4_if([$#$1], [1], [], [/* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE @@ -248,9 +248,8 @@ $1 (b4_c_ansi_formals(m4_shift2($@)))[]dnl # -------------------------------------- # Output the arguments ANSI-C definition. m4_define([b4_c_ansi_formals], -[m4_case([$@], - [], [void], - [[]], [void], +[m4_if([$#], [0], [void], + [$#$1], [1], [void], [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])]) m4_define([b4_c_ansi_formal], diff --git a/data/java.m4 b/data/java.m4 index 13876941..9ee581a2 100644 --- a/data/java.m4 +++ b/data/java.m4 @@ -106,7 +106,7 @@ m4_define([b4_token_enum], # ----------------------------------------------------- # Output the definition of the tokens (if there are) as enums. m4_define([b4_token_enums], -[m4_if([$@], [[]], [], +[m4_if([$#$1], [1], [], [/* Tokens. */ m4_map([b4_token_enum], [$@])]) ]) diff --git a/data/m4sugar/m4sugar.m4 b/data/m4sugar/m4sugar.m4 index 97b38a4d..be390961 100644 --- a/data/m4sugar/m4sugar.m4 +++ b/data/m4sugar/m4sugar.m4 @@ -403,29 +403,6 @@ m4_define([m4_cdr], [m4_dquote(m4_shift($@))])]) -# m4_map(MACRO, LIST) -# ------------------- -# Invoke MACRO($1), MACRO($2) etc. where $1, $2... are the elements -# of LIST (which can be lists themselves, for multiple arguments MACROs). -m4_define([m4_fst], [$1]) -m4_define([m4_map], -[m4_if([$2], [[]], [], - [_m4_map([$1], [$2])])]) -m4_define([_m4_map], -[m4_ifval([$2], - [$1(m4_fst($2))[]_m4_map([$1], m4_cdr($2))])]) - - -# m4_map_sep(MACRO, SEPARATOR, LIST) -# ---------------------------------- -# Invoke MACRO($1), SEPARATOR, MACRO($2), ..., MACRO($N) where $1, $2... $N -# are the elements of LIST (which can be lists themselves, for multiple -# arguments MACROs). -m4_define([m4_map_sep], -[m4_if([$3], [[]], [], - [$1(m4_fst($3))[]_m4_map([$2[]$1], m4_cdr($3))])]) - - ## ---------------------------------------- ## ## 6. Enhanced version of some primitives. ## ## ---------------------------------------- ## @@ -647,6 +624,27 @@ m4_define([m4_wrap], m4_define([m4_wrap_lifo], [_m4_wrap([$1[]])]) +## ------------------------- ## +## 7. Quoting manipulation. ## +## ------------------------- ## + + +# m4_apply(MACRO, LIST) +# --------------------- +# Invoke MACRO, with arguments provided from the quoted list of +# comma-separated quoted arguments. If LIST is empty, invoke MACRO +# without arguments. The expansion will not be concatenated with +# subsequent text. +m4_define([m4_apply], +[m4_if([$2], [], [$1], [$1($2)])[]]) + +# _m4_apply(MACRO, LIST) +# ---------------------- +# Like m4_apply, except do nothing if LIST is empty. +m4_define([_m4_apply], +[m4_if([$2], [], [], [$1($2)[]])]) + + ## -------------------------- ## ## 8. Implementing m4 loops. ## ## -------------------------- ## @@ -801,6 +799,65 @@ m4_define([m4_foreach_w], [m4_foreach([$1], m4_split(m4_normalize([$2])), [$3])]) +# m4_map(MACRO, LIST) +# m4_mapall(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. +# If LIST contains an empty sublist, m4_map skips the expansion of +# MACRO, while m4_mapall expands MACRO with no arguments. +# +# 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. +m4_define([m4_map], +[_m4_map([_m4_apply([$1]], [], $2)]) + +m4_define([m4_mapall], +[m4_if([$2], [], [], + [_m4_map([m4_apply([$1]], [], $2)])]) + + +# m4_map_sep(MACRO, SEPARATOR, LIST) +# m4_mapall_sep(MACRO, SEPARATOR, LIST) +# ------------------------------------- +# Invoke MACRO($1), SEPARATOR, MACRO($2), ..., MACRO($N) where $1, +# $2... $N are the elements of LIST, and are in turn lists appropriate +# for m4_apply. SEPARATOR is expanded, in order to allow the creation +# of a list of arguments by using a single-quoted comma as the +# separator. For each empty sublist, m4_map_sep skips the expansion +# of MACRO and SEPARATOR, while m4_mapall_sep expands MACRO with no +# arguments. +# +# For m4_mapall_sep, merely expand the first iteration without the +# separator, then include separator as part of subsequent recursion. +# For m4_map_sep, things are trickier - we don't know if the first +# list element is an empty sublist, so we must define a self-modifying +# 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_define([m4_mapall_sep], +[m4_if([$3], [], [], + [m4_apply([$1], m4_car($3))_m4_map([m4_apply([$2[]$1]], $3)])]) + +# _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. +m4_define([_m4_map], +[m4_if([$#], [2], [], + [$1, [$3])$0([$1], m4_shift2($@))])]) + ## --------------------------- ## ## 9. More diversion support. ##