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>
* 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.
** 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.
@ -61,10 +67,7 @@ GNU Autoconf NEWS - User visible changes.
expanded libdir value of /usr/lib, not /usr//lib.
** AT_SETUP now handles macro expansions properly when calculating line
length. However, as a side effect, any whitespace immediately
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.
length.
** Autotest now determines $srcdir correctly.
@ -78,18 +81,20 @@ GNU Autoconf NEWS - User visible changes.
- The following macros were previously available as undocumented
interfaces; the macros are now documented as stable interfaces.
__oline__ m4_assert m4_bmatch m4_bpatsubsts m4_case
m4_default m4_divert_once m4_divert_pop m4_divert_push
__oline__ m4_assert m4_bmatch m4_bpatsubsts m4_car m4_case
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_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
interfaces, but had bugs. Packages that relied on the
undocumented and buggy behavior should analyze their code to make
sure it still works with the new documented behavior.
interfaces, but had bug fixes or semantic changes as part of this
release. Packages that relied on the undocumented 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
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.
** 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
'configure' with an unknown --enable-* or --with-* option.

View File

@ -455,6 +455,7 @@ Programming in M4sugar
* Looping constructs:: Iteration in M4
* Evaluation Macros:: More quotation and evaluation control
* Text processing Macros:: String manipulation in M4
* Number processing Macros:: Arithmetic computation in M4
* Forbidden Patterns:: Catching unexpanded macros
Writing Autoconf Macros
@ -10087,6 +10088,7 @@ define your own macros into these namespaces.
* Looping constructs:: Iteration in M4
* Evaluation Macros:: More quotation and evaluation control
* Text processing Macros:: String manipulation in M4
* Number processing Macros:: Arithmetic computation in M4
* Forbidden Patterns:: Catching unexpanded macros
@end menu
@ -10585,7 +10587,42 @@ Expand to @var{text}, and add a newline if @var{text} is not empty.
@node 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}, @
@var{expression})
@ -10607,8 +10644,9 @@ outputs two lines:
@example
m4_foreach([myvar], [[foo], [bar, baz]],
[echo myvar
])
])dnl
@result{}echo foo
@result{}echo bar, baz
@end example
@end defmac
@ -10622,13 +10660,26 @@ The deprecated macro @code{AC_FOREACH} is an alias of
@code{m4_foreach_w}.
@end defmac
The following macros are useful in implementing recursive algorithms.
@defmac m4_do (@dots{})
@msindex{do}
This macro loops over its arguments and expands each one in sequence.
Its main use is for readability; it allows the use of indentation and
fewer @code{dnl} to result in the same expansion.
@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{})
@ -10639,7 +10690,8 @@ fewer @code{dnl} to result in the same expansion.
@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
@ -10649,53 +10701,188 @@ for two and three shifts, respectively.
@subsection Evaluation Macros
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
programmers.
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
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{})
@msindex{dquote}
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
@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{})
@msindex{quote}
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
The following example aims at emphasizing the difference between (i), not
using these macros, (ii), using @code{m4_quote}, and (iii), using
@code{m4_dquote}.
@defmac m4_unquote (@var{arg1}, @dots{})
@msindex{unquote}
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
$ @kbd{cat example.m4}
# Overquote, so that quotes are visible.
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_divert(0)dnl
m4_divert([0])dnl
show(a, b)
show([a, b])
show(m4_quote(a, b))
show(m4_dquote(a, b))
show(m4_expand([a, b]))
arg1(mkargs)
arg1([mkargs])
arg1(m4_defn([mkargs]))
arg1(m4_quote(mkargs))
arg1(m4_dquote(mkargs))
arg1(m4_expand([mkargs]))
$ @kbd{autom4te -l m4sugar example.m4}
$1 = a, $@@ = [a],[b]
$1 = a,b, $@@ = [a,b]
$1 = [a],[b], $@@ = [[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
mkargs
1, 2, 3
1,2,3
[1],[2],[3]
1, 2[,] 3
1,2, 3
[1],[2, 3]
1,2, 3
@end example
@node Text processing Macros
@subsection Text processing Macros
@subsection String manipulation in M4
The following macros may be used to manipulate strings in M4.
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}
to grow strings without duplicating substrings. Additionally,
@code{m4_append_uniq} takes two optional parameters; @var{if-uniq} is
expanded if @var{string} was appended, and @var{if-duplicate} is
expanded if @var{string} was already present.
@code{m4_append_uniq} takes two optional parameters as of Autoconf 2.62;
@var{if-uniq} is expanded if @var{string} was appended, and
@var{if-duplicate} is expanded if @var{string} was already present.
@example
m4_define([active], [ACTIVE])dnl
@ -10760,8 +10947,18 @@ still a quoted string.
@defmac m4_join (@ovar{separator}, @var{args}@dots{})
@msindex{join}
Concatenate each @var{arg}, separated by @var{separator}. The result is
a quoted string.
Concatenate each @var{arg}, separated by @var{separator}, with the
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
@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
line, and @var{prefix} is prepended to each continuation line. As a
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:
@example
m4_text_wrap([Short string */], [@ @ @ ], [/* ], [20])
m4_text_wrap([Short string */], [ ], [/* ], [20])
@result{}/* Short string */
m4_text_wrap([Much longer string */], [@ @ @ ], [/* ], [20])
m4_text_wrap([Much longer string */], [ ], [/* ], [20])
@result{}/* Much longer
@result{}@ @ @ string */
m4_text_wrap([Short doc.], [@ @ @ @ @ @ @ @ @ @ ], [@ @ --short ], [30])
@result{}@ @ --short Short doc.
m4_text_wrap([Short doc.], [@ @ @ @ @ @ @ @ @ @ ], [@ @ --too-wide ], [30])
@result{}@ @ --too-wide
@result{}@ @ @ @ @ @ @ @ @ @ Short doc.
m4_text_wrap([Super long documentation.], [@ @ @ @ @ ],
[@ @ --too-wide ], 30)
@result{}@ @ --too-wide
@result{}@ @ @ @ @ Super long
@result{}@ @ @ @ @ documentation.
@result{} string */
m4_text_wrap([Short doc.], [ ], [ --short ], [30])
@result{} --short Short doc.
m4_text_wrap([Short doc.], [ ], [ --too-wide ], [30])
@result{} --too-wide
@result{} Short doc.
m4_text_wrap([Super long documentation.], [ ],
[ --too-wide ], 30)
@result{} --too-wide
@result{} Super long
@result{} documentation.
@end example
@end defmac
@ -10852,17 +11051,76 @@ Return @var{string} with letters converted to upper or lower case,
respectively.
@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}
@defmac m4_version_compare (@var{version-1}, @var{version-2})
@msindex{version_compare}
This macro was introduced in Autoconf 2.53. Compare the version strings
@var{version-1} and @var{version-2}, and expand to @samp{-1} if
@var{version-1} is smaller, @samp{0} if they are the same, or @samp{1}
@var{version-2} is smaller. Version strings must be a list of elements
separated by @samp{.}, where each element is a number along with an
optional lower case letter. The comparison stops at the leftmost
element that contains a difference, although a 0 element compares equal
to a missing element.
This macro was introduced in Autoconf 2.53, but had a number of
usability limitations that were not lifted until Autoconf 2.62. Compare
the version strings @var{version-1} and @var{version-2}, and expand to
@samp{-1} if @var{version-1} is smaller, @samp{0} if they are the same,
or @samp{1} @var{version-2} is smaller. Version strings must be a list
of elements separated by @samp{.}, where each element is a number along
with optional case-insensitive letters designating beta releases. The
comparison stops at the leftmost element that contains a difference,
although a 0 element compares equal to a missing element.
@example
m4_version_compare([1.1], [2.0])
@ -10875,6 +11133,8 @@ m4_version_compare([1.2], [1.1.1a])
@result{}1
m4_version_compare([1.0], [1])
@result{}0
m4_version_compare([1.1pre], [1.1PRE])
@result{}0
m4_version_compare([1.1a], [1,10])
@result{}-1
@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
by all shells!
Shell functions are considered portable nowadays, though Autoconf
still does not use them (Autotest does). However, inside a shell
function you should not be using @code{$?} to check the return code
of a subshell invocation; in general, since the caller of a shell
function might look at the function's return code, make sure that the
last statement of a shell function does not invoke a subshell.
Using subshells triggers bugs in zsh 4.x; while Autoconf tries
to find a shell that does not exhibit the bug, zsh might be the
only shell present on the user's machine.
Shell functions are considered portable nowadays, though Autoconf still
does not use them (Autotest does). However, inside a shell function,
you should not rely on the error status of a subshell if the last
command of that subshell was @code{exit} or @code{trap}, as this
triggers bugs in zsh 4.x; while Autoconf tries 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
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.
@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}
Expands into an help string that looks pretty when the user executes
@ -17041,9 +17300,6 @@ AC_ARG_WITH([foo],
[use_foo=no])
@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
this:
@ -17052,16 +17308,42 @@ this:
--with-foo use foo (default is no)
@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
@var{left-hand-side} and/or @var{right-hand-side} are composed of macro
arguments, as shown in the following example.
@example
AC_DEFUN([MY_ARG_WITH],
[AC_ARG_WITH([$1],
[AS_HELP_STRING([--with-$1], [use $1 (default is $2)])],
[AC_ARG_WITH(m4_translit([[$1]], [_], [-]),
[AS_HELP_STRING([--with-m4_translit([$1], [_], [-])],
[use $1 (default is $2)])],
[use_[]$1=$withval],
[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 defmac

View File

@ -1289,7 +1289,7 @@ m4_define([AT_SETUP],
m4_define([AT_capture_files], [])
m4_define([AT_line], AT_LINE)
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_append([AT_groups_all], [ ]m4_defn([AT_ordinal]))
m4_divert_push([TEST_FUNCTIONS])dnl

View File

@ -197,7 +197,7 @@ _AS_BOURNE_COMPATIBLE
$1
_ASEOF
}],
[(eval "AS_ESCAPE(m4_quote($1))")])])
[(eval "AS_ESCAPE(m4_expand([$1]))")])])
# _AS_DETECT_REQUIRED(TEST)
@ -1158,14 +1158,21 @@ m4_define([_AS_BOX_INDIR],
_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
# the user executes "script --help". This macro takes three
# arguments, a "left hand side" (LHS), a "right hand side" (RHS), and
# the COLUMN which is a string of white spaces which leads to the
# the RHS column (default: 26 white spaces).
# Format a help string so that it looks pretty when the user executes
# "script --help". This macro takes up to four arguments, a
# "left hand side" (LHS), a "right hand side" (RHS), a decimal
# INDENT-COLUMN which is the column where wrapped lines should begin
# (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
# a help string (e.g. AC_ARG_WITH).
@ -1185,9 +1192,9 @@ _ASBOX])
# "--with-readline", while the RHS is "support fancy command line
# editing".
#
# If the LHS contains more than (COLUMN - 3) characters, then the LHS is
# terminated with a newline so that the RHS starts on a line of its own
# beginning with COLUMN. In the default case, this corresponds to an
# If the LHS contains more than (INDENT-COLUMN - 3) characters, then the
# LHS is terminated with a newline so that the RHS starts on a line of its
# own beginning at INDENT-COLUMN. In the default case, this corresponds to an
# LHS with more than 23 characters.
#
# Therefore, in the example, if the LHS were instead
@ -1206,12 +1213,10 @@ _ASBOX])
# know quadrigraphs.
#
m4_define([AS_HELP_STRING],
[m4_pushdef([AS_Prefix], m4_default([$3], [ ]))dnl
m4_pushdef([AS_Prefix_Format],
[ %-]m4_eval(m4_len(AS_Prefix) - 3)[s ])dnl [ %-23s ]
m4_text_wrap([$2], AS_Prefix, m4_format(AS_Prefix_Format, [[$1]]))dnl
m4_popdef([AS_Prefix_Format])dnl
m4_popdef([AS_Prefix])dnl
[m4_text_wrap([$2], m4_cond([[$3]], [], [ ],
[m4_eval([$3]+0)], [0], [[$3]],
[m4_format([[%*s]], [$3], [])]),
m4_expand([ $1 ]), [$4])dnl
])# AS_HELP_STRING

View File

@ -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])
# -------------------------------------------------------------------
@ -435,29 +447,6 @@ m4_define([m4_cond],
[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. ##
## ---------------------------------------- ##
@ -483,7 +472,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],
@ -491,18 +480,6 @@ m4_define([_m4_bpatsubsts],
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)
# -------------------------------
# If MACRO is undefined, set it to VALUE.
@ -577,14 +554,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(...)
@ -593,6 +580,21 @@ 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_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)
# -----------------
# Like the original, except don't tolerate undefining something which is
@ -610,16 +612,31 @@ m4_define([m4_undefine],
## 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
# is stripped.
#
# 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], [[$*]])
# 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
# 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)
@ -628,16 +645,116 @@ m4_define([m4_quote], [[$*]])
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)
# ------------------
# Return the result of ignoring all quotes in STRING and invoking the
# macros it contains. Amongst other things, this is useful for enabling
# 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_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. ##
## -------------------------- ##
@ -779,13 +896,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)
@ -803,6 +925,31 @@ m4_define([m4_foreach_w],
[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. ##
@ -1645,13 +1792,24 @@ m4_define([m4_normalize],
# m4_join(SEP, ARG1, ARG2...)
# ---------------------------
# Produce ARG1SEPARG2...SEPARGn.
m4_defun([m4_join],
[m4_case([$#],
[1], [],
[2], [[$2]],
[[$2][$1]$0([$1], m4_shift2($@))])])
# Produce ARG1SEPARG2...SEPARGn. Avoid back-to-back SEP when a given ARG
# 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;
# 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])
@ -1726,6 +1884,9 @@ m4_define([m4_append_uniq],
# if the length of FIRST-PREFIX is greater than that of PREFIX, then
# 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:
#
# 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
# the first word, and then ` ' (single space) for all the others.
#
# The algorithm overquotes m4_Prefix1 to avoid m4_defn overhead, and bypasses
# m4_popdef overhead with m4_builtin since no user macro expansion occurs in
# the meantime.
# The algorithm overquotes m4_Prefix and m4_Prefix1 to avoid m4_defn
# overhead, and bypasses m4_popdef overhead with m4_builtin since no user
# 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_pushdef([m4_Prefix], [$2])dnl
m4_pushdef([m4_Prefix1], m4_dquote(m4_default([$3], [m4_Prefix])))dnl
m4_pushdef([m4_Width], m4_default([$4], 79))dnl
m4_pushdef([m4_Cursor], m4_qlen(m4_Prefix1))dnl
m4_pushdef([m4_Separator], [])dnl
m4_Prefix1[]dnl
m4_cond([m4_eval(m4_qlen(m4_Prefix1) > m4_len(m4_Prefix))],
[1], [m4_define([m4_Cursor], m4_len(m4_Prefix))
m4_Prefix],
[m4_eval(m4_qlen(m4_Prefix1) < m4_len(m4_Prefix))],
[0], [],
[m4_define([m4_Cursor], m4_len(m4_Prefix))[]dnl
m4_format([%*s],
m4_max([0], m4_eval(m4_len(m4_Prefix) - m4_qlen(m4_Prefix1))),
[])])[]dnl
m4_foreach_w([m4_Word], [$1],
[m4_define([m4_Cursor],
m4_eval(m4_Cursor + m4_qlen(m4_builtin([defn], [m4_Word])) + 1))dnl
dnl New line if too long, else insert a space unless it is the first
dnl of the words.
m4_if(m4_eval(m4_Cursor > m4_Width),
1, [m4_define([m4_Cursor],
m4_eval(m4_len(m4_Prefix)
+ m4_qlen(m4_builtin([defn], [m4_Word])) + 1))]
m4_Prefix,
[m4_Separator])[]dnl
m4_builtin([defn], [m4_Word])[]dnl
m4_define([m4_Separator], [ ])])dnl
m4_builtin([popdef], [m4_Separator])dnl
m4_builtin([popdef], [m4_Cursor])dnl
m4_builtin([popdef], [m4_Width])dnl
m4_builtin([popdef], [m4_Prefix1])dnl
m4_builtin([popdef], [m4_Prefix])dnl
])
m4_do(dnl set up local variables, to avoid repeated calculations
[[m4_pushdef([m4_Prefix], [[$2]])]],
[[m4_pushdef([m4_Prefix1], m4_if([$3], [], [m4_Prefix], [[[$3]]]))]],
[[m4_pushdef([m4_Width], m4_default([$4], 79))]],
[[m4_pushdef([m4_Indent], m4_qlen(m4_Prefix))]],
[[m4_pushdef([m4_Cursor], m4_qlen(m4_Prefix1))]],
[[m4_pushdef([m4_Separator], [m4_define([m4_Separator], [ ])])]],
dnl expand the first prefix, then check its length vs. regular prefix
dnl same length: nothing special
dnl prefix1 longer: output on line by itself, and reset cursor
dnl prefix1 shorter: pad to length of prefix, and reset cursor
[[m4_Prefix1[]m4_cond([m4_Cursor], m4_Indent, [],
[m4_eval(m4_Cursor > m4_Indent)], [1], [
m4_Prefix[]m4_define([m4_Cursor], m4_Indent)],
[m4_format([%*s], m4_max([0],
m4_eval(m4_Indent - m4_Cursor)), [])m4_define([m4_Cursor], m4_Indent)])]],
dnl now, for each word, compute the curser after the word is output, then
dnl check if the cursor would exceed the wrap column
dnl if so, reset cursor, and insert newline and prefix
dnl if not, insert the separator (usually a space)
dnl either way, insert the word
[[m4_foreach_w([m4_Word], [$1],
[m4_define([m4_Cursor],
m4_eval(m4_Cursor + m4_qlen(m4_builtin([defn], [m4_Word]))
+ 1))m4_if(m4_eval(m4_Cursor > m4_Width),
[1], [m4_define([m4_Cursor],
m4_eval(m4_Indent
+ m4_qlen(m4_builtin([defn], [m4_Word])) + 1))
m4_Prefix[]],
[m4_Separator[]])m4_builtin([defn], [m4_Word])])]],
dnl finally, clean up the local variabls
[[m4_builtin([popdef], [m4_Separator])]],
[[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 = `-'])
@ -1805,7 +1971,7 @@ m4_builtin([popdef], [m4_Prefix])dnl
# using FRAME-CHARACTER in the border.
m4_define([m4_text_box],
[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_Border @%:@@%:@
@%:@@%:@ $1 @%:@@%:@
@ -1850,42 +2016,50 @@ m4_define([m4_cmp],
# m4_list_cmp(A, B)
# -----------------
#
# Compare the two lists of integers A and B. For instance:
# m4_list_cmp((1, 0), (1)) -> 0
# m4_list_cmp((1, 0), (1, 0)) -> 0
# 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, 0), (1, 2)) -> -1
# m4_list_cmp((1), (1, 2)) -> -1
# 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]) -> 0
# 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, 0], [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_if([$1$2], [()()], 0,
[$1], [()], [$0((0), [$2])],
[$2], [()], [$0([$1], (0))],
[m4_case(m4_cmp(m4_car$1, m4_car$2),
-1, -1,
1, 1,
0, [$0((m4_shift$1), (m4_shift$2))])])])
[m4_if([$1$2], [], 0,
[$1], [], [$0(0, [$2])],
[$2], [], [$0([$1], 0)],
[$1], [$2], 0,
[_$0(m4_cmp(m4_car($1), m4_car($2)))([$0(m4_cdr($1), m4_cdr($2))])])])
m4_define([_m4_list_cmp],
[m4_if([$1], 0, [m4_unquote], [$1m4_ignore])])
# m4_max(A, B, ...)
# m4_min(A, B, ...)
# m4_max(EXPR, ...)
# 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
# if both arguments are identical, but be aware of m4_max(0xa, 10) (hence
# the use of <=, not just <, in the second multiply).
m4_define([m4_max],
[m4_if([$#], [0], [m4_fatal([too few arguments to $0])],
[$#], [1], [$1],
[$#$1], [2$2], [$1],
[$#], [1], [m4_eval([$1])],
[$#$1], [2$2], [m4_eval([$1])],
[$#], [2],
[m4_eval((([$1]) > ([$2])) * ([$1]) + (([$1]) <= ([$2])) * ([$2]))],
[$0($0([$1], [$2]), m4_shift2($@))])])
m4_define([m4_min],
[m4_if([$#], [0], [m4_fatal([too few arguments to $0])],
[$#], [1], [$1],
[$#$1], [2$2], [$1],
[$#], [1], [m4_eval([$1])],
[$#$1], [2$2], [m4_eval([$1])],
[$#], [2],
[m4_eval((([$1]) < ([$2])) * ([$1]) + (([$1]) >= ([$2])) * ([$2]))],
[$0($0([$1], [$2]), m4_shift2($@))])])
@ -1906,23 +2080,29 @@ m4_define([m4_sign],
# 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#)
#
#i.e., 2.14a -> 2.15.-1.1, 2.14b -> 2.15.-1.2, etc.
# This macro is absolutely not robust to active macro, it expects
# reasonable version numbers and is valid up to `z', no double letters.
# for example:
# [2.14a] -> [2.14+1.-1.[0r36:a]] -> 2.15.-1.10
# [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_translit(m4_bpatsubsts(m4_tolower([[$1]]),
[\([0-9]+\)\([abcdefghi]\)],
[m4_eval(\1 + 1).-1.\2],
[\([0-9]+\)\([jklmnopqrs]\)],
[m4_eval(\1 + 1).-1.1\2],
[\([0-9]+\)\([tuvwxyz]\)],
[m4_eval(\1 + 1).-1.2\2]),
[abcdefghijklmnopqrstuvwxyz],
[12345678901234567890123456])])
[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])))[[+],
[+1.-1.[0r36:\&]]),
[.], [,])])
# m4_version_compare(VERSION-1, VERSION-2)
@ -1932,8 +2112,7 @@ m4_define([m4_version_unletter],
# 0 if =
# 1 if >
m4_define([m4_version_compare],
[m4_list_cmp((m4_translit(m4_version_unletter([$1]), [.], [,])),
(m4_translit(m4_version_unletter([$2]), [.], [,])))])
[m4_list_cmp(_m4_version_unletter([$1]), _m4_version_unletter([$2]))])
# m4_PACKAGE_NAME
@ -1949,12 +2128,12 @@ m4_include([m4sugar/version.m4])
# ----------------------------------------------------
# Check this Autoconf version against VERSION.
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_fatal([Autoconf version $1 or higher is required],
63)])],
[$2])[]dnl
])
[63])])],
[$2])])

