Merge deferred handling of -D option from branch.
[m4.git] / tests / macros.at
blobcba534bc8e38c108ef29fd98badbf11a81d263bb
1 # Hand crafted tests for GNU M4.                               -*- Autotest -*-
2 # Copyright (C) 2001, 2006 Free Software Foundation, Inc.
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2, or (at your option)
7 # any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 # 02110-1301, USA.
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 AT_CLEANUP
137 ## ---------------- ##
138 ## pushdef/popdef.  ##
139 ## ---------------- ##
141 AT_SETUP([pushdef/popdef])
143 AT_DATA([[pushpop.m4]],
144 [[divert(-1)
145 pushdef(`hej', `def 1.')
146 dumpdef(`hej')
147 pushdef(`hej', `def 2.')
148 dumpdef(`hej')
149 pushdef(`hej', `def 3.')
150 dumpdef(`hej')
151 pushdef(`hej', `def 4.')
152 dumpdef(`hej')
154 popdef(`hej')
155 dumpdef(`hej')
156 popdef(`hej')
157 dumpdef(`hej')
158 popdef(`hej')
159 dumpdef(`hej')
160 popdef(`hej')
161 dumpdef(`hej')
163 dumpdef(`mac2')
164 popdef(`mac2')
167 AT_CHECK_M4([pushpop.m4], 0, [],
168 [[hej:  `def 1.'
169 hej:    `def 2.'
170 hej:    `def 3.'
171 hej:    `def 4.'
172 hej:    `def 3.'
173 hej:    `def 2.'
174 hej:    `def 1.'
175 m4:pushpop.m4:18: Warning: dumpdef: undefined macro `hej'
176 m4:pushpop.m4:20: Warning: dumpdef: undefined macro `mac2'
177 m4:pushpop.m4:21: Warning: popdef: undefined macro `mac2'
180 AT_CLEANUP
184 ## ---------------------- ##
185 ## Tracing Hanoi Towers.  ##
186 ## ---------------------- ##
188 AT_SETUP([Tracing Hanoi Towers])
190 AT_DATA([[trace.m4]],
191 [[divert(-1)
193 # move(from, to)
194 define(`move', `Move one disk from `$1' to `$2'.
197 # _hanoi (cnt, from, to, aux)
198 define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)',
199 `_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')')
201 # hanoi (cnt)
202 define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)')
203 divert`'dnl
205 # Debugmode t
206 debugmode(`t')
207 hanoi(2)
209 # Debugmode taeq
210 debugmode(`taeq')
211 hanoi(2)
213 # Debugmode OFF
214 debugmode
215 hanoi(2)
217 # Debugmode ae
218 debugmode(`ae')
219 traceon(`move', `_hanoi')
220 hanoi(2)
223 AT_DATA([[expout]],
225 # Debugmode t
227 Move one disk from source to auxilliary.
228 Move one disk from source to destination.
229 Move one disk from auxilliary to destination.
232 # Debugmode taeq
234 Move one disk from source to auxilliary.
235 Move one disk from source to destination.
236 Move one disk from auxilliary to destination.
239 # Debugmode OFF
241 Move one disk from source to auxilliary.
242 Move one disk from source to destination.
243 Move one disk from auxilliary to destination.
246 # Debugmode ae
249 Move one disk from source to auxilliary.
250 Move one disk from source to destination.
251 Move one disk from auxilliary to destination.
255 AT_DATA([[experr]],
256 [[m4trace: -1- hanoi
257 m4trace: -1- _hanoi
258 m4trace: -2- eval
259 m4trace: -1- ifelse
260 m4trace: -2- decr
261 m4trace: -1- _hanoi
262 m4trace: -2- eval
263 m4trace: -1- ifelse
264 m4trace: -1- move
265 m4trace: -1- move
266 m4trace: -2- decr
267 m4trace: -1- _hanoi
268 m4trace: -2- eval
269 m4trace: -1- ifelse
270 m4trace: -1- move
271 m4trace: -1- debugmode
272 m4trace: -1- hanoi(`2') -> `_hanoi(`2', source, destination, auxilliary)'
273 m4trace: -1- _hanoi(`2', `source', `destination', `auxilliary') -> `ifelse(eval(`2'<=1), 1, `move(source, destination)',
274 `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)')'
275 m4trace: -2- eval(`2<=1') -> `0'
276 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)'
277 m4trace: -2- decr(`2') -> `1'
278 m4trace: -1- _hanoi(`1', `source', `auxilliary', `destination') -> `ifelse(eval(`1'<=1), 1, `move(source, auxilliary)',
279 `_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)')'
280 m4trace: -2- eval(`1<=1') -> `1'
281 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)'
282 m4trace: -1- move(`source', `auxilliary') -> `Move one disk from `source' to `auxilliary'.
284 m4trace: -1- move(`source', `destination') -> `Move one disk from `source' to `destination'.
286 m4trace: -2- decr(`2') -> `1'
287 m4trace: -1- _hanoi(`1', `auxilliary', `destination', `source') -> `ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)',
288 `_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)')'
289 m4trace: -2- eval(`1<=1') -> `1'
290 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)'
291 m4trace: -1- move(`auxilliary', `destination') -> `Move one disk from `auxilliary' to `destination'.
293 m4trace: -1- debugmode -> @&t@
294 m4trace: -1- _hanoi(2, source, destination, auxilliary) -> ifelse(eval(`2'<=1), 1, `move(source, destination)',
295 `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)')
296 m4trace: -1- _hanoi(1, source, auxilliary, destination) -> ifelse(eval(`1'<=1), 1, `move(source, auxilliary)',
297 `_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)')
298 m4trace: -1- move(source, auxilliary) -> Move one disk from `source' to `auxilliary'.
300 m4trace: -1- move(source, destination) -> Move one disk from `source' to `destination'.
302 m4trace: -1- _hanoi(1, auxilliary, destination, source) -> ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)',
303 `_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)')
304 m4trace: -1- move(auxilliary, destination) -> Move one disk from `auxilliary' to `destination'.
308 AT_CHECK_M4([trace.m4], 0, expout, experr)
310 AT_CLEANUP
314 ## ------------------------------- ##
315 ## Propagation of trace requests.  ##
316 ## ------------------------------- ##
318 AT_SETUP([Propagation of traceon])
320 AT_DATA([[trace2.m4]],
321 [[traceon(`define')
322 debugmode(`aeq')
324 # copy the `define' builtin definition to another symbol
325 define(`my_define', defn(`define'))
327 # delete the original
328 undefine(`define')
330 # Does it work?
331 my_define(`foo', `bar')
333 # Use the new definition to redefine the original symbol
334 my_define(`define', defn(`my_define'))
336 # Torture the flag propogation
337 undefine(`my_define')
338 define(`my_define', defn(`define'))
340 # There are now 2 symbols pointing to the same builtin function
341 my_define(`foo', `bar')
342 define(`foo', `bar')
345 AT_DATA([[expout]],
349 # copy the `define' builtin definition to another symbol
352 # delete the original
355 # Does it work?
358 # Use the new definition to redefine the original symbol
361 # Torture the flag propogation
365 # There are now 2 symbols pointing to the same builtin function
370 AT_DATA([[experr]],
371 [[m4trace: -1- define(`my_define', <define>) -> `'
372 m4trace: -1- define(`my_define', <define>) -> `'
373 m4trace: -1- define(`foo', `bar') -> `'
376 AT_CHECK_M4([trace2.m4], 0, expout, experr)
378 AT_CLEANUP
382 ## ------------------------ ##
383 ## Propagation of --trace.  ##
384 ## ------------------------ ##
386 AT_SETUP([Propagation of --trace])
388 AT_DATA([[trace3.m4]],
389 [[# copy the `define' builtin definition to another symbol
390 define(`my_define', defn(`define'))
392 # delete the original
393 undefine(`define')
395 # Does it work?
396 my_define(`foo', `bar')
398 # Use the new definition to redefine the original symbol
399 my_define(`define', defn(`my_define'))
401 # Torture the flag propogation
402 undefine(`my_define')
403 define(`my_define', defn(`define'))
405 # There are now 2 symbols pointing to the same builtin function
406 my_define(`foo', `bar')
407 define(`foo', `bar')
410 AT_DATA([[expout]],
411 [[# copy the `define' builtin definition to another symbol
414 # delete the original
417 # Does it work?
420 # Use the new definition to redefine the original symbol
423 # Torture the flag propogation
427 # There are now 2 symbols pointing to the same builtin function
432 AT_DATA([[experr]],
433 [[m4trace: -1- define(`my_define', <define>) -> `'
434 m4trace: -1- define(`my_define', <define>) -> `'
435 m4trace: -1- define(`foo', `bar') -> `'
438 AT_CHECK_M4([-t define -daeq trace3.m4], 0, expout, experr)
440 AT_CLEANUP
443 ## --------------------- ##
444 ## Renamesyms collisions ##
445 ## --------------------- ##
447 AT_SETUP([Renamesyms collisions])
449 dnl FIXME - We should gracefully detect rename collisions, rather than
450 dnl violating the invariants of the symbol table.
451 AT_XFAIL_IF([:])
453 AT_DATA([in], [[define(`bar', `1')define(`baz', `2')dnl
454 renamesyms(`^ba.$', `baa')
457 AT_CHECK_M4([in], [0], [[
458 ]], [ignore])
460 AT_CLEANUP