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 <ebb9@byu.net>
This commit is contained in:
Eric Blake
2008-08-15 10:59:32 -06:00
parent 8dce3875bc
commit 6bbb2ed5ef
4 changed files with 99 additions and 30 deletions

View File

@@ -1,3 +1,16 @@
2008-08-15 Eric Blake <ebb9@byu.net>
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 <jdenny@ces.clemson.edu> 2008-08-07 Joel E. Denny <jdenny@ces.clemson.edu>
Keep .version and PACKAGE_VERSION in sync. Keep .version and PACKAGE_VERSION in sync.

View File

@@ -90,7 +90,7 @@ b4_parse_param)
# the formal name to FORMAL, and evaluating the BODY. # the formal name to FORMAL, and evaluating the BODY.
m4_define([b4_parse_param_for], m4_define([b4_parse_param_for],
[m4_foreach([$1_$2], m4_defn([b4_parse_param]), [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 m4_pushdef([$2], m4_shift($1_$2))dnl
$3[]dnl $3[]dnl
m4_popdef([$2])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. # Output the definition of the tokens (if there are) as #defines.
m4_define([b4_token_defines], m4_define([b4_token_defines],
[m4_if([$@], [[]], [], [m4_if([$#$1], [1], [],
[/* Tokens. */ [/* Tokens. */
m4_map([b4_token_define], [$@])]) 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. # Output the definition of the tokens (if there are) as enums.
m4_define([b4_token_enums], m4_define([b4_token_enums],
[m4_if([$@], [[]], [], [m4_if([$#$1], [1], [],
[/* Tokens. */ [/* Tokens. */
#ifndef YYTOKENTYPE #ifndef YYTOKENTYPE
# define YYTOKENTYPE # define YYTOKENTYPE
@@ -248,9 +248,8 @@ $1 (b4_c_ansi_formals(m4_shift2($@)))[]dnl
# -------------------------------------- # --------------------------------------
# Output the arguments ANSI-C definition. # Output the arguments ANSI-C definition.
m4_define([b4_c_ansi_formals], m4_define([b4_c_ansi_formals],
[m4_case([$@], [m4_if([$#], [0], [void],
[], [void], [$#$1], [1], [void],
[[]], [void],
[m4_map_sep([b4_c_ansi_formal], [, ], [$@])])]) [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])])
m4_define([b4_c_ansi_formal], m4_define([b4_c_ansi_formal],

View File

@@ -106,7 +106,7 @@ m4_define([b4_token_enum],
# ----------------------------------------------------- # -----------------------------------------------------
# Output the definition of the tokens (if there are) as enums. # Output the definition of the tokens (if there are) as enums.
m4_define([b4_token_enums], m4_define([b4_token_enums],
[m4_if([$@], [[]], [], [m4_if([$#$1], [1], [],
[/* Tokens. */ [/* Tokens. */
m4_map([b4_token_enum], [$@])]) m4_map([b4_token_enum], [$@])])
]) ])

View File

@@ -403,29 +403,6 @@ m4_define([m4_cdr],
[m4_dquote(m4_shift($@))])]) [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. ## ## 6. Enhanced version of some primitives. ##
## ---------------------------------------- ## ## ---------------------------------------- ##
@@ -647,6 +624,27 @@ m4_define([m4_wrap],
m4_define([m4_wrap_lifo], m4_define([m4_wrap_lifo],
[_m4_wrap([$1[]])]) [_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. ## ## 8. Implementing m4 loops. ##
## -------------------------- ## ## -------------------------- ##
@@ -801,6 +799,65 @@ m4_define([m4_foreach_w],
[m4_foreach([$1], m4_split(m4_normalize([$2])), [$3])]) [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. ## ## 9. More diversion support. ##