Make gnulib a git submodule.
[m4.git] / tests / macros.at
blobfe4251894a71114a995525d6d0f11c192473535b
1 # Hand crafted tests for GNU M4.                               -*- Autotest -*-
2 # Copyright (C) 2001, 2006, 2007, 2008 Free Software Foundation, Inc.
4 # This file is part of GNU M4.
6 # GNU M4 is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # GNU M4 is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 AT_BANNER([Macro definitions.])
21 # Checking everything related to macro definitions: the expansion of
22 # user macros, the propagation of various bits (tracing, number of
23 # arguments and so on).
25 ## ---------------- ##
26 ## Arity and defn.  ##
27 ## ---------------- ##
29 AT_SETUP([Arity and defn])
31 # Check that the arity checking of define is correctly propagated.
33 AT_DATA([[input.m4]],
34 [[define(`defun', defn(`define'))
35 define
36 define(`foo')
37 define(`foo', `bar')
38 define(`foo', `bar', `baz')
40 defun
41 defun(`foo')
42 defun(`foo', `bar')
43 defun(`foo', `bar', `baz')
44 ]])
46 AT_DATA([[expout]],
48 define
53 defun
57 ]])
59 AT_CHECK_M4([input.m4], 0, [expout],
60 [[m4:input.m4:5: Warning: define: extra arguments ignored: 3 > 2
61 m4:input.m4:10: Warning: defun: extra arguments ignored: 3 > 2
62 ]])
64 AT_CLEANUP
67 ## ------------------------- ##
68 ## Arity, defn, and freeze.  ##
69 ## ------------------------- ##
71 AT_SETUP([Arity, defn, and freeze])
72 AT_KEYWORDS([frozen])
74 AT_DATA([[freezeme.m4]],
75 [[define(`defun', defn(`define'))dnl
76 undefine(`define')dnl
77 ]])
79 AT_CHECK_M4([--freeze-state=frozen.m4f freezeme.m4], 0)
81 AT_DATA([[input.m4]],
82 [[defun
83 defun(`foo')
84 defun(`foo', `bar')
85 defun(`foo', `bar', `baz')
86 ]])
88 AT_DATA([[expout]],
89 [[defun
93 ]])
95 AT_CHECK_M4([--reload-state=frozen.m4f input.m4], 0, expout,
96 [[m4:input.m4:4: Warning: defun: extra arguments ignored: 3 > 2
97 ]])
99 AT_CLEANUP(freezeme.m4 frozen.m4f)
102 ## ------------------- ##
103 ## Command line define ##
104 ## ------------------- ##
106 AT_SETUP([Command line define])
108 dnl Test that -D after last file still affects m4wrap'd text.
109 AT_DATA([in1], [[m4wrap(`foo
110 ')foo
112 AT_DATA([in2], [[foo
114 AT_CHECK_M4([-Dfoo=1 in1 -Dfoo=2 in2 -Dfoo=3], [0],
120 dnl Test that -D only affects top-most definition.
121 AT_DATA([in1], [[define(`foo', `1')pushdef(`foo', `2')dnl
123 AT_DATA([in2], [[foo
124 popdef(`foo')foo
125 popdef(`foo')foo
127 AT_CHECK_M4([in1 -Dfoo=3 in2], [0],
133 dnl Test that -D and -U interact in correct order
134 AT_DATA([in], [[foo
136 AT_CHECK_M4([-Dfoo=bar in -Ufoo in], [0], [[bar
139 AT_CHECK_M4([-Ufoo in -Dfoo=bar in], [0], [[foo
143 dnl Test macro arguments defined via -D
144 AT_DATA([in], [[-foo-foo(1)-foo(1,2)-
145 -bar-bar(1)-bar(1,2)-
147 AT_CHECK_M4([-Dfoo -Dbar='$@' in], [0],
148 [[----
149 --1-1,2-
152 AT_CLEANUP
156 ## -------------------- ##
157 ## Command line pushdef ##
158 ## -------------------- ##
160 AT_SETUP([Command line pushdef])
162 dnl Test that -p after last file still affects m4wrap'd text.
163 AT_DATA([in1], [[m4wrap(`foo
164 ')foo
166 AT_DATA([in2], [[foo
168 AT_CHECK_M4([-pfoo=1 in1 -pfoo=2 in2 -pfoo=3], [0],
174 dnl Test that -p adds a definition.
175 AT_DATA([in1], [[define(`foo', `1')pushdef(`foo', `2')dnl
177 AT_DATA([in2], [[foo
178 popdef(`foo')foo
179 popdef(`foo')foo
181 AT_CHECK_M4([in1 -pfoo=3 in2], [0],
187 dnl Test that --pushdef and --popdef interact in correct order
188 AT_DATA([in], [[foo
190 AT_CHECK_M4([-Dfoo=1 --pushdef=foo=2 in --popdef=foo in], [0],
194 AT_CHECK_M4([--popdef=foo in --pushdef=foo=1 in], [0],
195 [[foo
199 AT_CLEANUP
203 ## ---------------- ##
204 ## pushdef/popdef.  ##
205 ## ---------------- ##
207 AT_SETUP([pushdef/popdef])
209 AT_DATA([[pushpop.m4]],
210 [[divert(-1)
211 pushdef(`hej', `def 1.')
212 dumpdef(`hej')
213 pushdef(`hej', `def 2.')
214 dumpdef(`hej')
215 pushdef(`hej', `def 3.')
216 dumpdef(`hej')
217 pushdef(`hej', `def 4.')
218 dumpdef(`hej')
220 popdef(`hej')
221 dumpdef(`hej')
222 popdef(`hej')
223 dumpdef(`hej')
224 popdef(`hej')
225 dumpdef(`hej')
226 popdef(`hej')
227 dumpdef(`hej')
229 dumpdef(`mac2')
230 popdef(`mac2')
233 AT_CHECK_M4([pushpop.m4], 0, [],
234 [[hej:  `def 1.'
235 hej:    `def 2.'
236 hej:    `def 3.'
237 hej:    `def 4.'
238 hej:    `def 3.'
239 hej:    `def 2.'
240 hej:    `def 1.'
241 m4:pushpop.m4:18: Warning: dumpdef: undefined macro `hej'
242 m4:pushpop.m4:20: Warning: dumpdef: undefined macro `mac2'
243 m4:pushpop.m4:21: Warning: popdef: undefined macro `mac2'
246 AT_CLEANUP
250 ## ---------------------- ##
251 ## Tracing Hanoi Towers.  ##
252 ## ---------------------- ##
254 AT_SETUP([Tracing Hanoi Towers])
256 AT_DATA([[trace.m4]],
257 [[divert(-1)
259 # move(from, to)
260 define(`move', `Move one disk from `$1' to `$2'.
263 # _hanoi (cnt, from, to, aux)
264 define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)',
265 `_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')')
267 # hanoi (cnt)
268 define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)')
269 divert`'dnl
271 # Debugmode t
272 debugmode(`t')
273 hanoi(2)
275 # Debugmode taeq
276 debugmode(`taeq')
277 hanoi(2)
279 # Debugmode OFF
280 debugmode
281 hanoi(2)
283 # Debugmode ae
284 debugmode(`ae')
285 traceon(`move', `_hanoi')
286 hanoi(2)
289 AT_DATA([[expout]],
291 # Debugmode t
293 Move one disk from source to auxilliary.
294 Move one disk from source to destination.
295 Move one disk from auxilliary to destination.
298 # Debugmode taeq
300 Move one disk from source to auxilliary.
301 Move one disk from source to destination.
302 Move one disk from auxilliary to destination.
305 # Debugmode OFF
307 Move one disk from source to auxilliary.
308 Move one disk from source to destination.
309 Move one disk from auxilliary to destination.
312 # Debugmode ae
315 Move one disk from source to auxilliary.
316 Move one disk from source to destination.
317 Move one disk from auxilliary to destination.
321 AT_DATA([[experr]],
322 [[m4trace: -1- hanoi
323 m4trace: -1- _hanoi
324 m4trace: -2- eval
325 m4trace: -1- ifelse
326 m4trace: -2- decr
327 m4trace: -1- _hanoi
328 m4trace: -2- eval
329 m4trace: -1- ifelse
330 m4trace: -1- move
331 m4trace: -1- move
332 m4trace: -2- decr
333 m4trace: -1- _hanoi
334 m4trace: -2- eval
335 m4trace: -1- ifelse
336 m4trace: -1- move
337 m4trace: -1- debugmode
338 m4trace: -1- hanoi(`2') -> `_hanoi(`2', source, destination, auxilliary)'
339 m4trace: -1- _hanoi(`2', `source', `destination', `auxilliary') -> `ifelse(eval(`2'<=1), 1, `move(source, destination)',
340 `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)')'
341 m4trace: -2- eval(`2<=1') -> `0'
342 m4trace: -1- ifelse(`0', `1', `move(source, destination)', `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)') -> `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)'
343 m4trace: -2- decr(`2') -> `1'
344 m4trace: -1- _hanoi(`1', `source', `auxilliary', `destination') -> `ifelse(eval(`1'<=1), 1, `move(source, auxilliary)',
345 `_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)')'
346 m4trace: -2- eval(`1<=1') -> `1'
347 m4trace: -1- ifelse(`1', `1', `move(source, auxilliary)', `_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)') -> `move(source, auxilliary)'
348 m4trace: -1- move(`source', `auxilliary') -> `Move one disk from `source' to `auxilliary'.
350 m4trace: -1- move(`source', `destination') -> `Move one disk from `source' to `destination'.
352 m4trace: -2- decr(`2') -> `1'
353 m4trace: -1- _hanoi(`1', `auxilliary', `destination', `source') -> `ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)',
354 `_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)')'
355 m4trace: -2- eval(`1<=1') -> `1'
356 m4trace: -1- ifelse(`1', `1', `move(auxilliary, destination)', `_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)') -> `move(auxilliary, destination)'
357 m4trace: -1- move(`auxilliary', `destination') -> `Move one disk from `auxilliary' to `destination'.
359 m4trace: -1- debugmode -> `'
360 m4trace: -1- _hanoi(2, source, destination, auxilliary) -> ifelse(eval(`2'<=1), 1, `move(source, destination)',
361 `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)')
362 m4trace: -1- _hanoi(1, source, auxilliary, destination) -> ifelse(eval(`1'<=1), 1, `move(source, auxilliary)',
363 `_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)')
364 m4trace: -1- move(source, auxilliary) -> Move one disk from `source' to `auxilliary'.
366 m4trace: -1- move(source, destination) -> Move one disk from `source' to `destination'.
368 m4trace: -1- _hanoi(1, auxilliary, destination, source) -> ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)',
369 `_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)')
370 m4trace: -1- move(auxilliary, destination) -> Move one disk from `auxilliary' to `destination'.
374 AT_CHECK_M4([trace.m4], 0, expout, experr)
376 AT_CLEANUP
380 ## ------------------------------- ##
381 ## Propagation of trace requests.  ##
382 ## ------------------------------- ##
384 AT_SETUP([Propagation of traceon])
386 AT_DATA([[trace2.m4]],
387 [[traceon(`define')
388 debugmode(`aeq')
390 # copy the `define' builtin definition to another symbol
391 define(`my_define', defn(`define'))
393 # delete the original
394 undefine(`define')
396 # Does it work?
397 my_define(`foo', `bar')
399 # Use the new definition to redefine the original symbol
400 my_define(`define', defn(`my_define'))
402 # Torture the flag propogation
403 undefine(`my_define')
404 define(`my_define', defn(`define'))
406 # There are now 2 symbols pointing to the same builtin function
407 my_define(`foo', `bar')
408 define(`foo', `bar')
411 AT_DATA([[expout]],
415 # copy the `define' builtin definition to another symbol
418 # delete the original
421 # Does it work?
424 # Use the new definition to redefine the original symbol
427 # Torture the flag propogation
431 # There are now 2 symbols pointing to the same builtin function
436 AT_DATA([[experr]],
437 [[m4trace: -1- define(`my_define', <define>) -> `'
438 m4trace: -1- define(`my_define', <define>) -> `'
439 m4trace: -1- define(`foo', `bar') -> `'
442 AT_CHECK_M4([trace2.m4], 0, expout, experr)
444 AT_CLEANUP
448 ## ------------------------ ##
449 ## Propagation of --trace.  ##
450 ## ------------------------ ##
452 AT_SETUP([Propagation of --trace])
454 AT_DATA([[trace3.m4]],
455 [[# copy the `define' builtin definition to another symbol
456 define(`my_define', defn(`define'))
458 # delete the original
459 undefine(`define')
461 # Does it work?
462 my_define(`foo', `bar')
464 # Use the new definition to redefine the original symbol
465 my_define(`define', defn(`my_define'))
467 # Torture the flag propogation
468 undefine(`my_define')
469 define(`my_define', defn(`define'))
471 # There are now 2 symbols pointing to the same builtin function
472 my_define(`foo', `bar')
473 define(`foo', `bar')
476 AT_DATA([[expout]],
477 [[# copy the `define' builtin definition to another symbol
480 # delete the original
483 # Does it work?
486 # Use the new definition to redefine the original symbol
489 # Torture the flag propogation
493 # There are now 2 symbols pointing to the same builtin function
498 AT_DATA([[experr]],
499 [[m4trace: -1- define(`my_define', <define>) -> `'
500 m4trace: -1- define(`my_define', <define>) -> `'
501 m4trace: -1- define(`foo', `bar') -> `'
504 AT_CHECK_M4([-t define -daeq trace3.m4], 0, expout, experr)
506 AT_CLEANUP
509 ## --------------------- ##
510 ## Renamesyms collisions ##
511 ## --------------------- ##
513 AT_SETUP([Renamesyms collisions])
515 dnl FIXME - We should gracefully detect rename collisions, rather than
516 dnl violating the invariants of the symbol table.
517 AT_XFAIL_IF([:])
519 AT_DATA([in], [[define(`bar', `1')define(`baz', `2')dnl
520 renamesyms(`^ba.$', `baa')
523 AT_CHECK_M4([in], [0], [[
524 ]], [ignore])
526 AT_CLEANUP
529 ## ----------------- ##
530 ## Rescanning macros ##
531 ## ----------------- ##
533 AT_SETUP([Rescanning macros])
535 dnl This is a series of tests that used to be included as undocumented tests
536 dnl in the branch m4.texinfo.  They exercise rescanning issues not stressed
537 dnl anywhere else in the suite, but which are used by autoconf.
538 AT_DATA([in], [[define(`x1', `len(`$1'')dnl
539 define(`y1', ``$1')')dnl
540 x1(`01234567890123456789')y1(`98765432109876543210')
543 AT_CHECK_M4([in], [0], [[40
546 AT_DATA([in], [[define(`echo', `$@')dnl
547 define(`foo', echo(`01234567890123456789')echo(`98765432109876543210'))dnl
551 AT_CHECK_M4([in], [0], [[0123456789012345678998765432109876543210
554 AT_DATA([in], [[define(`a', `A')define(`echo', `$@')define(`join', `$1$2')dnl
555 define(`abcdefghijklmnopqrstuvwxyz', `Z')dnl
556 join(`a', `bcdefghijklmnopqrstuvwxyz')
557 join(`a', echo(`bcdefghijklmnopqrstuvwxyz'))
560 AT_CHECK_M4([in], [0], [[Z
564 AT_DATA([in], [[define(`echo', `$@')dnl
565 echo(echo(`01234567890123456789', `01234567890123456789')
566 echo(`98765432109876543210', `98765432109876543210'))
567 len((echo(`01234567890123456789',
568           `01234567890123456789')echo(`98765432109876543210',
569                                       `98765432109876543210')))
570 indir(`echo', indir(`echo', `01234567890123456789',
571                             `01234567890123456789')
572 indir(`echo', `98765432109876543210', `98765432109876543210'))
573 define(`argn', `$#')dnl
574 define(`echo1', `-$@-')define(`echo2', `,$@,')dnl
575 echo1(`1', `2', `3') argn(echo1(`1', `2', `3'))
576 echo2(`1', `2', `3') argn(echo2(`1', `2', `3'))
579 AT_CHECK_M4([in], [0], [[01234567890123456789,01234567890123456789
580 98765432109876543210,98765432109876543210
582 01234567890123456789,01234567890123456789
583 98765432109876543210,98765432109876543210
584 -1,2,3- 3
585 ,1,2,3, 5
588 AT_CLEANUP