mirror of
git://git.sv.gnu.org/autoconf
synced 2025-02-17 14:01:27 +08:00
A few more m4sugar improvements, to benefit libtool.
* lib/m4sugar/m4sugar.m4 (m4_bpatsubsts, _m4_shiftn): Reduce size of expansion by avoiding extra uses of $@. (m4_shiftn): Avoid extra dnl, and forbid shifting by 0. (_m4_cdr): New helper macro. (_m4_map, m4_map_sep): Use it to reduce size of expansion. (_m4_shift3): New helper macro. (_m4_foreach): Swap argument order, and use new macro to reduce size of expansion. * doc/autoconf.texi (Looping constructs) <m4_shiftn>: Mention that count must be positive. Signed-off-by: Eric Blake <ebb9@byu.net>
This commit is contained in:
parent
d5f5cd5bf3
commit
f3b4cc104e
12
ChangeLog
12
ChangeLog
@ -1,5 +1,17 @@
|
||||
2007-10-16 Eric Blake <ebb9@byu.net>
|
||||
|
||||
A few more m4sugar improvements, to benefit libtool.
|
||||
* lib/m4sugar/m4sugar.m4 (m4_bpatsubsts, _m4_shiftn): Reduce size
|
||||
of expansion by avoiding extra uses of $@.
|
||||
(m4_shiftn): Avoid extra dnl, and forbid shifting by 0.
|
||||
(_m4_cdr): New helper macro.
|
||||
(_m4_map, m4_map_sep): Use it to reduce size of expansion.
|
||||
(_m4_shift3): New helper macro.
|
||||
(_m4_foreach): Swap argument order, and use new macro to reduce
|
||||
size of expansion.
|
||||
* doc/autoconf.texi (Looping constructs) <m4_shiftn>: Mention that
|
||||
count must be positive.
|
||||
|
||||
* doc/autoconf.texi (Evaluation Macros) <m4_expand>: Fix typo.
|
||||
Reported by Ralf Wildenhues.
|
||||
|
||||
|
@ -10670,7 +10670,8 @@ The deprecated macro @code{AC_FOREACH} is an alias of
|
||||
@msindex{shiftn}
|
||||
@code{m4_shiftn} performs @var{count} iterations of @code{m4_shift},
|
||||
along with validation that enough arguments were passed in to match the
|
||||
shift count. @code{m4_shift2} and @code{m4_shift3} are specializations
|
||||
shift count, and that the count is positive. @code{m4_shift2} and
|
||||
@code{m4_shift3} are specializations
|
||||
of @code{m4_shiftn}, introduced in Autoconf 2.62, and are more efficient
|
||||
for two and three shifts, respectively.
|
||||
@end defmac
|
||||
|
@ -398,6 +398,18 @@ m4_define([m4_cdr],
|
||||
[$#], 1, [],
|
||||
[m4_dquote(m4_shift($@))])])
|
||||
|
||||
# _m4_cdr(LIST)
|
||||
# -------------
|
||||
# Like m4_cdr, except include a leading comma unless only one element
|
||||
# remains. Why? Because comparing a large list against [] is more
|
||||
# expensive in expansion time than comparing the number of arguments; so
|
||||
# _m4_cdr can be used to reduce the number of arguments when it is time
|
||||
# to end recursion.
|
||||
m4_define([_m4_cdr],
|
||||
[m4_if([$#], 1, [],
|
||||
[, m4_dquote(m4_shift($@))])])
|
||||
|
||||
|
||||
|
||||
# m4_cond(TEST1, VAL1, IF-VAL1, TEST2, VAL2, IF-VAL2, ..., [DEFAULT])
|
||||
# -------------------------------------------------------------------
|
||||
@ -439,13 +451,12 @@ m4_define([m4_cond],
|
||||
# -------------------
|
||||
# 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_if([$#], [1], [],
|
||||
[$1(m4_unquote(m4_car($2)))[]_m4_map([$1]_m4_cdr($2))])])
|
||||
|
||||
|
||||
# m4_map_sep(MACRO, SEPARATOR, LIST)
|
||||
@ -455,7 +466,7 @@ m4_define([_m4_map],
|
||||
# arguments MACROs).
|
||||
m4_define([m4_map_sep],
|
||||
[m4_if([$3], [[]], [],
|
||||
[$1(m4_fst($3))[]_m4_map([$2[]$1], m4_cdr($3))])])
|
||||
[$1(m4_unquote(m4_car($3)))[]_m4_map([$2[]$1]_m4_cdr($3))])])
|
||||
|
||||
|
||||
## ---------------------------------------- ##
|
||||
@ -483,7 +494,7 @@ m4_define([m4_map_sep],
|
||||
m4_define([m4_bpatsubsts],
|
||||
[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
|
||||
[$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
|
||||
[$#], 2, [m4_builtin([patsubst], $@)],
|
||||
[$#], 2, [m4_builtin([patsubst], [$1], [$2])],
|
||||
[_$0($@m4_if(m4_eval($# & 1), 0, [,]))])])
|
||||
m4_define([_m4_bpatsubsts],
|
||||
[m4_if([$#], 2, [$1],
|
||||
@ -565,14 +576,24 @@ m4_define([m4_popdef],
|
||||
# m4_shiftn(N, ...)
|
||||
# -----------------
|
||||
# Returns ... shifted N times. Useful for recursive "varargs" constructs.
|
||||
#
|
||||
# Autoconf does not use this macro, because it is inherently slower than
|
||||
# calling the common cases of m4_shift2 or m4_shift3 directly. But it
|
||||
# might as well be fast for other clients, such as Libtool. One way to
|
||||
# do this is to expand $@ only once in _m4_shiftn (otherwise, for long
|
||||
# lists, the expansion of m4_if takes twice as much memory as what the
|
||||
# list itself occupies, only to throw away the unused branch). The end
|
||||
# result is strictly equivalent to
|
||||
# m4_if([$1], 1, [m4_shift(,m4_shift(m4_shift($@)))],
|
||||
# [_m4_shiftn(m4_decr([$1]), m4_shift(m4_shift($@)))])
|
||||
# but with the final `m4_shift(m4_shift($@)))' shared between the two
|
||||
# paths. The first leg uses a no-op m4_shift(,$@) to balance out the ().
|
||||
m4_define([m4_shiftn],
|
||||
[m4_assert(0 <= $1 && $1 < $#)dnl
|
||||
_m4_shiftn($@)])
|
||||
[m4_assert(0 < $1 && $1 < $#)_$0($@)])
|
||||
|
||||
m4_define([_m4_shiftn],
|
||||
[m4_if([$1], 0,
|
||||
[m4_shift($@)],
|
||||
[_m4_shiftn(m4_eval([$1]-1), m4_shift(m4_shift($@)))])])
|
||||
[m4_if([$1], 1, [m4_shift(],
|
||||
[$0(m4_decr([$1])]), m4_shift(m4_shift($@)))])
|
||||
|
||||
# m4_shift2(...)
|
||||
# m4_shift3(...)
|
||||
@ -581,6 +602,17 @@ m4_define([_m4_shiftn],
|
||||
m4_define([m4_shift2], [m4_shift(m4_shift($@))])
|
||||
m4_define([m4_shift3], [m4_shift(m4_shift(m4_shift($@)))])
|
||||
|
||||
# _m4_shift3(...)
|
||||
# ---------------
|
||||
# Like m4_shift3, except include a leading comma unless there were exactly
|
||||
# three arguments. Why? Because in recursion, it is nice to distinguish
|
||||
# between 1 element left and 0 elements left, based on how many arguments
|
||||
# this shift expands to.
|
||||
m4_define([_m4_shift3],
|
||||
[m4_if([$#], [3], [],
|
||||
[, m4_shift(m4_shift(m4_shift($@)))])])
|
||||
|
||||
|
||||
# m4_undefine(NAME)
|
||||
# -----------------
|
||||
# Like the original, except don't tolerate undefining something which is
|
||||
@ -827,13 +859,18 @@ m4_if(m4_defn([$1]), [$2], [],
|
||||
# => -active--active-
|
||||
#
|
||||
# This macro is called frequently, so avoid extra expansions such as
|
||||
# m4_ifval and dnl.
|
||||
# m4_ifval and dnl. Also, since $2 might be quite large, try to use it
|
||||
# as little as possible in _m4_foreach; each extra use requires that much
|
||||
# more memory for expansion. So, rather than directly compare $2 against
|
||||
# [] and use m4_car/m4_cdr for recursion, we instead unbox the list (which
|
||||
# requires swapping the argument order in the helper) and use _m4_shift3
|
||||
# to detect when recursion is complete.
|
||||
m4_define([m4_foreach],
|
||||
[m4_pushdef([$1])_$0($@)m4_popdef([$1])])
|
||||
[m4_pushdef([$1])_$0([$1], [$3]m4_if([$2], [], [], [, $2]))m4_popdef([$1])])
|
||||
|
||||
m4_define([_m4_foreach],
|
||||
[m4_if([$2], [], [],
|
||||
[m4_define([$1], m4_car($2))$3[]$0([$1], m4_cdr($2), [$3])])])
|
||||
[m4_if([$#], [2], [],
|
||||
[m4_define([$1], [$3])$2[]$0([$1], [$2]_m4_shift3($@))])])
|
||||
|
||||
|
||||
# m4_foreach_w(VARIABLE, LIST, EXPRESSION)
|
||||
|
Loading…
Reference in New Issue
Block a user