From 6e1d6e2c5bea266157056e5fce5fe9113f14002e Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 13 Oct 2007 07:47:46 -0600 Subject: [PATCH] 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. Signed-off-by: Eric Blake --- ChangeLog | 24 ++++++ NEWS | 19 +++-- doc/autoconf.texi | 179 +++++++++++++++++++++++++++++++++++------ lib/m4sugar/m4sugar.m4 | 160 +++++++++++++++++++++--------------- tests/m4sugar.at | 9 +++ 5 files changed, 295 insertions(+), 96 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7c3bb048..ac752fd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2007-10-13 Eric Blake + + 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 * doc/autoconf.texi (Text processing Macros): Fix bad merge. diff --git a/NEWS b/NEWS index 00d30191..95c7e3bd 100644 --- a/NEWS +++ b/NEWS @@ -78,18 +78,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_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 +117,8 @@ 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_cond m4_ignore 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. diff --git a/doc/autoconf.texi b/doc/autoconf.texi index 26ca6fd7..f63dfa20 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -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 an implementation of @code{m4_map}; note how each +iteration of the helper macro @code{_m4_map} checks for the end of +recursion, then merely applies the first argument to the first element +of the list, then recurses with the rest of the list. +@example +m4_define([m4_map], [m4_if([$2], [[]], [], [_$0($@@)])])dnl +m4_define([_m4_map], [m4_ifval([$2], + [$1(m4_unquote(m4_car($2)))[]$0([$1], m4_cdr($2))])])dnl +m4_map([ m4_eval], [[1],[1+1]]) +@result{} 1 2 +@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,14 +10660,7 @@ 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. -@end defmac +@c TODO document m4_map, m4_map_sep @defmac m4_shiftn (@var{count}, @dots{}) @defmacx m4_shift2 (@dots{}) @@ -10649,18 +10680,59 @@ 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_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_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 + +@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 + +@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 (i), not @@ -10695,7 +10767,7 @@ mkargs @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. @@ -10852,17 +10924,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 +11006,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 diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index 677695b7..dd5138ef 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -491,18 +491,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. @@ -610,16 +598,15 @@ m4_define([m4_undefine], ## 7. Quoting manipulation. ## ## ------------------------- ## -# m4_quote(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], [[$*]]) +# 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 +615,47 @@ m4_define([m4_quote], [[$*]]) m4_define([m4_dquote], [[$@]]) +# 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_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. +# +# 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_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. ## ## -------------------------- ## @@ -1850,42 +1868,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_max(A, B, ...) -# m4_min(A, B, ...) +[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(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 +1932,28 @@ 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], [.], _$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 +1963,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 +1979,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])]) diff --git a/tests/m4sugar.at b/tests/m4sugar.at index 3c537e00..a946104d 100644 --- a/tests/m4sugar.at +++ b/tests/m4sugar.at @@ -313,6 +313,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 +327,10 @@ m4_version_compare([1.1a], [1.1a.1]) 0 0 -1 +1 +0 +0 +-1 ]]) AT_CLEANUP -- 2.47.2