tests: update `x' quotes to 'x' to match gnulib outputs.
[m4/ericb.git] / tests / builtins.at
blob1147972ac8c1cae6f37ac9d930d5b5005ab35c98
1 # Hand crafted tests for GNU M4.                               -*- Autotest -*-
2 # Copyright (C) 2001, 2006, 2007, 2008, 2009, 2010 Free Software
3 # Foundation, 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 "$top_srcdir/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 "$top_srcdir/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 'NOFILE': No such file or directory
616 m4:include.m4:6: include: cannot open '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_DYNAMIC_MODULE
810 AT_CHECK_GMP
812 AT_DATA([[in]],
813 [[divert(-1)
814 # forloop(i, from, to, stmt)
816 define(`forloop', `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')')
817 define(`_forloop',
818        `$4`'ifelse($1, `$3', ,
819                          `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
820 divert
821 forloop(`x', 1, 100, `2**x = mpeval(2**x)
825 AT_DATA([[expout]],
827 2**1 = 2
828 2**2 = 4
829 2**3 = 8
830 2**4 = 16
831 2**5 = 32
832 2**6 = 64
833 2**7 = 128
834 2**8 = 256
835 2**9 = 512
836 2**10 = 1024
837 2**11 = 2048
838 2**12 = 4096
839 2**13 = 8192
840 2**14 = 16384
841 2**15 = 32768
842 2**16 = 65536
843 2**17 = 131072
844 2**18 = 262144
845 2**19 = 524288
846 2**20 = 1048576
847 2**21 = 2097152
848 2**22 = 4194304
849 2**23 = 8388608
850 2**24 = 16777216
851 2**25 = 33554432
852 2**26 = 67108864
853 2**27 = 134217728
854 2**28 = 268435456
855 2**29 = 536870912
856 2**30 = 1073741824
857 2**31 = 2147483648
858 2**32 = 4294967296
859 2**33 = 8589934592
860 2**34 = 17179869184
861 2**35 = 34359738368
862 2**36 = 68719476736
863 2**37 = 137438953472
864 2**38 = 274877906944
865 2**39 = 549755813888
866 2**40 = 1099511627776
867 2**41 = 2199023255552
868 2**42 = 4398046511104
869 2**43 = 8796093022208
870 2**44 = 17592186044416
871 2**45 = 35184372088832
872 2**46 = 70368744177664
873 2**47 = 140737488355328
874 2**48 = 281474976710656
875 2**49 = 562949953421312
876 2**50 = 1125899906842624
877 2**51 = 2251799813685248
878 2**52 = 4503599627370496
879 2**53 = 9007199254740992
880 2**54 = 18014398509481984
881 2**55 = 36028797018963968
882 2**56 = 72057594037927936
883 2**57 = 144115188075855872
884 2**58 = 288230376151711744
885 2**59 = 576460752303423488
886 2**60 = 1152921504606846976
887 2**61 = 2305843009213693952
888 2**62 = 4611686018427387904
889 2**63 = 9223372036854775808
890 2**64 = 18446744073709551616
891 2**65 = 36893488147419103232
892 2**66 = 73786976294838206464
893 2**67 = 147573952589676412928
894 2**68 = 295147905179352825856
895 2**69 = 590295810358705651712
896 2**70 = 1180591620717411303424
897 2**71 = 2361183241434822606848
898 2**72 = 4722366482869645213696
899 2**73 = 9444732965739290427392
900 2**74 = 18889465931478580854784
901 2**75 = 37778931862957161709568
902 2**76 = 75557863725914323419136
903 2**77 = 151115727451828646838272
904 2**78 = 302231454903657293676544
905 2**79 = 604462909807314587353088
906 2**80 = 1208925819614629174706176
907 2**81 = 2417851639229258349412352
908 2**82 = 4835703278458516698824704
909 2**83 = 9671406556917033397649408
910 2**84 = 19342813113834066795298816
911 2**85 = 38685626227668133590597632
912 2**86 = 77371252455336267181195264
913 2**87 = 154742504910672534362390528
914 2**88 = 309485009821345068724781056
915 2**89 = 618970019642690137449562112
916 2**90 = 1237940039285380274899124224
917 2**91 = 2475880078570760549798248448
918 2**92 = 4951760157141521099596496896
919 2**93 = 9903520314283042199192993792
920 2**94 = 19807040628566084398385987584
921 2**95 = 39614081257132168796771975168
922 2**96 = 79228162514264337593543950336
923 2**97 = 158456325028528675187087900672
924 2**98 = 316912650057057350374175801344
925 2**99 = 633825300114114700748351602688
926 2**100 = 1267650600228229401496703205376
930 AT_CHECK_M4([-m mpeval in], 0, expout)
932 AT_CLEANUP
936 ## ----------- ##
937 ## multiquotes ##
938 ## ----------- ##
940 AT_SETUP([multiquotes])
942 AT_DATA([[multiquotes.m4]],
943 [[traceon
944 changequote([,])dnl
945 changequote([``], [''])dnl
946 ````traceon''''
947 define(``foo'', ````FOO'''')dnl
948 dumpdef(``foo'')dnl
949 changequote(``!'', ``!'')dnl
950 !foo!
952 dumpdef(!foo!)dnl
953 define(!bar!, !BAR!)
955 changequote(!>*>*>*>*>!, !<*<*<*<*<!)dnl five of each
956 >*>*>*>*>foo bar<*<*<*<*<
957 foo bar
958 >*>*>*>*>*>*><*<*<*<*<*<*<
959 dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<)dnl
962 AT_DATA([[expout]],
964 ``traceon''
966 ``FOO''
969 foo bar
970 ``FOO'' BAR
971 *>*>*<*<
974 AT_DATA([[experr]],
975 [[m4trace: -1- changequote(`[', `]') -> []
976 m4trace: -1- dnl -> []
977 m4trace: -1- changequote([``], ['']) -> ``''
978 m4trace: -1- dnl -> ``''
979 m4trace: -1- define(``foo'', ````FOO'''') -> ``''
980 m4trace: -1- dnl -> ``''
981 foo:    ````FOO''''
982 m4trace: -1- dumpdef(``foo'') -> ``''
983 m4trace: -1- dnl -> ``''
984 m4trace: -1- changequote(``!'', ``!'') -> !!
985 m4trace: -1- dnl -> !!
986 m4trace: -1- foo -> !``FOO''!
987 foo:    !``FOO''!
988 m4trace: -1- dumpdef(!foo!) -> !!
989 m4trace: -1- dnl -> !!
990 m4trace: -1- define(!bar!, !BAR!) -> !!
991 m4trace: -1- bar -> !BAR!
992 m4trace: -1- changequote(!>*>*>*>*>!, !<*<*<*<*<!) -> >*>*>*>*><*<*<*<*<
993 m4trace: -1- dnl -> >*>*>*>*><*<*<*<*<
994 m4trace: -1- foo -> >*>*>*>*>``FOO''<*<*<*<*<
995 m4trace: -1- bar -> >*>*>*>*>BAR<*<*<*<*<
996 bar:    >*>*>*>*>BAR<*<*<*<*<
997 foo:    >*>*>*>*>``FOO''<*<*<*<*<
998 m4trace: -1- dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<) -> >*>*>*>*><*<*<*<*<
999 m4trace: -1- dnl -> >*>*>*>*><*<*<*<*<
1002 AT_CHECK_M4([multiquotes.m4], 0, expout, experr)
1004 AT_CLEANUP
1008 ## -------- ##
1009 ## patsubst ##
1010 ## -------- ##
1012 AT_SETUP([patsubst])
1014 AT_DATA([[patsubst.m4]],
1015 [[# traceon(`patsubst')
1016 patsubst(`GNUs not Unix.', `^', `OBS: ')
1017 patsubst(`GNUs not Unix.', `\<', `OBS: ')
1018 patsubst(`GNUs not Unix.', `\<\w', `\&=')
1019 patsubst(`GNUs not Unix.', `\w*', `(\&)')
1020 patsubst(`GNUs not Unix.', `\w+', `(\&)')
1021 patsubst(`GNUs not Unix.', `\w+')
1022 patsubst(`GNUs   not  '`         Unix.', `[      ]+', ` ')
1025 AT_DATA([[expout]],
1026 [[# traceon(`patsubst')
1027 OBS: GNUs not Unix.
1028 OBS: GNUs OBS: not OBS: Unix.
1029 G=NUs n=ot U=nix.
1030 (GNUs)() (not)() (Unix)().()
1031 (GNUs) (not) (Unix).
1032   .
1033 GNUs not Unix.
1036 AT_CHECK_M4([patsubst.m4], 0, expout)
1038 AT_CLEANUP
1042 ## ------ ##
1043 ## regexp ##
1044 ## ------ ##
1046 AT_SETUP([regexp])
1048 AT_DATA([[regexp.m4]],
1049 [[traceon(`regexp')dnl
1050 regexp(`hej med dig', `.*', `>>\&<<')
1051 regexp(`hej med dig', `\w*', `>>\&<<')
1052 regexp(`hej med dig', `.+', `>>\&<<')
1053 regexp(`hej med dig', `m\w+', `>>\&<<')
1054 regexp(`hej med dig', `m\(.*\)', `>>\&<< >>\1<<')
1056 regexp(`hej med dig', `.*')
1057 regexp(`hej med dig', `\w*')
1058 regexp(`hej med dig', `.+')
1059 regexp(`hej med dig', `m\w+')
1060 regexp(`hej med dig', `m\(.*\)')
1063 AT_DATA([[expout]],
1064 [[>>hej med dig<<
1065 >>hej<<
1066 >>hej med dig<<
1067 >>med<<
1068 >>med dig<< >>ed dig<<
1077 AT_DATA([[experr]],
1078 [[m4trace: -1- regexp(`hej med dig', `.*', `>>\&<<') -> `>>hej med dig<<'
1079 m4trace: -1- regexp(`hej med dig', `\w*', `>>\&<<') -> `>>hej<<'
1080 m4trace: -1- regexp(`hej med dig', `.+', `>>\&<<') -> `>>hej med dig<<'
1081 m4trace: -1- regexp(`hej med dig', `m\w+', `>>\&<<') -> `>>med<<'
1082 m4trace: -1- regexp(`hej med dig', `m\(.*\)', `>>\&<< >>\1<<') -> `>>med dig<< >>ed dig<<'
1083 m4trace: -1- regexp(`hej med dig', `.*') -> `0'
1084 m4trace: -1- regexp(`hej med dig', `\w*') -> `0'
1085 m4trace: -1- regexp(`hej med dig', `.+') -> `0'
1086 m4trace: -1- regexp(`hej med dig', `m\w+') -> `4'
1087 m4trace: -1- regexp(`hej med dig', `m\(.*\)') -> `4'
1090 AT_CHECK_M4([regexp.m4], 0, expout, experr)
1092 AT_CLEANUP
1096 ## ------------ ##
1097 ## sync-lines.  ##
1098 ## ------------ ##
1100 AT_SETUP([sync-lines])
1102 AT_DATA([[in]],
1103 [[syncoutput(on)dnl
1104 # Several input lines, expanding to one
1105 define(`foo', ``foo' line one.
1106 `foo' line two.
1107 `foo' line three.') xyz
1109 # Several input lines, expanding to none
1110 define(`foo', ``foo' line one.
1111 `foo' line two.
1112 `foo' line three.')dnl
1113 # one input line, expanding to several output lines
1114 foo foo
1117 AT_CHECK_M4([[in]], 0,
1118 [[#line 2 "in"
1119 # Several input lines, expanding to one
1120 #line 5
1121  xyz
1122 foo line one.
1123 #line 6
1124 foo line two.
1125 #line 6
1126 foo line three.
1127 # Several input lines, expanding to none
1128 #line 11
1129 # one input line, expanding to several output lines
1130 foo line one.
1131 #line 12
1132 foo line two.
1133 #line 12
1134 foo line three. foo line one.
1135 #line 12
1136 foo line two.
1137 #line 12
1138 foo line three.
1141 AT_CLEANUP
1144 ## ------ ##
1145 ## syscmd ##
1146 ## ------ ##
1148 AT_SETUP([syscmd])
1150 dnl Ensure that syscmd does not inherit any unnecessary fds from trace.
1151 AT_DATA([in.m4], [[syscmd(`echo hi >&3')ifelse(sysval,
1152 `0', `skipping: sh cannot detect closed fds
1153 m4exit(`77')')dnl
1155 AT_CHECK_M4([3>&-], [0], [], [stderr], [in.m4])
1156 mv stderr experr
1157 AT_CHECK_M4([--debugfile=trace -tdnl 3>&-], [0], [], [experr], [in.m4])
1158 AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `'
1161 dnl Ensure that syscmd does not inherit any unnecessary fds from diversions.
1162 AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f
1163 world
1164 syscmd(`echo hi >&3')divert
1165 hello
1167 AT_CHECK_M4([3>&-], [0], [stdout-nolog], [experr], [in.m4])
1168 AT_CHECK([$SED -ne '/./p' stdout], [0], [[hello
1169 world
1172 dnl Ensure that syscmd does not inherit any unnecessary fds from input files.
1173 AT_DATA([in.m4], [[hello syscmd(`cat <&3')dnl
1174 dnl this line should not be read by cat
1175 world
1177 AT_CHECK_M4([3>&-], [0], [[hello world
1178 ]], [stderr], [in.m4])
1179 mv stderr experr
1180 AT_CHECK_M4([in.m4 3>&-], [0], [[hello world
1181 ]], [experr])
1183 AT_CLEANUP
1186 ## -------- ##
1187 ## translit ##
1188 ## -------- ##
1190 AT_SETUP([translit])
1192 AT_DATA([[translit.m4]],
1193 [[# traceon(`translit')dnl
1194 translit(`GNUs not Unix', `a-z')
1195 translit(`GNUs not Unix', `a-z', `A-Z')
1196 translit(`GNUs not Unix', `A-Z', `a-z')
1197 translit(`GNUs not Unix', `A-Z')
1198 translit(`a-z', `a-')
1199 translit(`A-Z', `A-Z-', `-A-Z')
1200 translit(`GNUs not Unix', `Z-A', `a-z')
1203 AT_CHECK_M4([translit.m4], 0,
1204 [[# traceon(`translit')dnl
1205 GNU  U
1206 GNUS NOT UNIX
1207 gnus not unix
1208 s not nix
1211 tmfs not fnix
1214 dnl This used to be quadratic, taking millions of comparisons,
1215 dnl but should now operate in linear time with only several thousand checks.
1216 AT_DATA([in], [M4_ONE_MEG_DEFN[dnl
1217 define(`a_', translit(substr(f, `0', `50000'), `
1218 ', `a'))dnl
1219 define(`b_', translit(substr(f, `0', `50000'), `
1220 ', `b'))dnl
1221 define(`d_', translit(substr(f, `0', `50000'), `
1222 ', `d'))dnl
1223 define(`c'd_, `pass')dnl
1224 translit(`a'b_, a_`b', `c'd_)
1226 AT_CHECK_M4([in], [0], [[pass
1229 dnl This validates that ranges are built using unsigned chars.
1230 AT_DATA([in], [[translit(`«abc~', `~-»')
1232 AT_CHECK_M4([in], [0], [[abc
1235 dnl Validate short strings, which take a different code path.
1236 AT_DATA([in], [[dnl
1237 translit(`abcdeabcde', `a')
1238 translit(`abcdeabcde', `ab')
1239 translit(`abcdeabcde', `a', `f')
1240 translit(`abcdeabcde', `aa', `fg')
1241 translit(`abcdeabcde', `a', `fg')
1242 translit(`abcdeabcde', `ab', `f')
1243 translit(`abcdeabcde', `ab', `fg')
1244 translit(`abcdeabcde', `ab', `ba')
1245 translit(`abcdeabcde', `e', `f')
1246 translit(`abc', `', `cde')
1247 translit(`', `a', `bc')
1249 AT_CHECK_M4([in], [0], [[bcdebcde
1250 cdecde
1251 fbcdefbcde
1252 fbcdefbcde
1253 fbcdefbcde
1254 fcdefcde
1255 fgcdefgcde
1256 bacdebacde
1257 abcdfabcdf
1262 AT_CLEANUP
1266 ## -------- ##
1267 ## undivert ##
1268 ## -------- ##
1270 AT_SETUP([undivert])
1272 AT_DATA([[undivert.m4]],
1273 [[define(`undiverted', `UNDIVERTED')
1274 # undiverted file.
1275 undivert(`undivert.incl')
1276 # included file.
1277 include(`undivert.incl')
1280 AT_DATA([[undivert.incl]],
1281 [[This is to be undiverted soon.
1284 AT_CHECK_M4([undivert.m4], 0,
1286 # undiverted file.
1287 This is to be undiverted soon.
1289 # included file.
1290 This is to be UNDIVERTED soon.
1294 AT_CLEANUP
1298 ## ---- ##
1299 ## wrap ##
1300 ## ---- ##
1302 AT_SETUP([wrap])
1304 AT_DATA([[wrap.m4]],
1305 [[divert(-1)
1306 m4wrap(`Wrapper no. 1
1309 m4wrap(`Wrapper no. 2
1310 m4wrap(`Wrapper no. 3
1311 m4wrap(`Wrapper no. 4
1312 ')')')
1313 divert
1314 No. 33: The End.
1317 AT_CHECK_M4([wrap.m4], 0,
1319 No. 33: The End.
1320 Wrapper no. 1
1321 Wrapper no. 2
1322 Wrapper no. 3
1323 Wrapper no. 4
1326 AT_CLEANUP