improve macro error messages
[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 AT_SETUP([keyword macro argument name with ! prefix])
279 AT_DATA([define.sps], [dnl
280 DEFINE !macro(!x=!TOKENS(1).
281 ])
282 AT_CHECK([pspp -O format=csv define.sps], [1], [dnl
283 "define.sps:1.15-1.16: error: DEFINE: Syntax error at `!x': Keyword macro parameter must be named in definition without ""!"" prefix."
284 ])
285 AT_CLEANUP
286
287 AT_SETUP([reserved macro keyword argument name])
288 AT_DATA([define.sps], [dnl
289 DEFINE !macro(if=!TOKENS(1).
290 ])
291 AT_CHECK([pspp -O format=csv define.sps], [1], [dnl
292 "define.sps:1.15-1.16: error: DEFINE: Syntax error at `if': Cannot use macro keyword ""if"" as an argument name."
293 ])
294 AT_CLEANUP
295
296 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) keyword argument],
297   [DEFINE !k(arg1 = !TOKENS(1)) k(!arg1) !ENDDEFINE.],
298   [!k arg1=x.
299 !k arg1=x y.
300 !k.],
301   [k(x)
302 k(x)
303 note: unexpanded token "y"
304 k( )])
305
306 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) keyword argument - negative],
307   [DEFINE !k(arg1 = !TOKENS(1)) k(!arg1) !ENDDEFINE.],
308   [!k arg1.
309 !k arg1=.], [dnl
310 define.sps:3: error: DEBUG EXPAND: Found `.' while expecting `=' reading
311 argument !arg1 to macro !k.
312 note: unexpanded token "!k"
313 note: unexpanded token "arg1"
314 define.sps:4: error: DEBUG EXPAND: Unexpected end of command reading argument !
315 arg1 to macro !k.
316 note: unexpanded token "!k"
317 note: unexpanded token "arg1"
318 note: unexpanded token "="], [1])
319
320 PSPP_CHECK_MACRO_EXPANSION([!CHAREND('/') keyword arguments], [dnl
321 DEFINE !k(arg1 = !CHAREND('/')
322          /arg2 = !CHAREND('/'))
323 k(!arg1, !arg2)
324 !ENDDEFINE.],
325   [!k arg1=x/ arg2=y/.
326 !k arg1=x/.
327 !k arg2=y/.
328 !k.],
329   [k(x, y)
330 k(x, )
331 k(, y)
332 k(, )])
333
334 PSPP_CHECK_MACRO_EXPANSION([!CHAREND('/') keyword arguments - negative], [dnl
335 DEFINE !k(arg1 = !CHAREND('/')
336          /arg2 = !CHAREND('/'))
337 k(!arg1, !arg2)
338 !ENDDEFINE.],
339   [!k arg1.
340 !k arg1=.
341 !k arg1=x.
342 !k arg1=x/ arg2=y.],
343   [define.sps:6: error: DEBUG EXPAND: Found `.' while expecting `=' reading
344 argument !arg1 to macro !k.
345 note: unexpanded token "!k"
346 note: unexpanded token "arg1"
347 define.sps:7: error: DEBUG EXPAND: Unexpected end of command reading argument !
348 arg1 to macro !k.
349 note: unexpanded token "!k"
350 note: unexpanded token "arg1"
351 note: unexpanded token "="
352 define.sps:8: error: DEBUG EXPAND: Unexpected end of command reading argument !
353 arg1 to macro !k.
354 note: unexpanded token "!k"
355 note: unexpanded token "arg1"
356 note: unexpanded token "="
357 note: unexpanded token "x"
358 define.sps:9: error: DEBUG EXPAND: Unexpected end of command reading argument !
359 arg2 to macro !k.
360 note: unexpanded token "!k"
361 note: unexpanded token "arg1"
362 note: unexpanded token "="
363 note: unexpanded token "x"
364 note: unexpanded token "/"
365 note: unexpanded token "arg2"
366 note: unexpanded token "="
367 note: unexpanded token "y"])
368
369 PSPP_CHECK_MACRO_EXPANSION([default keyword arguments],
370   [DEFINE !k(arg1 = !DEFAULT(a b c) !CMDEND) k(!arg1) !ENDDEFINE],
371   [!k arg1=x.
372 !k],
373   [k(x)
374 k(a b c)])
375
376 dnl Keep this test in sync with the examples for !BLANKS in the manual.
377 PSPP_CHECK_MACRO_EXPANSION([!BLANKS],
378   [DEFINE !b()
379 !BLANKS(0).
380 !QUOTE(!BLANKS(0)).
381 !BLANKS(1).
382 !QUOTE(!BLANKS(1)).
383 !BLANKS(2).
384 !QUOTE(!BLANKS(2)).
385 !BLANKS(5).
386 !QUOTE(!BLANKS(5)).
387 !ENDDEFINE],
388   [!b.],
389   [.
390 ''.
391 .
392 ' '.
393 .
394 '  '.
395 .
396 '     '.])
397
398 dnl Keep this test in sync with the examples for !CONCAT in the manual.
399 PSPP_CHECK_MACRO_EXPANSION([!CONCAT],
400   [DEFINE !c()
401 !CONCAT(x, y).
402 !CONCAT('x', 'y').
403 !CONCAT(12, 34).
404 !CONCAT(!NULL, 123).
405 !CONCAT(x, 0).
406 !CONCAT(x, 0, y).
407 !CONCAT(0, x).
408 !CONCAT(0, x, y).
409 !ENDDEFINE],
410   [!c.],
411   [xy.
412 xy.
413 1234.
414 123.
415 x0.
416 x0y.
417 0 x.
418 0 xy.])
419
420 dnl Keep this test in sync with the examples for !EVAL in the manual.
421 PSPP_CHECK_MACRO_EXPANSION([!EVAL],
422   [DEFINE !vars() a b c !ENDDEFINE.
423 DEFINE !e()
424 !vars.
425 !QUOTE(!vars).
426 !EVAL(!vars).
427 !QUOTE(!EVAL(!vars)).
428 !ENDDEFINE
429 DEFINE !e2(!positional !enclose('(',')'))
430 !1.
431 !QUOTE(!1).
432 !EVAL(!1).
433 !QUOTE(!EVAL(!1)).
434 !ENDDEFINE],
435   [!e.
436 !e2(!vars)],
437   [a b c.
438 '!vars'.
439 a b c.
440 'a b c'.
441 a b c.
442 '!vars'.
443 a b c.
444 'a b c'.])
445
446 dnl Keep this test in sync with the examples for !HEAD in the manual.
447 PSPP_CHECK_MACRO_EXPANSION([!HEAD],
448   [DEFINE !h()
449 !HEAD('a b c').
450 !HEAD('a').
451 !HEAD(!NULL).
452 !HEAD('').
453 !ENDDEFINE],
454   [!h.],
455   [a.
456 a.
457 .
458 .])
459
460 dnl Keep this test in sync with the examples for !TAIL in the manual.
461 PSPP_CHECK_MACRO_EXPANSION([!TAIL],
462   [DEFINE !t()
463 !TAIL('a b c').
464 !TAIL('a').
465 !TAIL(!NULL).
466 !TAIL('').
467 !ENDDEFINE],
468   [!t.],
469   [b c.
470 .
471 .
472 .])
473
474 dnl Keep this test in sync with the examples for !INDEX in the manual.
475 PSPP_CHECK_MACRO_EXPANSION([!INDEX],
476   [DEFINE !i()
477 !INDEX(banana, an).
478 !INDEX(banana, nan).
479 !INDEX(banana, apple).
480 !INDEX("banana", nan).
481 !INDEX("banana", "nan").
482 !INDEX(!UNQUOTE("banana"), !UNQUOTE("nan")).
483 !ENDDEFINE],
484   [!i.],
485   [2.
486 3.
487 0.
488 4.
489 0.
490 3.])
491
492 dnl Keep this test in sync with the examples for !LENGTH in the manual.
493 PSPP_CHECK_MACRO_EXPANSION([!LENGTH],
494   [DEFINE !l()
495 !LENGTH(123).
496 !LENGTH(123.00).
497 !LENGTH( 123 ).
498 !LENGTH("123").
499 !LENGTH(xyzzy).
500 !LENGTH("xyzzy").
501 !LENGTH("xy""zzy").
502 !LENGTH(!UNQUOTE("xyzzy")).
503 !LENGTH(!UNQUOTE("xy""zzy")).
504 !LENGTH(!NULL).
505 !ENDDEFINE.
506 DEFINE !la(!positional !enclose('(',')'))
507 !LENGTH(!1).
508 !ENDDEFINE.],
509   [!l.
510 !la(a b c).
511 !la().],
512   [3.
513 6.
514 3.
515 5.
516 5.
517 7.
518 9.
519 5.
520 6.
521 0.
522 5.
523 0.])
524
525 dnl Keep this test in sync with the examples for !SUBSTR in the manual.
526 PSPP_CHECK_MACRO_EXPANSION([!SUBSTR],
527   [DEFINE !s()
528 !SUBSTR(banana, 3).
529 !SUBSTR(banana, 3, 3).
530 !SUBSTR("banana", 3).
531 !SUBSTR(!UNQUOTE("banana"), 3).
532 !SUBSTR("banana", 3, 3).
533 !SUBSTR(banana, 3, 0).
534 !SUBSTR(banana, 3, 10).
535 !SUBSTR(banana, 10, 3).
536 !ENDDEFINE.],
537   [!s.],
538   [error
539 nana.
540 nan.
541 anana.
542 nana.
543 ana.
544 .
545 nana.
546 .])
547
548 dnl Keep this test in sync with the examples for !UPCASE in the manual.
549 PSPP_CHECK_MACRO_EXPANSION([!UPCASE],
550   [DEFINE !u()
551 !UPCASE(freckle).
552 !UPCASE('freckle').
553 !UPCASE('a b c').
554 !UPCASE('A B C').
555 !ENDDEFINE.],
556   [!u.],
557   [FRECKLE.
558 FRECKLE.
559 A B C.
560 A B C.])
561
562
563 dnl !* is implemented separately inside and outside function arguments
564 dnl so this test makes sure to include both.
565 PSPP_CHECK_MACRO_EXPANSION([!*], [dnl
566 DEFINE !m(!POSITIONAL !TOKENS(1)
567          /!POSITIONAL !TOKENS(1))
568 !*/
569 !LENGTH(!*)/
570 !SUBSTR(!*, 3)/
571 !QUOTE(!*).
572 !ENDDEFINE.],
573   [!m 123 b
574 !m 2 3
575 !m '' 'b'.
576 ], [123 b / 5 / 3 b / '123 b'.
577 2 3 / 3 / 3 / '2 3'.
578 '' 'b' / 6 / 'b' / ''''' ''b'''.])
579
580 AT_SETUP([macro maximum nesting level (MNEST)])
581 AT_KEYWORDS([MNEST])
582 AT_DATA([define.sps], [dnl
583 DEFINE !macro()
584 !macro
585 !ENDDEFINE.
586 !macro.
587 ])
588 AT_CHECK([pspp -O format=csv define.sps], [1], [dnl
589 maximum nesting level exceeded
590 define.sps:4.1-4.6: error: Syntax error at `!macro' (in expansion of `!macro'): expecting command name.
591 ])
592 AT_CLEANUP
593
594 AT_SETUP([macro !IF condition])
595 AT_KEYWORDS([if])
596 for operators in \
597     '!eq !ne !lt !gt !le !ge' \
598     '  =  <>   <   >  <=  >='
599 do
600     set $operators
601     AS_BOX([$operators])
602     cat > define.sps <<EOF
603 DEFINE !test(!positional !tokens(1))
604 !if (!1 $1 1) !then true !else false !ifend
605 !if (!1 $2 1) !then true !else false !ifend
606 !if (!1 $3 1) !then true !else false !ifend
607 !if (!1 $4 1) !then true !else false !ifend
608 !if (!1 $5 1) !then true !else false !ifend
609 !if (!1 $6 1) !then true !else false !ifend.
610 !ENDDEFINE.
611 DEBUG EXPAND.
612 !test 0
613 !test 1
614 !test 2
615 !test '1'
616 !test 1.0
617 EOF
618     AT_CAPTURE_FILE([define.sps])
619     AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
620 false true true false true false.
621
622 true false false false true true.
623
624 false true false true false true.
625
626 true false false false true true.
627
628 false true false true false true.
629 ])
630 done
631 AT_CLEANUP
632
633 AT_SETUP([macro !IF condition -- case sensitivity])
634 AT_KEYWORDS([if])
635 for operators in \
636     '!eq !ne !lt !gt !le !ge' \
637     '  =  <>   <   >  <=  >='
638 do
639     set $operators
640     AS_BOX([$operators])
641     cat > define.sps <<EOF
642 DEFINE !test(!positional !tokens(1))
643 !if (!1 $1 a) !then true !else false !ifend
644 !if (!1 $1 A) !then true !else false !ifend
645 !if (!1 $2 a) !then true !else false !ifend
646 !if (!1 $2 A) !then true !else false !ifend
647 !if (!1 $3 a) !then true !else false !ifend
648 !if (!1 $3 A) !then true !else false !ifend
649 !if (!1 $4 a) !then true !else false !ifend
650 !if (!1 $4 A) !then true !else false !ifend
651 !if (!1 $5 a) !then true !else false !ifend
652 !if (!1 $5 A) !then true !else false !ifend
653 !if (!1 $6 a) !then true !else false !ifend
654 !if (!1 $6 A) !then true !else false !ifend
655 !if (!1 $1 !null) !then true !else false !ifend
656 !if (!1 $2 !null) !then true !else false !ifend.
657 !ENDDEFINE.
658 DEBUG EXPAND.
659 !test a
660 !test A
661 !test b
662 !test B
663 EOF
664     AT_CAPTURE_FILE([define.sps])
665     AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
666 true false false true false false false true true false true true false true.
667
668 false true true false true false false false true true false true false true.
669
670 false false true true false false true true false false true true false true.
671
672 false false true true true false false true true false false true false true.
673 ])
674 done
675 AT_CLEANUP
676
677 AT_SETUP([macro !IF condition -- logical operators])
678 AT_KEYWORDS([if])
679 for operators in \
680     '!and !or !not' \
681     '   &   |    ~'
682 do
683     set $operators
684     AS_BOX([$operators])
685     cat > define.sps <<EOF
686 DEFINE !test_binary(!positional !tokens(1)/!positional !tokens(1))
687 !if !1 $1 !2 !then true !else false !ifend
688 !if !1 $2 !2 !then true !else false !ifend.
689 !ENDDEFINE.
690
691 DEFINE !test_unary(!positional !tokens(1))
692 !if $3 !1 !then true !else false !ifend.
693 !ENDDEFINE.
694
695 * These are:
696   ((not A) and B) or C
697   not (A and B) or C
698   not A and (B or C)
699 DEFINE !test_prec(!pos !tokens(1)/!pos !tokens(1)/!pos !tokens(1))
700 !if $3 !1 $1 !2 $2 !3 !then true !else false !ifend
701 !if $3 (!1 $1 !2) $2 !3 !then true !else false !ifend
702 !if $3 !1 $1 (!2 $2 !3) !then true !else false !ifend
703 !ENDDEFINE.
704
705 DEBUG EXPAND.
706 !test_binary 0 0
707 !test_binary 0 1
708 !test_binary 1 0
709 !test_binary 1 1
710 !test_unary 0
711 !test_unary 1
712 !test_prec 0 0 0 !test_prec 0 0 1 !test_prec 0 1 0 !test_prec 0 1 1.
713 !test_prec 1 0 0 !test_prec 1 0 1 !test_prec 1 1 0 !test_prec 1 1 1.
714 EOF
715     AT_CAPTURE_FILE([define.sps])
716     AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
717 false false.
718
719 false true.
720
721 false true.
722
723 true true.
724
725 true.
726
727 false.
728
729 false true false
730 true true true
731 true true true
732 true true true
733
734 false true false
735 true true false
736 false false false
737 true true false
738 ])
739 done
740 AT_CLEANUP
741
742 AT_SETUP([macro !LET])
743 AT_KEYWORDS([let])
744 AT_DATA([define.sps], [dnl
745 DEFINE !macro(!POS !CMDEND)
746 !LET !v1 = !CONCAT('x',!1,'y')
747 !LET !v2 = !QUOTE(!v1)
748 !LET !v3 = (!LENGTH(!1) = 1)
749 !LET !v4 = (!SUBSTR(!1, 3) = !NULL)
750 v1=!v1.
751 v2=!v2.
752 v3=!v3.
753 v4=!v4.
754 !ENDDEFINE.
755 DEBUG EXPAND.
756 !macro 0.
757 !macro.
758 !macro xyzzy.
759 ])
760 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
761 v1 = x0y.
762 v2 = x0y.
763 v3 = 1.
764 v4 = 1.
765
766 v1 = xy.
767 v2 = xy.
768 v3 = 0.
769 v4 = 1.
770
771 v1 = xxyzzyy.
772 v2 = xxyzzyy.
773 v3 = 0.
774 v4 = 0.
775 ])
776 AT_CLEANUP
777
778 AT_SETUP([macro indexed !DO])
779 AT_KEYWORDS([index do])
780 AT_DATA([define.sps], [dnl
781 DEFINE !title(!POS !TOKENS(1)) !1. !ENDDEFINE.
782
783 DEFINE !for(!POS !TOKENS(1) / !POS !TOKENS(1))
784 !DO !var = !1 !TO !2 !var !DOEND.
785 !ENDDEFINE.
786
787 DEFINE !forby(!POS !TOKENS(1) / !POS !TOKENS(1) / !POS !TOKENS(1))
788 !DO !var = !1 !TO !2 !BY !3 !var !DOEND.
789 !ENDDEFINE.
790
791 DEBUG EXPAND.
792 !title "increasing".
793 !for 1 5.
794 !forby 1 5 1.
795 !forby 1 5 2.
796 !forby 1 5 2.5.
797 !forby 1 5 -1.
798
799 !title "decreasing".
800 !for 5 1.
801 !forby 5 1 1.
802 !forby 5 1 -1.
803 !forby 5 1 -2.
804 !forby 5 1 -3.
805
806 !title "non-integer".
807 !for 1.5 3.5.
808 ])
809 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
810 "increasing".
811
812 1 2 3 4 5.
813
814 1 2 3 4 5.
815
816 1 3 5.
817
818 1 3.5.
819
820 .
821
822 "decreasing".
823
824 .
825
826 .
827
828 5 4 3 2 1.
829
830 5 3 1.
831
832 5 2.
833
834 "non-integer".
835
836 1.5 2.5 3.5.
837 ])
838 AT_CLEANUP
839
840 AT_SETUP([macro !DO invalid variable names])
841 AT_KEYWORDS([index do])
842 AT_DATA([define.sps], [dnl
843 DEFINE !for(x=!TOKENS(1) / y=!TOKENS(1))
844 !DO !x = !x !TO !y !var !DOEND.
845 !ENDDEFINE.
846
847 DEFINE !for2(x=!TOKENS(1) / y=!TOKENS(1))
848 !DO !noexpand = !x !TO !y !var !DOEND.
849 !ENDDEFINE.
850
851 DEBUG EXPAND.
852 !for x=1 y=5.
853 !for2 x=1 y=5.
854 ])
855 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
856 cannot use argument name or macro keyword as !DO variable
857 cannot use argument name or macro keyword as !DO variable
858 !DO 1 = 1 !TO 5 !var !DOEND.
859
860 !DO !noexpand = 1 !TO 5 !var !DOEND.
861 ])
862 AT_CLEANUP
863
864 AT_SETUP([macro indexed !DO reaches MITERATE])
865 AT_KEYWORDS([index do])
866 AT_DATA([define.sps], [dnl
867 DEFINE !title(!POS !TOKENS(1)) !1. !ENDDEFINE.
868
869 DEFINE !for(!POS !TOKENS(1) / !POS !TOKENS(1))
870 !DO !var = !1 !TO !2 !var !DOEND.
871 !ENDDEFINE.
872
873 DEFINE !forby(!POS !TOKENS(1) / !POS !TOKENS(1) / !POS !TOKENS(1))
874 !DO !var = !1 !TO !2 !BY !3 !var !DOEND.
875 !ENDDEFINE.
876
877 SET MITERATE=3.
878 DEBUG EXPAND.
879 !title "increasing".
880 !for 1 5.
881 !forby 1 5 1.
882 !forby 1 5 2.
883 !forby 1 5 2.5.
884 !forby 1 5 -1.
885
886 !title "decreasing".
887 !for 5 1.
888 !forby 5 1 1.
889 !forby 5 1 -1.
890 !forby 5 1 -2.
891 !forby 5 1 -3.
892
893 !title "non-integer".
894 !for 1.5 3.5.
895 ])
896 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
897 exceeded maximum number of iterations 3
898 exceeded maximum number of iterations 3
899 exceeded maximum number of iterations 3
900 "increasing".
901
902 1 2 3 4.
903
904 1 2 3 4.
905
906 1 3 5.
907
908 1 3.5.
909
910 .
911
912 "decreasing".
913
914 .
915
916 .
917
918 5 4 3 2.
919
920 5 3 1.
921
922 5 2.
923
924 "non-integer".
925
926 1.5 2.5 3.5.
927 ])
928 AT_CLEANUP
929
930 AT_SETUP([!BREAK with macro indexed !DO])
931 AT_KEYWORDS([index do break])
932 AT_DATA([define.sps], [dnl
933 DEFINE !title(!POS !TOKENS(1)) !1. !ENDDEFINE.
934
935 DEFINE !for(!POS !TOKENS(1) / !POS !TOKENS(1) / !POS !TOKENS(1))
936 !DO !var = !1 !TO !2
937   !var
938   !IF 1 !THEN
939     !IF !var = !3 !THEN
940       x
941       !BREAK
942       y
943     !IFEND
944     ,
945   !IFEND
946 !DOEND.
947 !ENDDEFINE.
948
949 DEBUG EXPAND.
950 !for 1 5 4.
951 ])
952 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
953 1, 2, 3, 4 x.
954 ])
955 AT_CLEANUP
956
957 AT_SETUP([macro list !DO])
958 AT_KEYWORDS([index do])
959 AT_DATA([define.sps], [dnl
960 DEFINE !for(!POS !CMDEND)
961 (!DO !i !IN (!1) (!i) !DOEND).
962 !ENDDEFINE.
963
964 DEBUG EXPAND.
965 !for a b c.
966 !for 'foo bar baz quux'.
967 !for.
968 ])
969 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
970 ( (a) (b) (c) ).
971
972 ( (foo) (bar) (baz) (quux) ).
973
974 ( ).
975 ])
976 AT_CLEANUP
977
978 AT_SETUP([macro list !DO reaches MITERATE])
979 AT_KEYWORDS([index do])
980 AT_DATA([define.sps], [dnl
981 DEFINE !for(!POS !CMDEND)
982 (!DO !i !IN (!1) (!i) !DOEND).
983 !ENDDEFINE.
984
985 SET MITERATE=2.
986 DEBUG EXPAND.
987 !for a b c.
988 !for 'foo bar baz quux'.
989 !for.
990 ])
991 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
992 exceeded maximum number of iterations 2
993 exceeded maximum number of iterations 2
994 ( (a) (b) ).
995
996 ( (foo) (bar) ).
997
998 ( ).
999 ])
1000 AT_CLEANUP
1001
1002 AT_SETUP([!BREAK with macro list !DO])
1003 AT_KEYWORDS([index break do])
1004 AT_DATA([define.sps], [dnl
1005 DEFINE !for(!POS !TOKENS(1) / !POS !CMDEND)
1006 (!DO !i !IN (!2)
1007   (!i)
1008   !IF 1 !THEN
1009     !IF !i = !1 !THEN
1010       x
1011       !BREAK
1012       y
1013     !IFEND
1014     ,
1015   !IFEND
1016 !DOEND).
1017 !ENDDEFINE.
1018
1019 DEBUG EXPAND.
1020 !for d a b c.
1021 !for baz 'foo bar baz quux'.
1022 !for e.
1023 ])
1024 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
1025 ( (a), (b), (c), ).
1026
1027 ( (foo), (bar), (baz)x).
1028
1029 ( ).
1030 ])
1031 AT_CLEANUP
1032
1033 AT_SETUP([macro !LET])
1034 AT_DATA([define.sps], [dnl
1035 DEFINE !macro(!pos !enclose('(',')'))
1036 !LET !x=!1
1037 !LET !y=!QUOTE(!1)
1038 !LET !z=(!y="abc")
1039 !y !z
1040 !ENDDEFINE.
1041
1042 DEBUG EXPAND.
1043 !macro(1+2).
1044 !macro(abc).
1045 ])
1046 AT_CHECK([pspp --testing-mode define.sps -O format=csv], [0], [dnl
1047 1 + 2 0
1048
1049 abc 1
1050 ])
1051 AT_CLEANUP
1052
1053 AT_SETUP([macro !LET invalid variable names])
1054 AT_DATA([define.sps], [dnl
1055 DEFINE !macro(x=!tokens(1))
1056 !LET !x=!x
1057 !ENDDEFINE.
1058
1059 DEFINE !macro2()
1060 !LET !do=x
1061 !ENDDEFINE.
1062
1063 DEBUG EXPAND.
1064 !macro 1.
1065 !macro2.
1066 ])
1067 AT_CHECK([pspp --testing-mode define.sps -O format=csv], [0], [dnl
1068 cannot use argument name or macro keyword as !LET variable
1069 cannot use argument name or macro keyword as !LET variable
1070 expected macro variable name following !DO
1071 !LET =
1072
1073 !LET !do = x
1074 ])
1075 AT_CLEANUP
1076
1077 AT_SETUP([BEGIN DATA inside a macro])
1078 AT_DATA([define.sps], [dnl
1079 DEFINE !macro()
1080 DATA LIST NOTABLE /x 1.
1081 BEGIN DATA
1082 1
1083 2
1084 3
1085 END DATA.
1086 LIST.
1087 !ENDDEFINE.
1088
1089 !macro
1090 ])
1091 AT_CHECK([pspp define.sps -O format=csv], [0], [dnl
1092 Table: Data List
1093 x
1094 1
1095 2
1096 3
1097 ])
1098 AT_CLEANUP
1099
1100 AT_SETUP([TITLE and SUBTITLE with macros])
1101 AT_KEYWORDS([macro])
1102 for command in TITLE SUBTITLE; do
1103     cat >title.sps <<EOF
1104 DEFINE !paste(!POS !TOKENS(1) / !POS !TOKENS(1))
1105 !CONCAT(!1,!2)
1106 !ENDDEFINE.
1107 $command prefix !paste foo bar suffix.
1108 SHOW $command.
1109 EOF
1110     cat >expout <<EOF
1111 title.sps:5: note: SHOW: $command is prefix foobar suffix.
1112 EOF
1113     AT_CHECK([pspp -O format=csv title.sps], [0], [expout])
1114 done
1115 AT_CLEANUP
1116
1117 AT_SETUP([error message within macro expansion])
1118 AT_DATA([define.sps], [dnl
1119 DEFINE !vars(!POS !TOKENS(1)) a b C !ENDDEFINE.
1120 DATA LIST NOTABLE /a b 1-2.
1121 COMPUTE x = !vars x.
1122 ])
1123 AT_CHECK([pspp -O format=csv define.sps], [1], [dnl
1124 define.sps:3.13-3.19: error: COMPUTE: Syntax error at `b' (in expansion of `!vars x'): expecting end of command.
1125 ])
1126 AT_CLEANUP