76685791a1e8f734e6ec05c5a0dfbfec6c88f699
[pspp] / tests / language / control / define.at
1 dnl PSPP - a program for statistical analysis.
2 dnl Copyright (C) 2017 Free Software Foundation, Inc.
3 dnl
4 dnl This program is free software: you can redistribute it and/or modify
5 dnl it under the terms of the GNU General Public License as published by
6 dnl the Free Software Foundation, either version 3 of the License, or
7 dnl (at your option) any later version.
8 dnl
9 dnl This program is distributed in the hope that it will be useful,
10 dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
11 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 dnl GNU nGeneral Public License for more details.
13 dnl
14 dnl You should have received a copy of the GNU General Public License
15 dnl along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 dnl
17 AT_BANNER([DEFINE])
18
19 m4_define([PSPP_CHECK_MACRO_EXPANSION],
20   [AT_SETUP([macro expansion - $1])
21    AT_KEYWORDS([m4_bpatsubst([$1], [!], [])])
22    AT_DATA([define.sps], [$2
23 DEBUG EXPAND.
24 $3
25 ])
26    AT_CAPTURE_FILE([define.sps])
27    AT_DATA([expout], [$4
28 ])
29    AT_CHECK([pspp --testing-mode define.sps | sed '/^$/d'], [$6], [expout])
30    AT_CLEANUP])
31
32 AT_SETUP([simple macro expansion])
33 AT_DATA([define.sps], [dnl
34 DEFINE !macro()
35 a b c d
36 e f g h.
37 i j k l
38 1,2,3,4.
39 5+6+7.
40 m(n,o).
41 "a" "b" "c" 'a' 'b' 'c'.
42 "x "" y".
43 !ENDDEFINE.
44 DEBUG EXPAND.
45 !macro
46 ])
47 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
48 a b c d e f g h.
49 i j k l 1, 2, 3, 4.
50 5 + 6 + 7.
51 m(n, o).
52 "a" "b" "c" 'a' 'b' 'c'.
53 "x "" y".
54 ])
55 AT_CLEANUP
56
57 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) positional argument],
58   [DEFINE !t1(!positional !tokens(1)) t1 (!1) !ENDDEFINE.],
59   [!t1 a.
60 !t1 b.
61 !t1 a b.],
62   [t1(a)
63 t1(b)
64 t1(a)
65 note: unexpanded token "b"])
66
67 AT_SETUP([macro expansion with positional arguments])
68 AT_DATA([define.sps], [dnl
69 DEFINE !title(!positional !tokens(1)) !1 !ENDDEFINE.
70 DEFINE !t1(!positional !tokens(1)) t1 (!1) !ENDDEFINE.
71 DEFINE !t2(!positional !tokens(2)) t2 (!1) !ENDDEFINE.
72
73 DEFINE !ce(!positional !charend('/')) ce (!1) !ENDDEFINE.
74 DEFINE !ce2(!positional !charend('(')
75            /!positional !charend(')'))
76 ce2 (!1, !2)
77 !ENDDEFINE.
78
79 DEFINE !e(!positional !enclose('{','}')) e (!1) !ENDDEFINE.
80
81 DEFINE !cmd(!positional !cmdend) cmd(!1) !ENDDEFINE.
82 DEFINE !cmd2(!positional !cmdend
83             /!positional !tokens(1))
84 cmd2(!1, !2)
85 !ENDDEFINE.
86
87 DEFINE !p(!positional !tokens(1)
88          /!positional !tokens(1)
89          /!positional !tokens(1))
90 p(!1, !2, !3)(!*)
91 !ENDDEFINE.
92
93 DEBUG EXPAND.
94 !title "!TOKENS(1) argument."
95 !t1 a.
96 !t1 b.
97 !t1 a b.
98
99 !title "!TOKENS(2) argument."
100 !t2 a b.
101 !t2 b c d.
102
103 !title "!CHAREND argument."
104 !ce/.
105 !ce x/.
106 !ce x y/.
107 !ce x y z/.
108
109 !title "Two !CHAREND arguments."
110 !ce2 x(y).
111 !ce2 1 2 3 4().
112
113 !title "!ENCLOSE argument."
114 !e {}.
115 !e {a}.
116 !e {a b}.
117
118 !title "!CMDEND argument."
119 !cmd 1 2 3 4.
120 !cmd2 5 6.
121 7.
122
123 !title "Three !TOKENS(1) arguments."
124 !p a b c.
125 !p 1 -2 -3.
126 ])
127 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
128 "!TOKENS(1) argument."
129
130 t1(a)
131
132 t1(b)
133
134 t1(a)
135
136 note: unexpanded token "b"
137
138 "!TOKENS(2) argument."
139
140 t2(a b)
141
142 t2(b c)
143
144 note: unexpanded token "d"
145
146 "!CHAREND argument."
147
148 ce( )
149
150 ce(x)
151
152 ce(x y)
153
154 ce(x y z)
155
156 "Two !CHAREND arguments."
157
158 ce2(x, y)
159
160 ce2(1 2 3 4, )
161
162 "!ENCLOSE argument."
163
164 e( )
165
166 e(a)
167
168 e(a b)
169
170 "!CMDEND argument."
171
172 cmd(1 2 3 4)
173
174 cmd2(5 6, 7)
175
176 "Three !TOKENS(1) arguments."
177
178 p(a, b, c) (a b c)
179
180 p(1, -2, -3) (1 -2 -3)
181 ])
182 AT_CLEANUP
183
184 AT_SETUP([macro expansion with positional arguments - negative])
185 AT_DATA([define.sps], [dnl
186 DEFINE !title(!positional !tokens(1)) !1 !ENDDEFINE.
187 DEFINE !p(!positional !tokens(1)
188          /!positional !tokens(1)
189          /!positional !tokens(1))
190 (!1, !2, !3)
191 !ENDDEFINE.
192
193 DEFINE !ce(!positional !charend('/')) ce(!1) !ENDDEFINE.
194
195 DEFINE !enc1(!positional !enclose('{', '}')) enc1(!1) !ENDDEFINE.
196 DEBUG EXPAND.
197 !title "Too few tokens for !TOKENS."
198 !p a b.
199 !p a.
200 !p.
201
202 !title "Missing charend delimiter."
203 !ce a b c.
204
205 !title "Missing start delimiter."
206 !enc1 a b c.
207
208 !title "Missing end delimiter."
209 !enc1{a b c.
210 ])
211 AT_CHECK([pspp --testing-mode define.sps], [1], [dnl
212 "Too few tokens for !TOKENS."
213
214 define.sps:13: error: DEBUG EXPAND: Unexpected end of command reading
215 argument !3 to macro !p.
216
217 note: unexpanded token "!p"
218
219 note: unexpanded token "a"
220
221 note: unexpanded token "b"
222
223 define.sps:14: error: DEBUG EXPAND: Unexpected end of command reading
224 argument !2 to macro !p.
225
226 note: unexpanded token "!p"
227
228 note: unexpanded token "a"
229
230 define.sps:15: error: DEBUG EXPAND: Unexpected end of command reading
231 argument !1 to macro !p.
232
233 note: unexpanded token "!p"
234
235 "Missing charend delimiter."
236
237 define.sps:18: error: DEBUG EXPAND: Unexpected end of command reading
238 argument !1 to macro !ce.
239
240 note: unexpanded token "!ce"
241
242 note: unexpanded token "a"
243
244 note: unexpanded token "b"
245
246 note: unexpanded token "c"
247
248 "Missing start delimiter."
249
250 define.sps:21: error: DEBUG EXPAND: Found `a' while expecting `{' reading
251 argument !1 to macro !enc1.
252
253 note: unexpanded token "!enc1"
254
255 note: unexpanded token "a"
256
257 note: unexpanded token "b"
258
259 note: unexpanded token "c"
260
261 "Missing end delimiter."
262
263 define.sps:24: error: DEBUG EXPAND: Unexpected end of command reading
264 argument !1 to macro !enc1.
265
266 note: unexpanded token "!enc1"
267
268 note: unexpanded token "{"
269
270 note: unexpanded token "a"
271
272 note: unexpanded token "b"
273
274 note: unexpanded token "c"
275 ])
276 AT_CLEANUP
277
278 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) keyword argument],
279   [DEFINE !k(arg1 = !TOKENS(1)) k(!arg1) !ENDDEFINE.],
280   [!k arg1=x.
281 !k arg1=x y.
282 !k.],
283   [k(x)
284 k(x)
285 note: unexpanded token "y"
286 k( )])
287
288 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) keyword argument - negative],
289   [DEFINE !k(arg1 = !TOKENS(1)) k(!arg1) !ENDDEFINE.],
290   [!k arg1.
291 !k arg1=.], [dnl
292 define.sps:3: error: DEBUG EXPAND: Found `.' while expecting `=' reading
293 argument !arg1 to macro !k.
294 note: unexpanded token "!k"
295 note: unexpanded token "arg1"
296 define.sps:4: error: DEBUG EXPAND: Unexpected end of command reading argument !
297 arg1 to macro !k.
298 note: unexpanded token "!k"
299 note: unexpanded token "arg1"
300 note: unexpanded token "="], [1])
301
302 PSPP_CHECK_MACRO_EXPANSION([!CHAREND('/') keyword arguments], [dnl
303 DEFINE !k(arg1 = !CHAREND('/')
304          /arg2 = !CHAREND('/'))
305 k(!arg1, !arg2)
306 !ENDDEFINE.],
307   [!k arg1=x/ arg2=y/.
308 !k arg1=x/.
309 !k arg2=y/.
310 !k.],
311   [k(x, y)
312 k(x, )
313 k(, y)
314 k(, )])
315
316 PSPP_CHECK_MACRO_EXPANSION([!CHAREND('/') keyword arguments - negative], [dnl
317 DEFINE !k(arg1 = !CHAREND('/')
318          /arg2 = !CHAREND('/'))
319 k(!arg1, !arg2)
320 !ENDDEFINE.],
321   [!k arg1.
322 !k arg1=.
323 !k arg1=x.
324 !k arg1=x/ arg2=y.],
325   [define.sps:6: error: DEBUG EXPAND: Found `.' while expecting `=' reading
326 argument !arg1 to macro !k.
327 note: unexpanded token "!k"
328 note: unexpanded token "arg1"
329 define.sps:7: error: DEBUG EXPAND: Unexpected end of command reading argument !
330 arg1 to macro !k.
331 note: unexpanded token "!k"
332 note: unexpanded token "arg1"
333 note: unexpanded token "="
334 define.sps:8: error: DEBUG EXPAND: Unexpected end of command reading argument !
335 arg1 to macro !k.
336 note: unexpanded token "!k"
337 note: unexpanded token "arg1"
338 note: unexpanded token "="
339 note: unexpanded token "x"
340 define.sps:9: error: DEBUG EXPAND: Unexpected end of command reading argument !
341 arg2 to macro !k.
342 note: unexpanded token "!k"
343 note: unexpanded token "arg1"
344 note: unexpanded token "="
345 note: unexpanded token "x"
346 note: unexpanded token "/"
347 note: unexpanded token "arg2"
348 note: unexpanded token "="
349 note: unexpanded token "y"])
350
351 PSPP_CHECK_MACRO_EXPANSION([default keyword arguments],
352   [DEFINE !k(arg1 = !DEFAULT(a b c) !CMDEND) k(!arg1) !ENDDEFINE],
353   [!k arg1=x.
354 !k],
355   [k(x)
356 k(a b c)])
357
358 dnl Keep this test in sync with the examples for !BLANKS in the manual.
359 PSPP_CHECK_MACRO_EXPANSION([!BLANKS],
360   [DEFINE !b()
361 !BLANKS(0).
362 !QUOTE(!BLANKS(0)).
363 !BLANKS(1).
364 !QUOTE(!BLANKS(1)).
365 !BLANKS(2).
366 !QUOTE(!BLANKS(2)).
367 !BLANKS(5).
368 !QUOTE(!BLANKS(5)).
369 !ENDDEFINE],
370   [!b.],
371   [.
372 ''.
373 .
374 ' '.
375 .
376 '  '.
377 .
378 '     '.])
379
380 dnl Keep this test in sync with the examples for !CONCAT in the manual.
381 PSPP_CHECK_MACRO_EXPANSION([!CONCAT],
382   [DEFINE !c()
383 !CONCAT(x, y).
384 !CONCAT('x', 'y').
385 !CONCAT(12, 34).
386 !CONCAT(!NULL, 123).
387 !ENDDEFINE],
388   [!c.],
389   [xy.
390 xy.
391 1234.
392 123.])
393
394 dnl Keep this test in sync with the examples for !EVAL in the manual.
395 PSPP_CHECK_MACRO_EXPANSION([!EVAL],
396   [DEFINE !vars() a b c !ENDDEFINE.
397 DEFINE !e()
398 !vars.
399 !QUOTE(!vars).
400 !EVAL(!vars).
401 !QUOTE(!EVAL(!vars)).
402 !ENDDEFINE
403 DEFINE !e2(!positional !enclose('(',')'))
404 !1.
405 !QUOTE(!1).
406 !EVAL(!1).
407 !QUOTE(!EVAL(!1)).
408 !ENDDEFINE],
409   [!e.
410 !e2(!vars)],
411   [a b c.
412 '!vars'.
413 a b c.
414 'a b c'.
415 a b c.
416 '!vars'.
417 a b c.
418 'a b c'.])
419
420 dnl Keep this test in sync with the examples for !HEAD in the manual.
421 PSPP_CHECK_MACRO_EXPANSION([!HEAD],
422   [DEFINE !h()
423 !HEAD('a b c').
424 !HEAD('a').
425 !HEAD(!NULL).
426 !HEAD('').
427 !ENDDEFINE],
428   [!h.],
429   [a.
430 a.
431 .
432 .])
433
434 dnl Keep this test in sync with the examples for !TAIL in the manual.
435 PSPP_CHECK_MACRO_EXPANSION([!TAIL],
436   [DEFINE !t()
437 !TAIL('a b c').
438 !TAIL('a').
439 !TAIL(!NULL).
440 !TAIL('').
441 !ENDDEFINE],
442   [!t.],
443   [b c.
444 .
445 .
446 .])
447
448 dnl Keep this test in sync with the examples for !INDEX in the manual.
449 PSPP_CHECK_MACRO_EXPANSION([!INDEX],
450   [DEFINE !i()
451 !INDEX(banana, an).
452 !INDEX(banana, nan).
453 !INDEX(banana, apple).
454 !INDEX("banana", nan).
455 !INDEX("banana", "nan").
456 !INDEX(!UNQUOTE("banana"), !UNQUOTE("nan")).
457 !ENDDEFINE],
458   [!i.],
459   [2.
460 3.
461 0.
462 4.
463 0.
464 3.])
465
466 dnl Keep this test in sync with the examples for !LENGTH in the manual.
467 PSPP_CHECK_MACRO_EXPANSION([!LENGTH],
468   [DEFINE !l()
469 !LENGTH(123).
470 !LENGTH(123.00).
471 !LENGTH( 123 ).
472 !LENGTH("123").
473 !LENGTH(xyzzy).
474 !LENGTH("xyzzy").
475 !LENGTH("xy""zzy").
476 !LENGTH(!UNQUOTE("xyzzy")).
477 !LENGTH(!UNQUOTE("xy""zzy")).
478 !LENGTH(!NULL).
479 !ENDDEFINE.
480 DEFINE !la(!positional !enclose('(',')'))
481 !LENGTH(!1).
482 !ENDDEFINE.],
483   [!l.
484 !la(a b c).
485 !la().],
486   [3.
487 6.
488 3.
489 5.
490 5.
491 7.
492 9.
493 5.
494 6.
495 0.
496 5.
497 0.])
498
499 dnl Keep this test in sync with the examples for !SUBSTR in the manual.
500 PSPP_CHECK_MACRO_EXPANSION([!SUBSTR],
501   [DEFINE !s()
502 !SUBSTR(banana, 3).
503 !SUBSTR(banana, 3, 3).
504 !SUBSTR("banana", 3).
505 !SUBSTR(!UNQUOTE("banana"), 3).
506 !SUBSTR("banana", 3, 3).
507 !SUBSTR(banana, 3, 0).
508 !SUBSTR(banana, 3, 10).
509 !SUBSTR(banana, 10, 3).
510 !ENDDEFINE.],
511   [!s.],
512   [error
513 nana.
514 nan.
515 anana.
516 nana.
517 ana.
518 .
519 nana.
520 .])
521
522 dnl Keep this test in sync with the examples for !UPCASE in the manual.
523 PSPP_CHECK_MACRO_EXPANSION([!UPCASE],
524   [DEFINE !u()
525 !UPCASE(freckle).
526 !UPCASE('freckle').
527 !UPCASE('a b c').
528 !UPCASE('A B C').
529 !ENDDEFINE.],
530   [!u.],
531   [FRECKLE.
532 FRECKLE.
533 A B C.
534 A B C.])
535
536
537 dnl !* is implemented separately inside and outside function arguments
538 dnl so this test makes sure to include both.
539 PSPP_CHECK_MACRO_EXPANSION([!*], [dnl
540 DEFINE !m(!POSITIONAL !TOKENS(1)
541          /!POSITIONAL !TOKENS(1))
542 !*/
543 !LENGTH(!*)/
544 !SUBSTR(!*, 3)/
545 !QUOTE(!*).
546 !ENDDEFINE.],
547   [!m 123 b
548 !m 2 3
549 !m '' 'b'.
550 ], [123 b / 5 / 3 b / '123 b'.
551 2 3 / 3 / 3 / '2 3'.
552 '' 'b' / 6 / 'b' / ''''' ''b'''.])
553
554 AT_SETUP([macro maximum nesting level (MNEST)])
555 AT_KEYWORDS([MNEST])
556 AT_DATA([define.sps], [dnl
557 DEFINE !macro()
558 !macro
559 !ENDDEFINE.
560 !macro.
561 ])
562 AT_CHECK([pspp define.sps], [1], [dnl
563 maximum nesting level exceeded
564 define.sps.1: error: Syntax error at `!macro': expecting command name.
565 ])
566 AT_CLEANUP
567
568 AT_SETUP([macro !IF condition])
569 AT_KEYWORDS([if])
570 for operators in \
571     '!eq !ne !lt !gt !le !ge' \
572     '  =  <>   <   >  <=  >='
573 do
574     set $operators
575     AS_BOX([$operators])
576     cat > define.sps <<EOF
577 DEFINE !test(!positional !tokens(1))
578 !if (!1 $1 1) !then true !else false !ifend
579 !if (!1 $2 1) !then true !else false !ifend
580 !if (!1 $3 1) !then true !else false !ifend
581 !if (!1 $4 1) !then true !else false !ifend
582 !if (!1 $5 1) !then true !else false !ifend
583 !if (!1 $6 1) !then true !else false !ifend.
584 !ENDDEFINE.
585 DEBUG EXPAND.
586 !test 0
587 !test 1
588 !test 2
589 !test '1'
590 !test 1.0
591 EOF
592     AT_CAPTURE_FILE([define.sps])
593     AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
594 false true true false true false.
595
596 true false false false true true.
597
598 false true false true false true.
599
600 true false false false true true.
601
602 false true false true false true.
603 ])
604 done
605 AT_CLEANUP
606
607 AT_SETUP([macro !IF condition -- case sensitivity])
608 AT_KEYWORDS([if])
609 for operators in \
610     '!eq !ne !lt !gt !le !ge' \
611     '  =  <>   <   >  <=  >='
612 do
613     set $operators
614     AS_BOX([$operators])
615     cat > define.sps <<EOF
616 DEFINE !test(!positional !tokens(1))
617 !if (!1 $1 a) !then true !else false !ifend
618 !if (!1 $1 A) !then true !else false !ifend
619 !if (!1 $2 a) !then true !else false !ifend
620 !if (!1 $2 A) !then true !else false !ifend
621 !if (!1 $3 a) !then true !else false !ifend
622 !if (!1 $3 A) !then true !else false !ifend
623 !if (!1 $4 a) !then true !else false !ifend
624 !if (!1 $4 A) !then true !else false !ifend
625 !if (!1 $5 a) !then true !else false !ifend
626 !if (!1 $5 A) !then true !else false !ifend
627 !if (!1 $6 a) !then true !else false !ifend
628 !if (!1 $6 A) !then true !else false !ifend.
629 !ENDDEFINE.
630 DEBUG EXPAND.
631 !test a
632 !test A
633 !test b
634 !test B
635 EOF
636     AT_CAPTURE_FILE([define.sps])
637     AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
638 true false false true false false false true true false true true.
639
640 false true true false true false false false true true false true.
641
642 false false true true false false true true false false true true.
643
644 false false true true true false false true true false false true.
645 ])
646 done
647 AT_CLEANUP
648
649 AT_SETUP([macro !IF condition -- logical operators])
650 AT_KEYWORDS([if])
651 for operators in \
652     '!and !or !not' \
653     '   &   |    ~'
654 do
655     set $operators
656     AS_BOX([$operators])
657     cat > define.sps <<EOF
658 DEFINE !test_binary(!positional !tokens(1)/!positional !tokens(1))
659 !if !1 $1 !2 !then true !else false !ifend
660 !if !1 $2 !2 !then true !else false !ifend.
661 !ENDDEFINE.
662
663 DEFINE !test_unary(!positional !tokens(1))
664 !if $3 !1 !then true !else false !ifend.
665 !ENDDEFINE.
666
667 * This is ((not A) and B) or C.
668 DEFINE !test_prec(!pos !tokens(1)/!pos !tokens(1)/!pos !tokens(1))
669 !if $3 !1 $1 !2 $2 !3 !then true !else false !ifend
670 !ENDDEFINE.
671
672 DEBUG EXPAND.
673 !test_binary 0 0
674 !test_binary 0 1
675 !test_binary 1 0
676 !test_binary 1 1
677 !test_unary 0
678 !test_unary 1
679 !test_prec 0 0 0 !test_prec 0 0 1 !test_prec 0 1 0 !test_prec 0 1 1.
680 !test_prec 1 0 0 !test_prec 1 0 1 !test_prec 1 1 0 !test_prec 1 1 1.
681 EOF
682     AT_CAPTURE_FILE([define.sps])
683     AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
684 false false.
685
686 false true.
687
688 false true.
689
690 true true.
691
692 true.
693
694 false.
695
696 false
697 true
698 true
699 true
700
701 false
702 true
703 false
704 true
705 ])
706 done
707 AT_CLEANUP
708