blob: 2a84843458f8da1b3a76ec29a22ff61cfb03d82e [file] [log] [blame]
# Hand crafted tests for GNU M4. -*- Autotest -*-
# Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
# This file is part of GNU M4.
#
# GNU M4 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.
#
# GNU M4 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_BANNER([Freezing state.])
## --------------- ##
## large diversion ##
## --------------- ##
AT_SETUP([large diversion])
AT_KEYWORDS([frozen])
# Check that large diversions are handled across freeze boundaries.
AT_DATA([[frozen.m4]], [M4_ONE_MEG_DEFN[divert(2)f
divert(1)hi
]])
AT_DATA([[unfrozen.m4]],
[[divert(3)bye
]])
# First generate the `expout' output by running over the sources before
# freezing.
AT_CHECK_M4([frozen.m4 unfrozen.m4], [0],
[stdout], [stderr])
mv stdout expout
mv stderr experr
# Now freeze the first source file.
AT_CHECK_M4([-F frozen.m4f frozen.m4], [0])
# Now rerun the original sequence, but using the frozen file.
AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0],
[expout], [experr])
AT_CLEANUP
## ---------------- ##
## loading format 1 ##
## ---------------- ##
AT_SETUP([loading format 1])
AT_KEYWORDS([frozen])
m4_if([
Note: frozen.m4f was obtained by deleting unneeded lines from the output of
a version of m4 1.4.5 with changeword support. Deleting lines is in effect
equivalent to using undefine(name) in the input. This test ensures we
behave well with the old format, including \ parsing, disappearing builtins
(okay so long as the input does not try to use them), and restoring sane
defaults for features that were only added in version 2 frozen format.
$ m4 --version | head -n1
GNU M4 1.4.5
$ cat frozen.m4
divert(`-1')
define(`foo', `\FOO')
pushdef(`foo', `bar${1}')
define(`my_define', defn(`define'))
define(`my_changeword', defn(`changeword'))
pushdef(`my_define', `define')
pushdef(`my_define', defn(`define'))
divert(`1')dnl
foo
divert`'dnl
changequote([,])dnl
changecom([/*], [*/])dnl
dnl Implied sequence of undefine(`name') due to hand-edits
$ m4 -F frozen.m4f frozen.m4
$
])
AT_DATA([frozen.m4f],
[[# This is a frozen state file generated by GNU M4 1.4.5
V1
Q1,1
[]
C2,2
/**/
F6,6
popdefpopdef
F13,10
my_changewordchangeword
F9,6
my_definedefine
T9,6
my_definedefine
F9,6
my_definedefine
T3,4
foo\FOO
T3,7
foobar${1}
F3,3
dnldnl
D1,8
bar${1}
D0,0
# End of frozen state file
]])
AT_DATA([input.m4],
[[foo([2]) /* foo */ popdef([foo])foo
my_define([bar], [1])[]popdef([my_define]) bar
my_define([bar], [2])[]popdef([my_define]) bar
my_define([bar], [3])[]popdef([my_define]) bar
my_define([bar], [4])[]popdef([my_define]) bar
]])
AT_CHECK_M4([-R frozen.m4f input.m4], [0],
[[bar${1} /* foo */ \FOO
1
define 1
3
my_define(bar, 4) 3
bar${1}
]],
[[m4:input.m4:5: Warning: popdef: undefined macro `my_define'
]])
AT_CLEANUP
## ---------------- ##
## loading format 2 ##
## ---------------- ##
AT_SETUP([loading format 2])
AT_KEYWORDS([frozen])
AT_DATA([frozen.m4f],
[[# Handcrafted file, obeying the version 2 spec
V2
# missing close quote should be supplied
Q1,0
>
# missing close comment should be supplied
C1,0
<
M2
m4
M3
gnu
F7,7,3
builtinbuiltingnu
# Text to negative diversion must not crash. Catches a regression
# introduced 2007-05-28 and fixed 2007-05-31.
D-1,5
12345
D0,0
# Testing escape sequences
T4,5
blah\t\477\040\X5C
# Long macro definition. Catches a regression introduced on 2007-01-20
# and patched 2007-02-25.
T4,122
long01234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789
01234567890123456789
]])
AT_DATA([input.m4],
[[< comment: builtin()
builtin(>define', foo, bar)
foo
blah
]])
AT_CHECK_M4([-R frozen.m4f input.m4], [0],
[[< comment: builtin()
bar
'7 \
]])
dnl We don't support anything larger than format 2; make sure of that...
AT_DATA([bogus.m4f], [[V3
]])
AT_CHECK_M4([-R bogus.m4f], [63], [],
[[m4: frozen file version 3 greater than max supported of 2
]])
AT_CLEANUP
## --------- ##
## changecom ##
## --------- ##
AT_SETUP([reloading changecom])
AT_KEYWORDS([frozen])
# Check that changesyntax is maintained across freeze boundaries.
AT_DATA([[frozen.m4]],
[[changecom`'changequote(<,>)dnl
]])
AT_DATA([[unfrozen.m4]],
[[define(<foo>, <bar>)
foo # foo
]])
# First generate the `expout' output by running over the sources before
# freezing.
AT_CHECK_M4([frozen.m4 unfrozen.m4], [0],
[stdout], [stderr])
mv stdout expout
mv stderr experr
# Now freeze the first source file.
AT_CHECK_M4([-F frozen.m4f frozen.m4], [0])
# Now rerun the original sequence, but using the frozen file.
AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0],
[expout], [experr])
AT_CLEANUP
## ------------ ##
## changesyntax ##
## ------------ ##
AT_SETUP([reloading changesyntax])
AT_KEYWORDS([frozen])
# Check that changesyntax is maintained across freeze boundaries.
AT_DATA([[frozen.m4]],
[[changesyntax(`W+.', `({', `)}')dnl
define{`a.b', `hello $1'}dnl
]])
AT_DATA([[unfrozen.m4]],
[[a.b{world}
]])
# First generate the `expout' output by running over the sources before
# freezing.
AT_CHECK_M4([frozen.m4 unfrozen.m4], [0],
[stdout], [stderr])
mv stdout expout
mv stderr experr
# Now freeze the first source file.
AT_CHECK_M4([-F frozen.m4f frozen.m4], [0])
# Now rerun the original sequence, but using the frozen file.
AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0],
[expout], [experr])
AT_CLEANUP
## ------------- ##
## regexp syntax ##
## ------------- ##
AT_SETUP([reloading regexp syntax])
AT_KEYWORDS([frozen])
# Check that regular expression syntax is maintained across freeze boundaries.
AT_DATA([[frozen.m4]],
[[changeresyntax(`POSIX_EXTENDED')dnl
]])
AT_DATA([[unfrozen.m4]],
[[regexp(`GNUs not Unix', `\w(\w*)$')
regexp(`GNUs not Unix', `\w\(\w*\)$', `GNU_M4')
]])
# First generate the `expout' output by running over the sources before
# freezing.
AT_CHECK_M4([frozen.m4 unfrozen.m4], [0],
[stdout], [stderr])
mv stdout expout
mv stderr experr
# Now freeze the first source file.
AT_CHECK_M4([-F frozen.m4f frozen.m4], [0],
[ignore], [ignore])
# Now rerun the original sequence, but using the frozen file.
AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0],
[expout], [experr])
AT_CLEANUP
## ---------------- ##
## unknown builtins ##
## ---------------- ##
AT_SETUP([reloading unknown builtin])
AT_KEYWORDS([frozen])
AT_DATA([[empty.m4]])
# Freeze default state. Also check for bug fixed 18 Oct, 2007.
AT_CHECK_M4([-F frozen.m4f -t undefined empty.m4])
# Add an unknown builtin.
echo 'F1,1' >> frozen.m4f
echo 'ab' >> frozen.m4f
AT_DATA([[input.m4]],
[[dnl The macro is defined; checking this is safe
ifdef(`a', `yes', `no')
dnl Grabbing the definition must warn; and the copy is the empty string
define(`c', defn(`a'))
dnl Invoking the macro directly must warn
a
dnl Invoking it indirectly must warn
indir(`a')
dnl The copy is a text string, not a placeholder
c
dnl Since it is defined, it must have a definition
dumpdef(`a', `c')
dnl Deleting it is safe
popdef(`a')
a
]])
AT_CHECK_M4([-R frozen.m4f input.m4], 0,
[[yes
a
]],
[[m4:input.m4:4: Warning: a: builtin `b' requested by frozen file not found
m4:input.m4:6: Warning: a: builtin `b' requested by frozen file not found
m4:input.m4:8: Warning: a: builtin `b' requested by frozen file not found
a: <<b>>
c: `'
]])
AT_CLEANUP