From: Ben Pfaff Date: Sun, 4 Jul 2021 04:41:36 +0000 (-0700) Subject: Full negative tests for macros. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fdev7;p=pspp Full negative tests for macros. --- diff --git a/src/language/lexer/macro.c b/src/language/lexer/macro.c index 8678a0bcdb..e4302bf2fa 100644 --- a/src/language/lexer/macro.c +++ b/src/language/lexer/macro.c @@ -1080,10 +1080,10 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, { struct string_array args; - if (parse_macro_function (ctx, &args, ss_cstr ("!length"), 1, 1, + if (parse_macro_function (ctx, &args, ss_cstr ("!LENGTH"), 1, 1, input_consumed)) ds_put_format (output, "%zu", strlen (args.strings[0])); - else if (parse_macro_function (ctx, &args, ss_cstr ("!blanks"), 1, 1, + else if (parse_macro_function (ctx, &args, ss_cstr ("!BLANKS"), 1, 1, input_consumed)) { int n; @@ -1098,14 +1098,14 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, ds_put_byte_multiple (output, ' ', n); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!concat"), 1, INT_MAX, + else if (parse_macro_function (ctx, &args, ss_cstr ("!CONCAT"), 1, INT_MAX, input_consumed)) { for (size_t i = 0; i < args.n; i++) if (!unquote_string (args.strings[i], ctx->segmenter_mode, output)) ds_put_cstr (output, args.strings[i]); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!head"), 1, 1, + else if (parse_macro_function (ctx, &args, ss_cstr ("!HEAD"), 1, 1, input_consumed)) { struct string tmp; @@ -1120,14 +1120,14 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, macro_tokens_uninit (&mts); ds_destroy (&tmp); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!index"), 2, 2, + else if (parse_macro_function (ctx, &args, ss_cstr ("!INDEX"), 2, 2, input_consumed)) { const char *haystack = args.strings[0]; const char *needle = strstr (haystack, args.strings[1]); ds_put_format (output, "%zu", needle ? needle - haystack + 1 : 0); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!quote"), 1, 1, + else if (parse_macro_function (ctx, &args, ss_cstr ("!QUOTE"), 1, 1, input_consumed)) { if (unquote_string (args.strings[0], ctx->segmenter_mode, NULL)) @@ -1145,7 +1145,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, ds_put_byte (output, '\''); } } - else if (parse_macro_function (ctx, &args, ss_cstr ("!substr"), 2, 3, + else if (parse_macro_function (ctx, &args, ss_cstr ("!SUBSTR"), 2, 3, input_consumed)) { int start; @@ -1165,7 +1165,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, macro_error (ctx->stack, NULL, _("Third argument of !SUBSTR must be " "non-negative integer (not \"%s\")."), - args.strings[1]); + args.strings[2]); string_array_destroy (&args); return false; } @@ -1173,7 +1173,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, struct substring s = ss_cstr (args.strings[0]); ds_put_substring (output, ss_substr (s, start - 1, count)); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!tail"), 1, 1, + else if (parse_macro_function (ctx, &args, ss_cstr ("!TAIL"), 1, 1, input_consumed)) { struct string tmp; @@ -1191,13 +1191,13 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, macro_tokens_uninit (&mts); ds_destroy (&tmp); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!unquote"), 1, 1, + else if (parse_macro_function (ctx, &args, ss_cstr ("!UNQUOTE"), 1, 1, input_consumed)) { if (!unquote_string (args.strings[0], ctx->segmenter_mode, output)) ds_put_cstr (output, args.strings[0]); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!upcase"), 1, 1, + else if (parse_macro_function (ctx, &args, ss_cstr ("!UPCASE"), 1, 1, input_consumed)) { struct string tmp; @@ -1208,7 +1208,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, free (upper); ds_destroy (&tmp); } - else if (parse_macro_function (ctx, &args, ss_cstr ("!eval"), 1, 1, + else if (parse_macro_function (ctx, &args, ss_cstr ("!EVAL"), 1, 1, input_consumed)) { struct macro_tokens mts = { .n = 0 }; @@ -1227,7 +1227,7 @@ expand_macro_function (struct parse_macro_function_ctx *ctx, } else if (ctx->n_input > 0 && ctx->input[0].token.type == T_MACRO_ID - && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null"))) + && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!NULL"))) { *input_consumed = 1; return true; @@ -1279,6 +1279,12 @@ macro_evaluate_literal (const struct expr_context *ctx, *tokens = p; return value; } + else if (p->token.type == T_RPAREN) + { + macro_error (ctx->stack, p, _("Expecting literal or function invocation " + "in macro expression.")); + return NULL; + } struct parse_macro_function_ctx fctx = { .input = p, @@ -1522,7 +1528,6 @@ macro_evaluate_number (const struct macro_token **tokens, size_t n_tokens, macro_tokens_from_string__ (&mts, ss_cstr (s), segmenter_mode, stack); if (mts.n != 1 || !token_is_number (&mts.mts[0].token)) { - macro_tokens_print (&mts, stdout); macro_error (stack, mts.n > 0 ? &mts.mts[0] : NULL, _("Macro expression must evaluate to " "a number (not \"%s\")."), s); diff --git a/tests/language/control/define.at b/tests/language/control/define.at index 989f4093ec..de89f1737f 100644 --- a/tests/language/control/define.at +++ b/tests/language/control/define.at @@ -1231,4 +1231,272 @@ AT_CHECK([pspp -O format=csv define.sps --testing-mode], [0], [dnl (x = 1) (y = 2) ]) -AT_CLEANUP \ No newline at end of file +AT_CLEANUP + +AT_SETUP([bad token in macro body]) +AT_DATA([define.sps], [dnl +DEFINE !x() +x'123' +!ENDDEFINE. +]) +AT_CHECK([pspp define.sps], [1], [dnl +define.sps:3: error: DEFINE: String of hex digits has 3 characters, which is +not a multiple of 2. +]) +AT_CLEANUP + +AT_SETUP([generic macro function syntax errors]) +AT_DATA([define.sps], [dnl +DEFINE !a() !SUBSTR !ENDDEFINE. +DEFINE !b() !SUBSTR x !ENDDEFINE. +DEFINE !c() !SUBSTR(1,2,3,4) !ENDDEFINE. +DEFINE !d() !SUBSTR(1x) !ENDDEFINE. +DEFINE !e() !SUBSTR(1 !ENDDEFINE. +dnl ) +DEBUG EXPAND. +!a. +!b. +!c. +!d. +!e. +]) +AT_CHECK([pspp --testing-mode define.sps], [1], [dnl +define.sps:1: In the expansion of `!a', +define.sps:7: error: DEBUG EXPAND: `(' expected following !SUBSTR. + +!SUBSTR + +define.sps:2: At `x' in the expansion of `!b', +define.sps:8: error: DEBUG EXPAND: `(' expected following !SUBSTR. + +!SUBSTR x + +define.sps:3: At `)' in the expansion of `!c', +define.sps:9: error: DEBUG EXPAND: Wrong number of arguments to macro +function !SUBSTR. + +!SUBSTR(1, 2, 3, 4) + +define.sps:4: At `x' in the expansion of `!d', +define.sps:10: error: DEBUG EXPAND: `,' or `)' expected in call to macro +function !SUBSTR. + +!SUBSTR(1 x) + +define.sps:5: In the expansion of `!e', +define.sps:11: error: DEBUG EXPAND: Missing `)' in call to macro function ! +SUBSTR. + +!SUBSTR(1 +]) +AT_CLEANUP + +AT_SETUP([specific macro function syntax errors]) +AT_DATA([define.sps], [dnl +DEFINE !a() !BLANKS(x). !ENDDEFINE. +DEFINE !b() !SUBSTR(x, y). !ENDDEFINE. +DEFINE !c() !SUBSTR(x, 1, z). !ENDDEFINE. +DEBUG EXPAND. +!a. +!b. +!c. +]) +AT_CHECK([pspp --testing-mode define.sps], [1], [dnl +define.sps:1: In the expansion of `!a', +define.sps:5: error: DEBUG EXPAND: Argument to !BLANKS must be non-negative +integer (not "x"). + +!BLANKS(x). + +define.sps:2: In the expansion of `!b', +define.sps:6: error: DEBUG EXPAND: Second argument of !SUBSTR must be positive +integer (not "y"). + +!SUBSTR(x, y). + +define.sps:3: In the expansion of `!c', +define.sps:7: error: DEBUG EXPAND: Third argument of !SUBSTR must be non- +negative integer (not "z"). + +!SUBSTR(x, 1, z). +]) +AT_CLEANUP + +AT_SETUP([macro expression errors]) +AT_DATA([define.sps], [dnl +DEFINE !a() !LET !x = (1. !ENDDEFINE dnl ) + +DEFINE !b() !DO !x = x. !ENDDEFINE. +DEFINE !c() !LET !x = (). !ENDDEFINE. +DEBUG EXPAND. +!a. +!b. +!c. +]) +AT_CHECK([pspp --testing-mode define.sps], [1], [dnl +define.sps:1-2: At `.' in the expansion of `!a', +define.sps:5: error: DEBUG EXPAND: Expecting ')' in macro expression. + +!LET !x = (1. + +At `x' in the expansion of `!DO', +define.sps:2: inside the expansion of `!b', +define.sps:6: error: DEBUG EXPAND: Macro expression must evaluate to a number +(not "x"). + +!DO !x = x. + +define.sps:3: At `)' in the expansion of `!c', +define.sps:7: error: DEBUG EXPAND: Expecting literal or function invocation in +macro expression. + +!LET !x = ( ). +]) +AT_CLEANUP + +AT_SETUP([macro !IF errors]) +AT_KEYWORDS([IF]) +AT_DATA([define.sps], [dnl +DEFINE !a() !IF 1 !ENDDEFINE. +DEFINE !b() !IF 1 !THEN !ENDDEFINE. +DEFINE !c() !IF 1 !THEN !ELSE !ENDDEFINE. +DEBUG EXPAND. +!a. +!b. +!c. +]) +AT_CHECK([pspp --testing-mode define.sps], [1], [dnl +define.sps:1: In the expansion of `!a', +define.sps:5: error: DEBUG EXPAND: !THEN expected in macro !IF construct. + +!IF 1 + +define.sps:2: In the expansion of `!b', +define.sps:6: error: DEBUG EXPAND: !ELSE or !IFEND expected in macro !IF +construct. + +!IF 1 !THEN + +define.sps:3: In the expansion of `!c', +define.sps:7: error: DEBUG EXPAND: !IFEND expected in macro !IF construct. + +!IF 1 !THEN !ELSE +]) +AT_CLEANUP + +AT_SETUP([macro !LET errors]) +AT_KEYWORDS([LET]) +AT_DATA([define.sps], [dnl +DEFINE !a() !LET !ENDDEFINE. +DEFINE !b() !LET 0 !ENDDEFINE. +DEFINE !c() !LET !x !ENDDEFINE. +DEFINE !d() !LET !x y !ENDDEFINE. +DEBUG EXPAND. +!a. +!b. +!c. +!d. +]) +AT_CHECK([pspp --testing-mode define.sps], [1], [dnl +define.sps:1: In the expansion of `!a', +define.sps:6: error: DEBUG EXPAND: Expected macro variable name following !LET. + +!LET + +define.sps:2: At `0' in the expansion of `!b', +define.sps:7: error: DEBUG EXPAND: Expected macro variable name following !LET. + +!LET 0 + +define.sps:3: In the expansion of `!c', +define.sps:8: error: DEBUG EXPAND: Expected `=' following !LET. + +!LET !x + +define.sps:4: At `y' in the expansion of `!d', +define.sps:9: error: DEBUG EXPAND: Expected `=' following !LET. + +!LET !x y +]) +AT_CLEANUP + +AT_SETUP([macro !DO errors]) +AT_KEYWORDS([DO]) +AT_DATA([define.sps], [dnl +DEFINE !a() !DO !ENDDEFINE. +DEFINE !b() !DO 0 !ENDDEFINE. +DEFINE !c() !DO !x !ENDDEFINE. +DEFINE !d() !DO !x !in (x) !ENDDEFINE. +DEFINE !e() !DO !x = x. !ENDDEFINE. +DEFINE !f() !DO !x = 5 x !ENDDEFINE. +DEFINE !g() !DO !x = 5 !TO 6 !BY 0 !ENDDEFINE. +DEFINE !h() !DO !x !ENDDEFINE. +DEFINE !i() !DO !x 0 !ENDDEFINE. +DEFINE !j() !BREAK !ENDDEFINE. +DEBUG EXPAND. +!a. +!b. +!c. +!d. +!e. +!f. +!g. +!h. +!i. +!j. +]) +AT_CHECK([pspp --testing-mode define.sps], [1], [dnl +define.sps:1: In the expansion of `!a', +define.sps:12: error: DEBUG EXPAND: Expected macro variable name following !DO. + +!DO + +define.sps:2: At `0' in the expansion of `!b', +define.sps:13: error: DEBUG EXPAND: Expected macro variable name following !DO. + +!DO 0 + +define.sps:3: In the expansion of `!c', +define.sps:14: error: DEBUG EXPAND: Expected `=' or !IN in !DO loop. + +!DO !x + +define.sps:4: In the expansion of `!d', +define.sps:15: error: DEBUG EXPAND: Missing !DOEND. + +!DO !x !in(x) + +At `x' in the expansion of `!DO', +define.sps:5: inside the expansion of `!e', +define.sps:16: error: DEBUG EXPAND: Macro expression must evaluate to a number +(not "x"). + +!DO !x = x. + +define.sps:6: At `x' in the expansion of `!f', +define.sps:17: error: DEBUG EXPAND: Expected !TO in numerical !DO loop. + +!DO !x = 5 x + +define.sps:7: In the expansion of `!g', +define.sps:18: error: DEBUG EXPAND: !BY value cannot be zero. + +!DO !x = 5 !TO 6 !BY 0 + +define.sps:8: In the expansion of `!h', +define.sps:19: error: DEBUG EXPAND: Expected `=' or !IN in !DO loop. + +!DO !x + +define.sps:9: At `0' in the expansion of `!i', +define.sps:20: error: DEBUG EXPAND: Expected `=' or !IN in !DO loop. + +!DO !x 0 + +define.sps:10: At `!BREAK' in the expansion of `!j', +define.sps:21: error: DEBUG EXPAND: !BREAK outside !DO. + +!BREAK +]) +AT_CLEANUP +