Merge branch 'master' of /home/eggert/src/gnu/autoconf-savannah/

This commit is contained in:
Paul Eggert 2007-10-16 13:11:38 -07:00
commit a574f37683
9 changed files with 879 additions and 244 deletions

View File

@ -1,3 +1,98 @@
2007-10-16 Eric Blake <ebb9@byu.net>
m4_map is a looping construct.
* lib/m4sugar/m4sugar.m4 (m4_map, _m4_map, m4_map_sep): Move.
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 $@.
(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.
2007-10-15 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* doc/autoconf.texi (Portable Shell): Improve description of zsh
4.x function subshell bug with exit and trap.
2007-10-15 Eric Blake <ebb9@byu.net>
Enhance AS_HELP_STRING.
* lib/m4sugar/m4sugar.m4 (m4_text_wrap): Don't expand arguments,
and reduce number of expansions.
* lib/m4sugar/m4sh.m4 (AS_HELP_STRING): Rework to use m4_expand,
and to take indent and wrap column numbers.
* tests/m4sh.at (AS@&t@_HELP_STRING): Update the test.
* doc/autoconf.texi (Pretty Help Strings): Document details about
arguments.
(Text processing Macros): Minor tweaks.
* NEWS: Document this change.
Fix 2007-10-03 regression with AT_SETUP([a, b]).
* lib/m4sugar/m4sugar.m4 (m4_expand): New macro.
(m4_text_box): Use it.
* lib/autotest/general.m4 (AT_SETUP): Use it.
* lib/m4sugar/m4sh.m4 (_AS_RUN): Use it.
* tests/autotest.at (AT_CHECK_AT_TITLE_CHAR): Test this.
* NEWS: Revert caveat about semantics change on comma.
* doc/autoconf.texi (Evaluation Macros): Document m4_expand.
2007-10-13 Eric Blake <ebb9@byu.net>
Change m4_join to match libtool's ltsugar semantics.
* lib/m4sugar/m4sugar.m4 (m4_join): Just define this, not defun.
Ignore empty arguments, using...
(_m4_join): ...this new helper.
* tests/m4sugar.at (m4@&t@_join): New test.
* doc/autoconf.texi (Text processing Macros): Document new
semantics of m4_join.
Make AC_PREREQ faster and more robust.
* lib/m4sugar/m4sugar.m4 (m4_ignore, m4_unquote): New macros.
(m4_version_prereq): Inline constant expansions.
(m4_list_cmp): Reduce number of expansions, by avoiding m4_case.
Rewrite in terms of [] list, not () list.
(_m4_list_cmp, _m4_version_unletter): New helper macros.
(m4_version_unletter): Write wrapper around new implementation to
preserve old semantics.
(m4_version_compare): Pass correct type of list, and avoid
overhead of flattening expressions too early.
(m4_do): Move to be near other quoting macros.
(m4_max, m4_min): Always result in decimal output.
* doc/autoconf.texi (Looping constructs): Add m4_car, m4_cdr.
Move m4_do...
(Evaluation Macros): ...here. Add m4_ignore, m4_unquote.
(Text processing Macros): Move m4_version_compare...
(Number processing Macros): ...to this new node; document m4_cmp,
m4_list_cmp, m4_sign, m4_max, m4_min.
* tests/m4sugar.at (m4@&t@_version_compare): Enhance test, to pick
up on bugs fixed by this patch.
* NEWS: Document new macros.
2007-10-12 Eric Blake <ebb9@byu.net> 2007-10-12 Eric Blake <ebb9@byu.net>
* doc/autoconf.texi (Text processing Macros): Fix bad merge. * doc/autoconf.texi (Text processing Macros): Fix bad merge.

33
NEWS
View File

@ -50,7 +50,13 @@ GNU Autoconf NEWS - User visible changes.
** AC_USE_SYSTEM_EXTENSIONS now defines _ALL_SOURCE for Interix platforms. ** AC_USE_SYSTEM_EXTENSIONS now defines _ALL_SOURCE for Interix platforms.
** AS_HELP_STRING no longer underquotes its first argument. ** AS_HELP_STRING no longer underquotes its first argument; it also handles
the case where the first argument contains single-quoted commas.
For example, "AS_HELP_STRING([-a, [--arg[=foo]]], [bar])" produces:
" -a, --arg=[foo] bar"
Additionally, the macro now takes two additional arguments,
indent-column and wrap-column; these should not normally be needed,
but can be used to fine-tune how the output text is wrapped.
** The command 'autoconf -' now correctly processes a file from stdin. ** The command 'autoconf -' now correctly processes a file from stdin.
@ -61,10 +67,7 @@ GNU Autoconf NEWS - User visible changes.
expanded libdir value of /usr/lib, not /usr//lib. expanded libdir value of /usr/lib, not /usr//lib.
** AT_SETUP now handles macro expansions properly when calculating line ** AT_SETUP now handles macro expansions properly when calculating line
length. However, as a side effect, any whitespace immediately length.
following a single-quoted comma is lost. If you previously used
AT_SETUP([a, b]), you could change to AT_SETUP([a,[] b]) to keep
the space.
** Autotest now determines $srcdir correctly. ** Autotest now determines $srcdir correctly.
@ -78,18 +81,20 @@ GNU Autoconf NEWS - User visible changes.
- The following macros were previously available as undocumented - The following macros were previously available as undocumented
interfaces; the macros are now documented as stable interfaces. interfaces; the macros are now documented as stable interfaces.
__oline__ m4_assert m4_bmatch m4_bpatsubsts m4_case __oline__ m4_assert m4_bmatch m4_bpatsubsts m4_car m4_case
m4_default m4_divert_once m4_divert_pop m4_divert_push m4_cdr m4_default m4_divert_once m4_divert_pop m4_divert_push
m4_divert_text m4_do m4_errprintn m4_fatal m4_flatten m4_divert_text m4_do m4_errprintn m4_fatal m4_flatten
m4_ifndef m4_ifset m4_ifval m4_ifvaln m4_location m4_ifndef m4_ifset m4_ifval m4_ifvaln m4_location
m4_n m4_shiftn m4_strip m4_version_compare m4_warn m4_n m4_shiftn m4_strip m4_warn
- The following macros were previously available as undocumented - The following macros were previously available as undocumented
interfaces, but had bugs. Packages that relied on the interfaces, but had bug fixes or semantic changes as part of this
undocumented and buggy behavior should analyze their code to make release. Packages that relied on the undocumented behavior
sure it still works with the new documented behavior. should be analyzed to make sure they will still work with the
new documented behavior.
m4_join m4_text_box m4_text_wrap 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 - Packages using the undocumented m4sugar macro m4_PACKAGE_VERSION
should consider using the new AC_AUTOCONF_VERSION instead. should consider using the new AC_AUTOCONF_VERSION instead.
@ -115,7 +120,9 @@ GNU Autoconf NEWS - User visible changes.
be used to take action depending on whether anything was appended. be used to take action depending on whether anything was appended.
** The following m4sugar macros are new: ** The following m4sugar macros are new:
m4_cond m4_newline m4_shift2 m4_shift3 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 ** Warnings are now generated by default when an installer invokes
'configure' with an unknown --enable-* or --with-* option. 'configure' with an unknown --enable-* or --with-* option.

View File

@ -455,6 +455,7 @@ Programming in M4sugar
* Looping constructs:: Iteration in M4 * Looping constructs:: Iteration in M4
* Evaluation Macros:: More quotation and evaluation control * Evaluation Macros:: More quotation and evaluation control
* Text processing Macros:: String manipulation in M4 * Text processing Macros:: String manipulation in M4
* Number processing Macros:: Arithmetic computation in M4
* Forbidden Patterns:: Catching unexpanded macros * Forbidden Patterns:: Catching unexpanded macros
Writing Autoconf Macros Writing Autoconf Macros
@ -10087,6 +10088,7 @@ define your own macros into these namespaces.
* Looping constructs:: Iteration in M4 * Looping constructs:: Iteration in M4
* Evaluation Macros:: More quotation and evaluation control * Evaluation Macros:: More quotation and evaluation control
* Text processing Macros:: String manipulation in M4 * Text processing Macros:: String manipulation in M4
* Number processing Macros:: Arithmetic computation in M4
* Forbidden Patterns:: Catching unexpanded macros * Forbidden Patterns:: Catching unexpanded macros
@end menu @end menu
@ -10585,7 +10587,42 @@ Expand to @var{text}, and add a newline if @var{text} is not empty.
@node Looping constructs @node Looping constructs
@subsection Looping constructs @subsection Looping constructs
The following macros implement loops in M4. The following macros are useful in implementing recursive algorithms in
M4, including loop operations. An M4 list is formed by quoting a list
of quoted elements; generally the lists are comma-separated, although
@code{m4_foreach_w} is whitespace-separated. For example, the list
@samp{[[a], [b,c]]} contains two elements: @samp{[a]} and @samp{[b,c]}.
It is common to see lists with unquoted elements when those elements are
not likely to be macro names, as in @samp{[fputc_unlocked,
fgetc_unlocked]}.
@defmac m4_car (@var{list})
@msindex{car}
Expands to the quoted first element of the comma-separated quoted
@var{list}. Often used with @code{m4_cdr} to recursively iterate
through a list. Generally, when using quoted lists of quoted elements,
@code{m4_car} should be called without any extra quotes.
@end defmac
@defmac m4_cdr (@var{list})
@msindex{cdr}
Expands to a quoted list of all but the first element of the
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 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_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
@defmac m4_for (@var{var}, @var{first}, @var{last}, @ovar{step}, @ @defmac m4_for (@var{var}, @var{first}, @var{last}, @ovar{step}, @
@var{expression}) @var{expression})
@ -10607,8 +10644,9 @@ outputs two lines:
@example @example
m4_foreach([myvar], [[foo], [bar, baz]], m4_foreach([myvar], [[foo], [bar, baz]],
[echo myvar [echo myvar
]) ])dnl
@result{}echo foo
@result{}echo bar, baz
@end example @end example
@end defmac @end defmac
@ -10622,13 +10660,26 @@ The deprecated macro @code{AC_FOREACH} is an alias of
@code{m4_foreach_w}. @code{m4_foreach_w}.
@end defmac @end defmac
The following macros are useful in implementing recursive algorithms. @defmac m4_map (@var{macro}, @var{list})
@defmacx m4_map_sep (@var{macro}, @var{separator}, @var{list})
@defmac m4_do (@dots{}) Loop over the comma separated quoted list of argument descriptions in
@msindex{do} @var{list}, and invoke @var{macro} with the arguments. An argument
This macro loops over its arguments and expands each one in sequence. description is in turn a comma-separated quoted list of quoted elements,
Its main use is for readability; it allows the use of indentation and suitable for @code{m4_apply}, making it possible to invoke @var{macro}
fewer @code{dnl} to result in the same expansion. 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 @end defmac
@defmac m4_shiftn (@var{count}, @dots{}) @defmac m4_shiftn (@var{count}, @dots{})
@ -10639,7 +10690,8 @@ fewer @code{dnl} to result in the same expansion.
@msindex{shiftn} @msindex{shiftn}
@code{m4_shiftn} performs @var{count} iterations of @code{m4_shift}, @code{m4_shiftn} performs @var{count} iterations of @code{m4_shift},
along with validation that enough arguments were passed in to match the 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 of @code{m4_shiftn}, introduced in Autoconf 2.62, and are more efficient
for two and three shifts, respectively. for two and three shifts, respectively.
@end defmac @end defmac
@ -10649,53 +10701,188 @@ for two and three shifts, respectively.
@subsection Evaluation Macros @subsection Evaluation Macros
The following macros give some control over the order of the evaluation The following macros give some control over the order of the evaluation
by adding or removing levels of quotes. They are meant for hard-core M4 by adding or removing levels of quotes.
programmers.
@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
sequence. Its main use is for readability; it allows the use of
indentation and fewer @code{dnl} to result in the same expansion.
@end defmac
@defmac m4_dquote (@var{arg1}, @dots{}) @defmac m4_dquote (@var{arg1}, @dots{})
@msindex{dquote} @msindex{dquote}
Return the arguments as a quoted list of quoted arguments. Return the arguments as a quoted list of quoted arguments.
Conveniently, if there is just one @var{arg}, this effectively adds a
level of quoting.
@end defmac @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
@code{m4_quote} is designed to collect expanded text into a single
argument, @code{m4_expand} is designed to perform one level of expansion
on quoted text. The distinction is in the treatment of whitespace
following a comma in the original @var{arg}. Any time multiple
arguments are collected into one with @code{m4_quote}, the M4 argument
collection rules discard the whitespace. However, with @code{m4_expand},
whitespace is discarded only if it results from unquoted commas in the
expansion of macros contained in @var{arg}.
@example
m4_define([active], [ACT, IVE])dnl
m4_define([active2], [[ACT, IVE]])dnl
m4_quote(active, active)
@result{}ACT,IVE,ACT,IVE
m4_expand([active, active])
@result{}ACT,IVE, ACT,IVE
m4_quote(active2, active2)
@result{}ACT, IVE,ACT, IVE
m4_expand([active2, active2])
@result{}ACT, IVE, ACT, IVE
@end example
@end defmac
@defmac m4_ignore (@dots{})
@msindex{ignore}
This macro was introduced in Autoconf 2.62. Expands to nothing,
ignoring all of its arguments. By itself, this isn't very useful.
However, it can be used to conditionally ignore an arbitrary number of
arguments, by making a decision about which macro name to apply to a
list of arguments.
@example
dnl foo outputs a message only if [debug] is defined.
m4_define([foo],
[m4_ifdef([debug],[AC_MSG_NOTICE],[m4_ignore])([debug message])])
@end example
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.
@defmac m4_quote (@var{arg1}, @dots{}) @defmac m4_quote (@var{arg1}, @dots{})
@msindex{quote} @msindex{quote}
Return the arguments as a single entity, i.e., wrap them into a pair of Return the arguments as a single entity, i.e., wrap them into a pair of
quotes. quotes. This effectively collapses multiple arguments into one,
although it loses whitespace after unquoted commas in the process.
@end defmac @end defmac
The following example aims at emphasizing the difference between (i), not @defmac m4_unquote (@var{arg1}, @dots{})
using these macros, (ii), using @code{m4_quote}, and (iii), using @msindex{unquote}
@code{m4_dquote}. This macro was introduced in Autoconf 2.62. Expand each argument,
separated by commas. For a single @var{arg}, this effectively removes a
layer of quoting, and @code{m4_unquote([@var{arg}])} is more efficient
than the equivalent @code{m4_do([@var{arg}])}. For multiple arguments,
this results in an unquoted list of expansions. This is commonly used
with @code{m4_split}, in order to convert a single quoted list into a
series of quoted elements.
@end defmac
The following example aims at emphasizing the difference between several
scenarios: not using these macros, using @code{m4_defn}, using
@code{m4_quote}, using @code{m4_dquote}, and using @code{m4_expand}.
@example @example
$ @kbd{cat example.m4} $ @kbd{cat example.m4}
# Overquote, so that quotes are visible. # Overquote, so that quotes are visible.
m4_define([show], [$[]1 = [$1], $[]@@ = [$@@]]) m4_define([show], [$[]1 = [$1], $[]@@ = [$@@]])
m4_define([mkargs], [1, 2, 3]) m4_define([a], [A])
m4_define([mkargs], [1, 2[,] 3])
m4_define([arg1], [[$1]]) m4_define([arg1], [[$1]])
m4_divert(0)dnl m4_divert([0])dnl
show(a, b) show(a, b)
show([a, b])
show(m4_quote(a, b)) show(m4_quote(a, b))
show(m4_dquote(a, b)) show(m4_dquote(a, b))
show(m4_expand([a, b]))
arg1(mkargs) arg1(mkargs)
arg1([mkargs]) arg1([mkargs])
arg1(m4_defn([mkargs])) arg1(m4_defn([mkargs]))
arg1(m4_quote(mkargs)) arg1(m4_quote(mkargs))
arg1(m4_dquote(mkargs)) arg1(m4_dquote(mkargs))
arg1(m4_expand([mkargs]))
$ @kbd{autom4te -l m4sugar example.m4} $ @kbd{autom4te -l m4sugar example.m4}
$1 = a, $@@ = [a],[b] $1 = A, $@@ = [A],[b]
$1 = a,b, $@@ = [a,b] $1 = a, b, $@@ = [a, b]
$1 = [a],[b], $@@ = [[a],[b]] $1 = A,b, $@@ = [A,b]
$1 = [A],[b], $@@ = [[A],[b]]
$1 = A, b, $@@ = [A, b]
1 1
mkargs mkargs
1, 2, 3 1, 2[,] 3
1,2,3 1,2, 3
[1],[2],[3] [1],[2, 3]
1,2, 3
@end example @end example
@node Text processing Macros @node Text processing Macros
@subsection Text processing Macros @subsection String manipulation in M4
The following macros may be used to manipulate strings in M4. The following macros may be used to manipulate strings in M4.
They are not intended for casual use. They are not intended for casual use.
@ -10714,9 +10901,9 @@ are expanded during this macro; instead, they are expanded when
@code{m4_append} can be used to grow strings, and @code{m4_append_uniq} @code{m4_append} can be used to grow strings, and @code{m4_append_uniq}
to grow strings without duplicating substrings. Additionally, to grow strings without duplicating substrings. Additionally,
@code{m4_append_uniq} takes two optional parameters; @var{if-uniq} is @code{m4_append_uniq} takes two optional parameters as of Autoconf 2.62;
expanded if @var{string} was appended, and @var{if-duplicate} is @var{if-uniq} is expanded if @var{string} was appended, and
expanded if @var{string} was already present. @var{if-duplicate} is expanded if @var{string} was already present.
@example @example
m4_define([active], [ACTIVE])dnl m4_define([active], [ACTIVE])dnl
@ -10760,8 +10947,18 @@ still a quoted string.
@defmac m4_join (@ovar{separator}, @var{args}@dots{}) @defmac m4_join (@ovar{separator}, @var{args}@dots{})
@msindex{join} @msindex{join}
Concatenate each @var{arg}, separated by @var{separator}. The result is Concatenate each @var{arg}, separated by @var{separator}, with the
a quoted string. exception that no back-to-back separators are issued for empty
arguments. The result is a quoted string.
@example
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 @end defmac
@defmac m4_newline @defmac m4_newline
@ -10822,25 +11019,27 @@ format those words to wrap within @var{width} columns, and without
trailing whitespace. If given, @var{prefix1} is prepended to the first trailing whitespace. If given, @var{prefix1} is prepended to the first
line, and @var{prefix} is prepended to each continuation line. As a line, and @var{prefix} is prepended to each continuation line. As a
special case, if @var{prefix1} is longer than @var{prefix}, the first special case, if @var{prefix1} is longer than @var{prefix}, the first
line will consist solely of @var{prefix1}. line will consist solely of @var{prefix1}. No expansions occur on
@var{prefix}, @var{prefix1}, or the words of @var{string}, although
quadrigraphs are recognized.
For some examples: For some examples:
@example @example
m4_text_wrap([Short string */], [@ @ @ ], [/* ], [20]) m4_text_wrap([Short string */], [ ], [/* ], [20])
@result{}/* Short string */ @result{}/* Short string */
m4_text_wrap([Much longer string */], [@ @ @ ], [/* ], [20]) m4_text_wrap([Much longer string */], [ ], [/* ], [20])
@result{}/* Much longer @result{}/* Much longer
@result{}@ @ @ string */ @result{} string */
m4_text_wrap([Short doc.], [@ @ @ @ @ @ @ @ @ @ ], [@ @ --short ], [30]) m4_text_wrap([Short doc.], [ ], [ --short ], [30])
@result{}@ @ --short Short doc. @result{} --short Short doc.
m4_text_wrap([Short doc.], [@ @ @ @ @ @ @ @ @ @ ], [@ @ --too-wide ], [30]) m4_text_wrap([Short doc.], [ ], [ --too-wide ], [30])
@result{}@ @ --too-wide @result{} --too-wide
@result{}@ @ @ @ @ @ @ @ @ @ Short doc. @result{} Short doc.
m4_text_wrap([Super long documentation.], [@ @ @ @ @ ], m4_text_wrap([Super long documentation.], [ ],
[@ @ --too-wide ], 30) [ --too-wide ], 30)
@result{}@ @ --too-wide @result{} --too-wide
@result{}@ @ @ @ @ Super long @result{} Super long
@result{}@ @ @ @ @ documentation. @result{} documentation.
@end example @end example
@end defmac @end defmac
@ -10852,17 +11051,76 @@ Return @var{string} with letters converted to upper or lower case,
respectively. respectively.
@end defmac @end defmac
@node Number processing Macros
@subsection Arithmetic computation in M4
The following macros make it easier to deal with arithmetic operations.
Where a parameter is documented as taking an arithmetic expression, you
can use anything that can be parsed by @code{m4_eval}.
@defmac m4_cmp (@var{expr-1}, @var{expr-2})
@msindex{cmp}
Compare the arithmetic expressions @var{expr-1} and @var{expr-2}, and
expand to @samp{-1} if @var{expr-1} is smaller, @samp{0} if they are
equal, and @samp{1} if @var{expr-1} is larger.
@end defmac
@defmac m4_list_cmp (@var{list-1}, @var{list-2})
@msindex{list_cmp}
Compare the two M4 lists consisting of comma-separated arithmetic
expressions, left to right. Expand to @samp{-1} for the first element
pairing where the value from @var{list-1} is smaller, @samp{1} where the
value from @var{list-2} is smaller, or @samp{0} if both lists have the
same values. If one list is shorter than the other, the remaining
elements of the longer list are compared against 0.
@example
m4_list_cmp([1, 0], [1])
@result{}0
m4_list_cmp([1, [1 * 0]], [1, 0])
@result{}0
m4_list_cmp([1, 2], [1, 0])
@result{}1
m4_list_cmp([1, [1+1], 3],[1, 2])
@result{}1
m4_list_cmp([1, 2, -3], [1, 2])
@result{}-1
m4_list_cmp([1, 0], [1, 2])
@result{}-1
m4_list_cmp([1], [1, 2])
@result{}-1
@end example
@end defmac
@defmac m4_max (@var{arg1}, @dots{})
@msindex{max}
This macro was introduced in Autoconf 2.62. Expand to the decimal value
of the maximum arithmetic expression among all the arguments.
@end defmac
@defmac m4_min (@var{arg1}, @dots{})
@msindex{min}
This macro was introduced in Autoconf 2.62. Expand to the decimal value
of the minimum arithmetic expression among all the arguments.
@end defmac
@defmac m4_sign (@var{expr})
@msindex{sign}
Expand to @samp{-1} if the arithmetic expression @var{expr} is negative,
@samp{1} if it is positive, and @samp{0} if it is zero.
@end defmac
@anchor{m4_version_compare} @anchor{m4_version_compare}
@defmac m4_version_compare (@var{version-1}, @var{version-2}) @defmac m4_version_compare (@var{version-1}, @var{version-2})
@msindex{version_compare} @msindex{version_compare}
This macro was introduced in Autoconf 2.53. Compare the version strings This macro was introduced in Autoconf 2.53, but had a number of
@var{version-1} and @var{version-2}, and expand to @samp{-1} if usability limitations that were not lifted until Autoconf 2.62. Compare
@var{version-1} is smaller, @samp{0} if they are the same, or @samp{1} the version strings @var{version-1} and @var{version-2}, and expand to
@var{version-2} is smaller. Version strings must be a list of elements @samp{-1} if @var{version-1} is smaller, @samp{0} if they are the same,
separated by @samp{.}, where each element is a number along with an or @samp{1} @var{version-2} is smaller. Version strings must be a list
optional lower case letter. The comparison stops at the leftmost of elements separated by @samp{.}, where each element is a number along
element that contains a difference, although a 0 element compares equal with optional case-insensitive letters designating beta releases. The
to a missing element. comparison stops at the leftmost element that contains a difference,
although a 0 element compares equal to a missing element.
@example @example
m4_version_compare([1.1], [2.0]) m4_version_compare([1.1], [2.0])
@ -10875,6 +11133,8 @@ m4_version_compare([1.2], [1.1.1a])
@result{}1 @result{}1
m4_version_compare([1.0], [1]) m4_version_compare([1.0], [1])
@result{}0 @result{}0
m4_version_compare([1.1pre], [1.1PRE])
@result{}0
m4_version_compare([1.1a], [1,10]) m4_version_compare([1.1a], [1,10])
@result{}-1 @result{}-1
@end example @end example
@ -11800,15 +12060,13 @@ that are not found in all Bourne-compatible shells; restrict yourself
to the lowest common denominator. Even @code{unset} is not supported to the lowest common denominator. Even @code{unset} is not supported
by all shells! by all shells!
Shell functions are considered portable nowadays, though Autoconf Shell functions are considered portable nowadays, though Autoconf still
still does not use them (Autotest does). However, inside a shell does not use them (Autotest does). However, inside a shell function,
function you should not be using @code{$?} to check the return code you should not rely on the error status of a subshell if the last
of a subshell invocation; in general, since the caller of a shell command of that subshell was @code{exit} or @code{trap}, as this
function might look at the function's return code, make sure that the triggers bugs in zsh 4.x; while Autoconf tries to find a shell that
last statement of a shell function does not invoke a subshell. does not exhibit the bug, zsh might be the only shell present on the
Using subshells triggers bugs in zsh 4.x; while Autoconf tries user's machine.
to find a shell that does not exhibit the bug, zsh might be the
only shell present on the user's machine.
Some ancient systems have quite Some ancient systems have quite
small limits on the length of the @samp{#!} line; for instance, 32 small limits on the length of the @samp{#!} line; for instance, 32
@ -17025,7 +17283,8 @@ your own @samp{help strings} to line up in the appropriate columns of
strings} do. This is the purpose of the @code{AS_HELP_STRING} macro. strings} do. This is the purpose of the @code{AS_HELP_STRING} macro.
@anchor{AS_HELP_STRING} @anchor{AS_HELP_STRING}
@defmac AS_HELP_STRING (@var{left-hand-side}, @var{right-hand-side}) @defmac AS_HELP_STRING (@var{left-hand-side}, @var{right-hand-side} @
@dvar{indent-column, 26}, @dvar{wrap-column, 79})
@asindex{HELP_STRING} @asindex{HELP_STRING}
Expands into an help string that looks pretty when the user executes Expands into an help string that looks pretty when the user executes
@ -17041,9 +17300,6 @@ AC_ARG_WITH([foo],
[use_foo=no]) [use_foo=no])
@end example @end example
The second argument of @code{AS_HELP_STRING} is
not a literal, and should not be double quoted.
@xref{Autoconf Language}, for a more detailed explanation.
Then the last few lines of @samp{configure --help} appear like Then the last few lines of @samp{configure --help} appear like
this: this:
@ -17052,16 +17308,42 @@ this:
--with-foo use foo (default is no) --with-foo use foo (default is no)
@end example @end example
Macro expansion is performed on the first argument. However, the second
argument of @code{AS_HELP_STRING} is treated as a whitespace separated
list of text to be reformatted, and is not subject to macro expansion.
Since it is not expanded, it should not be double quoted.
@xref{Autoconf Language}, for a more detailed explanation.
The @code{AS_HELP_STRING} macro is particularly helpful when the The @code{AS_HELP_STRING} macro is particularly helpful when the
@var{left-hand-side} and/or @var{right-hand-side} are composed of macro @var{left-hand-side} and/or @var{right-hand-side} are composed of macro
arguments, as shown in the following example. arguments, as shown in the following example.
@example @example
AC_DEFUN([MY_ARG_WITH], AC_DEFUN([MY_ARG_WITH],
[AC_ARG_WITH([$1], [AC_ARG_WITH(m4_translit([[$1]], [_], [-]),
[AS_HELP_STRING([--with-$1], [use $1 (default is $2)])], [AS_HELP_STRING([--with-m4_translit([$1], [_], [-])],
[use $1 (default is $2)])],
[use_[]$1=$withval], [use_[]$1=$withval],
[use_[]$1=$2])]) [use_[]$1=$2])])
MY_ARG_WITH([a_b], [no])
@end example
@noindent
Here, the last few lines of @samp{configure --help} will include:
@example
--enable and --with options recognized:
--with-a-b use a_b (default is no)
@end example
The parameters @var{indent-column} and @var{wrap-column} were introduced
in Autoconf 2.62. Generally, they should not be specified; they exist
for fine-tuning of the wrapping.
@example
AS_HELP_STRING([--option], [description of option])
@result{} --option description of option
AS_HELP_STRING([--option], [description of option], [15], [30])
@result{} --option description of
@result{} option
@end example @end example
@end defmac @end defmac

View File

@ -1289,7 +1289,7 @@ m4_define([AT_SETUP],
m4_define([AT_capture_files], []) m4_define([AT_capture_files], [])
m4_define([AT_line], AT_LINE) m4_define([AT_line], AT_LINE)
m4_define([AT_xfail], [at_xfail=no]) m4_define([AT_xfail], [at_xfail=no])
m4_define([AT_description], m4_quote($1)) m4_define([AT_description], m4_expand([$1]))
m4_define([AT_ordinal], m4_incr(AT_ordinal)) m4_define([AT_ordinal], m4_incr(AT_ordinal))
m4_append([AT_groups_all], [ ]m4_defn([AT_ordinal])) m4_append([AT_groups_all], [ ]m4_defn([AT_ordinal]))
m4_divert_push([TEST_FUNCTIONS])dnl m4_divert_push([TEST_FUNCTIONS])dnl

View File

@ -197,7 +197,7 @@ _AS_BOURNE_COMPATIBLE
$1 $1
_ASEOF _ASEOF
}], }],
[(eval "AS_ESCAPE(m4_quote($1))")])]) [(eval "AS_ESCAPE(m4_expand([$1]))")])])
# _AS_DETECT_REQUIRED(TEST) # _AS_DETECT_REQUIRED(TEST)
@ -1158,14 +1158,21 @@ m4_define([_AS_BOX_INDIR],
_ASBOX]) _ASBOX])
# AS_HELP_STRING(LHS, RHS, [COLUMN]) # AS_HELP_STRING(LHS, RHS, [INDENT-COLUMN = 26], [WRAP-COLUMN = 79])
# ---------------------------------- # ------------------------------------------------------------------
# #
# Format a help string so that it looks pretty when # Format a help string so that it looks pretty when the user executes
# the user executes "script --help". This macro takes three # "script --help". This macro takes up to four arguments, a
# arguments, a "left hand side" (LHS), a "right hand side" (RHS), and # "left hand side" (LHS), a "right hand side" (RHS), a decimal
# the COLUMN which is a string of white spaces which leads to the # INDENT-COLUMN which is the column where wrapped lines should begin
# the RHS column (default: 26 white spaces). # (the default of 26 is recommended), and a decimal WRAP-COLUMN which is
# the column where lines should wrap (the default of 79 is recommended).
# LHS is expanded, RHS is not.
#
# For backwards compatibility not documented in the manual, INDENT-COLUMN
# can also be specified as a string of white spaces, whose width
# determines the indentation column. Using TABs in INDENT-COLUMN is not
# recommended, since screen width of TAB is not computed.
# #
# The resulting string is suitable for use in other macros that require # The resulting string is suitable for use in other macros that require
# a help string (e.g. AC_ARG_WITH). # a help string (e.g. AC_ARG_WITH).
@ -1185,9 +1192,9 @@ _ASBOX])
# "--with-readline", while the RHS is "support fancy command line # "--with-readline", while the RHS is "support fancy command line
# editing". # editing".
# #
# If the LHS contains more than (COLUMN - 3) characters, then the LHS is # If the LHS contains more than (INDENT-COLUMN - 3) characters, then the
# terminated with a newline so that the RHS starts on a line of its own # LHS is terminated with a newline so that the RHS starts on a line of its
# beginning with COLUMN. In the default case, this corresponds to an # own beginning at INDENT-COLUMN. In the default case, this corresponds to an
# LHS with more than 23 characters. # LHS with more than 23 characters.
# #
# Therefore, in the example, if the LHS were instead # Therefore, in the example, if the LHS were instead
@ -1206,12 +1213,10 @@ _ASBOX])
# know quadrigraphs. # know quadrigraphs.
# #
m4_define([AS_HELP_STRING], m4_define([AS_HELP_STRING],
[m4_pushdef([AS_Prefix], m4_default([$3], [ ]))dnl [m4_text_wrap([$2], m4_cond([[$3]], [], [ ],
m4_pushdef([AS_Prefix_Format], [m4_eval([$3]+0)], [0], [[$3]],
[ %-]m4_eval(m4_len(AS_Prefix) - 3)[s ])dnl [ %-23s ] [m4_format([[%*s]], [$3], [])]),
m4_text_wrap([$2], AS_Prefix, m4_format(AS_Prefix_Format, [[$1]]))dnl m4_expand([ $1 ]), [$4])dnl
m4_popdef([AS_Prefix_Format])dnl
m4_popdef([AS_Prefix])dnl
])# AS_HELP_STRING ])# AS_HELP_STRING

View File

@ -398,6 +398,18 @@ m4_define([m4_cdr],
[$#], 1, [], [$#], 1, [],
[m4_dquote(m4_shift($@))])]) [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]) # m4_cond(TEST1, VAL1, IF-VAL1, TEST2, VAL2, IF-VAL2, ..., [DEFAULT])
# ------------------------------------------------------------------- # -------------------------------------------------------------------
@ -435,29 +447,6 @@ m4_define([m4_cond],
[m4_if($1, [$2], [$3], [$0(m4_shift3($@))])])]) [m4_if($1, [$2], [$3], [$0(m4_shift3($@))])])])
# 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. ##
## ---------------------------------------- ## ## ---------------------------------------- ##
@ -483,7 +472,7 @@ m4_define([m4_map_sep],
m4_define([m4_bpatsubsts], m4_define([m4_bpatsubsts],
[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])], [m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
[$#], 1, [m4_fatal([$0: too few arguments: $#: $1])], [$#], 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, [,]))])]) [_$0($@m4_if(m4_eval($# & 1), 0, [,]))])])
m4_define([_m4_bpatsubsts], m4_define([_m4_bpatsubsts],
[m4_if([$#], 2, [$1], [m4_if([$#], 2, [$1],
@ -491,18 +480,6 @@ m4_define([_m4_bpatsubsts],
m4_shift3($@))])]) m4_shift3($@))])])
# m4_do(STRING, ...)
# ------------------
# This macro invokes all its arguments (in sequence, of course). It is
# useful for making your macros more structured and readable by dropping
# unnecessary dnl's and have the macros indented properly.
m4_define([m4_do],
[m4_if($#, 0, [],
$#, 1, [$1],
[$1[]m4_do(m4_shift($@))])])
# m4_define_default(MACRO, VALUE) # m4_define_default(MACRO, VALUE)
# ------------------------------- # -------------------------------
# If MACRO is undefined, set it to VALUE. # If MACRO is undefined, set it to VALUE.
@ -577,14 +554,24 @@ m4_define([m4_popdef],
# m4_shiftn(N, ...) # m4_shiftn(N, ...)
# ----------------- # -----------------
# Returns ... shifted N times. Useful for recursive "varargs" constructs. # 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_define([m4_shiftn],
[m4_assert(0 <= $1 && $1 < $#)dnl [m4_assert(0 < $1 && $1 < $#)_$0($@)])
_m4_shiftn($@)])
m4_define([_m4_shiftn], m4_define([_m4_shiftn],
[m4_if([$1], 0, [m4_if([$1], 1, [m4_shift(],
[m4_shift($@)], [$0(m4_decr([$1])]), m4_shift(m4_shift($@)))])
[_m4_shiftn(m4_eval([$1]-1), m4_shift(m4_shift($@)))])])
# m4_shift2(...) # m4_shift2(...)
# m4_shift3(...) # m4_shift3(...)
@ -593,6 +580,21 @@ m4_define([_m4_shiftn],
m4_define([m4_shift2], [m4_shift(m4_shift($@))]) m4_define([m4_shift2], [m4_shift(m4_shift($@))])
m4_define([m4_shift3], [m4_shift(m4_shift(m4_shift($@)))]) m4_define([m4_shift3], [m4_shift(m4_shift(m4_shift($@)))])
# _m4_shift2(...)
# _m4_shift3(...)
# ---------------
# 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($@)))])])
# m4_undefine(NAME) # m4_undefine(NAME)
# ----------------- # -----------------
# Like the original, except don't tolerate undefining something which is # Like the original, except don't tolerate undefining something which is
@ -610,16 +612,31 @@ m4_define([m4_undefine],
## 7. Quoting manipulation. ## ## 7. Quoting manipulation. ##
## ------------------------- ## ## ------------------------- ##
# m4_quote(ARGS)
# 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 ARGS as a single argument. Any whitespace after unquoted commas # Return a count of how many ARGS are present.
# is stripped. m4_define([m4_count], [$#])
#
# It is important to realize the difference between `m4_quote(exp)' and
# `[exp]': in the first case you obtain the quoted *result* of the # m4_do(STRING, ...)
# expansion of EXP, while in the latter you just obtain the string # ------------------
# `exp'. # This macro invokes all its arguments (in sequence, of course). It is
m4_define([m4_quote], [[$*]]) # useful for making your macros more structured and readable by dropping
# unnecessary dnl's and have the macros indented properly.
m4_define([m4_do],
[m4_if([$#], 0, [],
[$#], 1, [$1],
[$1[]m4_do(m4_shift($@))])])
# m4_dquote(ARGS) # m4_dquote(ARGS)
@ -628,16 +645,116 @@ m4_define([m4_quote], [[$*]])
m4_define([m4_dquote], [[$@]]) 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
# correctly preserves whitespace following single-quoted commas that appeared
# within ARG (however, it does not preserve whitespace after any unquoted
# commas encountered in the expansion).
#
# m4_define([active], [ACT, IVE])
# m4_define([active2], [[ACT, IVE]])
# m4_quote(active, active2)
# => ACT,IVE,ACT, IVE
# m4_expand([active, active2])
# => ACT,IVE, ACT, IVE
#
# Splitting a quoted ARG on `,' preserves space, but produces a quoted list.
# Unquote the list, then expand each argument while preserving the leading
# spaces; finally, collect each argument back into the final string.
m4_define([m4_expand],
[m4_quote(_$0(m4_unquote(m4_split([$1], [,]))))])
# _m4_expand(ARGS)
# ----------------
# Return the expansion of each ARG, separated by `,'. Less efficient than
# m4_unquote, but preserves quoted leading space in each ARG.
m4_define([_m4_expand],
[m4_if([$#], [0], [],
[$#], [1], [$1],
[$1,$0(m4_shift($@))])])
# m4_ignore(ARGS)
# ---------------
# Expands to nothing. Useful for conditionally ignoring an arbitrary
# number of arguments (see _m4_list_cmp for an example).
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) # m4_noquote(STRING)
# ------------------ # ------------------
# Return the result of ignoring all quotes in STRING and invoking the # Return the result of ignoring all quotes in STRING and invoking the
# macros it contains. Amongst other things, this is useful for enabling # macros it contains. Amongst other things, this is useful for enabling
# macro invocations inside strings with [] blocks (for instance regexps # macro invocations inside strings with [] blocks (for instance regexps
# and help-strings). # and help-strings). On the other hand, since all quotes are disabled,
# any macro expanded during this time that relies on nested [] quoting
# will likely crash and burn. This macro is seldom useful; consider
# m4_unquote instead.
m4_define([m4_noquote], m4_define([m4_noquote],
[m4_changequote(-=<{,}>=-)$1-=<{}>=-m4_changequote([,])]) [m4_changequote(-=<{,}>=-)$1-=<{}>=-m4_changequote([,])])
# m4_quote(ARGS)
# --------------
# Return ARGS as a single argument. Any whitespace after unquoted commas
# 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
# expansion of EXP, while in the latter you just obtain the string
# `exp'.
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
# expansion. For one argument, m4_unquote([arg]) is more efficient than
# m4_do([arg]), but for multiple arguments, the difference is that
# m4_unquote separates arguments with commas while m4_do concatenates.
m4_define([m4_unquote], [$*])
## -------------------------- ## ## -------------------------- ##
## 8. Implementing m4 loops. ## ## 8. Implementing m4 loops. ##
## -------------------------- ## ## -------------------------- ##
@ -779,13 +896,18 @@ m4_if(m4_defn([$1]), [$2], [],
# => -active--active- # => -active--active-
# #
# This macro is called frequently, so avoid extra expansions such as # 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_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_define([_m4_foreach],
[m4_if([$2], [], [], [m4_if([$#], [2], [],
[m4_define([$1], m4_car($2))$3[]$0([$1], m4_cdr($2), [$3])])]) [m4_define([$1], [$3])$2[]$0([$1], [$2]_m4_shift3($@))])])
# m4_foreach_w(VARIABLE, LIST, EXPRESSION) # m4_foreach_w(VARIABLE, LIST, EXPRESSION)
@ -803,6 +925,31 @@ 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)
# -------------------
# 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.
#
# 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], [], [],
[_$0([$1], $2)])])
m4_define([_m4_map],
[m4_if([$#], [1], [],
[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, and are in turn lists appropriate for m4_apply.
# SEPARATOR is not further expanded.
m4_define([m4_map_sep],
[m4_if([$3], [], [],
[m4_apply([$1], m4_car($3))m4_map([[$2]$1]_m4_cdr($3))])])
## --------------------------- ## ## --------------------------- ##
## 9. More diversion support. ## ## 9. More diversion support. ##
@ -1645,13 +1792,24 @@ m4_define([m4_normalize],
# m4_join(SEP, ARG1, ARG2...) # m4_join(SEP, ARG1, ARG2...)
# --------------------------- # ---------------------------
# Produce ARG1SEPARG2...SEPARGn. # Produce ARG1SEPARG2...SEPARGn. Avoid back-to-back SEP when a given ARG
m4_defun([m4_join], # is the empty string. No expansion is performed on SEP or ARGs.
[m4_case([$#], #
[1], [], # Since the number of arguments to join can be arbitrarily long, we
[2], [[$2]], # want to avoid having more than one $@ in the macro definition;
[[$2][$1]$0([$1], m4_shift2($@))])]) # otherwise, the expansion would require twice the memory of the already
# long list. Hence, m4_join merely looks for the first non-empty element,
# and outputs just that element; while _m4_join looks for all non-empty
# elements, and outputs them following a separator. The final trick to
# note is that we decide between recursing with $0 or _$0 based on the
# nested m4_if ending with `_'.
m4_define([m4_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift2($@))])])
m4_define([_m4_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift2($@))])])
# m4_append(MACRO-NAME, STRING, [SEPARATOR]) # m4_append(MACRO-NAME, STRING, [SEPARATOR])
@ -1726,6 +1884,9 @@ m4_define([m4_append_uniq],
# if the length of FIRST-PREFIX is greater than that of PREFIX, then # if the length of FIRST-PREFIX is greater than that of PREFIX, then
# FIRST-PREFIX will be left alone on the first line. # FIRST-PREFIX will be left alone on the first line.
# #
# No expansion occurs on the contents STRING, PREFIX, or FIRST-PREFIX,
# although quadrigraphs are correctly recognized.
#
# Typical outputs are: # Typical outputs are:
# #
# m4_text_wrap([Short string */], [ ], [/* ], 20) # m4_text_wrap([Short string */], [ ], [/* ], 20)
@ -1756,44 +1917,49 @@ m4_define([m4_append_uniq],
# all the words are preceded by m4_Separator which is defined to empty for # all the words are preceded by m4_Separator which is defined to empty for
# the first word, and then ` ' (single space) for all the others. # the first word, and then ` ' (single space) for all the others.
# #
# The algorithm overquotes m4_Prefix1 to avoid m4_defn overhead, and bypasses # The algorithm overquotes m4_Prefix and m4_Prefix1 to avoid m4_defn
# m4_popdef overhead with m4_builtin since no user macro expansion occurs in # overhead, and bypasses m4_popdef overhead with m4_builtin since no user
# the meantime. # macro expansion occurs in the meantime. Also, the definition is written
# with m4_do, to avoid time wasted on dnl during expansion (since this is
# already a time-consuming macro).
m4_define([m4_text_wrap], m4_define([m4_text_wrap],
[m4_pushdef([m4_Prefix], [$2])dnl m4_do(dnl set up local variables, to avoid repeated calculations
m4_pushdef([m4_Prefix1], m4_dquote(m4_default([$3], [m4_Prefix])))dnl [[m4_pushdef([m4_Prefix], [[$2]])]],
m4_pushdef([m4_Width], m4_default([$4], 79))dnl [[m4_pushdef([m4_Prefix1], m4_if([$3], [], [m4_Prefix], [[[$3]]]))]],
m4_pushdef([m4_Cursor], m4_qlen(m4_Prefix1))dnl [[m4_pushdef([m4_Width], m4_default([$4], 79))]],
m4_pushdef([m4_Separator], [])dnl [[m4_pushdef([m4_Indent], m4_qlen(m4_Prefix))]],
m4_Prefix1[]dnl [[m4_pushdef([m4_Cursor], m4_qlen(m4_Prefix1))]],
m4_cond([m4_eval(m4_qlen(m4_Prefix1) > m4_len(m4_Prefix))], [[m4_pushdef([m4_Separator], [m4_define([m4_Separator], [ ])])]],
[1], [m4_define([m4_Cursor], m4_len(m4_Prefix)) dnl expand the first prefix, then check its length vs. regular prefix
m4_Prefix], dnl same length: nothing special
[m4_eval(m4_qlen(m4_Prefix1) < m4_len(m4_Prefix))], dnl prefix1 longer: output on line by itself, and reset cursor
[0], [], dnl prefix1 shorter: pad to length of prefix, and reset cursor
[m4_define([m4_Cursor], m4_len(m4_Prefix))[]dnl [[m4_Prefix1[]m4_cond([m4_Cursor], m4_Indent, [],
m4_format([%*s], [m4_eval(m4_Cursor > m4_Indent)], [1], [
m4_max([0], m4_eval(m4_len(m4_Prefix) - m4_qlen(m4_Prefix1))), m4_Prefix[]m4_define([m4_Cursor], m4_Indent)],
[])])[]dnl [m4_format([%*s], m4_max([0],
m4_foreach_w([m4_Word], [$1], m4_eval(m4_Indent - m4_Cursor)), [])m4_define([m4_Cursor], m4_Indent)])]],
[m4_define([m4_Cursor], dnl now, for each word, compute the curser after the word is output, then
m4_eval(m4_Cursor + m4_qlen(m4_builtin([defn], [m4_Word])) + 1))dnl dnl check if the cursor would exceed the wrap column
dnl New line if too long, else insert a space unless it is the first dnl if so, reset cursor, and insert newline and prefix
dnl of the words. dnl if not, insert the separator (usually a space)
m4_if(m4_eval(m4_Cursor > m4_Width), dnl either way, insert the word
1, [m4_define([m4_Cursor], [[m4_foreach_w([m4_Word], [$1],
m4_eval(m4_len(m4_Prefix) [m4_define([m4_Cursor],
+ m4_qlen(m4_builtin([defn], [m4_Word])) + 1))] m4_eval(m4_Cursor + m4_qlen(m4_builtin([defn], [m4_Word]))
m4_Prefix, + 1))m4_if(m4_eval(m4_Cursor > m4_Width),
[m4_Separator])[]dnl [1], [m4_define([m4_Cursor],
m4_builtin([defn], [m4_Word])[]dnl m4_eval(m4_Indent
m4_define([m4_Separator], [ ])])dnl + m4_qlen(m4_builtin([defn], [m4_Word])) + 1))
m4_builtin([popdef], [m4_Separator])dnl m4_Prefix[]],
m4_builtin([popdef], [m4_Cursor])dnl [m4_Separator[]])m4_builtin([defn], [m4_Word])])]],
m4_builtin([popdef], [m4_Width])dnl dnl finally, clean up the local variabls
m4_builtin([popdef], [m4_Prefix1])dnl [[m4_builtin([popdef], [m4_Separator])]],
m4_builtin([popdef], [m4_Prefix])dnl [[m4_builtin([popdef], [m4_Cursor])]],
]) [[m4_builtin([popdef], [m4_Indent])]],
[[m4_builtin([popdef], [m4_Width])]],
[[m4_builtin([popdef], [m4_Prefix1])]],
[[m4_builtin([popdef], [m4_Prefix])]]))
# m4_text_box(MESSAGE, [FRAME-CHARACTER = `-']) # m4_text_box(MESSAGE, [FRAME-CHARACTER = `-'])
@ -1805,7 +1971,7 @@ m4_builtin([popdef], [m4_Prefix])dnl
# using FRAME-CHARACTER in the border. # using FRAME-CHARACTER in the border.
m4_define([m4_text_box], m4_define([m4_text_box],
[m4_pushdef([m4_Border], [m4_pushdef([m4_Border],
m4_translit(m4_format([%*s], m4_qlen(m4_quote($1)), []), m4_translit(m4_format([%*s], m4_qlen(m4_expand([$1])), []),
[ ], m4_if([$2], [], [[-]], [[$2]])))dnl [ ], m4_if([$2], [], [[-]], [[$2]])))dnl
@%:@@%:@ m4_Border @%:@@%:@ @%:@@%:@ m4_Border @%:@@%:@
@%:@@%:@ $1 @%:@@%:@ @%:@@%:@ $1 @%:@@%:@
@ -1850,42 +2016,50 @@ m4_define([m4_cmp],
# m4_list_cmp(A, B) # m4_list_cmp(A, B)
# ----------------- # -----------------
# #
# Compare the two lists of integers A and B. For instance: # Compare the two lists of integer expressions A and B. For instance:
# m4_list_cmp((1, 0), (1)) -> 0 # m4_list_cmp([1, 0], [1]) -> 0
# m4_list_cmp((1, 0), (1, 0)) -> 0 # m4_list_cmp([1, 0], [1, 0]) -> 0
# m4_list_cmp((1, 2), (1, 0)) -> 1 # m4_list_cmp([1, 2], [1, 0]) -> 1
# m4_list_cmp((1, 2, 3), (1, 2)) -> 1 # m4_list_cmp([1, 2, 3], [1, 2]) -> 1
# m4_list_cmp((1, 2, -3), (1, 2)) -> -1 # m4_list_cmp([1, 2, -3], [1, 2]) -> -1
# m4_list_cmp((1, 0), (1, 2)) -> -1 # m4_list_cmp([1, 0], [1, 2]) -> -1
# m4_list_cmp((1), (1, 2)) -> -1 # m4_list_cmp([1], [1, 2]) -> -1
# m4_define([xa], [oops])dnl
# m4_list_cmp([[0xa]], [5+5]) -> 0
#
# Rather than face the overhead of m4_case, we use a helper function whose
# expansion includes the name of the macro to invoke on the tail, either
# m4_ignore or m4_unquote. This is particularly useful when comparing
# long lists, since less text is being expanded to determine when to recurse.
m4_define([m4_list_cmp], m4_define([m4_list_cmp],
[m4_if([$1$2], [()()], 0, [m4_if([$1$2], [], 0,
[$1], [()], [$0((0), [$2])], [$1], [], [$0(0, [$2])],
[$2], [()], [$0([$1], (0))], [$2], [], [$0([$1], 0)],
[m4_case(m4_cmp(m4_car$1, m4_car$2), [$1], [$2], 0,
-1, -1, [_$0(m4_cmp(m4_car($1), m4_car($2)))([$0(m4_cdr($1), m4_cdr($2))])])])
1, 1, m4_define([_m4_list_cmp],
0, [$0((m4_shift$1), (m4_shift$2))])])]) [m4_if([$1], 0, [m4_unquote], [$1m4_ignore])])
# m4_max(A, B, ...) # m4_max(EXPR, ...)
# m4_min(A, B, ...) # m4_min(EXPR, ...)
# ----------------- # -----------------
# Return the maximum (or minimum) of a series of integer expressions. # Return the decimal value of the maximum (or minimum) in a series of
# integer expressions.
# #
# M4 1.4.x doesn't provide ?:. Hence this huge m4_eval. Avoid m4_eval # M4 1.4.x doesn't provide ?:. Hence this huge m4_eval. Avoid m4_eval
# if both arguments are identical, but be aware of m4_max(0xa, 10) (hence # if both arguments are identical, but be aware of m4_max(0xa, 10) (hence
# the use of <=, not just <, in the second multiply). # the use of <=, not just <, in the second multiply).
m4_define([m4_max], m4_define([m4_max],
[m4_if([$#], [0], [m4_fatal([too few arguments to $0])], [m4_if([$#], [0], [m4_fatal([too few arguments to $0])],
[$#], [1], [$1], [$#], [1], [m4_eval([$1])],
[$#$1], [2$2], [$1], [$#$1], [2$2], [m4_eval([$1])],
[$#], [2], [$#], [2],
[m4_eval((([$1]) > ([$2])) * ([$1]) + (([$1]) <= ([$2])) * ([$2]))], [m4_eval((([$1]) > ([$2])) * ([$1]) + (([$1]) <= ([$2])) * ([$2]))],
[$0($0([$1], [$2]), m4_shift2($@))])]) [$0($0([$1], [$2]), m4_shift2($@))])])
m4_define([m4_min], m4_define([m4_min],
[m4_if([$#], [0], [m4_fatal([too few arguments to $0])], [m4_if([$#], [0], [m4_fatal([too few arguments to $0])],
[$#], [1], [$1], [$#], [1], [m4_eval([$1])],
[$#$1], [2$2], [$1], [$#$1], [2$2], [m4_eval([$1])],
[$#], [2], [$#], [2],
[m4_eval((([$1]) < ([$2])) * ([$1]) + (([$1]) >= ([$2])) * ([$2]))], [m4_eval((([$1]) < ([$2])) * ([$1]) + (([$1]) >= ([$2])) * ([$2]))],
[$0($0([$1], [$2]), m4_shift2($@))])]) [$0($0([$1], [$2]), m4_shift2($@))])])
@ -1906,23 +2080,29 @@ m4_define([m4_sign],
# m4_version_unletter(VERSION) # m4_version_unletter(VERSION)
# ---------------------------- # ----------------------------
# Normalize beta version numbers with letters to numbers only for comparison. # Normalize beta version numbers with letters to numeric expressions, which
# can then be handed to m4_eval for the purpose of comparison.
# #
# Nl -> (N+1).-1.(l#) # Nl -> (N+1).-1.(l#)
# #
#i.e., 2.14a -> 2.15.-1.1, 2.14b -> 2.15.-1.2, etc. # for example:
# This macro is absolutely not robust to active macro, it expects # [2.14a] -> [2.14+1.-1.[0r36:a]] -> 2.15.-1.10
# reasonable version numbers and is valid up to `z', no double letters. # [2.14b] -> [2.15+1.-1.[0r36:b]] -> 2.15.-1.11
# [2.61aa.b] -> [2.61+1.-1.[0r36:aa],+1.-1.[0r36:b]] -> 2.62.-1.370.1.-1.11
#
# This macro expects reasonable version numbers, but can handle double
# letters and does not expand one-letter macros. Inline constant expansions,
# to avoid m4_defn overhead. _m4_version_unletter is the real workhorse
# 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_define([m4_version_unletter],
[m4_translit(m4_bpatsubsts(m4_tolower([[$1]]), [m4_map_sep([m4_eval], [.],
[\([0-9]+\)\([abcdefghi]\)], m4_dquote(m4_dquote_elt(m4_unquote(_$0([$1])))))])
[m4_eval(\1 + 1).-1.\2], m4_define([_m4_version_unletter],
[\([0-9]+\)\([jklmnopqrs]\)], [m4_translit(m4_bpatsubst([[[$1]]], ]dnl
[m4_eval(\1 + 1).-1.1\2], m4_dquote(m4_dquote(m4_defn([m4_cr_Letters])))[[+],
[\([0-9]+\)\([tuvwxyz]\)], [+1.-1.[0r36:\&]]),
[m4_eval(\1 + 1).-1.2\2]), [.], [,])])
[abcdefghijklmnopqrstuvwxyz],
[12345678901234567890123456])])
# m4_version_compare(VERSION-1, VERSION-2) # m4_version_compare(VERSION-1, VERSION-2)
@ -1932,8 +2112,7 @@ m4_define([m4_version_unletter],
# 0 if = # 0 if =
# 1 if > # 1 if >
m4_define([m4_version_compare], m4_define([m4_version_compare],
[m4_list_cmp((m4_translit(m4_version_unletter([$1]), [.], [,])), [m4_list_cmp(_m4_version_unletter([$1]), _m4_version_unletter([$2]))])
(m4_translit(m4_version_unletter([$2]), [.], [,])))])
# m4_PACKAGE_NAME # m4_PACKAGE_NAME
@ -1949,12 +2128,12 @@ m4_include([m4sugar/version.m4])
# ---------------------------------------------------- # ----------------------------------------------------
# Check this Autoconf version against VERSION. # Check this Autoconf version against VERSION.
m4_define([m4_version_prereq], m4_define([m4_version_prereq],
[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]), [$1]), -1, [m4_if(m4_version_compare(]m4_dquote(m4_defn([m4_PACKAGE_VERSION]))[, [$1]),
[-1],
[m4_default([$3], [m4_default([$3],
[m4_fatal([Autoconf version $1 or higher is required], [m4_fatal([Autoconf version $1 or higher is required],
63)])], [63])])],
[$2])[]dnl [$2])])
])

View File

@ -290,7 +290,7 @@ AT_CHECK_AT_TITLE_CHAR([Backslash], [\])
AT_CHECK_AT_TITLE_CHAR([Brackets], [[[]]], [[]]) AT_CHECK_AT_TITLE_CHAR([Brackets], [[[]]], [[]])
AT_CHECK_AT_TITLE_CHAR([Pound], [[#]], [#]) AT_CHECK_AT_TITLE_CHAR([Pound], [[#]], [#])
AT_CHECK_AT_TITLE_CHAR([Quoted comma],[[,]], [,]) AT_CHECK_AT_TITLE_CHAR([Quoted comma],[[,]], [,])
AT_CHECK_AT_TITLE_CHAR([Comma], [,[]], [,]) AT_CHECK_AT_TITLE_CHAR([Comma], [,], [,])
AT_CHECK_AT_TITLE_CHAR([Quoted Macro], [[macro_name]], [macro_name]) AT_CHECK_AT_TITLE_CHAR([Quoted Macro], [[macro_name]], [macro_name])
AT_CHECK_AT_TITLE_CHAR([Macro], [macro_name], [macro_expanded]) AT_CHECK_AT_TITLE_CHAR([Macro], [macro_name], [macro_expanded])

View File

@ -490,10 +490,8 @@ AT_CLEANUP
## AS_HELP_STRING ## ## AS_HELP_STRING ##
## -------------- ## ## -------------- ##
# I'm not totally certain that we want to enforce the defaults here,
# but at least it is being tested.
AT_SETUP([AS@&t@_HELP_STRING]) AT_SETUP([AS@&t@_HELP_STRING])
AT_KEYWORDS([m4@&t@_text_wrap])
AT_DATA_M4SH([script.as], AT_DATA_M4SH([script.as],
[[AS_INIT [[AS_INIT
@ -545,6 +543,18 @@ echo "AS_HELP_STRING([[--foo[=bar]123456789012]],
[some other t[]t which should wrap at our default of 80 characters.])" [some other t[]t which should wrap at our default of 80 characters.])"
echo "AS_HELP_STRING([[--foo[=bar]1234567890123]], echo "AS_HELP_STRING([[--foo[=bar]1234567890123]],
[some other t[]t which should wrap at our default of 80 characters.])" [some other t[]t which should wrap at our default of 80 characters.])"
m4_define([mac], [MACRO])dnl
echo "AS_HELP_STRING([--mac], [mac])"
echo "AS_HELP_STRING([--o1, --o2], [two
options, one description])"
echo "AS_HELP_STRING([--tune1], [check out the tuned formatting],
[ ])"
echo "AS_HELP_STRING([--tune2], [check out the tuned formatting],
[12])"
echo "AS_HELP_STRING([--tune3], [check out the tuned formatting],
[], [40])"
echo "AS_HELP_STRING([--tune4], [check out the tuned formatting],
[12], [40])"
]]) ]])
AT_CHECK_M4SH AT_CHECK_M4SH
@ -600,6 +610,15 @@ AT_CHECK([./script], [0],
--foo[=bar]1234567890123 --foo[=bar]1234567890123
some other t[]t which should wrap at our default of some other t[]t which should wrap at our default of
80 characters. 80 characters.
--MACRO mac
--o1, --o2 two options, one description
--tune1 check out the tuned formatting
--tune2 check out the tuned formatting
--tune3 check out the
tuned
formatting
--tune4 check out the tuned
formatting
]]) ]])
AT_CLEANUP AT_CLEANUP

View File

@ -44,6 +44,8 @@ AT_CHECK_M4SUGAR([-o-],, [$2], [$3])
# #
# - m4_append # - m4_append
# #
# - m4_join
#
# - m4_text_wrap # - m4_text_wrap
# uses m4_split code. # uses m4_split code.
@ -251,6 +253,43 @@ one, two, three
AT_CLEANUP AT_CLEANUP
## --------- ##
## m4_join. ##
## --------- ##
AT_SETUP([m4@&t@_join])
AT_CHECK_M4SUGAR_TEXT(
[[m4_define([active], [ACTIVE])
m4_join
m4_join([|])
m4_join([, ], [one], [two])
m4_dquote(m4_join([, ], [one], [two]))
m4_join([|], [active], [active])
m4_join([|], ,,,[one])
m4_join([|], [one],,,)
m4_join([], ,,,[two])
m4_join([], [two],,,)
m4_join([ active ], [one], , [two])
m4_join([], [one], [two])
]],
[[
one, two
[one, two]
active|active
one
one
two
two
one active two
onetwo
]])
AT_CLEANUP
## -------------- ## ## -------------- ##
## m4_text_wrap. ## ## m4_text_wrap. ##
## -------------- ## ## -------------- ##
@ -313,6 +352,11 @@ m4_version_compare([1.2], [1.1.1a])
m4_version_compare([1.0], [1]) m4_version_compare([1.0], [1])
m4_version_compare([1.0a], [1.0a]) m4_version_compare([1.0a], [1.0a])
m4_version_compare([1.1a], [1.1a.1]) m4_version_compare([1.1a], [1.1a.1])
m4_version_compare([1.10], [1.1a])
m4_version_compare([1.1a], [1.1A])
m4_define([a], [oops])dnl
m4_version_compare([1.1a], [1.1A])
m4_version_compare([1z], [1aa])
]], ]],
[[-1 [[-1
1 1
@ -322,6 +366,10 @@ m4_version_compare([1.1a], [1.1a.1])
0 0
0 0
-1 -1
1
0
0
-1
]]) ]])
AT_CLEANUP AT_CLEANUP