1 dnl PSPP - a program for statistical analysis.
2 dnl Copyright (C) 2017 Free Software Foundation, Inc.
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.
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.
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/>.
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
26 AT_CAPTURE_FILE([define.sps])
29 AT_CHECK([pspp --testing-mode define.sps | sed '/^$/d'], [$6], [expout])
32 AT_SETUP([simple macro expansion])
33 AT_DATA([define.sps], [dnl
41 "a" "b" "c" 'a' 'b' 'c'.
47 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
52 "a" "b" "c" 'a' 'b' 'c'.
57 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) positional argument],
58 [DEFINE !t1(!positional !tokens(1)) t1 (!1) !ENDDEFINE.],
65 note: unexpanded token "b"])
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.
73 DEFINE !ce(!positional !charend('/')) ce (!1) !ENDDEFINE.
74 DEFINE !ce2(!positional !charend('(')
75 /!positional !charend(')'))
79 DEFINE !e(!positional !enclose('{','}')) e (!1) !ENDDEFINE.
81 DEFINE !cmd(!positional !cmdend) cmd(!1) !ENDDEFINE.
82 DEFINE !cmd2(!positional !cmdend
83 /!positional !tokens(1))
87 DEFINE !p(!positional !tokens(1)
88 /!positional !tokens(1)
89 /!positional !tokens(1))
94 !title "!TOKENS(1) argument."
99 !title "!TOKENS(2) argument."
103 !title "!CHAREND argument."
109 !title "Two !CHAREND arguments."
113 !title "!ENCLOSE argument."
118 !title "!CMDEND argument."
123 !title "Three !TOKENS(1) arguments."
127 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
128 "!TOKENS(1) argument."
136 note: unexpanded token "b"
138 "!TOKENS(2) argument."
144 note: unexpanded token "d"
156 "Two !CHAREND arguments."
176 "Three !TOKENS(1) arguments."
180 p(1, -2, -3) (1 -2 -3)
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))
193 DEFINE !ce(!positional !charend('/')) ce(!1) !ENDDEFINE.
195 DEFINE !enc1(!positional !enclose('{', '}')) enc1(!1) !ENDDEFINE.
197 !title "Too few tokens for !TOKENS."
202 !title "Missing charend delimiter."
205 !title "Missing start delimiter."
208 !title "Missing end delimiter."
211 AT_CHECK([pspp --testing-mode define.sps], [1], [dnl
212 "Too few tokens for !TOKENS."
214 define.sps:13: error: DEBUG EXPAND: Unexpected end of command reading
215 argument !3 to macro !p.
217 note: unexpanded token "!p"
219 note: unexpanded token "a"
221 note: unexpanded token "b"
223 define.sps:14: error: DEBUG EXPAND: Unexpected end of command reading
224 argument !2 to macro !p.
226 note: unexpanded token "!p"
228 note: unexpanded token "a"
230 define.sps:15: error: DEBUG EXPAND: Unexpected end of command reading
231 argument !1 to macro !p.
233 note: unexpanded token "!p"
235 "Missing charend delimiter."
237 define.sps:18: error: DEBUG EXPAND: Unexpected end of command reading
238 argument !1 to macro !ce.
240 note: unexpanded token "!ce"
242 note: unexpanded token "a"
244 note: unexpanded token "b"
246 note: unexpanded token "c"
248 "Missing start delimiter."
250 define.sps:21: error: DEBUG EXPAND: Found `a' while expecting `{' reading
251 argument !1 to macro !enc1.
253 note: unexpanded token "!enc1"
255 note: unexpanded token "a"
257 note: unexpanded token "b"
259 note: unexpanded token "c"
261 "Missing end delimiter."
263 define.sps:24: error: DEBUG EXPAND: Unexpected end of command reading
264 argument !1 to macro !enc1.
266 note: unexpanded token "!enc1"
268 note: unexpanded token "{"
270 note: unexpanded token "a"
272 note: unexpanded token "b"
274 note: unexpanded token "c"
278 AT_SETUP([keyword macro argument name with ! prefix])
279 AT_DATA([define.sps], [dnl
280 DEFINE !macro(!x=!TOKENS(1).
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."
287 AT_SETUP([reserved macro keyword argument name])
288 AT_DATA([define.sps], [dnl
289 DEFINE !macro(if=!TOKENS(1).
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."
296 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) keyword argument],
297 [DEFINE !k(arg1 = !TOKENS(1)) k(!arg1) !ENDDEFINE.],
303 note: unexpanded token "y"
306 PSPP_CHECK_MACRO_EXPANSION([one !TOKENS(1) keyword argument - negative],
307 [DEFINE !k(arg1 = !TOKENS(1)) k(!arg1) !ENDDEFINE.],
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 !
316 note: unexpanded token "!k"
317 note: unexpanded token "arg1"
318 note: unexpanded token "="], [1])
320 PSPP_CHECK_MACRO_EXPANSION([!CHAREND('/') keyword arguments], [dnl
321 DEFINE !k(arg1 = !CHAREND('/')
322 /arg2 = !CHAREND('/'))
334 PSPP_CHECK_MACRO_EXPANSION([!CHAREND('/') keyword arguments - negative], [dnl
335 DEFINE !k(arg1 = !CHAREND('/')
336 /arg2 = !CHAREND('/'))
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 !
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 !
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 !
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"])
369 PSPP_CHECK_MACRO_EXPANSION([default keyword arguments],
370 [DEFINE !k(arg1 = !DEFAULT(a b c) !CMDEND) k(!arg1) !ENDDEFINE],
376 dnl Keep this test in sync with the examples for !BLANKS in the manual.
377 PSPP_CHECK_MACRO_EXPANSION([!BLANKS],
398 dnl Keep this test in sync with the examples for !CONCAT in the manual.
399 PSPP_CHECK_MACRO_EXPANSION([!CONCAT],
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.
427 !QUOTE(!EVAL(!vars)).
429 DEFINE !e2(!positional !enclose('(',')'))
446 dnl Keep this test in sync with the examples for !HEAD in the manual.
447 PSPP_CHECK_MACRO_EXPANSION([!HEAD],
460 dnl Keep this test in sync with the examples for !TAIL in the manual.
461 PSPP_CHECK_MACRO_EXPANSION([!TAIL],
474 dnl Keep this test in sync with the examples for !INDEX in the manual.
475 PSPP_CHECK_MACRO_EXPANSION([!INDEX],
479 !INDEX(banana, apple).
480 !INDEX("banana", nan).
481 !INDEX("banana", "nan").
482 !INDEX(!UNQUOTE("banana"), !UNQUOTE("nan")).
492 dnl Keep this test in sync with the examples for !LENGTH in the manual.
493 PSPP_CHECK_MACRO_EXPANSION([!LENGTH],
502 !LENGTH(!UNQUOTE("xyzzy")).
503 !LENGTH(!UNQUOTE("xy""zzy")).
506 DEFINE !la(!positional !enclose('(',')'))
525 dnl Keep this test in sync with the examples for !SUBSTR in the manual.
526 PSPP_CHECK_MACRO_EXPANSION([!SUBSTR],
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).
548 dnl Keep this test in sync with the examples for !UPCASE in the manual.
549 PSPP_CHECK_MACRO_EXPANSION([!UPCASE],
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))
576 ], [123 b / 5 / 3 b / '123 b'.
578 '' 'b' / 6 / 'b' / ''''' ''b'''.])
580 AT_SETUP([macro maximum nesting level (MNEST)])
582 AT_DATA([define.sps], [dnl
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.
594 AT_SETUP([macro !IF condition])
597 '!eq !ne !lt !gt !le !ge' \
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.
618 AT_CAPTURE_FILE([define.sps])
619 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
620 false true true false true false.
622 true false false false true true.
624 false true false true false true.
626 true false false false true true.
628 false true false true false true.
633 AT_SETUP([macro !IF condition -- case sensitivity])
636 '!eq !ne !lt !gt !le !ge' \
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.
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.
668 false true true false true false false false true true false true false true.
670 false false true true false false true true false false true true false true.
672 false false true true true false false true true false false true false true.
677 AT_SETUP([macro !IF condition -- logical 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.
691 DEFINE !test_unary(!positional !tokens(1))
692 !if $3 !1 !then true !else false !ifend.
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
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.
715 AT_CAPTURE_FILE([define.sps])
716 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
742 AT_SETUP([macro !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)
760 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
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.
783 DEFINE !for(!POS !TOKENS(1) / !POS !TOKENS(1))
784 !DO !var = !1 !TO !2 !var !DOEND.
787 DEFINE !forby(!POS !TOKENS(1) / !POS !TOKENS(1) / !POS !TOKENS(1))
788 !DO !var = !1 !TO !2 !BY !3 !var !DOEND.
806 !title "non-integer".
809 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
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.
847 DEFINE !for2(x=!TOKENS(1) / y=!TOKENS(1))
848 !DO !noexpand = !x !TO !y !var !DOEND.
855 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
856 cannot use argument name or macro keyword !x as !DO variable
857 cannot use argument name or macro keyword !noexpand as !DO variable
858 !DO 1 = 1 !TO 5 !var !DOEND.
860 !DO !noexpand = 1 !TO 5 !var !DOEND.
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.
869 DEFINE !for(!POS !TOKENS(1) / !POS !TOKENS(1))
870 !DO !var = !1 !TO !2 !var !DOEND.
873 DEFINE !forby(!POS !TOKENS(1) / !POS !TOKENS(1) / !POS !TOKENS(1))
874 !DO !var = !1 !TO !2 !BY !3 !var !DOEND.
893 !title "non-integer".
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
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.
935 DEFINE !for(!POS !TOKENS(1) / !POS !TOKENS(1) / !POS !TOKENS(1))
952 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
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).
966 !for 'foo bar baz quux'.
969 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
972 ( (foo) (bar) (baz) (quux) ).
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).
988 !for 'foo bar baz quux'.
991 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
992 exceeded maximum number of iterations 2
993 exceeded maximum number of iterations 2
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)
1021 !for baz 'foo bar baz quux'.
1024 AT_CHECK([pspp --testing-mode define.sps], [0], [dnl
1027 ( (foo), (bar), (baz)x).
1033 AT_SETUP([macro !LET])
1034 AT_DATA([define.sps], [dnl
1035 DEFINE !macro(!pos !enclose('(',')'))
1046 AT_CHECK([pspp --testing-mode define.sps -O format=csv], [0], [dnl
1053 AT_SETUP([macro !LET invalid variable names])
1054 AT_DATA([define.sps], [dnl
1055 DEFINE !macro(x=!tokens(1))
1067 AT_CHECK([pspp --testing-mode define.sps -O format=csv], [0], [dnl
1068 cannot use argument name or macro keyword !x as !LET variable
1069 cannot use argument name or macro keyword !do as !LET variable
1070 expected macro variable name following !DO
1077 AT_SETUP([BEGIN DATA inside a macro])
1078 AT_DATA([define.sps], [dnl
1080 DATA LIST NOTABLE /x 1.
1091 AT_CHECK([pspp define.sps -O format=csv], [0], [dnl
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))
1107 $command prefix !paste foo bar suffix.
1111 title.sps:5: note: SHOW: $command is prefix foobar suffix.
1113 AT_CHECK([pspp -O format=csv title.sps], [0], [expout])
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.
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.