Full negative tests for macros.
[pspp] / src / language / lexer / macro.c
index 8678a0bcdb5f808bcf2f1f872356624706a5b221..e4302bf2fa91e121a09638a3dbf1ea3f13bdd2f1 100644 (file)
@@ -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);