mirror of
git://git.sv.gnu.org/autoconf
synced 2024-11-27 01:49:56 +08:00
Fix m4_map, and add some more utility macros.
* lib/m4sugar/m4sugar.m4 (m4_apply, m4_count, m4_dquote_elt) (m4_echo, m4_make_list): New documented macros. (_m4_quote, _m4_shift2): New helper macros. (m4_map): Change semantics to allow calling macro without arguments. (m4_map_sep): Likewise. Also change semantics to quote separator, to match m4_join and m4_append. (m4_version_unletter): Fix use of m4_map. * doc/autoconf.texi (Evaluation Macros): Document m4_apply, m4_count, m4_dquote_elt, m4_echo, m4_make_list. (Text processing Macros): Mention m4_dquote as a faster alternative to joining with commas. (Looping constructs): Document m4_map, m4_map_sep. * NEWS: Mention new macros. Signed-off-by: Eric Blake <ebb9@byu.net>
This commit is contained in:
parent
f3b4cc104e
commit
33239cbd38
16
ChangeLog
16
ChangeLog
@ -1,5 +1,21 @@
|
||||
2007-10-16 Eric Blake <ebb9@byu.net>
|
||||
|
||||
Fix m4_map, and add some more utility macros.
|
||||
* lib/m4sugar/m4sugar.m4 (m4_apply, m4_count, m4_dquote_elt)
|
||||
(m4_echo, m4_make_list): New documented macros.
|
||||
(_m4_quote, _m4_shift2): New helper macros.
|
||||
(m4_map): Change semantics to allow calling macro without
|
||||
arguments.
|
||||
(m4_map_sep): Likewise. Also change semantics to quote separator,
|
||||
to match m4_join and m4_append.
|
||||
(m4_version_unletter): Fix use of m4_map.
|
||||
* doc/autoconf.texi (Evaluation Macros): Document m4_apply,
|
||||
m4_count, m4_dquote_elt, m4_echo, m4_make_list.
|
||||
(Text processing Macros): Mention m4_dquote as a faster
|
||||
alternative to joining with commas.
|
||||
(Looping constructs): Document m4_map, m4_map_sep.
|
||||
* NEWS: Mention new macros.
|
||||
|
||||
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 $@.
|
||||
|
9
NEWS
9
NEWS
@ -93,8 +93,8 @@ GNU Autoconf NEWS - User visible changes.
|
||||
should be analyzed to make sure they will still work with the
|
||||
new documented behavior.
|
||||
|
||||
m4_cmp m4_list_cmp m4_join m4_sign m4_text_box m4_text_wrap
|
||||
m4_version_compare
|
||||
m4_cmp m4_list_cmp m4_join m4_map m4_map_sep m4_sign
|
||||
m4_text_box m4_text_wrap m4_version_compare
|
||||
|
||||
- Packages using the undocumented m4sugar macro m4_PACKAGE_VERSION
|
||||
should consider using the new AC_AUTOCONF_VERSION instead.
|
||||
@ -120,8 +120,9 @@ GNU Autoconf NEWS - User visible changes.
|
||||
be used to take action depending on whether anything was appended.
|
||||
|
||||
** The following m4sugar macros are new:
|
||||
m4_cond m4_expand m4_ignore m4_max m4_min m4_newline
|
||||
m4_shift2 m4_shift3 m4_unquote
|
||||
m4_apply m4_cond m4_count m4_dquote_elt m4_echo m4_expand
|
||||
m4_ignore m4_make_list m4_max m4_min m4_newline m4_shift2
|
||||
m4_shift3 m4_unquote
|
||||
|
||||
** Warnings are now generated by default when an installer invokes
|
||||
'configure' with an unknown --enable-* or --with-* option.
|
||||
|
@ -10611,16 +10611,16 @@ comma-separated quoted @var{list}, or the empty string if @var{list} had
|
||||
only one element. Generally, when using quoted lists of quoted
|
||||
elements, @code{m4_cdr} should be called without any extra quotes.
|
||||
|
||||
For example, this is an implementation of @code{m4_map}; note how each
|
||||
iteration of the helper macro @code{_m4_map} checks for the end of
|
||||
recursion, then merely applies the first argument to the first element
|
||||
of the list, then recurses with the rest of the list.
|
||||
For example, this is a simple implementation of @code{m4_map}; note how
|
||||
each iteration checks for the end of recursion, then merely applies the
|
||||
first argument to the first element of the list, then recurses with the
|
||||
rest of the list. (The actual implementation in M4sugar is a bit more
|
||||
involved, to gain some speed and share code with @code{m4_map_sep}).
|
||||
@example
|
||||
m4_define([m4_map], [m4_if([$2], [[]], [], [_$0($@@)])])dnl
|
||||
m4_define([_m4_map], [m4_ifval([$2],
|
||||
[$1(m4_unquote(m4_car($2)))[]$0([$1], m4_cdr($2))])])dnl
|
||||
m4_map([ m4_eval], [[1],[1+1]])
|
||||
@result{} 1 2
|
||||
m4_define([m4_map], [m4_ifval([$2],
|
||||
[m4_apply([$1], m4_car($2))[]$0([$1], m4_cdr($2))])])dnl
|
||||
m4_map([ m4_eval], [[[1]], [[1+1]], [[10],[16]]])
|
||||
@result{} 1 2 a
|
||||
@end example
|
||||
@end defmac
|
||||
|
||||
@ -10660,7 +10660,27 @@ The deprecated macro @code{AC_FOREACH} is an alias of
|
||||
@code{m4_foreach_w}.
|
||||
@end defmac
|
||||
|
||||
@c TODO document m4_map, m4_map_sep
|
||||
@defmac m4_map (@var{macro}, @var{list})
|
||||
@defmacx m4_map_sep (@var{macro}, @var{separator}, @var{list})
|
||||
Loop over the comma separated quoted list of argument descriptions in
|
||||
@var{list}, and invoke @var{macro} with the arguments. An argument
|
||||
description is in turn a comma-separated quoted list of quoted elements,
|
||||
suitable for @code{m4_apply}, making it possible to invoke @var{macro}
|
||||
without arguments if an argument description is empty.
|
||||
@code{m4_map_sep} additionally outputs @var{separator} between macro
|
||||
invocations, with no additional expansion of the separator.
|
||||
@example
|
||||
m4_map([m4_count], [])
|
||||
@result{}
|
||||
m4_map([ m4_count], [[],
|
||||
[[1]],
|
||||
[[1], [2]]])
|
||||
@result{} 0 1 2
|
||||
m4_map_sep([m4_eval], [,], [[[1+2]],
|
||||
[[10], [16]]])
|
||||
@result{}3,a
|
||||
@end example
|
||||
@end defmac
|
||||
|
||||
@defmac m4_shiftn (@var{count}, @dots{})
|
||||
@defmacx m4_shift2 (@dots{})
|
||||
@ -10683,6 +10703,29 @@ for two and three shifts, respectively.
|
||||
The following macros give some control over the order of the evaluation
|
||||
by adding or removing levels of quotes.
|
||||
|
||||
@defmac m4_apply (@var{macro}, @var{list})
|
||||
@msindex apply
|
||||
Apply the elements of the quoted, comma-separated @var{list} as the
|
||||
arguments to @var{macro}. If @var{list} is empty, invoke @var{macro}
|
||||
without arguments.
|
||||
@example
|
||||
m4_apply([m4_count], [])
|
||||
@result{}0
|
||||
m4_apply([m4_count], [[]])
|
||||
@result{}1
|
||||
m4_apply([m4_count], [[1], [2]])
|
||||
@result{}2
|
||||
m4_apply([m4_join], [[|], [1], [2]])
|
||||
@result{}1|2
|
||||
@end example
|
||||
@end defmac
|
||||
|
||||
@defmac m4_count (@var{arg1}, @dots{})
|
||||
@msindex{count}
|
||||
This macro returns the decimal count of the number of arguments it was
|
||||
passed.
|
||||
@end defmac
|
||||
|
||||
@defmac m4_do (@var{arg1}, @dots{})
|
||||
@msindex{do}
|
||||
This macro loops over its arguments and expands each @var{arg} in
|
||||
@ -10697,6 +10740,19 @@ Conveniently, if there is just one @var{arg}, this effectively adds a
|
||||
level of quoting.
|
||||
@end defmac
|
||||
|
||||
@defmac m4_dquote_elt (@var{arg1}, @dots{})
|
||||
@msindex{dquote_elt}
|
||||
Return the arguments as a series of double-quoted arguments. Whereas
|
||||
@code{m4_dquote} returns a single argument, @code{m4_dquote_elt} returns
|
||||
as many arguments as it was passed.
|
||||
@end defmac
|
||||
|
||||
@defmac m4_echo (@var{arg1}, @dots{})
|
||||
@msindex{echo}
|
||||
Return the arguments, with the same level of quoting. Other than
|
||||
discarding whitespace after unquoted commas, this macro is a no-op.
|
||||
@end defmac
|
||||
|
||||
@defmac m4_expand (@var{arg})
|
||||
@msindex{expand}
|
||||
Return the expansion of @var{arg} as a quoted string. Whereas
|
||||
@ -10740,6 +10796,29 @@ Note that for earlier versions of Autoconf, the macro @code{__gnu__} can
|
||||
serve the same purpose, although it is less readable.
|
||||
@end defmac
|
||||
|
||||
@defmac m4_make_list (@var{arg1}, @dots{})
|
||||
@msindex{make_list}
|
||||
This macro exists to aid debugging of M4sugar algorithms. Its net
|
||||
effect is similar to @code{m4_dquote}---it produces a quoted list of
|
||||
quoted arguments, for each @var{arg}. The difference is that this
|
||||
version uses a comma-newline separator instead of just comma, to improve
|
||||
readability of the list; with the result that it is less efficient than
|
||||
@code{m4_dquote}.
|
||||
@example
|
||||
m4_define([zero],[0])m4_define([one],[1])m4_define([two],[2])dnl
|
||||
m4_dquote(zero, [one], [[two]])
|
||||
@result{}[0],[one],[[two]]
|
||||
m4_make_list(zero, [one], [[two]])
|
||||
@result{}[0],
|
||||
@result{}[one],
|
||||
@result{}[[two]]
|
||||
m4_foreach([number], m4_dquote(zero, [one], [[two]]), [ number])
|
||||
@result{} 0 1 two
|
||||
m4_foreach([number], m4_make_list(zero, [one], [[two]]), [ number])
|
||||
@result{} 0 1 two
|
||||
@end example
|
||||
@end defmac
|
||||
|
||||
@c m4_noquote is too dangerous to document - it invokes macros that
|
||||
@c probably rely on @samp{[]} nested quoting for proper operation. The
|
||||
@c user should generally prefer m4_unquote instead.
|
||||
@ -10876,6 +10955,10 @@ m4_define([active], [ACTIVE])dnl
|
||||
m4_join([|], [one], [], [active], [two])
|
||||
@result{}one|active|two
|
||||
@end example
|
||||
|
||||
Note that if all you intend to do is join @var{args} with commas between
|
||||
them, to form a quoted list suitable for @code{m4_foreach}, it is more
|
||||
efficient to use @code{m4_dquote}.
|
||||
@end defmac
|
||||
|
||||
@defmac m4_newline
|
||||
|
@ -450,23 +450,27 @@ m4_define([m4_cond],
|
||||
# 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).
|
||||
# of LIST. $1, $2... must in turn be lists, appropriate for m4_apply.
|
||||
#
|
||||
# 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, and use _m4_shift2 to detect the end of recursion.
|
||||
m4_define([m4_map],
|
||||
[m4_if([$2], [[]], [],
|
||||
[_m4_map([$1], [$2])])])
|
||||
[m4_if([$2], [], [],
|
||||
[_$0([$1], $2)])])
|
||||
m4_define([_m4_map],
|
||||
[m4_if([$#], [1], [],
|
||||
[$1(m4_unquote(m4_car($2)))[]_m4_map([$1]_m4_cdr($2))])])
|
||||
[m4_apply([$1], [$2])$0([$1]_m4_shift2($@))])])
|
||||
|
||||
|
||||
# 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).
|
||||
# are the elements of LIST, and are in turn lists appropriate for m4_apply.
|
||||
# SEPARATOR is not further expanded.
|
||||
m4_define([m4_map_sep],
|
||||
[m4_if([$3], [[]], [],
|
||||
[$1(m4_unquote(m4_car($3)))[]_m4_map([$2[]$1]_m4_cdr($3))])])
|
||||
[m4_if([$3], [], [],
|
||||
[m4_apply([$1], m4_car($3))m4_map([[$2]$1]_m4_cdr($3))])])
|
||||
|
||||
|
||||
## ---------------------------------------- ##
|
||||
@ -602,12 +606,16 @@ m4_define([_m4_shiftn],
|
||||
m4_define([m4_shift2], [m4_shift(m4_shift($@))])
|
||||
m4_define([m4_shift3], [m4_shift(m4_shift(m4_shift($@)))])
|
||||
|
||||
# _m4_shift2(...)
|
||||
# _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.
|
||||
# Like m4_shift2 or m4_shift3, except include a leading comma unless shifting
|
||||
# consumes all 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_shift2],
|
||||
[m4_if([$#], [2], [],
|
||||
[, m4_shift(m4_shift($@))])])
|
||||
m4_define([_m4_shift3],
|
||||
[m4_if([$#], [3], [],
|
||||
[, m4_shift(m4_shift(m4_shift($@)))])])
|
||||
@ -630,6 +638,22 @@ m4_define([m4_undefine],
|
||||
## 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.
|
||||
m4_define([m4_apply],
|
||||
[m4_if([$2], [], [$1], [$1($2)])[]])
|
||||
|
||||
|
||||
# m4_count(ARGS)
|
||||
# --------------
|
||||
# Return a count of how many ARGS are present.
|
||||
m4_define([m4_count], [$#])
|
||||
|
||||
|
||||
# m4_do(STRING, ...)
|
||||
# ------------------
|
||||
# This macro invokes all its arguments (in sequence, of course). It is
|
||||
@ -647,6 +671,22 @@ m4_define([m4_do],
|
||||
m4_define([m4_dquote], [[$@]])
|
||||
|
||||
|
||||
# m4_dquote_elt(ARGS)
|
||||
# -------------------
|
||||
# Return ARGS as an unquoted list of double-quoted arguments.
|
||||
m4_define([m4_dquote_elt],
|
||||
[m4_if([$#], [0], [],
|
||||
[$#], [1], [[[$1]]],
|
||||
[[[$1]],$0(m4_shift($@))])])
|
||||
|
||||
|
||||
# m4_echo(ARGS)
|
||||
# -------------
|
||||
# Return the ARGS, with the same level of quoting. Whitespace after
|
||||
# unquoted commas are consumed.
|
||||
m4_define([m4_echo], [$@])
|
||||
|
||||
|
||||
# m4_expand(ARG)
|
||||
# --------------
|
||||
# Return the expansion of ARG as a single string. Unlike m4_quote($1), this
|
||||
@ -684,6 +724,18 @@ m4_define([_m4_expand],
|
||||
m4_define([m4_ignore])
|
||||
|
||||
|
||||
# m4_make_list(ARGS)
|
||||
# ------------------
|
||||
# Similar to m4_dquote, this creates a quoted list of quoted ARGS. This
|
||||
# version is less efficient than m4_dquote, but separates each argument
|
||||
# with a comma and newline, rather than just comma, for readability.
|
||||
# When developing an m4sugar algorithm, you could temporarily use
|
||||
# m4_pushdef([m4_dquote],m4_defn([m4_make_list]))
|
||||
# around your code to make debugging easier.
|
||||
m4_define([m4_make_list], [m4_join([,
|
||||
], m4_dquote_elt($@))])
|
||||
|
||||
|
||||
# m4_noquote(STRING)
|
||||
# ------------------
|
||||
# Return the result of ignoring all quotes in STRING and invoking the
|
||||
@ -700,7 +752,7 @@ m4_define([m4_noquote],
|
||||
# m4_quote(ARGS)
|
||||
# --------------
|
||||
# Return ARGS as a single argument. Any whitespace after unquoted commas
|
||||
# is stripped.
|
||||
# is stripped. There is always output, even when there were no arguments.
|
||||
#
|
||||
# It is important to realize the difference between `m4_quote(exp)' and
|
||||
# `[exp]': in the first case you obtain the quoted *result* of the
|
||||
@ -709,6 +761,17 @@ m4_define([m4_noquote],
|
||||
m4_define([m4_quote], [[$*]])
|
||||
|
||||
|
||||
# _m4_quote(ARGS)
|
||||
# ---------------
|
||||
# Like m4_quote, except that when there are no arguments, there is no
|
||||
# output. For conditional scenarios (such as passing _m4_quote as the
|
||||
# macro name in m4_map), this feature can be used to distinguish between
|
||||
# one argument of the empty string vs. no arguments. However, in the
|
||||
# normal case with arguments present, this is less efficient than m4_quote.
|
||||
m4_define([_m4_quote],
|
||||
[m4_if([$#], [0], [], [[$*]])])
|
||||
|
||||
|
||||
# m4_unquote(ARGS)
|
||||
# ----------------
|
||||
# Remove one layer of quotes from each ARG, performing one level of
|
||||
@ -1731,7 +1794,7 @@ m4_define([m4_normalize],
|
||||
# m4_join(SEP, ARG1, ARG2...)
|
||||
# ---------------------------
|
||||
# Produce ARG1SEPARG2...SEPARGn. Avoid back-to-back SEP when a given ARG
|
||||
# is the empty string.
|
||||
# is the empty string. No expansion is performed on SEP or ARGs.
|
||||
#
|
||||
# Since the number of arguments to join can be arbitrarily long, we
|
||||
# want to avoid having more than one $@ in the macro definition;
|
||||
@ -2034,7 +2097,8 @@ m4_define([m4_sign],
|
||||
# used by m4_version_compare, but since [0r36:a] is less readable than 10,
|
||||
# we provide a wrapper for human use.
|
||||
m4_define([m4_version_unletter],
|
||||
[m4_map_sep([m4_eval], [.], _$0([$1]))])
|
||||
[m4_map_sep([m4_eval], [.],
|
||||
m4_dquote(m4_dquote_elt(m4_unquote(_$0([$1])))))])
|
||||
m4_define([_m4_version_unletter],
|
||||
[m4_translit(m4_bpatsubst([[[$1]]], ]dnl
|
||||
m4_dquote(m4_dquote(m4_defn([m4_cr_Letters])))[[+],
|
||||
|
Loading…
Reference in New Issue
Block a user