mirror of
git://git.sv.gnu.org/autoconf
synced 2025-02-23 14:09:51 +08:00
* lib/m4sugar/m4sugar.m4 (_m4_version_unletter): Also treat - as a component separator. * doc/autoconf.texi (Number processing Macros) <m4_version_compare>: Document this change. * tests/m4sugar.at (m4@&t@_version_compare): Test it. Signed-off-by: Eric Blake <ebb9@byu.net>
675 lines
13 KiB
Plaintext
675 lines
13 KiB
Plaintext
# -*- Autotest -*-
|
|
|
|
AT_BANNER([M4sugar.])
|
|
|
|
# Copyright (C) 2000, 2001, 2002, 2005, 2006, 2007 Free Software Foundation, Inc.
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
# AT_CHECK_M4SUGAR_TEXT(CODE, STDOUT, STDERR)
|
|
# -------------------------------------------
|
|
# Check that m4sugar CODE expands to STDOUT and emits STDERR.
|
|
m4_define([AT_CHECK_M4SUGAR_TEXT],
|
|
[
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_divert_push(0)[]dnl
|
|
]$1[[]dnl
|
|
m4_divert_pop(0)
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-],, [$2], [$3])
|
|
])# AT_CHECK_M4SUGAR_TEXT
|
|
|
|
|
|
# Order of the tests:
|
|
# - m4_warn
|
|
#
|
|
# - m4_require
|
|
# uses warn/error code.
|
|
#
|
|
# - m4_split
|
|
#
|
|
# - m4_append
|
|
#
|
|
# - m4_join
|
|
#
|
|
# - m4_text_wrap
|
|
# uses m4_split code.
|
|
|
|
## --------- ##
|
|
## m4_warn. ##
|
|
## --------- ##
|
|
|
|
AT_SETUP([m4@&t@_warn])
|
|
|
|
# m4_text_wrap is used to display the help strings. Also, check that
|
|
# commas are not swallowed. This can easily happen because of
|
|
# m4-listification.
|
|
|
|
# FIXME: For the time being we use -f to make sure we do issue the
|
|
# warnings. But maybe autom4te should handle that by itself?
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_defun([cross_warning], [m4_warn([cross], [cross])])
|
|
|
|
m4_divert([0])dnl
|
|
m4_warn([obsolete], [obsolete])dnl
|
|
cross_warning[]dnl
|
|
m4_warn([syntax], [syntax])dnl
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 0, [],
|
|
[script.4s:7: warning: syntax
|
|
])
|
|
|
|
AT_CHECK_M4SUGAR([-o- -Wall -f], 0, [],
|
|
[script.4s:5: warning: obsolete
|
|
script.4s:6: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:6: the top level
|
|
script.4s:7: warning: syntax
|
|
])
|
|
|
|
AT_CHECK_M4SUGAR([-o- -Wnone,cross -f], 0, [],
|
|
[script.4s:6: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:6: the top level
|
|
])
|
|
|
|
AT_CHECK_M4SUGAR([-o- -Wnone,cross,error -f], 1, [],
|
|
[[script.4s:6: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:6: the top level
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------------------- ##
|
|
## m4_require: error message. ##
|
|
## --------------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_require: error message])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_defun([foo], [FOO])
|
|
m4_require([foo])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:2: error: m4@&t@_require(foo): cannot be used outside of an m4_defun'd macro
|
|
script.4s:2: the top level
|
|
autom4te: m4 failed with exit status: 1
|
|
]])
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------------------------------- ##
|
|
## m4_require: circular dependencies. ##
|
|
## ----------------------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_require: circular dependencies])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_defun([foo], [m4_require([bar])])
|
|
|
|
m4_defun([bar], [m4_require([foo])])
|
|
|
|
m4_defun([baz], [m4_require([foo])])
|
|
|
|
m4_init
|
|
m4_divert([0])dnl
|
|
baz
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:9: error: m4@&t@_require: circular dependency of foo
|
|
script.4s:3: bar is expanded from...
|
|
script.4s:1: foo is expanded from...
|
|
script.4s:5: baz is expanded from...
|
|
script.4s:9: the top level
|
|
autom4te: m4 failed with exit status: 1
|
|
]])
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------- ##
|
|
## m4_split. ##
|
|
## ---------- ##
|
|
|
|
AT_SETUP([m4@&t@_split])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_define([active], [ACT, IVE])m4_define([bd], [oops])
|
|
m4_split
|
|
m4_split([[]])
|
|
m4_split([ ])
|
|
m4_split([active])
|
|
m4_split([ active active ])end
|
|
m4_split([ ], [ ])
|
|
m4_split([active], [ ])
|
|
m4_split([ active active ], [ ])end
|
|
m4_split([abcde], [bd])
|
|
m4_split([abcde], [[bd]])
|
|
m4_split([foo=`` bar=''])
|
|
m4_split([foo='' bar=``])
|
|
]],
|
|
[[
|
|
|
|
[[]]
|
|
[], []
|
|
[active]
|
|
[], [active], [active], []end
|
|
[], []
|
|
[active]
|
|
[], [active active], []end
|
|
[abcde]
|
|
[a], [c], [e]
|
|
[foo=``], [bar='']
|
|
[foo=''], [bar=``]
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------- ##
|
|
## m4_append. ##
|
|
## ----------- ##
|
|
|
|
AT_SETUP([m4@&t@_append])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_define([active], [ACTIVE])dnl
|
|
m4_append([sentence], [This is an])dnl
|
|
m4_append([sentence], [ active ])dnl
|
|
m4_append([sentence], [symbol.])dnl
|
|
sentence
|
|
m4_undefine([active])dnl
|
|
sentence
|
|
m4_define([active], [ACTIVE])dnl
|
|
m4_append([hooks], [m4_define([act1], [act2])])dnl
|
|
m4_append([hooks], [m4_define([act2], [active])])dnl
|
|
m4_undefine([active])dnl
|
|
act1
|
|
hooks
|
|
act1
|
|
dnl Test for bug fixed in 2.62 when separator is active.
|
|
m4_define([a], [A])dnl
|
|
m4_append_uniq([foo], [-], [a])dnl
|
|
m4_append_uniq([foo], [-], [a])dnl
|
|
m4_append_uniq([bar], [-], [a])dnl
|
|
m4_append_uniq([bar], [~], [a])dnl
|
|
m4_append_uniq([bar], [-], [a])dnl
|
|
m4_defn([foo])
|
|
m4_defn([bar])
|
|
foo
|
|
bar
|
|
m4_append_uniq([blah], [one], [, ], [new], [existing])
|
|
m4_append_uniq([blah], [two], [, ], [new], [existing])
|
|
m4_append_uniq([blah], [two], [, ], [new], [existing])
|
|
m4_append_uniq([blah], [three], [, ], [new], [existing])
|
|
m4_append([blah], [two], [, ])dnl
|
|
blah
|
|
m4_dquote(blah)
|
|
m4_append([list], [one], [[, ]])dnl
|
|
m4_append([list], [two], [[, ]])dnl
|
|
m4_append([list], [three], [[, ]])dnl
|
|
list
|
|
m4_dquote(list)
|
|
m4_append_uniq_w([numbers], [1 1 2])dnl
|
|
m4_append_uniq_w([numbers], [ 2 3 ])dnl
|
|
numbers
|
|
]],
|
|
[[This is an ACTIVE symbol.
|
|
This is an active symbol.
|
|
act1
|
|
|
|
active
|
|
-
|
|
-a~
|
|
-
|
|
-A~
|
|
new
|
|
new
|
|
existing
|
|
new
|
|
one, two, three, two
|
|
[one],[two],[three],[two]
|
|
one, two, three
|
|
[one, two, three]
|
|
1 2 3
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_append_uniq([str], [a], [ ])
|
|
m4_append_uniq([str], [a b], [ ])
|
|
m4_divert([0])dnl
|
|
str
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 0, [[a a b
|
|
]], [[script.4s:2: warning: m4@&t@_append_uniq: `a b' contains ` '
|
|
]])
|
|
|
|
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. ##
|
|
## -------------- ##
|
|
|
|
AT_SETUP([m4@&t@_text_wrap])
|
|
|
|
# m4_text_wrap is used to display the help strings. Also, check that
|
|
# commas are not swallowed. This can easily happen because of
|
|
# m4-listification.
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_divert([0])dnl
|
|
m4_text_wrap([Short string */], [ ], [/* ], 20)
|
|
|
|
m4_text_wrap([Much longer string */], [ ], [/* ], 20)
|
|
|
|
m4_text_wrap([Short doc.], [ ], [ --short ], 30)
|
|
|
|
m4_text_wrap([Short doc.], [ ], [ --too-wide], 30)
|
|
|
|
m4_text_wrap([Super long documentation.], [ ], [ --too-wide], 30)
|
|
|
|
m4_text_wrap([First, second , third, [,quoted]])
|
|
]])
|
|
|
|
AT_DATA([expout],
|
|
[[/* Short string */
|
|
|
|
/* Much longer
|
|
string */
|
|
|
|
--short Short doc.
|
|
|
|
--too-wide
|
|
Short doc.
|
|
|
|
--too-wide
|
|
Super long
|
|
documentation.
|
|
|
|
First, second , third, [,quoted]
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 0, [expout])
|
|
|
|
AT_CLEANUP
|
|
|
|
## -------------------- ##
|
|
## m4_version_compare. ##
|
|
## -------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_version_compare])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_version_compare([1.1], [2.0])
|
|
m4_version_compare([2.0b], [2.0a])
|
|
m4_version_compare([2.0z], [2.0y])
|
|
m4_version_compare([1.1.1], [1.1.1a])
|
|
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])
|
|
m4_version_compare([2.61a], [2.61a-248-dc51])
|
|
m4_version_compare([2.61b], [2.61a-248-dc51])
|
|
]],
|
|
[[-1
|
|
1
|
|
1
|
|
-1
|
|
1
|
|
0
|
|
0
|
|
-1
|
|
1
|
|
0
|
|
0
|
|
-1
|
|
-1
|
|
1
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------------ ##
|
|
## Standard regular expressions. ##
|
|
## ------------------------------ ##
|
|
|
|
AT_SETUP([Standard regular expressions])
|
|
|
|
# AT_CHECK_M4RE(RE-NAME, TEXT, INTENT = `ok' | `')
|
|
# ------------------------------------------------
|
|
# Check whether RE-NAME (a macro whose definition is a regular expression)
|
|
# matches TEXT. INTENT = `ok' if the match should succeed or else empty.
|
|
m4_define([AT_CHECK_M4RE],
|
|
[AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_bregexp([$2], ^m4_defn([$1])$, [ok])
|
|
]], [$3
|
|
])])
|
|
|
|
AT_CHECK_M4RE([m4_re_word], [ab9_c], [ok])
|
|
AT_CHECK_M4RE([m4_re_word], [_9abc], [ok])
|
|
AT_CHECK_M4RE([m4_re_word], [9ab_c])
|
|
|
|
AT_CHECK_M4RE([m4_re_string], [ab9_c], [ok])
|
|
AT_CHECK_M4RE([m4_re_string], [_9abc], [ok])
|
|
AT_CHECK_M4RE([m4_re_string], [9ab_c], [ok])
|
|
AT_CHECK_M4RE([m4_re_string], [9a@_c])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ---------- ##
|
|
## M4 Loops. ##
|
|
## ---------- ##
|
|
|
|
AT_SETUP([M4 loops])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_define([myvar], [outer value])dnl
|
|
m4_for([myvar], 1, 3, 1, [ myvar])
|
|
m4_for([myvar], 1, 3, , [ myvar])
|
|
m4_for([myvar], 3, 1,-1, [ myvar])
|
|
m4_for([myvar], 3, 1, , [ myvar])
|
|
m4_for([myvar], 1, 3, 2, [ myvar])
|
|
m4_for([myvar], 3, 1,-2, [ myvar])
|
|
m4_for([myvar],-1,-3,-2, [ myvar])
|
|
m4_for([myvar],-3,-1, 2, [ myvar])
|
|
dnl Make sure we recalculate the bounds correctly:
|
|
m4_for([myvar], 1, 3, 3, [ myvar])
|
|
m4_for([myvar], 1, 6, 3, [ myvar])
|
|
m4_for([myvar],22,-7,-5, [ myvar])
|
|
m4_for([myvar],-2,-7,-4, [ myvar])
|
|
m4_for([myvar],-7,-2, 4, [ myvar])
|
|
dnl Make sure we are not exposed to division truncation:
|
|
m4_for([myvar], 2, 5, 2, [ myvar])
|
|
m4_for([myvar],-5,-2, 2, [ myvar])
|
|
m4_for([myvar], 5, 2,-2, [ myvar])
|
|
m4_for([myvar],-2,-5,-2, [ myvar])
|
|
dnl Make sure we do not divide by zero:
|
|
m4_for([myvar], 1, 1, , [ myvar])
|
|
m4_for([myvar], 1, 1,+2, [ myvar])
|
|
m4_for([myvar], 1, 1,-2, [ myvar])
|
|
dnl Make sure we do not loop endlessly
|
|
m4_for([myval], 1, 1, 0, [ myval])
|
|
dnl Make sure to properly parenthesize
|
|
m4_for([myvar], 3-5, -2+8, , [ myvar])
|
|
m4_for([myvar], -2+8, 3-5, , [ myvar])
|
|
m4_for([myvar], 8, 16, 3 * 2, [ myvar])
|
|
m4_for([myvar], 8, 16, -3 * -2, [ myvar])
|
|
m4_for([myvar], [2<<2], [2<<3], [-3 * (-2)], [ myvar])
|
|
dnl Make sure we can do nameless iteration
|
|
m4_for(, 1, 10, , -)
|
|
dnl foreach tests
|
|
m4_foreach([myvar], [[a], [b, c], [d], [e
|
|
],[f]], [ myvar|])
|
|
m4_foreach_w([myvar], [a b c, d,e f
|
|
g], [ myvar|])
|
|
myvar
|
|
]],
|
|
[[ 1 2 3
|
|
1 2 3
|
|
3 2 1
|
|
3 2 1
|
|
1 3
|
|
3 1
|
|
-1 -3
|
|
-3 -1
|
|
1
|
|
1 4
|
|
22 17 12 7 2 -3
|
|
-2 -6
|
|
-7 -3
|
|
2 4
|
|
-5 -3
|
|
5 3
|
|
-2 -4
|
|
1
|
|
1
|
|
1
|
|
1
|
|
-2 -1 0 1 2 3 4 5 6
|
|
6 5 4 3 2 1 0 -1 -2
|
|
8 14
|
|
8 14
|
|
8 14
|
|
----------
|
|
a| b, c| d| e
|
|
| f|
|
|
a| b| c,| d,e| f| g|
|
|
outer value
|
|
]], [])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_divert([0])dnl
|
|
m4_for([myvar], 1, 3,-1, [ myvar])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:3: error: assert failed: -1 > 0
|
|
script.4s:3: the top level
|
|
autom4te: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_divert([0])dnl
|
|
m4_for([myvar], 1, 2, 0, [ myvar])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:3: error: assert failed: 0 > 0
|
|
script.4s:3: the top level
|
|
autom4te: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_divert([0])dnl
|
|
m4_for([myvar], 2, 1, 0, [ myvar])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:3: error: assert failed: 0 < 0
|
|
script.4s:3: the top level
|
|
autom4te: m4 failed with exit status: 1
|
|
]])
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------- ##
|
|
## m4_map{,_sep}. ##
|
|
## --------------- ##
|
|
|
|
AT_SETUP([m4@&t@_map])
|
|
AT_KEYWORDS([m4@&t@_apply])
|
|
AT_KEYWORDS([m4@&t@_count])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_map([m4_count], [])
|
|
m4_map([ m4_count], [[],
|
|
[[1]],
|
|
[[1], [2]]])
|
|
m4_map_sep([m4_eval], [,], [[[1+2]],
|
|
[[10], [16]]])
|
|
m4_define([a], [m4_if([$#], [0], [oops], [$1], [a], [pass], [oops])])dnl
|
|
m4_define([a1], [oops])dnl
|
|
m4_define([pass1], [oops])dnl
|
|
m4_map([a], [[[a]]])1
|
|
m4_map([m4_unquote([a])], [m4_dquote([a])])
|
|
]],
|
|
[[
|
|
0 1 2
|
|
3,a
|
|
pass1
|
|
pass
|
|
]], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------ ##
|
|
## m4_combine. ##
|
|
## ------------ ##
|
|
|
|
AT_SETUP([m4@&t@_combine])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_define([a], [oops])dnl
|
|
m4_combine([, ], [[a], [b], [c]], [-], [1], [2], [3])
|
|
m4_combine([, ], [[a], [b]], [-])
|
|
m4_combine([, ], [[a], [b]], [-], [])
|
|
m4_combine([, ], [], [-], [a], [b])
|
|
m4_combine([, ], [[]], [-], [a], [b])
|
|
m4_combine([ a ], [[-], [+]], [a], [-], [+])
|
|
]],
|
|
[[a-1, a-2, a-3, b-1, b-2, b-3, c-1, c-2, c-3
|
|
|
|
a-, b-
|
|
|
|
-a, -b
|
|
-a- a -a+ a +a- a +a+
|
|
]], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## -------------- ##
|
|
## m4_{max,min}. ##
|
|
## -------------- ##
|
|
|
|
AT_SETUP([m4@&t@_max and m4@&t@_min])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_max
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:1: error: too few arguments to m4@&t@_max
|
|
script.4s:1: the top level
|
|
autom4te: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_min
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:1: error: too few arguments to m4@&t@_min
|
|
script.4s:1: the top level
|
|
autom4te: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_min(0)
|
|
m4_min(0xa)
|
|
m4_min(0, 0)
|
|
m4_min(0, 1)
|
|
m4_min(1, 0)
|
|
m4_min(0+1, 1+1)
|
|
m4_min(0+1, 1+0)
|
|
m4_min(0, 1, 2)
|
|
m4_min(2, 1, 0)
|
|
m4_min(1m4_for([i], 2, 100, , [,i]))
|
|
m4_min(m4_for([i], 100, 2, , [i,])1)
|
|
----
|
|
m4_max(0)
|
|
m4_max(0xa)
|
|
m4_max(0, 0)
|
|
m4_max(0, 1)
|
|
m4_max(1, 0)
|
|
m4_max(1+0, 1+1)
|
|
m4_max(1+0, 1+0)
|
|
m4_max(0, 1, 2)
|
|
m4_max(2, 1, 0)
|
|
m4_max(1m4_for([i], 2, 100, , [,i]))
|
|
m4_max(m4_for([i], 100, 2, , [i,])1)
|
|
]],
|
|
[[0
|
|
10
|
|
0
|
|
0
|
|
0
|
|
1
|
|
1
|
|
0
|
|
0
|
|
1
|
|
1
|
|
----
|
|
0
|
|
10
|
|
0
|
|
1
|
|
1
|
|
2
|
|
1
|
|
2
|
|
2
|
|
100
|
|
100
|
|
]], [])
|
|
|
|
AT_CLEANUP
|