View File

@ -290,7 +290,7 @@ AT_CHECK_AT_TITLE_CHAR([Backslash], [\])
AT_CHECK_AT_TITLE_CHAR([Brackets], [[[]]], [[]])
AT_CHECK_AT_TITLE_CHAR([Pound], [[#]], [#])
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([Macro], [macro_name], [macro_expanded])

View File

@ -490,10 +490,8 @@ AT_CLEANUP
## 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_KEYWORDS([m4@&t@_text_wrap])
AT_DATA_M4SH([script.as],
[[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.])"
echo "AS_HELP_STRING([[--foo[=bar]1234567890123]],
[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
@ -600,6 +610,15 @@ AT_CHECK([./script], [0],
--foo[=bar]1234567890123
some other t[]t which should wrap at our default of
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

View File

@ -44,6 +44,8 @@ AT_CHECK_M4SUGAR([-o-],, [$2], [$3])
#
# - m4_append
#
# - m4_join
#
# - m4_text_wrap
# uses m4_split code.
@ -251,6 +253,43 @@ one, two, three
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. ##
## -------------- ##
@ -313,6 +352,11 @@ m4_version_compare([1.2], [1.1.1a])
m4_version_compare([1.0], [1])
m4_version_compare([1.0a], [1.0a])
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
@ -322,6 +366,10 @@ m4_version_compare([1.1a], [1.1a.1])
0
0
-1
1
0
0
-1
]])
AT_CLEANUP