modules: clean up no-longer supported preloading references.
[m4/ericb.git] / tests / builtins.at
blob8bda542e6b5a94e2eb38028629a6938524f963db
1 # Hand crafted tests for GNU M4.                               -*- Autotest -*-
2 # Copyright (C) 2001, 2006-2010, 2013-2014 Free Software Foundation,
3 # Inc.
5 # This file is part of GNU M4.
7 # GNU M4 is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # GNU M4 is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 AT_BANNER([Torturing builtins.])
23 ## -------- ##
24 ## __file__ ##
25 ## -------- ##
27 AT_SETUP([__@&t@file__])
29 dnl Unfortunately, AT_DATA does not make it easy to create files without
30 dnl a trailing newline.
31 [echo $ECHO_N "__line"__:__"file__$ECHO_C"] > nested
32 AT_DATA([outer],
33 [[__file__:__line__
34 include(`nested')
35 __file__:__line__
36 ]])
38 dnl Make sure line numbers are consistent, even if include file does not
39 dnl end with a newline
40 AT_CHECK_M4([outer], [0],
41 [[outer:1
42 1:nested
43 outer:3
44 ]])
46 AT_CLEANUP
49 ## -------- ##
50 ## __line__ ##
51 ## -------- ##
53 AT_SETUP([__@&t@line__])
55 dnl Unfortunately, AT_DATA does not make it easy to create files without
56 dnl a trailing newline.
57 [echo $ECHO_N "__file"__:__"line__$ECHO_C"] > nested
58 AT_DATA([outer],
59 [[__file__:__line__
60 include(`nested')
61 __file__:__line__
62 ]])
64 dnl Make sure line numbers are consistent, even if include file does not
65 dnl end with a newline
66 AT_CHECK_M4([outer], [0],
67 [[outer:1
68 nested:1
69 outer:3
70 ]])
72 AT_CLEANUP
75 ## -------------- ##
76 ## __m4_version__ ##
77 ## -------------- ##
79 AT_SETUP([__m4_@&t@version__])
81 AT_DATA([in], [[defn(`__m4_version__')
82 ]])
83 AT_CHECK_M4([--version], [0], [stdout])
84 AT_CHECK([[$SED -e 's/.*(GNU M4\(.*\)) \([^ ]*\).*/\2\1/;q' < stdout]],
85 [0], [stdout])
86 mv stdout expout
87 AT_CHECK_M4([in], [0], [expout])
89 dnl Prove that __m4_version__ is unquoted, by making '.' an active character.
90 AT_DATA([in], [[changesyntax(`A.')define(`.', `errprint(`hi
91 ')undefine(`.').')dnl
92 __m4_version__
93 ]])
94 AT_CHECK_M4([in], [0], [expout], [[hi
95 ]])
97 AT_CLEANUP
100 ## ------- ##
101 ## builtin ##
102 ## ------- ##
104 AT_SETUP([builtin])
106 dnl This was a regression in 1.4.10b.
107 AT_DATA([in.m4],
108 [[define(`s', `builtin(`shift', $@)')dnl
109 define(`loop', `ifelse(`$2', `', `-', `$1$2: $0(`$1', s(s($@)))')')dnl
110 loop(`1')
111 loop(`1', `2')
112 loop(`1', `2', `3')
113 loop(`1', `2', `3', `4')
114 loop(`1', `2', `3', `4', `5')
116 AT_CHECK_M4([in.m4], [0],
118 12: -
119 12: 13: -
120 12: 13: 14: -
121 12: 13: 14: 15: -
124 AT_CLEANUP
127 ## ----------- ##
128 ## changequote ##
129 ## ----------- ##
131 AT_SETUP([changequote])
133 AT_DATA([in.m4],
134 [[define(`aaaaaaaaaaaaaaaaaaaa', `A')define(`q', `"$@"')
135 changequote(`"', `"')
136 q(q("aaaaaaaaaaaaaaaaaaaa", "a"))
137 changequote`'define(`echo', `$@')dnl
138 changequote(`<<<', `>>')dnl
139 echo(<<<a<<<b>>>>)
142 AT_CHECK_M4([in.m4], [0], [[
145 a<<<b>>
148 AT_CLEANUP
151 ## ----- ##
152 ## debug ##
153 ## ----- ##
155 AT_SETUP([debug])
157 AT_DATA([[debug.m4]],
158 [[define(`countdown', `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')')
159 debugmode(`aeqc')
160 traceon(`countdown')
161 countdown(2)
164 AT_DATA([[expout]],
168 2 1 0 Liftoff
171 AT_DATA([[experr]],
172 [[m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')'
173 m4trace: -1- countdown(`2') -> `2 ifelse(eval(2 > 0), 1, `countdown(decr(2))', `Liftoff')'
174 m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')'
175 m4trace: -1- countdown(`1') -> `1 ifelse(eval(1 > 0), 1, `countdown(decr(1))', `Liftoff')'
176 m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')'
177 m4trace: -1- countdown(`0') -> `0 ifelse(eval(0 > 0), 1, `countdown(decr(0))', `Liftoff')'
180 AT_CHECK_M4([debug.m4], 0, expout, experr)
182 dnl Test a regression introduced 2008-05-08, fixed 2008-07-30.
183 AT_DATA([debug.m4], [[debugmode(`e')traceon(`ifelse')dnl
184 define(`e', `ifelse(`$1', `$2', `ifelse(`$1', `$2', `e(shift($@))')', `$2')')
185 e(`1', `1', `a')
188 AT_CHECK_M4([debug.m4], [0], [[
190 ]], [[m4trace: -1- ifelse -> ifelse(`1', `1', `e(shift(`1',`1',`a'))')
191 m4trace: -1- ifelse -> e(shift(`1',`1',`a'))
192 m4trace: -1- ifelse -> a
195 AT_CLEANUP
198 ## ------ ##
199 ## define ##
200 ## ------ ##
202 AT_SETUP([define])
204 AT_DATA([[define.m4]],
205 [[undefine(`macro')dnl
206 pushdef(`macro', `base value')dnl
207 pushdef(`macro', `hello, world')dnl
208 pushdef(`macro', `top value')dnl
209 define(`macro', `new value')dnl
210 macro.
211 popdef(`macro')dnl
212 macro.
213 popdef(`macro')dnl
214 macro.
217 AT_CHECK_M4([define.m4], 0,
218 [[new value.
219 hello, world.
220 base value.
221 ]], [[m4:define.m4:1: warning: undefine: undefined macro 'macro'
224 AT_CHECK_M4([--traditional define.m4], 0,
225 [[new value.
226 hello, world.
227 base value.
228 ]], [[m4:define.m4:1: warning: undefine: undefined macro 'macro'
231 dnl check regression present 2008-02-22 to 2008-04-30.
232 AT_DATA([in.m4], [[define(`qq', ``$*;$@'')dnl
233 define(`foo', qq(`a', `b'))dnl
235 defn(`foo')
237 AT_CHECK_M4([in.m4], [0], [[a,b;a,b
238 a,b;`a',`b'
241 dnl Check hashing performance.
242 AT_DATA([in.m4], [[include(`forloop3.m4')dnl
243 forloop(`i', `1', `10000', `define(`m'i, i)')m10000
244 forloop(`i', `1', `10000', `undefine(`m'i)')m10000
246 AT_CHECK_M4([-I "$abs_top_srcdir/doc/examples" in.m4], [0], [[10000
247 m10000
250 AT_CLEANUP
254 ## ---- ##
255 ## defn ##
256 ## ---- ##
258 AT_SETUP([defn])
260 AT_DATA([[in.m4]],
261 [[define(`e', `$@')define(`q', ``$@'')define(`u', `$*')
262 define(`cmp', `ifelse($1, $2, `yes', `no')')define(`d', defn(`defn'))
263 cmp(`defn(`defn')', `defn(`d')')
264 cmp(`defn(`defn')', ``<defn>'')
265 cmp(`q(defn(`defn'))', `q(defn(`d'))')
266 cmp(`q(defn(`defn'))', `q(`<defn>')')
267 cmp(`q(defn(`defn'))', ``'')
268 cmp(`q(`1', `2', defn(`defn'))', `q(`1', `2', defn(`d'))')
269 cmp(`q(`1', `2', defn(`defn'))', `q(`1', `2', `<defn>')')
270 cmp(`q(`1', `2', defn(`defn'))', ```1',`2',<defn>'')
271 cmp(`q(`1', `2', defn(`defn'))', ```1',`2',`''')
272 define(`cat', `$1`'ifelse(`$@%:@', `1', `', `$0(shift($@))')')
273 cat(`define(`foo',', defn(`divnum'), `)foo')
274 cat(e(`define(`bar',', defn(`divnum'), `)bar'))
275 m4wrap(`u('q(`cat(`define(`baz','', defn(`divnum'), ``)baz')')`)
279 AT_CHECK_M4([in.m4], [0], [[
297 AT_CLEANUP
300 ## ------ ##
301 ## divert ##
302 ## ------ ##
304 AT_SETUP([divert])
306 AT_DATA([[divert.m4]],
307 [[divert(1)Text diverted a first time.
308 divert(0)undivert(1)dnl
309 divert(1)Text diverted a second time.
310 divert(0)undivert(1)dnl
313 AT_CHECK_M4([divert.m4], 0,
314 [[Text diverted a first time.
315 Text diverted a second time.
318 dnl Test second divert argument, added for m4 2.0
319 AT_DATA([in.m4], [[define(`echo',`$1')dnl
320 divert(`-1', `discarded without warning')
321 divert`'dnl
322 echo(` world'divert(divnum, `hello'))
325 AT_CHECK_M4([-s in.m4], [0], [[#line 4 "in.m4"
326 hello world
329 dnl Test large diversions, which were broken in m4 1.4.8-1.4.10.
330 dnl Hopefully $SED doesn't choke on the over-long second line.
331 AT_CHECK([echo 'divert(1)hi
332 format(%1000000d, 1)' | $M4 | $SED -n 1p], [0], [[hi
335 AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`2')f`'dnl
336 divert(`1')hello
337 divert(`3')goodbye
340 dnl Rather than open-code the 1 megabyte expected output, we reduce the
341 dnl size of testsuite by constructing it.
342 AT_DATA([expout], [[
344 cat expout expout > expout2
345 cat expout2 expout2 > expout
346 cat expout expout > expout2
347 cat expout2 expout2 > expout
348 cat expout expout > expout2
349 cat expout2 expout2 > expout
350 cat expout expout > expout2
351 cat expout2 expout2 > expout
352 cat expout expout > expout2
353 cat expout2 expout2 > expout
354 cat expout expout > expout2
355 cat expout2 expout2 > expout
356 cat expout expout > expout2
357 cat expout2 expout2 > expout
358 cat expout expout > expout2
359 cat expout2 expout2 > expout
360 cat expout expout > expout2
361 cat expout2 expout2 > expout
362 cat expout expout > expout2 # 512 kilobytes
363 echo hello > expout
364 cat expout2 expout2 >> expout # 1 megabyte
365 echo goodbye >> expout
366 rm expout2
368 AT_CHECK_M4([in.m4], [0], [expout])
370 dnl Avoid quadratic copying time when transferring diversions; test
371 dnl both in-memory and diversions spilled to a file.
372 AT_DATA([in.m4], [[include(`forloop2.m4')dnl
373 divert(`1')format(`%10000s', `')dnl
374 forloop(`i', `1', `10000',
375   `divert(incr(i))undivert(i)')dnl
376 divert(`9001')format(`%1000000s', `')dnl
377 forloop(`i', `9001', `10000',
378   `divert(incr(i))undivert(i)')dnl
379 divert(`-1')undivert
382 AT_CHECK_M4([-I "$abs_top_srcdir/doc/examples" in.m4])
384 AT_CLEANUP
387 ## --- ##
388 ## dnl ##
389 ## --- ##
391 AT_SETUP([d@&t@nl])
393 dnl Unfortunately, AT_DATA does not make it easy to create files without
394 dnl a trailing newline.
395 [echo $ECHO_N "__file"__:__"line__ d""nl ignored$ECHO_C"] > nested
396 AT_DATA([outer],
397 [[__file__:__line__
398 include(`nested') still ignored
399 __file__:__line__
400 define(`foo', `dnl
401 __file__:__line__ include(`nested') ignored
402 dnl')dnl
403 foo ignored
404 __file__:__line__
407 dnl Make sure line numbers are consistent, even if include file does not
408 dnl end with a newline
409 AT_CHECK_M4([outer], [0],
410 [[outer:1
411 nested:1 outer:3
412 outer:7 nested:1 outer:8
415 AT_CLEANUP
418 ## ------- ##
419 ## dumpdef ##
420 ## ------- ##
422 AT_SETUP([dumpdef])
424 dnl Make sure that stderr and stdout are properly interleaved when directed
425 dnl to the same file.
426 AT_DATA([in], [[1dumpdef(`defn')3
428 AT_CHECK_M4([in], [0], [[13
429 ]], [[defn:     <defn>
431 AT_CHECK_M4([in 2>&1], [0], [[1defn:    <defn>
435 AT_CLEANUP
438 ## -------- ##
439 ## errprint ##
440 ## -------- ##
442 AT_SETUP([errprint])
444 dnl Make sure that stderr and stdout are properly interleaved when directed
445 dnl to the same file.
446 AT_DATA([in], [[1errprint(`2')3errprint(`
449 AT_CHECK_M4([in], [0], [[13
450 ]], [[2
452 AT_CHECK_M4([in 2>&1], [0], [[123
456 AT_CLEANUP
459 ## ------- ##
460 ## esyscmd ##
461 ## ------- ##
463 AT_SETUP([esyscmd])
465 AT_DATA([[esyscmd.m4]],
466 [[# Cannot use real hostname program because test would fail
467 define(`hostname', esyscmd(`echo www.gnu.org'))dnl
468 `hostname = >>'hostname`<<'
469 define(`hostname',
470 pushdef(`_tmp', `$1')_tmp(translit(esyscmd(`echo www.gnu.org'), `.', `,'))`'popdef(`_tmp'))dnl
471 `hostname = >>'hostname`<<'
474 AT_CHECK_M4([esyscmd.m4], 0,
475 [[# Cannot use real hostname program because test would fail
476 hostname = >>www.gnu.org
478 hostname = >>www<<
481 dnl Ensure that esyscmd does not inherit any unnecessary fds from trace.
482 AT_DATA([in.m4], [[esyscmd(`echo hi >&3')ifelse(sysval,
483 `0', `skipping: sh cannot detect closed fds
484 m4exit(`77')')dnl
486 AT_CHECK_M4([3>&-], [0], [], [stderr], [in.m4])
487 mv stderr experr
488 AT_CHECK_M4([--debugfile=trace -tdnl 3>&-], [0], [], [experr], [in.m4])
489 AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `'
492 dnl Ensure that esyscmd does not inherit any unnecessary fds from diversions.
493 AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f
494 world
495 esyscmd(`echo hi >&3')divert
496 hello
498 AT_CHECK_M4([3>&-], [0], [stdout-nolog], [experr], [in.m4])
499 AT_CHECK([$SED -ne '/./p' stdout], [0], [[hello
500 world
503 dnl Ensure that esyscmd does not inherit any unnecessary fds from input files.
504 AT_DATA([in.m4], [[hello esyscmd(`cat <&3')dnl
505 dnl this line should not be read by cat
506 world
508 AT_CHECK_M4([3>&-], [0], [[hello world
509 ]], [stderr], [in.m4])
510 mv stderr experr
511 AT_CHECK_M4([in.m4 3>&-], [0], [[hello world
512 ]], [experr])
514 AT_CLEANUP
517 ## ------ ##
518 ## ifelse ##
519 ## ------ ##
521 AT_TEST_M4([ifelse],
522 dnl ensure that comparisons work regardless of reference chains in the middle
523 [[define(`e', `$@')define(`long', `01234567890123456789')
524 dnl in isolation
525 ifelse(long, `01234567890123456789', `yes', `no')
526 ifelse(`01234567890123456789', long, `yes', `no')
527 ifelse(long, `01234567890123456789-', `yes', `no')
528 ifelse(`01234567890123456789-', long, `yes', `no')
529 dnl through macro expansion
530 ifelse(e(long), `01234567890123456789', `yes', `no')
531 ifelse(`01234567890123456789', e(long), `yes', `no')
532 ifelse(e(long), `01234567890123456789-', `yes', `no')
533 ifelse(`01234567890123456789-', e(long), `yes', `no')
534 dnl concatenate macro expansion with unquoted characters
535 ifelse(-e(long), `-01234567890123456789', `yes', `no')
536 ifelse(-`01234567890123456789', -e(long), `yes', `no')
537 ifelse(-e(long), `-01234567890123456789-', `yes', `no')
538 ifelse(`-01234567890123456789-', -e(long), `yes', `no')
539 ifelse(-e(long)-, `-01234567890123456789-', `yes', `no')
540 ifelse(-`01234567890123456789-', -e(long)-, `yes', `no')
541 ifelse(-e(long)-, `-01234567890123456789', `yes', `no')
542 ifelse(`-01234567890123456789', -e(long)-, `yes', `no')
543 dnl concatenate macro expansion with quoted characters
544 ifelse(`-'e(long), `-01234567890123456789', `yes', `no')
545 ifelse(-`01234567890123456789', `-'e(long), `yes', `no')
546 ifelse(`-'e(long), `-01234567890123456789-', `yes', `no')
547 ifelse(`-01234567890123456789-', `-'e(long), `yes', `no')
548 ifelse(`-'e(long)`-', `-01234567890123456789-', `yes', `no')
549 ifelse(-`01234567890123456789-', `-'e(long)`-', `yes', `no')
550 ifelse(`-'e(long)`-', `-01234567890123456789', `yes', `no')
551 ifelse(`-01234567890123456789', `-'e(long)`-', `yes', `no')
552 ]], [[
580 ## ------- ##
581 ## include ##
582 ## ------- ##
584 AT_SETUP([include])
586 AT_DATA([[include.m4]],
587 [[Beginning.
588 include(`NOFILE')
589 Intermediate
590 include(`incl-test.m4')
591 After
592 include(`NOFILE')
593 very late
596 AT_DATA([[incl-test.m4]],
597 [[dnl noauto
598 `include test file.'
599 define()
602 AT_DATA([[expout]],
603 [[Beginning.
605 Intermediate
606 include test file.
609 After
611 very late
614 AT_DATA([[experr]],
615 [[m4:include.m4:2: include: cannot open file 'NOFILE': No such file or directory
616 m4:include.m4:6: include: cannot open file 'NOFILE': No such file or directory
619 AT_CHECK_M4([include.m4], 1, expout, experr)
621 dnl make sure files are handled correctly even via builtin
622 AT_DATA([foo], [[bar
624 AT_DATA([in], [[builtin(`include', `foo')dnl
627 AT_CHECK_M4([in], [0], [[bar
630 AT_CLEANUP
634 ## ----- ##
635 ## index ##
636 ## ----- ##
638 AT_SETUP([index])
640 dnl This used to be quadratic, taking millions of comparisons,
641 dnl but should now operate in linear time with only several thousand checks.
642 AT_DATA([in], [M4_ONE_MEG_DEFN[dnl
643 index(substr(f, `0', `500000')-, substr(f, `0', `100000')-)
645 AT_CHECK_M4([in], [0], [[400000
648 dnl This validates that index is 8-bit safe.
649 AT_DATA([in], [[index(`1«2', `»')
650 index(`1«2', `«')
651 index(`1«2', `«1')
652 index(`1«2', `«2')
654 AT_CHECK_M4([in], [0], [[-1
660 AT_CLEANUP
664 ## ----- ##
665 ## indir ##
666 ## ----- ##
668 AT_SETUP([indir])
670 AT_DATA([[indir.m4]],
671 [[define(`%%$$##', `>>>$0<<< cnt $#')
673 # indir(`%%$$##', nonsense, nonsense)
674 indir(`%%$$##', nonsense, nonsense)
676 # indir(`indir', `%%$$##', nonsense)
677 indir(`indir', `%%$$##', nonsense)
679 # indir(`indir', `indir', `indir', `indir', `%%$$##')
680 indir(`indir', `indir', `indir', `indir', `%%$$##')
683 AT_DATA([[expout]],
686 # indir(`%%$$##', nonsense, nonsense)
687 >>>%%$$##<<< cnt 2
689 # indir(`indir', `%%$$##', nonsense)
690 >>>%%$$##<<< cnt 1
692 # indir(`indir', `indir', `indir', `indir', `%%$$##')
693 >>>%%$$##<<< cnt 0
696 AT_CHECK_M4([indir.m4], 0, expout)
698 AT_CLEANUP
701 ## ------ ##
702 ## m4exit ##
703 ## ------ ##
705 AT_SETUP([m4exit])
707 dnl Ensure that spilled diversions are gracefully cleaned up
708 AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f
709 m4exit
711 AT_CHECK([rm -Rf tmpdir && mkdir tmpdir && test -d tmpdir])
712 TMPDIR=tmpdir
713 export TMPDIR
714 AT_CHECK_M4([in.m4], [0])
715 AT_CHECK([rmdir tmpdir])
717 AT_CLEANUP
720 ## ------- ##
721 ## mkdtemp ##
722 ## ------- ##
724 AT_SETUP([mkdtemp])
726 dnl Check that on error, the expansion is void
727 AT_DATA([[in]],
728 [[mkdtemp(`no_such_dir/m4-fooXXXXXX')
730 AT_CHECK_M4([in], [0], [[
731 ]], [[m4:in:1: warning: mkdtemp: cannot create directory from template 'no_such_dir/m4-fooXXXXXX': No such file or directory
734 dnl Check that umask has an effect.  drws--S--T is okay.
735 AT_DATA([[in]],
736 [[translit(substr(esyscmd(`ls -ld 'mkdtemp(`m4-fooXXXXXX')), `0', `10'),
737            `SsT', `-x-')
739 AT_CHECK([$M4 < in], [0], [[drwx------
741 AT_CHECK([umask 700; $M4 < in], [0], [[d---------
744 AT_CLEANUP
747 ## -------- ##
748 ## maketemp ##
749 ## -------- ##
751 AT_SETUP([mkstemp])
753 AT_KEYWORDS([maketemp])
755 dnl Check that on error, the expansion is void
756 AT_DATA([[in]],
757 [[mkstemp(`no_such_dir/m4-fooXXXXXX')
759 AT_CHECK_M4([in], [0], [[
760 ]], [[m4:in:1: warning: mkstemp: cannot create file from template 'no_such_dir/m4-fooXXXXXX': No such file or directory
763 dnl Check that extra X are appended, but not trailing NUL
764 AT_DATA([[in]], [[len(mkstemp(`m4-fooXXXXX'))
766 AT_CHECK_M4([in], [0], [[12
769 dnl Check that umask has an effect
770 AT_DATA([[in]],
771 [[substr(esyscmd(`ls -ld 'mkstemp(`m4-fooXXXXXX')), `0', `10')
773 AT_CHECK([$M4 < in], [0], [[-rw-------
775 AT_CHECK([umask 700; $M4 < in], [0], [[----------
778 dnl Check for Solaris compatibility of maketemp.  Hopefully the pid is
779 dnl less than 20 decimal digits.  Also check that --safer does not affect
780 dnl traditional behavior of maketemp, which is textual only.
781 AT_DATA([[in]],
782 [[maketemp()
783 maketemp(X)
784 maketemp(XX)
785 maketemp(XXXXXXXXXXXXXXXXXXXXX)
786 maketemp(no_such_dir/XXXXXX)
788 dnl Abuse our knowledge of AT_CHECK_M4 so that we can get stderr filtering...
789 AT_CHECK_M4([-G -Q --safer], [0], [stdout], [],
790 [in& echo $! > pid; wait $!])
791 pid=`cat pid`
792 cat >expout <<EOF
795 X`$SED -e 's/.*\(.\)$/\1/' pid`
796 X`echo "$pid" | $SED -e "s/.*/00000000000000000000&/" -e 's/.*\(.\{20\}$\)/\1/'`
797 no_such_dir/`echo "$pid" | $SED -e "s/.*/000000&/" -e 's/.*\(.\{6\}$\)/\1/'`
799 AT_CHECK([cat stdout], [0], [expout])
801 AT_CLEANUP
804 ## ------ ##
805 ## mpeval ##
806 ## ------ ##
808 AT_SETUP([mpeval])
809 AT_CHECK_GMP
811 AT_DATA([[in]],
812 [[divert(-1)
813 # forloop(i, from, to, stmt)
815 define(`forloop', `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')')
816 define(`_forloop',
817        `$4`'ifelse($1, `$3', ,
818                          `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
819 divert
820 forloop(`x', 1, 100, `2**x = mpeval(2**x)
824 AT_DATA([[expout]],
826 2**1 = 2
827 2**2 = 4
828 2**3 = 8
829 2**4 = 16
830 2**5 = 32
831 2**6 = 64
832 2**7 = 128
833 2**8 = 256
834 2**9 = 512
835 2**10 = 1024
836 2**11 = 2048
837 2**12 = 4096
838 2**13 = 8192
839 2**14 = 16384
840 2**15 = 32768
841 2**16 = 65536
842 2**17 = 131072
843 2**18 = 262144
844 2**19 = 524288
845 2**20 = 1048576
846 2**21 = 2097152
847 2**22 = 4194304
848 2**23 = 8388608
849 2**24 = 16777216
850 2**25 = 33554432
851 2**26 = 67108864
852 2**27 = 134217728
853 2**28 = 268435456
854 2**29 = 536870912
855 2**30 = 1073741824
856 2**31 = 2147483648
857 2**32 = 4294967296
858 2**33 = 8589934592
859 2**34 = 17179869184
860 2**35 = 34359738368
861 2**36 = 68719476736
862 2**37 = 137438953472
863 2**38 = 274877906944
864 2**39 = 549755813888
865 2**40 = 1099511627776
866 2**41 = 2199023255552
867 2**42 = 4398046511104
868 2**43 = 8796093022208
869 2**44 = 17592186044416
870 2**45 = 35184372088832
871 2**46 = 70368744177664
872 2**47 = 140737488355328
873 2**48 = 281474976710656
874 2**49 = 562949953421312
875 2**50 = 1125899906842624
876 2**51 = 2251799813685248
877 2**52 = 4503599627370496
878 2**53 = 9007199254740992
879 2**54 = 18014398509481984
880 2**55 = 36028797018963968
881 2**56 = 72057594037927936
882 2**57 = 144115188075855872
883 2**58 = 288230376151711744
884 2**59 = 576460752303423488
885 2**60 = 1152921504606846976
886 2**61 = 2305843009213693952
887 2**62 = 4611686018427387904
888 2**63 = 9223372036854775808
889 2**64 = 18446744073709551616
890 2**65 = 36893488147419103232
891 2**66 = 73786976294838206464
892 2**67 = 147573952589676412928
893 2**68 = 295147905179352825856
894 2**69 = 590295810358705651712
895 2**70 = 1180591620717411303424
896 2**71 = 2361183241434822606848
897 2**72 = 4722366482869645213696
898 2**73 = 9444732965739290427392
899 2**74 = 18889465931478580854784
900 2**75 = 37778931862957161709568
901 2**76 = 75557863725914323419136
902 2**77 = 151115727451828646838272
903 2**78 = 302231454903657293676544
904 2**79 = 604462909807314587353088
905 2**80 = 1208925819614629174706176
906 2**81 = 2417851639229258349412352
907 2**82 = 4835703278458516698824704
908 2**83 = 9671406556917033397649408
909 2**84 = 19342813113834066795298816
910 2**85 = 38685626227668133590597632
911 2**86 = 77371252455336267181195264
912 2**87 = 154742504910672534362390528
913 2**88 = 309485009821345068724781056
914 2**89 = 618970019642690137449562112
915 2**90 = 1237940039285380274899124224
916 2**91 = 2475880078570760549798248448
917 2**92 = 4951760157141521099596496896
918 2**93 = 9903520314283042199192993792
919 2**94 = 19807040628566084398385987584
920 2**95 = 39614081257132168796771975168
921 2**96 = 79228162514264337593543950336
922 2**97 = 158456325028528675187087900672
923 2**98 = 316912650057057350374175801344
924 2**99 = 633825300114114700748351602688
925 2**100 = 1267650600228229401496703205376
929 AT_CHECK_M4([mpeval in], 0, expout)
931 AT_CLEANUP
935 ## ----------- ##
936 ## multiquotes ##
937 ## ----------- ##
939 AT_SETUP([multiquotes])
941 AT_DATA([[multiquotes.m4]],
942 [[traceon
943 changequote([,])dnl
944 changequote([``], [''])dnl
945 ````traceon''''
946 define(``foo'', ````FOO'''')dnl
947 dumpdef(``foo'')dnl
948 changequote(``!'', ``!'')dnl
949 !foo!
951 dumpdef(!foo!)dnl
952 define(!bar!, !BAR!)
954 changequote(!>*>*>*>*>!, !<*<*<*<*<!)dnl five of each
955 >*>*>*>*>foo bar<*<*<*<*<
956 foo bar
957 >*>*>*>*>*>*><*<*<*<*<*<*<
958 dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<)dnl
961 AT_DATA([[expout]],
963 ``traceon''
965 ``FOO''
968 foo bar
969 ``FOO'' BAR
970 *>*>*<*<
973 AT_DATA([[experr]],
974 [[m4trace: -1- changequote(`[', `]') -> []
975 m4trace: -1- dnl -> []
976 m4trace: -1- changequote([``], ['']) -> ``''
977 m4trace: -1- dnl -> ``''
978 m4trace: -1- define(``foo'', ````FOO'''') -> ``''
979 m4trace: -1- dnl -> ``''
980 foo:    ````FOO''''
981 m4trace: -1- dumpdef(``foo'') -> ``''
982 m4trace: -1- dnl -> ``''
983 m4trace: -1- changequote(``!'', ``!'') -> !!
984 m4trace: -1- dnl -> !!
985 m4trace: -1- foo -> !``FOO''!
986 foo:    !``FOO''!
987 m4trace: -1- dumpdef(!foo!) -> !!
988 m4trace: -1- dnl -> !!
989 m4trace: -1- define(!bar!, !BAR!) -> !!
990 m4trace: -1- bar -> !BAR!
991 m4trace: -1- changequote(!>*>*>*>*>!, !<*<*<*<*<!) -> >*>*>*>*><*<*<*<*<
992 m4trace: -1- dnl -> >*>*>*>*><*<*<*<*<
993 m4trace: -1- foo -> >*>*>*>*>``FOO''<*<*<*<*<
994 m4trace: -1- bar -> >*>*>*>*>BAR<*<*<*<*<
995 bar:    >*>*>*>*>BAR<*<*<*<*<
996 foo:    >*>*>*>*>``FOO''<*<*<*<*<
997 m4trace: -1- dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<) -> >*>*>*>*><*<*<*<*<
998 m4trace: -1- dnl -> >*>*>*>*><*<*<*<*<
1001 AT_CHECK_M4([multiquotes.m4], 0, expout, experr)
1003 AT_CLEANUP
1007 ## -------- ##
1008 ## patsubst ##
1009 ## -------- ##
1011 AT_SETUP([patsubst])
1013 AT_DATA([[patsubst.m4]],
1014 [[# traceon(`patsubst')
1015 patsubst(`GNUs not Unix.', `^', `OBS: ')
1016 patsubst(`GNUs not Unix.', `\<', `OBS: ')
1017 patsubst(`GNUs not Unix.', `\<\w', `\&=')
1018 patsubst(`GNUs not Unix.', `\w*', `(\&)')
1019 patsubst(`GNUs not Unix.', `\w+', `(\&)')
1020 patsubst(`GNUs not Unix.', `\w+')
1021 patsubst(`GNUs   not  '`         Unix.', `[      ]+', ` ')
1024 AT_DATA([[expout]],
1025 [[# traceon(`patsubst')
1026 OBS: GNUs not Unix.
1027 OBS: GNUs OBS: not OBS: Unix.
1028 G=NUs n=ot U=nix.
1029 (GNUs)() (not)() (Unix)().()
1030 (GNUs) (not) (Unix).
1031   .
1032 GNUs not Unix.
1035 AT_CHECK_M4([patsubst.m4], 0, expout)
1037 AT_CLEANUP
1041 ## ------ ##
1042 ## regexp ##
1043 ## ------ ##
1045 AT_SETUP([regexp])
1047 AT_DATA([[regexp.m4]],
1048 [[traceon(`regexp')dnl
1049 regexp(`hej med dig', `.*', `>>\&<<')
1050 regexp(`hej med dig', `\w*', `>>\&<<')
1051 regexp(`hej med dig', `.+', `>>\&<<')
1052 regexp(`hej med dig', `m\w+', `>>\&<<')
1053 regexp(`hej med dig', `m\(.*\)', `>>\&<< >>\1<<')
1055 regexp(`hej med dig', `.*')
1056 regexp(`hej med dig', `\w*')
1057 regexp(`hej med dig', `.+')
1058 regexp(`hej med dig', `m\w+')
1059 regexp(`hej med dig', `m\(.*\)')
1062 AT_DATA([[expout]],
1063 [[>>hej med dig<<
1064 >>hej<<
1065 >>hej med dig<<
1066 >>med<<
1067 >>med dig<< >>ed dig<<
1076 AT_DATA([[experr]],
1077 [[m4trace: -1- regexp(`hej med dig', `.*', `>>\&<<') -> `>>hej med dig<<'
1078 m4trace: -1- regexp(`hej med dig', `\w*', `>>\&<<') -> `>>hej<<'
1079 m4trace: -1- regexp(`hej med dig', `.+', `>>\&<<') -> `>>hej med dig<<'
1080 m4trace: -1- regexp(`hej med dig', `m\w+', `>>\&<<') -> `>>med<<'
1081 m4trace: -1- regexp(`hej med dig', `m\(.*\)', `>>\&<< >>\1<<') -> `>>med dig<< >>ed dig<<'
1082 m4trace: -1- regexp(`hej med dig', `.*') -> `0'
1083 m4trace: -1- regexp(`hej med dig', `\w*') -> `0'
1084 m4trace: -1- regexp(`hej med dig', `.+') -> `0'
1085 m4trace: -1- regexp(`hej med dig', `m\w+') -> `4'
1086 m4trace: -1- regexp(`hej med dig', `m\(.*\)') -> `4'
1089 AT_CHECK_M4([regexp.m4], 0, expout, experr)
1091 AT_CLEANUP
1095 ## ------------ ##
1096 ## sync-lines.  ##
1097 ## ------------ ##
1099 AT_SETUP([sync-lines])
1101 AT_DATA([[in]],
1102 [[syncoutput(on)dnl
1103 # Several input lines, expanding to one
1104 define(`foo', ``foo' line one.
1105 `foo' line two.
1106 `foo' line three.') xyz
1108 # Several input lines, expanding to none
1109 define(`foo', ``foo' line one.
1110 `foo' line two.
1111 `foo' line three.')dnl
1112 # one input line, expanding to several output lines
1113 foo foo
1116 AT_CHECK_M4([[in]], 0,
1117 [[#line 2 "in"
1118 # Several input lines, expanding to one
1119 #line 5
1120  xyz
1121 foo line one.
1122 #line 6
1123 foo line two.
1124 #line 6
1125 foo line three.
1126 # Several input lines, expanding to none
1127 #line 11
1128 # one input line, expanding to several output lines
1129 foo line one.
1130 #line 12
1131 foo line two.
1132 #line 12
1133 foo line three. foo line one.
1134 #line 12
1135 foo line two.
1136 #line 12
1137 foo line three.
1140 AT_CLEANUP
1143 ## ------ ##
1144 ## syscmd ##
1145 ## ------ ##
1147 AT_SETUP([syscmd])
1149 dnl Ensure that syscmd does not inherit any unnecessary fds from trace.
1150 AT_DATA([in.m4], [[syscmd(`echo hi >&3')ifelse(sysval,
1151 `0', `skipping: sh cannot detect closed fds
1152 m4exit(`77')')dnl
1154 AT_CHECK_M4([3>&-], [0], [], [stderr], [in.m4])
1155 mv stderr experr
1156 AT_CHECK_M4([--debugfile=trace -tdnl 3>&-], [0], [], [experr], [in.m4])
1157 AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `'
1160 dnl Ensure that syscmd does not inherit any unnecessary fds from diversions.
1161 AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f
1162 world
1163 syscmd(`echo hi >&3')divert
1164 hello
1166 AT_CHECK_M4([3>&-], [0], [stdout-nolog], [experr], [in.m4])
1167 AT_CHECK([$SED -ne '/./p' stdout], [0], [[hello
1168 world
1171 dnl Ensure that syscmd does not inherit any unnecessary fds from input files.
1172 AT_DATA([in.m4], [[hello syscmd(`cat <&3')dnl
1173 dnl this line should not be read by cat
1174 world
1176 AT_CHECK_M4([3>&-], [0], [[hello world
1177 ]], [stderr], [in.m4])
1178 mv stderr experr
1179 AT_CHECK_M4([in.m4 3>&-], [0], [[hello world
1180 ]], [experr])
1182 AT_CLEANUP
1185 ## -------- ##
1186 ## translit ##
1187 ## -------- ##
1189 AT_SETUP([translit])
1191 AT_DATA([[translit.m4]],
1192 [[# traceon(`translit')dnl
1193 translit(`GNUs not Unix', `a-z')
1194 translit(`GNUs not Unix', `a-z', `A-Z')
1195 translit(`GNUs not Unix', `A-Z', `a-z')
1196 translit(`GNUs not Unix', `A-Z')
1197 translit(`a-z', `a-')
1198 translit(`A-Z', `A-Z-', `-A-Z')
1199 translit(`GNUs not Unix', `Z-A', `a-z')
1202 AT_CHECK_M4([translit.m4], 0,
1203 [[# traceon(`translit')dnl
1204 GNU  U
1205 GNUS NOT UNIX
1206 gnus not unix
1207 s not nix
1210 tmfs not fnix
1213 dnl This used to be quadratic, taking millions of comparisons,
1214 dnl but should now operate in linear time with only several thousand checks.
1215 AT_DATA([in], [M4_ONE_MEG_DEFN[dnl
1216 define(`a_', translit(substr(f, `0', `50000'), `
1217 ', `a'))dnl
1218 define(`b_', translit(substr(f, `0', `50000'), `
1219 ', `b'))dnl
1220 define(`d_', translit(substr(f, `0', `50000'), `
1221 ', `d'))dnl
1222 define(`c'd_, `pass')dnl
1223 translit(`a'b_, a_`b', `c'd_)
1225 AT_CHECK_M4([in], [0], [[pass
1228 dnl This validates that ranges are built using unsigned chars.
1229 AT_DATA([in], [[translit(`«abc~', `~-»')
1231 AT_CHECK_M4([in], [0], [[abc
1234 dnl Validate short strings, which take a different code path.
1235 AT_DATA([in], [[dnl
1236 translit(`abcdeabcde', `a')
1237 translit(`abcdeabcde', `ab')
1238 translit(`abcdeabcde', `a', `f')
1239 translit(`abcdeabcde', `aa', `fg')
1240 translit(`abcdeabcde', `a', `fg')
1241 translit(`abcdeabcde', `ab', `f')
1242 translit(`abcdeabcde', `ab', `fg')
1243 translit(`abcdeabcde', `ab', `ba')
1244 translit(`abcdeabcde', `e', `f')
1245 translit(`abc', `', `cde')
1246 translit(`', `a', `bc')
1248 AT_CHECK_M4([in], [0], [[bcdebcde
1249 cdecde
1250 fbcdefbcde
1251 fbcdefbcde
1252 fbcdefbcde
1253 fcdefcde
1254 fgcdefgcde
1255 bacdebacde
1256 abcdfabcdf
1261 AT_CLEANUP
1265 ## -------- ##
1266 ## undivert ##
1267 ## -------- ##
1269 AT_SETUP([undivert])
1271 AT_DATA([[undivert.m4]],
1272 [[define(`undiverted', `UNDIVERTED')
1273 # undiverted file.
1274 undivert(`undivert.incl')
1275 # included file.
1276 include(`undivert.incl')
1279 AT_DATA([[undivert.incl]],
1280 [[This is to be undiverted soon.
1283 AT_CHECK_M4([undivert.m4], 0,
1285 # undiverted file.
1286 This is to be undiverted soon.
1288 # included file.
1289 This is to be UNDIVERTED soon.
1293 AT_CLEANUP
1297 ## ---- ##
1298 ## wrap ##
1299 ## ---- ##
1301 AT_SETUP([wrap])
1303 AT_DATA([[wrap.m4]],
1304 [[divert(-1)
1305 m4wrap(`Wrapper no. 1
1308 m4wrap(`Wrapper no. 2
1309 m4wrap(`Wrapper no. 3
1310 m4wrap(`Wrapper no. 4
1311 ')')')
1312 divert
1313 No. 33: The End.
1316 AT_CHECK_M4([wrap.m4], 0,
1318 No. 33: The End.
1319 Wrapper no. 1
1320 Wrapper no. 2
1321 Wrapper no. 3
1322 Wrapper no. 4
1325 AT_CLEANUP