mirror of
git://git.sv.gnu.org/autoconf
synced 2025-01-30 11:01:45 +08:00
9c3f25710d
* bootstrap (PACKAGE_NAME, PACKAGE_BUGREPORT): * lib/autoconf/status.m4 (AC_OUTPUT_MAKE_DEFS): * maint.mk (longopt_re, gpg_key_ID): * tests/m4sugar.at (m4_dumpdef): Avoid \] in POSIX-specified regular expressions, as POSIX says \] produces undefined results in BREs and EREs.
2194 lines
45 KiB
Plaintext
2194 lines
45 KiB
Plaintext
# -*- Autotest -*-
|
|
|
|
AT_BANNER([M4sugar.])
|
|
|
|
# Copyright (C) 2000-2002, 2005-2017, 2020-2022 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 <https://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([])[]dnl
|
|
]$1[[]dnl
|
|
m4_divert_pop([])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-],, [$2], [$3])
|
|
])# AT_CHECK_M4SUGAR_TEXT
|
|
|
|
|
|
## ------------------ ##
|
|
## m4_stack_foreach. ##
|
|
## ------------------ ##
|
|
|
|
AT_SETUP([m4@&t@_stack])
|
|
|
|
AT_KEYWORDS([m4@&t@_stack_foreach m4@&t@_stack_foreach_lifo])
|
|
AT_KEYWORDS([m4@&t@_stack_foreach_sep m4@&t@_stack_foreach_sep_lifo])
|
|
AT_KEYWORDS([m4@&t@_copy m4@&t@_n])
|
|
|
|
# Test the semantics of macros to walk stacked macro definitions.
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_pushdef([abc], [def])dnl
|
|
m4_pushdef([abc], [ghi])dnl
|
|
m4_pushdef([abc], [jkl])dnl
|
|
m4_stack_foreach([abc], [m4_n])
|
|
abc
|
|
m4_stack_foreach_lifo([abc], [m4_n])
|
|
m4_stack_foreach([abc], [m4_n])
|
|
m4_copy([abc], [foo])dnl
|
|
m4_stack_foreach([foo], [m4_n])
|
|
m4_stack_foreach_lifo([foo], [m4_n])
|
|
m4_stack_foreach_sep([abc], [ m4_index([abcdefghijkl],], [)])
|
|
m4_define([colon], [:])m4_define([lt], [<])m4_define([gt], [>])dnl
|
|
m4_stack_foreach_sep_lifo([abc], [lt], [gt], [colon])
|
|
m4_pushdef([xyz], [123])dnl
|
|
m4_pushdef([xyz], [456])dnl
|
|
m4_define([doit], [[$1](m4_stack_foreach_sep([xyz], [m4_dquote(], [)], [,]))
|
|
])dnl
|
|
m4_stack_foreach([abc], [doit])]],
|
|
[[def
|
|
ghi
|
|
jkl
|
|
|
|
jkl
|
|
jkl
|
|
ghi
|
|
def
|
|
|
|
def
|
|
ghi
|
|
jkl
|
|
|
|
def
|
|
ghi
|
|
jkl
|
|
|
|
jkl
|
|
ghi
|
|
def
|
|
|
|
3 6 9
|
|
<jkl>:<ghi>:<def>
|
|
def([123],[456])
|
|
ghi([123],[456])
|
|
jkl([123],[456])
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------- ##
|
|
## m4_defn. ##
|
|
## --------- ##
|
|
|
|
AT_SETUP([m4@&t@_defn])
|
|
|
|
AT_KEYWORDS([m4@&t@_popdef m4@&t@_undefine m4@&t@_copy m4@&t@_rename
|
|
m4@&t@_copy_force m4@&t@_rename_force])
|
|
|
|
# Ensure that m4sugar dies when dereferencing undefined macros, whether
|
|
# this is provided by m4 natively or faked by wrappers in m4sugar.
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_define([good])
|
|
m4_defn([good], [oops])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
|
|
AT_CHECK([grep good stderr], [1])
|
|
AT_CHECK([grep 'm4@&t@_defn: undefined.*oops' stderr], [0], [ignore])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_define([good])
|
|
m4_popdef([good], [oops])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
|
|
AT_CHECK([grep good stderr], [1])
|
|
AT_CHECK([grep 'm4@&t@_popdef: undefined.*oops' stderr], [0], [ignore])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_define([good])
|
|
m4_undefine([good], [oops])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
|
|
AT_CHECK([grep good stderr], [1])
|
|
AT_CHECK([grep 'm4@&t@_undefine: undefined.*oops' stderr], [0], [ignore])
|
|
|
|
# Cannot rename an undefined macro.
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_rename([oops], [good])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
|
|
AT_CHECK([grep 'm4@&t@_undefine: undefined.*oops' stderr], [0], [ignore])
|
|
|
|
# Check that pushdef stacks can be renamed.
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_pushdef([a], [1])dnl
|
|
m4_pushdef([a], [2])dnl
|
|
m4_pushdef([a], m4_defn([m4_divnum]))dnl
|
|
a b c
|
|
m4_rename([a], [b])dnl
|
|
a b c
|
|
m4_copy([b], [c])dnl
|
|
a b c
|
|
m4_popdef([b], [c])dnl
|
|
a b c
|
|
m4_popdef([b], [c])dnl
|
|
a b c
|
|
m4_popdef([b], [c])dnl
|
|
a b c
|
|
dnl m4_copy is intentionally a no-op on undefined source
|
|
m4_copy([oops], [dummy])m4_ifdef([dummy], [[oops]])dnl
|
|
dnl allow forceful overwrites
|
|
m4_define([d], [4])m4_define([e], [5])m4_define([f], [6])dnl
|
|
m4_copy_force([d], [e])dnl
|
|
m4_rename_force([d], [f])dnl
|
|
d e f
|
|
m4_popdef([e], [f])dnl
|
|
d e f
|
|
]], [[0 b c
|
|
a 0 c
|
|
a 0 0
|
|
a 2 2
|
|
a 1 1
|
|
a b c
|
|
d 4 4
|
|
d e f
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------ ##
|
|
## m4_dumpdef. ##
|
|
## ------------ ##
|
|
|
|
AT_SETUP([m4@&t@_dumpdef])
|
|
|
|
AT_KEYWORDS([m4@&t@_dumpdefs])
|
|
|
|
# Ensure that m4sugar dies when dereferencing undefined macros.
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_define([good], [yep])
|
|
m4_dumpdef([good], [oops])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
|
|
AT_CHECK([grep '^good: \[[yep]]$' stderr], [0], [ignore])
|
|
AT_CHECK([grep 'm4@&t@_dumpdef: undefined.*oops' stderr], [0], [ignore])
|
|
|
|
# Check that pushdef stacks can be dumped.
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_divert_push([KILL])
|
|
m4_pushdef([a], [1])
|
|
m4_pushdef([a], [2])
|
|
m4_dumpdef([a])
|
|
m4_dumpdefs([oops], [a])
|
|
m4_divert_pop([KILL])dnl
|
|
]], [],
|
|
[[a: [2]
|
|
a: [2]
|
|
a: [1]
|
|
]])
|
|
|
|
# Check behavior when dumping builtins. Unfortunately, when using M4 1.4.x
|
|
# (or more precisely, when __m4_version__ is undefined), builtins get
|
|
# flattened to an empty string. It takes M4 1.6 to work around this.
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_ifdef([__m4_version__], [_m4_undefine([__m4_version__])])
|
|
m4_init
|
|
m4_dumpdef([m4_define])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], [0], [],
|
|
[[m4_define: []
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_ifdef([__m4_version__],
|
|
[m4_dumpdef([m4_define])],
|
|
[m4_errprintn([m4_define: <define>])])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], [0], [],
|
|
[[m4_define: <define>
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------- ##
|
|
## m4_warn. ##
|
|
## --------- ##
|
|
|
|
AT_SETUP([m4@&t@_warn])
|
|
|
|
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
|
|
cross_warning[]dnl
|
|
m4_warn([syntax], [syntax])dnl
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 0, [],
|
|
[script.4s:4: warning: prefer named diversions
|
|
script.4s:5: warning: obsolete
|
|
script.4s:7: warning: syntax
|
|
script.4s:9: warning: syntax
|
|
])
|
|
|
|
AT_CHECK_M4SUGAR([-o- -Wall], 0, [],
|
|
[script.4s:4: warning: prefer named diversions
|
|
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
|
|
script.4s:8: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:8: the top level
|
|
script.4s:9: warning: syntax
|
|
])
|
|
|
|
AT_CHECK_M4SUGAR([-o- -Wnone,cross], 0, [],
|
|
[script.4s:6: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:6: the top level
|
|
script.4s:8: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:8: the top level
|
|
])
|
|
|
|
AT_CHECK_M4SUGAR([-o- -Wnone,cross,error], 1, [],
|
|
[[script.4s:6: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:6: the top level
|
|
script.4s:8: warning: cross
|
|
script.4s:2: cross_warning is expanded from...
|
|
script.4s:8: the top level
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------------- ##
|
|
## m4_divert_stack. ##
|
|
## ----------------- ##
|
|
|
|
AT_SETUP([m4@&t@_divert_stack])
|
|
AT_KEYWORDS([m4@&t@_divert m4@&t@_divert_push m4@&t@_divert_pop
|
|
m4@&t@_undivert m4@&t@_cleardivert m4@&t@_divert_text])
|
|
|
|
dnl This test names some diversions to avoid a warning.
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_define([_m4_divert(ten)], [10])dnl
|
|
m4_define([_m4_divert(twenty)], [20])dnl
|
|
m4_define([_m4_divert(thirty)], [30])dnl
|
|
1.m4_divert_stack
|
|
m4_divert_push([ten])2.m4_divert_stack
|
|
m4_divert_text([twenty], [3.m4_divert_stack])dnl
|
|
m4_divert([thirty])4.m4_divert_stack
|
|
m4_divert_pop([thirty])dnl
|
|
5.m4_undivert([twenty], [thirty])
|
|
m4_pattern_allow([^m4_divert])dnl
|
|
]], [[1.script.4s:2: m4@&t@_divert_push:
|
|
script.4s:1: m4@&t@_divert: KILL
|
|
5.3.script.4s:8: m4@&t@_divert_push: twenty
|
|
script.4s:7: m4@&t@_divert_push: ten
|
|
script.4s:2: m4@&t@_divert_push:
|
|
script.4s:1: m4@&t@_divert: KILL
|
|
4.script.4s:9: m4@&t@_divert: thirty
|
|
script.4s:2: m4@&t@_divert_push:
|
|
script.4s:1: m4@&t@_divert: KILL
|
|
|
|
2.script.4s:7: m4@&t@_divert_push: ten
|
|
script.4s:2: m4@&t@_divert_push:
|
|
script.4s:1: m4@&t@_divert: KILL
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_divert_text([3], [three])dnl
|
|
m4_divert_text([4], [four])dnl
|
|
m4_divert_text([1], [one])dnl
|
|
m4_divert_text([2], [two])dnl
|
|
m4_cleardivert([2], [3])dnl
|
|
]],
|
|
[[one
|
|
four
|
|
]],
|
|
[[script.4s:4: warning: prefer named diversions
|
|
script.4s:5: warning: prefer named diversions
|
|
script.4s:6: warning: prefer named diversions
|
|
script.4s:7: warning: prefer named diversions
|
|
script.4s:8: warning: prefer named diversions
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_divert_pop
|
|
]])
|
|
AT_CHECK_M4SUGAR([-o-], [1], [],
|
|
[[script.4s:1: error: too many m4@&t@_divert_pop
|
|
script.4s:1: the top level
|
|
autom4te: error: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_divert_push([1])
|
|
m4_divert_pop([2])
|
|
]])
|
|
AT_CHECK_M4SUGAR([-o-], [1], [],
|
|
[[script.4s:3: error: m4@&t@_divert_pop(2): diversion mismatch:
|
|
script.4s:2: m4@&t@_divert_push: 1
|
|
script.4s:1: m4@&t@_divert: KILL
|
|
script.4s:3: the top level
|
|
autom4te: error: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_divert([1])
|
|
m4_init
|
|
m4_divert_push([2])
|
|
]])
|
|
AT_CHECK_M4SUGAR([-o-], [1], [],
|
|
[[script.4s:2: error: m4@&t@_init: unbalanced m4@&t@_divert_push:
|
|
script.4s:3: m4@&t@_divert_push: 2
|
|
script.4s:2: m4@&t@_divert: KILL
|
|
script.4s:2: the top level
|
|
autom4te: error: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## -------------------- ##
|
|
## m4_expansion_stack. ##
|
|
## -------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_expansion_stack])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[1.m4_expansion_stack
|
|
m4_defun([a], [b])dnl
|
|
m4_define([c], [d])dnl
|
|
m4_defun([d], [2.m4_expansion_stack])dnl
|
|
m4_defun([b], [c])dnl
|
|
a
|
|
3.m4_ifdef([_m4_expansion_stack], [m4_expansion_stack])
|
|
]], [[1.script.4s:3: the top level
|
|
2.script.4s:6: d is expanded from...
|
|
script.4s:7: b is expanded from...
|
|
script.4s:4: a is expanded from...
|
|
script.4s:8: the top level
|
|
3.
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------------------- ##
|
|
## m4_require: error message. ##
|
|
## --------------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_require: error message])
|
|
AT_KEYWORDS([m4@&t@_require])
|
|
|
|
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: error: m4 failed with exit status: 1
|
|
]])
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------------------------- ##
|
|
## m4_require: warning message. ##
|
|
## ----------------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_require: warning message])
|
|
AT_KEYWORDS([m4@&t@_require m4@&t@_require_silent_probe])
|
|
|
|
# Mirror the job of aclocal on a typical scenario: the user invokes a
|
|
# single macro that comes from one included file, which in turn requires
|
|
# another macro from a second file. When using the incomplete set of
|
|
# files, we want a warning, unless we are merely learning which additional
|
|
# macros are needed in order to regenerate the list of files to include.
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_include([script1.4s])
|
|
foo
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script1.4s],
|
|
[[m4_defun([foo], [m4_require([bar])])
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script2.4s],
|
|
[[m4_defun([bar], [BAR])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], [0], [],
|
|
[[script.4s:3: warning: bar is m4@&t@_require'd but not m4@&t@_defun'd
|
|
script1.4s:1: foo is expanded from...
|
|
script.4s:3: the top level
|
|
]])
|
|
|
|
# Inline expansion of AT_CHECK_M4SUGAR, mirroring how aclocal will
|
|
# inject a definition of our witness macro for a silent run.
|
|
echo 'm4@&t@_define([m4@&t@_require_silent_probe])' |
|
|
AT_CHECK_AUTOM4TE([--language=m4sugar - script.4s -o script],
|
|
[0], [], [])
|
|
|
|
# Now that we have recomputed the set of include files, things should work.
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_include([script1.4s])
|
|
m4_include([script2.4s])
|
|
foo
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([], [0], [], [])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------------------------------- ##
|
|
## m4_require: circular dependencies. ##
|
|
## ----------------------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_require: circular dependencies])
|
|
AT_KEYWORDS([m4@&t@_require])
|
|
|
|
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: error: m4 failed with exit status: 1
|
|
]])
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------------- ##
|
|
## m4_require: one-shot. ##
|
|
## ---------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_require: one-shot initialization])
|
|
AT_KEYWORDS([m4@&t@_require])
|
|
AT_KEYWORDS([m4@&t@_defun_init m4@&t@_copy m4@&t@_defun_once])
|
|
|
|
dnl check out m4_defun_init, m4_copy, and odd macro names
|
|
AT_CHECK_M4SUGAR_TEXT([[
|
|
m4_define([t], [text])dnl
|
|
m4_defun_init([a], [[init a
|
|
]], [[common a] t])dnl
|
|
m4_defun([b], [[b]m4_require([a])])dnl
|
|
m4_defun([c], [[c]m4_require([a])])dnl
|
|
b
|
|
c
|
|
a()dnl
|
|
|
|
m4_defun_init([-], [hello, ], [m4_if([$#], [0], [world], [[$1]])])dnl
|
|
m4_copy([-], [.])dnl
|
|
m4_indir([.])
|
|
m4_indir([.], [goodbye])
|
|
m4_indir([-], [again])
|
|
]], [[
|
|
init a
|
|
common a text
|
|
b
|
|
c
|
|
common a text
|
|
hello, world
|
|
goodbye
|
|
hello, again
|
|
]])
|
|
|
|
dnl Check m4_defun_once behavior
|
|
AT_CHECK_M4SUGAR_TEXT([[
|
|
m4_defun_once([a], [[a]])dnl
|
|
m4_defun([b], [[b]m4_require([a])])dnl
|
|
m4_defun([c], [[c]a[]m4_require([b])])dnl
|
|
c
|
|
a
|
|
m4_defun_once([d], [[d]m4_require([a])])dnl
|
|
d
|
|
m4_defun_once([e], [[e]])dnl
|
|
m4_defun([f], [[f]m4_require([e])e])dnl
|
|
f
|
|
]], [[
|
|
a
|
|
b
|
|
c
|
|
|
|
d
|
|
e
|
|
f
|
|
]])
|
|
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## -------------------- ##
|
|
## m4_require: nested. ##
|
|
## -------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_require: nested])
|
|
AT_KEYWORDS([m4@&t@_require m4@&t@_defun])
|
|
|
|
dnl From the m4sugar.m4 discourse: Require chains, top level
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_defun([a], [[a]])dnl aka TEST2a
|
|
m4_defun([b], [[b]m4_require([a])])dnl aka TEST3
|
|
m4_defun([c], [[c]m4_require([b])])dnl aka TEST2b
|
|
m4_defun([d], [[d]m4_require([a])m4_require([c])])dnl aka TEST1
|
|
pre
|
|
d
|
|
d
|
|
post
|
|
]],
|
|
[[pre
|
|
a
|
|
b
|
|
c
|
|
d
|
|
d
|
|
post
|
|
]])
|
|
|
|
dnl From the m4sugar.m4 discourse: Require chains, nested
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_defun([a], [[a]])dnl aka TEST2a
|
|
m4_defun([b], [[b]m4_require([a])])dnl aka TEST3
|
|
m4_defun([c], [[c]m4_require([b])])dnl aka TEST2b
|
|
m4_defun([d], [[d]m4_require([a])m4_require([c])])dnl aka TEST1
|
|
m4_defun([wrap],
|
|
[pre
|
|
d
|
|
d
|
|
post])dnl
|
|
wrap
|
|
]],
|
|
[[a
|
|
b
|
|
c
|
|
pre
|
|
d
|
|
d
|
|
post
|
|
]])
|
|
|
|
dnl Direct invocation, nested requires, top level
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_defun([a], [[a]])dnl
|
|
m4_defun([b], [[b]m4_require([a])])dnl
|
|
m4_defun([c], [[c]m4_require([b])])dnl
|
|
pre
|
|
a
|
|
c
|
|
a
|
|
c
|
|
post
|
|
]],
|
|
[[pre
|
|
a
|
|
b
|
|
c
|
|
a
|
|
c
|
|
post
|
|
]])
|
|
|
|
dnl Direct invocation, nested requires, nested defun. This is an example
|
|
dnl of expansion before requirement, such that b occurs before its
|
|
dnl prerequisite a. This indicates a bug in the macros (but not in
|
|
dnl autoconf), so we should be emitting a warning.
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_defun([a], [[a]])dnl
|
|
m4_defun([b], [[b]m4_require([a])])dnl
|
|
m4_defun([c], [[c]m4_require([b])])dnl
|
|
dnl the extra macro layer works around line number differences in older m4
|
|
m4_define([foo], [m4_defun([outer],
|
|
[pre
|
|
a
|
|
c
|
|
a
|
|
c
|
|
post])])foo[]dnl
|
|
outer
|
|
]],
|
|
[[a
|
|
b
|
|
pre
|
|
a
|
|
c
|
|
a
|
|
c
|
|
post
|
|
]],
|
|
[[script.4s:15: warning: m4@&t@_require: 'a' was expanded before it was required
|
|
script.4s:15: https://www.gnu.org/software/autoconf/manual/autoconf.html#Expanded-Before-Required
|
|
script.4s:5: b is expanded from...
|
|
script.4s:6: c is expanded from...
|
|
script.4s:14: outer is expanded from...
|
|
script.4s:15: the top level
|
|
]])
|
|
|
|
dnl Direct invocation, expand-before-require but no nested require. As this
|
|
dnl is common in real life, but does not result in out-of-order expansion,
|
|
dnl we silently permit this.
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_defun([a], [[a]])dnl
|
|
m4_defun([b], [[b]m4_require([a])])dnl
|
|
m4_defun([c], [[c]])dnl
|
|
m4_defun([d], [[d]m4_require([c])])dnl
|
|
pre1
|
|
a
|
|
b
|
|
a
|
|
b
|
|
post1
|
|
m4_defun([outer],
|
|
[pre2
|
|
c
|
|
d
|
|
c
|
|
d
|
|
post2])dnl
|
|
outer
|
|
m4_defun([e], [[e]])dnl
|
|
m4_defun([f], [[f]m4_require([e])])dnl
|
|
m4_defun([g], [[g]
|
|
e
|
|
f])dnl
|
|
m4_defun([h], [[h]m4_require([g])])dnl
|
|
h
|
|
m4_defun([i], [[i]])dnl
|
|
m4_defun([j], [[j]
|
|
i])dnl
|
|
m4_defun([k], [[k]m4_require([i])])dnl
|
|
m4_defun([l], [[l]m4_require([k])])dnl
|
|
m4_defun([m], [[m]m4_require([j])m4_require([l])])dnl
|
|
m
|
|
]],
|
|
[[pre1
|
|
a
|
|
b
|
|
a
|
|
b
|
|
post1
|
|
pre2
|
|
c
|
|
d
|
|
c
|
|
d
|
|
post2
|
|
g
|
|
e
|
|
f
|
|
h
|
|
j
|
|
i
|
|
k
|
|
l
|
|
m
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------------------------------------------- ##
|
|
## m4_ifval, m4_ifblank, m4_ifset, m4_default, etc. ##
|
|
## ------------------------------------------------- ##
|
|
|
|
AT_SETUP([m4sugar shorthand conditionals])
|
|
AT_KEYWORDS([m4@&t@_ifval m4@&t@_ifblank m4@&t@_ifnblank m4@&t@_ifset
|
|
m4@&t@_default m4@&t@_default_quoted m4@&t@_default_nblank
|
|
m4@&t@_default_nblank_quoted])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_define([active], [ACTIVE])m4_define([empty])
|
|
m4_ifval([active], [yes], [no])
|
|
m4_ifval([empty], [yes], [no])
|
|
m4_ifval([ ], [yes], [no])
|
|
m4_ifval([], [yes], [no])
|
|
m4_ifblank([active], [yes], [no])
|
|
m4_ifblank([empty], [yes], [no])
|
|
m4_ifblank([ ], [yes], [no])
|
|
m4_ifblank([], [yes], [no])
|
|
m4_ifnblank([active], [yes], [no])
|
|
m4_ifnblank([empty], [yes], [no])
|
|
m4_ifnblank([ ], [yes], [no])
|
|
m4_ifnblank([], [yes], [no])
|
|
m4_ifset([active], [yes], [no])
|
|
m4_ifset([empty], [yes], [no])
|
|
m4_ifset([ ], [yes], [no])
|
|
m4_ifset([], [yes], [no])
|
|
---
|
|
m4_define([demo1], [m4_default([$1], [$2])])dnl
|
|
m4_define([demo2], [m4_default_quoted([$1], [$2])])dnl
|
|
m4_define([demo3], [m4_default_nblank([$1], [$2])])dnl
|
|
m4_define([demo4], [m4_default_nblank_quoted([$1], [$2])])dnl
|
|
demo1([active], [default])
|
|
demo1([], [active])
|
|
demo1([empty], [text])
|
|
-demo1([ ], [active])-
|
|
demo2([active], [default])
|
|
demo2([], [active])
|
|
demo2([empty], [text])
|
|
-demo2([ ], [active])-
|
|
demo3([active], [default])
|
|
demo3([], [active])
|
|
demo3([empty], [text])
|
|
-demo3([ ], [active])-
|
|
demo4([active], [default])
|
|
demo4([], [active])
|
|
demo4([empty], [text])
|
|
-demo4([ ], [active])-
|
|
]], [[
|
|
yes
|
|
yes
|
|
yes
|
|
no
|
|
no
|
|
no
|
|
yes
|
|
yes
|
|
yes
|
|
yes
|
|
no
|
|
no
|
|
yes
|
|
no
|
|
no
|
|
no
|
|
---
|
|
ACTIVE
|
|
ACTIVE
|
|
|
|
- -
|
|
active
|
|
active
|
|
empty
|
|
- -
|
|
ACTIVE
|
|
ACTIVE
|
|
|
|
-ACTIVE-
|
|
active
|
|
active
|
|
empty
|
|
-active-
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## --------- ##
|
|
## m4_cond. ##
|
|
## --------- ##
|
|
|
|
AT_SETUP([m4@&t@_cond])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_define([side], [m4_errprintn([$1])$1])
|
|
m4_cond([side(1)], [1], [a],
|
|
[side(1)], [1], [b],
|
|
[side(1)], [2], [c])
|
|
m4_cond([side(2)], [1], [a],
|
|
[side(2)], [1], [b],
|
|
[side(2)], [2], [c],
|
|
[side(2)])
|
|
m4_cond([side(3)], [1], [a],
|
|
[side(3)], [1], [b],
|
|
[side(3)], [2], [c],
|
|
[side(3)])
|
|
m4_cond([a,a], [a,a], [yes], [no])
|
|
m4_cond([[a,a]], [a,a], [yes])
|
|
m4_cond([a,a], [a,b], [yes], [no])
|
|
m4_cond([a,a], [a,b], [yes])
|
|
m4_cond([m4_eval([0xa])])
|
|
m4_define([ab], [AB])dnl
|
|
m4_cond([a])b
|
|
m4_cond([1], [1], [a])b
|
|
m4_cond([1], [2], [3], [a])b
|
|
]], [[
|
|
a
|
|
c
|
|
3
|
|
yes
|
|
yes
|
|
no
|
|
|
|
10
|
|
AB
|
|
AB
|
|
AB
|
|
]], [[1
|
|
2
|
|
2
|
|
2
|
|
3
|
|
3
|
|
3
|
|
3
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------- ##
|
|
## m4 lists. ##
|
|
## ---------- ##
|
|
|
|
AT_SETUP([m4 lists])
|
|
|
|
AT_KEYWORDS([m4@&t@_car m4@&t@_cdr m4@&t@_argn _m4@&t_cdr])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_define([a], [A])m4_define([b], [B])m4_define([c], [C])
|
|
m4_argn([1], [a], [b], [c])
|
|
m4_argn([2], [a], [b], [c])
|
|
m4_argn([3], [a], [b], [c])
|
|
m4_argn([4], [a], [b], [c])
|
|
m4_car([a], [b], [c])
|
|
m4_cdr([a], [b], [c])
|
|
m4_cdr([a], [b])
|
|
m4_cdr([a])
|
|
_m4_cdr([a], [b], [c])
|
|
_m4_cdr([a], [b])
|
|
_m4_cdr([a])
|
|
m4_if(m4_cdr([], []), [[]], [good], [bad])
|
|
m4_if(m4_cdr([]), [], [good], [bad])
|
|
]], [[
|
|
a
|
|
b
|
|
c
|
|
|
|
a
|
|
[b],[c]
|
|
[b]
|
|
|
|
, [b],[c]
|
|
, [b]
|
|
|
|
good
|
|
good
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_argn([0], [a], [b], [c])
|
|
]])
|
|
AT_CHECK_M4SUGAR([-o-], [1], [],
|
|
[[script.4s:2: error: assert failed: 0 < 0
|
|
script.4s:2: the top level
|
|
autom4te: error: 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=``])
|
|
dnl these next two are from the manual; keep this in sync if the internal
|
|
dnl quoting strings in m4_split are changed
|
|
m4_define([a], [A])m4_define([b], [B])m4_define([c], [C])dnl
|
|
m4_split([a )}>=- b -=<{( c])
|
|
m4_split([a )}@&t@>=- b -=<@&t@{( c])
|
|
]],
|
|
[[
|
|
|
|
[[]]
|
|
[], []
|
|
[active]
|
|
[], [active], [active], []end
|
|
[], []
|
|
[active]
|
|
[], [active active], []end
|
|
[abcde]
|
|
[a], [c], [e]
|
|
[foo=``], [bar='']
|
|
[foo=''], [bar=``]
|
|
[a], [], [B], [], [c]
|
|
[a], [)}>=@&t@-], [b], [-@&t@=<{(], [c]
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------- ##
|
|
## m4_do. ##
|
|
## ------- ##
|
|
|
|
AT_SETUP([m4@&t@_do])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_define([ab], [1])m4_define([bc], [2])m4_define([abc], [3])dnl
|
|
m4_define([AB], [4])m4_define([BC], [5])m4_define([ABC], [6])dnl
|
|
m4_do
|
|
m4_do([a])
|
|
m4_do([a], [b])c
|
|
m4_unquote(m4_join([], [a], [b]))c
|
|
m4_define([a], [A])m4_define([b], [B])m4_define([c], [C])dnl
|
|
m4_do([a], [b])c
|
|
m4_unquote(m4_join([], [a], [b]))c
|
|
]],
|
|
[[
|
|
a
|
|
abc
|
|
3
|
|
ABC
|
|
3
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------- ##
|
|
## m4_append. ##
|
|
## ----------- ##
|
|
|
|
AT_SETUP([m4@&t@_append])
|
|
AT_KEYWORDS([m4@&t@_append_uniq m4@&t@_append_uniq_w])
|
|
|
|
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_init[]dnl
|
|
m4_append_uniq([str], [a], [ ])
|
|
m4_append_uniq([str], [a b], [ ])
|
|
m4_divert([])dnl
|
|
str
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 0, [[a a b
|
|
]], [[script.4s:3: warning: m4@&t@_append_uniq: 'a b' contains ' '
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------- ##
|
|
## m4_join. ##
|
|
## --------- ##
|
|
|
|
AT_SETUP([m4@&t@_join])
|
|
|
|
AT_KEYWORDS([m4@&t@_joinall])
|
|
|
|
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])
|
|
m4_joinall([-], [one], [], [two])
|
|
m4_joinall([-], [], [], [three], [], [])
|
|
m4_joinall([], [one], [], [two])
|
|
m4_joinall
|
|
m4_joinall([-])
|
|
m4_joinall([-], [one])
|
|
]],
|
|
[[
|
|
|
|
|
|
one, two
|
|
[one, two]
|
|
active|active
|
|
one
|
|
one
|
|
two
|
|
two
|
|
one active two
|
|
onetwo
|
|
one--two
|
|
--three--
|
|
onetwo
|
|
|
|
|
|
one
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ----------- ##
|
|
## m4_expand. ##
|
|
## ----------- ##
|
|
|
|
AT_SETUP([m4@&t@_expand])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_define([active], [ACTIVE])dnl
|
|
m4_expand([#active
|
|
active])
|
|
m4_expand([[active]])
|
|
dnl properly quoted case statements
|
|
m4_expand([case a in @%:@(
|
|
*) echo active, ;;
|
|
esac
|
|
case b in
|
|
*[)] echo active, ;;
|
|
esac])
|
|
dnl unbalanced underquoted ')', but we manage anyway (gasp!)
|
|
m4_expand([case c in #(
|
|
*) echo active, ;;
|
|
esac
|
|
case d in
|
|
*) echo active, ;;
|
|
esac])
|
|
dnl unterminated comment/dnl
|
|
m4_expand([active # active])
|
|
m4_expand([a
|
|
dnl])
|
|
m4_expand([a
|
|
-dnl])
|
|
]],
|
|
[[#active
|
|
ACTIVE
|
|
active
|
|
case a in #(
|
|
*) echo ACTIVE, ;;
|
|
esac
|
|
case b in
|
|
*) echo ACTIVE, ;;
|
|
esac
|
|
case c in #(
|
|
*) echo ACTIVE, ;;
|
|
esac
|
|
case d in
|
|
*) echo ACTIVE, ;;
|
|
esac
|
|
ACTIVE # active
|
|
a
|
|
a
|
|
-
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ------------- ##
|
|
## m4_text_box. ##
|
|
## ------------- ##
|
|
|
|
AT_SETUP([m4@&t@_text_box])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[
|
|
m4_text_box([a $1 @&t@b])
|
|
m4_text_box([a $1 @&t@b], [$])
|
|
m4_text_box([a $1 @&t@b], [,])
|
|
]], [[
|
|
## ------ ##
|
|
## a $1 b ##
|
|
## ------ ##
|
|
## $$$$$$ ##
|
|
## a $1 b ##
|
|
## $$$$$$ ##
|
|
## ,,,,,, ##
|
|
## a $1 b ##
|
|
## ,,,,,, ##
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## -------------- ##
|
|
## m4_text_wrap. ##
|
|
## -------------- ##
|
|
|
|
AT_SETUP([m4@&t@_text_wrap])
|
|
AT_KEYWORDS([m4@&t@_escape])
|
|
|
|
# m4_text_wrap is used to display the help strings. Also, check that
|
|
# commas and $ are not swallowed. This can easily happen because of
|
|
# m4-listification.
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init[]m4_divert([])dnl
|
|
m4_define([a], [OOPS])dnl
|
|
m4_escape([a[b $c#]d])
|
|
m4_if(m4_escape([a[b $c#]d]), [a[b $c#]d], [oops],
|
|
m4_escape([a[b $c#]d]), [a@<:@b @S|@c@%:@@:>@d], [pass], [oops])
|
|
|
|
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 space]])
|
|
m4_define([xfff], [oops])
|
|
m4_text_wrap([Some $1 $2 $3 $4 embedded dollars.], [ $* ], [ $@ ], [0xfff & 20])
|
|
]])
|
|
|
|
AT_DATA([expout],
|
|
[[a[b $c#]d
|
|
pass
|
|
|
|
/* Short string */
|
|
|
|
/* Much longer
|
|
string */
|
|
|
|
--short Short doc.
|
|
|
|
--too-wide
|
|
Short doc.
|
|
|
|
--too-wide
|
|
Super long
|
|
documentation.
|
|
|
|
First, second , third, [,quoted space]
|
|
|
|
$@ Some $1 $2 $3
|
|
$* $4 embedded
|
|
$* dollars.
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], 0, [expout])
|
|
|
|
AT_CLEANUP
|
|
|
|
## -------------------- ##
|
|
## m4_version_compare. ##
|
|
## -------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_version_compare])
|
|
|
|
AT_KEYWORDS([m4@&t@_list_cmp])
|
|
|
|
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])
|
|
m4_version_compare([08], [09])
|
|
m4_version_compare([010], [8])
|
|
dnl Test that side effects to m4_list_cmp occur exactly once
|
|
m4_list_cmp([[0], [0], [0]m4_errprintn([hi])],
|
|
[[0], [0], [0]m4_errprintn([hi])])
|
|
m4_list_cmp([[0], [0], [0]m4_errprintn([hi])],
|
|
[[0], [0], [0]m4_errprintn([bye])])
|
|
]],
|
|
[[-1
|
|
1
|
|
1
|
|
-1
|
|
1
|
|
0
|
|
0
|
|
-1
|
|
1
|
|
0
|
|
0
|
|
-1
|
|
-1
|
|
1
|
|
-1
|
|
1
|
|
0
|
|
0
|
|
]], [[hi
|
|
hi
|
|
hi
|
|
bye
|
|
]])
|
|
|
|
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_bmatch. ##
|
|
## ----------- ##
|
|
|
|
AT_SETUP([m4@&t@_bmatch])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_bmatch([abc], [default\])
|
|
m4_bmatch([abc], [^a], [yes])
|
|
m4_bmatch([abc], [^a], [yes], [no])
|
|
m4_bmatch([abc], [^.a], [yes])
|
|
m4_bmatch([abc], [^.a], [yes], [no\])
|
|
m4_bmatch([abc], [a], [1], [b], [2])
|
|
m4_bmatch([abc], [A], [1], [b], [2])
|
|
m4_define([ab], [AB])dnl
|
|
m4_bmatch([$*], [a])b
|
|
m4_bmatch([$*], [\*], [a])b
|
|
m4_bmatch([$*], [1], [2], [a])b
|
|
]], [[default\
|
|
yes
|
|
yes
|
|
|
|
no\
|
|
1
|
|
2
|
|
AB
|
|
AB
|
|
AB
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ------------------------ ##
|
|
## m4_toupper, m4_tolower. ##
|
|
## ------------------------ ##
|
|
|
|
AT_SETUP([m4@&t@_toupper and m4@&t@_tolower])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_define([abc], [hI])m4_define([ABC], [Hi])
|
|
m4_toupper(abc aBc ABC)
|
|
m4_tolower(abc aBc ABC)
|
|
m4_toupper([abc aBc ABC])
|
|
m4_tolower([abc aBc ABC])
|
|
m4_echo(m4_toupper(abc aBc ABC))
|
|
m4_echo(m4_tolower(abc aBc ABC))
|
|
m4_echo(m4_toupper([abc aBc ABC]))
|
|
m4_echo(m4_tolower([abc aBc ABC]))
|
|
m4_do(m4_toupper(abc aBc ABC))
|
|
m4_do(m4_tolower(abc aBc ABC))
|
|
m4_do(m4_toupper([abc aBc ABC]))
|
|
m4_do(m4_tolower([abc aBc ABC]))
|
|
]], [[
|
|
HI ABC HI
|
|
hi abc hi
|
|
ABC ABC ABC
|
|
abc abc abc
|
|
HI ABC HI
|
|
hi abc hi
|
|
ABC ABC ABC
|
|
abc abc abc
|
|
HI Hi HI
|
|
hi hI hi
|
|
Hi Hi Hi
|
|
hI hI hI
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## --------------- ##
|
|
## m4_bpatsubsts. ##
|
|
## --------------- ##
|
|
|
|
AT_SETUP([m4@&t@_bpatsubsts])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_bpatsubsts([11], [^..$])
|
|
m4_bpatsubsts([11], [\(.\)1], [\12])
|
|
m4_bpatsubsts([11], [^..$], [], [1], [2])
|
|
m4_bpatsubsts([11], [\(.\)1], [\12], [1], [3])
|
|
m4_define([a], [oops])m4_define([c], [oops])dnl
|
|
m4_define([AB], [good])m4_define([bc], [good])dnl
|
|
m4_bpatsubsts([abc], [a], [A], [b], [B], [c])
|
|
m4_bpatsubsts([ab], [a])c
|
|
m4_bpatsubsts([ab], [c], [C], [a])c
|
|
m4_bpatsubsts([$1$*$@], [\$\*], [$#])
|
|
]], [[11
|
|
21
|
|
22
|
|
23
|
|
good
|
|
good
|
|
good
|
|
$1$#$@
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## -------------- ##
|
|
## m4_esyscmd_s. ##
|
|
## -------------- ##
|
|
|
|
AT_SETUP([m4@&t@_esyscmd_s])
|
|
AT_KEYWORDS([m4@&t@_chomp m4@&t@_chomp_all])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_define([world], [WORLD])dnl
|
|
m4_chomp([abc])
|
|
m4_chomp([world
|
|
|
|
])
|
|
m4_esyscmd_s([echo hello world])
|
|
m4_esyscmd_s([echo '[goodbye,
|
|
cruel world
|
|
|
|
]'])
|
|
]], [[abc
|
|
world
|
|
|
|
hello WORLD
|
|
goodbye,
|
|
cruel world
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
## ---------- ##
|
|
## M4 Loops. ##
|
|
## ---------- ##
|
|
|
|
AT_SETUP([M4 loops])
|
|
|
|
AT_KEYWORDS([m4@&t@_for m4@&t@_foreach m4@&t@_foreach_w m4@&t@_map_args_w])
|
|
|
|
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 Modifying var does not affect the number of iterations
|
|
m4_for([myvar], 1, 5, , [ myvar[]m4_define([myvar], 5)])
|
|
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
|
|
m4_map_args_w([a b c, d,e f
|
|
g], [ ], [|])
|
|
m4_map_args_w([a b], [\1], [/])
|
|
m4_define([dashes], [--])dnl
|
|
m4_map_args_w([a b c], [/], [\1], [dashes])
|
|
dnl only one side effect expansion, prior to visiting list elements
|
|
m4_foreach([i], [[1], [2], [3]m4_errprintn([hi])], [m4_errprintn(i)])dnl
|
|
dnl shifting forms an important part of loops
|
|
m4_shift3:m4_shift3(1,2,3):m4_shift3(1,2,3,4)
|
|
m4_shiftn(3,1,2,3):m4_shiftn(3,1,2,3,4)
|
|
]],
|
|
[[ 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
|
|
1 2 3 4 5
|
|
----------
|
|
a| b, c| d| e
|
|
| f|
|
|
a| b| c,| d,e| f| g|
|
|
outer value
|
|
a| b| c,| d,e| f| g|
|
|
\1a/\1b/
|
|
/a\1--/b\1--/c\1
|
|
::4
|
|
:4
|
|
]], [[hi
|
|
1
|
|
2
|
|
3
|
|
]])
|
|
|
|
dnl bounds checking in m4_for
|
|
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: error: 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: error: 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: error: m4 failed with exit status: 1
|
|
]])
|
|
|
|
dnl m4_shiftn also does bounds checking
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_divert([0])dnl
|
|
m4_shiftn(3,1,2)
|
|
]])
|
|
AT_CHECK_M4SUGAR([], 1, [],
|
|
[[script.4s:3: error: assert failed: 0 < 3 && 3 < 3
|
|
script.4s:3: the top level
|
|
autom4te: error: m4 failed with exit status: 1
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------------- ##
|
|
## m4_map{,all}{,_sep}. ##
|
|
## --------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_map])
|
|
AT_KEYWORDS([m4@&t@_apply m4@&t@_map_sep m4@&t@_mapall m4@&t@_mapall_sep])
|
|
AT_KEYWORDS([m4@&t@_count])
|
|
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_map([m4_count], [])
|
|
m4_map([ m4_count], [[],
|
|
[[1]],
|
|
[[1], [2]]])
|
|
m4_mapall([ m4_count], [[],
|
|
[[1]],
|
|
[[1], [2]]])
|
|
m4_map_sep([m4_eval], [,], [[[1+2]],
|
|
[[10], [16]]])
|
|
m4_count(m4_map_sep([m4_echo], [,], [[], [[1]], [[2]]]))
|
|
m4_count(m4_mapall_sep([m4_echo], [,], [[], [[1]], [[2]]]))
|
|
m4_map_sep([m4_eval], [[,]], [[[1+2]],
|
|
[[10], [16]]])
|
|
m4_count(m4_map_sep([m4_echo], [[,]], [[], [[1]], [[2]]]))
|
|
m4_count(m4_mapall_sep([m4_echo], [[,]], [[], [[1]], [[2]]]))
|
|
m4_map([-], [[]])
|
|
m4_mapall([-], [[]])
|
|
m4_map_sep([-], [:], [[]])
|
|
m4_mapall_sep([-], [:], [[]])
|
|
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])])
|
|
dnl only one side effect expansion, prior to visiting list elements
|
|
m4_map([m4_errprintn], [[[1]], [[2]], [[3]]m4_errprintn([hi])])dnl
|
|
m4_map_sep([m4_errprintn], [], [[[1]], [[2]], [[3]]m4_errprintn([hi])])dnl
|
|
m4_mapall([m4_errprintn], [[[1]], [[2]], [[3]]m4_errprintn([hi])])dnl
|
|
m4_mapall_sep([m4_errprintn], [], [[[1]], [[2]], [[3]]m4_errprintn([hi])])dnl
|
|
]],
|
|
[[
|
|
1 2
|
|
0 1 2
|
|
3,a
|
|
2
|
|
3
|
|
3,a
|
|
1
|
|
1
|
|
|
|
-
|
|
|
|
-
|
|
pass1
|
|
pass
|
|
]], [[hi
|
|
1
|
|
2
|
|
3
|
|
hi
|
|
1
|
|
2
|
|
3
|
|
hi
|
|
1
|
|
2
|
|
3
|
|
hi
|
|
1
|
|
2
|
|
3
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## --------------------------------------- ##
|
|
## m4_map_args{,_sep,_pair} and m4_curry. ##
|
|
## --------------------------------------- ##
|
|
|
|
AT_SETUP([m4@&t@_map_args and m4@&t@_curry])
|
|
AT_KEYWORDS([m4@&t@_map_args_sep m4@&t@_map_args_pair m4@&t@_reverse
|
|
m4@&t@_map])
|
|
|
|
dnl First, make sure we can curry in isolation.
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_curry([m4_echo])([1])
|
|
m4_curry([m4_curry], [m4_reverse], [1])([2])([3])
|
|
m4_define([add], [m4_eval(([$1]) + ([$2]))])dnl
|
|
m4_define([add_one], [m4_curry([add], [1])])dnl
|
|
add_one()([4])
|
|
]],
|
|
[[1
|
|
3, 2, 1
|
|
5
|
|
]])
|
|
|
|
dnl Now, check that we can map a list of arguments.
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_define([active], [ACTIVE])dnl
|
|
m4_map_args([ m4_echo])
|
|
m4_map_args([ m4_echo], [plain], [active])
|
|
m4_map_args([m4_unquote], [plain], [active])
|
|
m4_map_args_pair([, m4_reverse], [])
|
|
m4_map_args_pair([, m4_reverse], [], [1])
|
|
m4_map_args_pair([, m4_reverse], [], [1], [2])
|
|
m4_map_args_pair([, m4_reverse], [], [1], [2], [3])
|
|
m4_map_args_pair([, m4_reverse], [], [1], [2], [3], [4])
|
|
m4_map_args_pair([, m4_reverse], [, m4_dquote], [1])
|
|
m4_map_args_pair([, m4_reverse], [, m4_dquote], [1], [2])
|
|
m4_map_args_pair([, m4_reverse], [, m4_dquote], [1], [2], [3])
|
|
m4_map_args_pair([, m4_reverse], [, m4_dquote], [1], [2], [3], [4])
|
|
m4_map_args_sep([<], [>], [:], [1], [2], [3])
|
|
m4_map_args_sep([m4_echo(], [)], [ ], [plain], [active])
|
|
]],
|
|
[[
|
|
plain active
|
|
plainACTIVE
|
|
|
|
, 1
|
|
, 2, 1
|
|
, 2, 1, 3
|
|
, 2, 1, 4, 3
|
|
, [1]
|
|
, 2, 1
|
|
, 2, 1, [3]
|
|
, 2, 1, 4, 3
|
|
<1>:<2>:<3>
|
|
plain active
|
|
]])
|
|
|
|
dnl Finally, put the two concepts together, to show the real power of the API.
|
|
AT_CHECK_M4SUGAR_TEXT(
|
|
[[m4_define([add], [m4_eval(([$1]) + ([$2]))])dnl
|
|
m4_define([list], [[-1], [0], [1]])dnl
|
|
dnl list_add_n(value, arg...)
|
|
dnl add VALUE to each ARG and output the resulting list
|
|
m4_define([list_add_n],
|
|
[m4_shift(m4_map_args([,m4_curry([add], [$1])], m4_shift($@)))])
|
|
list_add_n([1], list)
|
|
list_add_n([2], list)
|
|
]], [[
|
|
0,1,2
|
|
1,2,3
|
|
]])
|
|
|
|
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], [-], [+])
|
|
m4_combine([$* ], [[$1], [$2]], [$#], [$@])
|
|
]],
|
|
[[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+
|
|
$1$#$@$* $2$#$@
|
|
]], [])
|
|
|
|
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: error: 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: error: 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
|
|
|
|
|
|
## ----------- ##
|
|
## Recursion. ##
|
|
## ----------- ##
|
|
|
|
AT_SETUP([recursion])
|
|
|
|
AT_KEYWORDS([m4@&t@_foreach m4@&t@_foreach_w m4@&t@_case m4@&t@_cond
|
|
m4@&t@_bpatsubsts m4@&t@_shiftn m4@&t@_do m4@&t@_dquote_elt m4@&t@_reverse
|
|
m4@&t@_map m4@&t@_join m4@&t@_joinall m4@&t@_list_cmp m4@&t@_max m4@&t@_min
|
|
m4@&t@_bmatch m4@&t@_map_args m4@&t@_map_args_pair])
|
|
|
|
dnl This test completes in a reasonable time if m4_foreach is linear,
|
|
dnl but thrashes if it is quadratic. If we are testing with m4 1.4.x,
|
|
dnl only the slower foreach.m4 implementation will work. But if we
|
|
dnl are testing with m4 1.6, we can rerun the test with __m4_version__
|
|
dnl undefined to exercise the alternate code path.
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_init
|
|
m4_divert_push([])[]dnl
|
|
m4_len(m4_foreach_w([j], m4_do(m4_for([i], [1], [10000], [], [,i ])), [j ]))
|
|
m4_shiftn(9998m4_for([i], [1], [10000], [], [,i]))
|
|
m4_len(m4_join([--],, m4_dquote_elt(m4_for([i], [1], [10000], [], [,i])),))
|
|
m4_len(m4_joinall([--], m4_map([, m4_echo],
|
|
m4_dquote([1]m4_for([i], [2], [10000], [], [,i])))))
|
|
m4_max(m4_min([1]m4_for([i], [2], [10000], [],
|
|
[,i]))m4_for([i], [2], [10000], [], [,i]))
|
|
m4_case([10000]m4_for([i], [1], [10000], [], [,i]),[end])
|
|
m4_list_cmp(m4_dquote(1m4_for([i], [2], [10000], [], [,i])),
|
|
m4_dquote(m4_reverse(10000m4_for([i], [9999], [1], [], [,i])), [0]))
|
|
m4_list_cmp([0], [0m4_for([i], [1], [10000], [], [,0])])
|
|
m4_list_cmp([0m4_for([i], [1], [10000], [], [,0])], [0])
|
|
m4_for([i], [1], [10000], [], [m4_define(i)])dnl
|
|
m4_undefine(1m4_for([i], [2], [10000], [], [,i]))dnl
|
|
m4_bpatsubsts([a1]m4_for([i], [1], [10000], [], [,i]), [a2], [A])
|
|
m4_bmatch([9997]m4_for([i], [1], [10000], [], [,^i$]))
|
|
m4_define([up], [m4_define([$1], m4_incr($1))$1])m4_define([j], 0)dnl
|
|
m4_cond(m4_for([i], [1], [10000], [], [[up([j])], [9990], i,]) [oops]) j
|
|
m4_count(m4_map_args_pair([,m4_quote], []m4_map_args([,m4_echo]m4_for([i],
|
|
[1], [10000], [], [,i]))))
|
|
m4_divert_pop([])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], [0], [[48894
|
|
9999,10000
|
|
78896
|
|
58894
|
|
10000
|
|
end
|
|
0
|
|
0
|
|
0
|
|
A
|
|
^9998$
|
|
9990 9990
|
|
5001
|
|
]])
|
|
|
|
AT_DATA_M4SUGAR([script.4s],
|
|
[[m4_ifdef([__m4_version__],
|
|
[m4_undefine([__m4_version__])],
|
|
[m4_divert_push([])48894
|
|
9999,10000
|
|
78896
|
|
58894
|
|
10000
|
|
end
|
|
0
|
|
0
|
|
0
|
|
A
|
|
^9998$
|
|
9990 9990
|
|
5001
|
|
m4_exit([0])])
|
|
m4_init
|
|
m4_divert_push([])[]dnl
|
|
m4_len(m4_foreach_w([j], m4_do(m4_for([i], [1], [10000], [], [,i ])), [j ]))
|
|
m4_shiftn(9998m4_for([i], [1], [10000], [], [,i]))
|
|
m4_len(m4_join([--],, m4_dquote_elt(m4_for([i], [1], [10000], [], [,i])),))
|
|
m4_len(m4_joinall([--], m4_map([, m4_echo],
|
|
m4_dquote([1]m4_for([i], [2], [10000], [], [,i])))))
|
|
m4_max(m4_min([1]m4_for([i], [2], [10000], [],
|
|
[,i]))m4_for([i], [2], [10000], [], [,i]))
|
|
m4_case([10000]m4_for([i], [1], [10000], [], [,i]),[end])
|
|
m4_list_cmp(m4_dquote(1m4_for([i], [2], [10000], [], [,i])),
|
|
m4_dquote(m4_reverse(10000m4_for([i], [9999], [1], [], [,i])), [0]))
|
|
m4_list_cmp([0], [0m4_for([i], [1], [10000], [], [,0])])
|
|
m4_list_cmp([0m4_for([i], [1], [10000], [], [,0])], [0])
|
|
m4_for([i], [1], [10000], [], [m4_define(i)])dnl
|
|
m4_undefine(1m4_for([i], [2], [10000], [], [,i]))dnl
|
|
m4_bpatsubsts([a1]m4_for([i], [1], [10000], [], [,i]), [a2], [A])
|
|
m4_bmatch([9997]m4_for([i], [1], [10000], [], [,^i$]))
|
|
m4_define([up], [m4_define([$1], m4_incr($1))$1])m4_define([j], 0)dnl
|
|
m4_cond(m4_for([i], [1], [10000], [], [[up([j])], [9990], i,]) [oops]) j
|
|
m4_count(m4_map_args_pair([,m4_quote], []m4_map_args([,m4_echo]m4_for([i],
|
|
[1], [10000], [], [,i]))))
|
|
m4_divert_pop([])
|
|
]])
|
|
|
|
AT_CHECK_M4SUGAR([-o-], [0], [[48894
|
|
9999,10000
|
|
78896
|
|
58894
|
|
10000
|
|
end
|
|
0
|
|
0
|
|
0
|
|
A
|
|
^9998$
|
|
9990 9990
|
|
5001
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------- ##
|
|
## m4_set_*. ##
|
|
## ---------- ##
|
|
|
|
AT_SETUP([m4@&t@_set])
|
|
|
|
AT_KEYWORDS([m4@&t@_set_add m4@&t@_set_add_all m4@&t@_set_contains
|
|
m4@&t@_set_contents m4@&t@_set_delete m4@&t@_set_difference m4@&t@_set_dump
|
|
m4@&t@_set_empty m4@&t@_set_foreach m4@&t@_set_intersection m4@&t@_set_list
|
|
m4@&t@_set_listc m4@&t@_set_map m4@&t@_set_remove m4@&t@_set_size
|
|
m4@&t@_set_union])
|
|
|
|
# Simple tests
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_set_contains([a], [1], [yes], [no])
|
|
m4_set_add([a], [1], [added], [dup])
|
|
m4_set_contains([a], [1], [yes], [no])
|
|
m4_set_add([a], [1], [added], [dup])
|
|
m4_set_contents([a])
|
|
m4_set_remove([a], [1], [removed], [missing])
|
|
m4_set_contains([a], [1], [yes], [no])
|
|
m4_set_remove([a], [1], [removed], [missing])
|
|
m4_set_add([a], [2], [added], [dup])
|
|
m4_set_empty([a], [yes], [no])
|
|
m4_set_delete([a])
|
|
m4_set_empty([a], [yes], [no])
|
|
m4_set_add_all([c], [1], [2], [3])
|
|
m4_set_add_all([a]m4_set_listc([c]))
|
|
m4_set_contents([c], [-])
|
|
m4_set_dump([a], [-])
|
|
m4_set_contents([a])
|
|
m4_set_add_all([a], [1], [2], [3])m4_set_add_all([b], [3], [], [4])
|
|
m4_set_difference([a], [b])
|
|
m4_set_difference([b], [a])
|
|
m4_set_intersection([a], [b])
|
|
m4_set_union([a], [b])
|
|
m4_define([printodd], [m4_if(m4_eval([$1 & 1]), [1], [:$1])])dnl
|
|
m4_set_map([a], [printodd])
|
|
m4_set_foreach([a], [i], [m4_if(m4_eval(i & 1), [1], [m4_set_remove([a], i)])])
|
|
m4_set_list([a])
|
|
m4_set_add([a], [])
|
|
m4_set_list([a])
|
|
m4_set_remove([a], [2])
|
|
m4_dquote(m4_set_list([a]))
|
|
m4_set_listc([a])
|
|
m4_set_size([a])
|
|
m4_set_delete([a])
|
|
m4_dquote(m4_set_list([a]))
|
|
m4_indir([m4_dquote]m4_set_listc([a]))
|
|
m4_set_listc([a])
|
|
m4_set_size([a])
|
|
]], [[no
|
|
added
|
|
yes
|
|
dup
|
|
1
|
|
removed
|
|
no
|
|
missing
|
|
added
|
|
no
|
|
|
|
yes
|
|
|
|
|
|
1-2-3
|
|
3-2-1
|
|
|
|
|
|
,1,2
|
|
,,4
|
|
,3
|
|
,1,2,3,,4
|
|
:1:3
|
|
|
|
2
|
|
|
|
2,
|
|
|
|
[]
|
|
,
|
|
1
|
|
|
|
[]
|
|
|
|
|
|
0
|
|
]])
|
|
|
|
# Stress tests - check for unusual names/values
|
|
AT_CHECK_M4SUGAR_TEXT([[m4_define([a], [oops])dnl
|
|
m4_set_add([a], [a])dnl
|
|
m4_set_remove([a], [oops], [yes], [no])
|
|
m4_set_add([a,b], [c])dnl
|
|
m4_set_add([a,b], [$*[]])dnl
|
|
m4_set_add_all([a], [b,c])dnl
|
|
m4_set_size([a])
|
|
m4_count(m4_set_contents([a], [,]))
|
|
m4_count(m4_set_list([a], [,]))
|
|
m4_set_dump([a], [,])
|
|
m4_set_contents([a,b], [,])
|
|
m4_set_list([a,b])
|
|
m4_set_foreach([$*[]], [$*[]], [oops])
|
|
m4_set_add([$*[]], [])dnl
|
|
m4_set_remove([$*[]], [a], [yes], [no])
|
|
m4_set_add([$*[]], [a])dnl
|
|
m4_set_foreach([$*[]], [$*[]], [-m4_defn([$*[]])m4_indir([$*[]])-])
|
|
m4_set_remove([$*[]], [], [yes], [no])
|
|
m4_set_add([c], [,])dnl
|
|
m4_set_foreach([a,b], [set], [:m4_set_listc(_m4_defn([set])):])
|
|
]],[[no
|
|
2
|
|
1
|
|
2
|
|
b,c,a
|
|
c,$*[]
|
|
c,$*[]
|
|
|
|
no
|
|
---aoops-
|
|
yes
|
|
:,,::,a:
|
|
]])
|
|
|
|
# Stress tests - check for linear scaling (won't necessarily fail if
|
|
# quadratic, but hopefully users will complain if it appears to hang)
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_for([i], [1], [10000], [], [m4_set_add([a], i)])dnl
|
|
m4_set_add_all([b]m4_for([i], [1], [10000], [], [,i]))dnl
|
|
m4_set_remove([a], [1])dnl
|
|
m4_set_remove([b], [10000])dnl
|
|
m4_set_add_all([a]m4_for([i], [1], [10000], [], [,i]))dnl
|
|
m4_for([i], [1], [10000], [], [m4_set_add([b], i)])dnl
|
|
m4_len(m4_set_contents([a]))
|
|
m4_len(m4_set_foreach([b], [b], [m4_if(m4_eval(b & 1), [1],
|
|
[m4_set_remove([b], b, [-])])]))
|
|
m4_set_size([b])
|
|
m4_define([prune3x], [m4_if(m4_eval([$1 % 3]), [0],
|
|
[m4_set_remove([a], [$1], [-])])])dnl
|
|
m4_len(m4_set_map([a], [prune3x]))
|
|
m4_count(m4_shift(m4_set_intersection([a], [b])))
|
|
]], [[38894
|
|
5000
|
|
5000
|
|
3333
|
|
3334
|
|
]])
|
|
|
|
AT_CLEANUP
|
|
|
|
|
|
## ---------------------- ##
|
|
## __file__ and __line__. ##
|
|
## ---------------------- ##
|
|
|
|
AT_SETUP([[__file__ and __line__]])
|
|
|
|
# Check that __file__ and __line__ work.
|
|
# Check that m4__file__ and m4__line__ are not defined
|
|
# (and get them to pass by the undefined-macro check).
|
|
# Try to not assume too much about AT_CHECK_M4SUGAR_TEXT.
|
|
AT_CHECK_M4SUGAR_TEXT([[dnl
|
|
m4_pattern_allow([m4__file__])dnl
|
|
m4_pattern_allow([m4__line__])dnl
|
|
m4__file__
|
|
m4__line__
|
|
__file__
|
|
m4_define([first], __line__)dnl
|
|
m4_define([second], __line__)dnl
|
|
m4_assert(first + 1 == second)dnl
|
|
]], [[m4@&t@__@&t@file__
|
|
m4@&t@__@&t@line__
|
|
script.4s
|
|
]])
|
|
|
|
AT_CLEANUP
|