check number of args to matrix functions
[pspp] / src / language / stats / matrix.c
index b507f022fa886bba070c7a67bacd393b3183c107..c166473e87d9f7f01aa90a04aa008e1ed35b4924 100644 (file)
@@ -2640,21 +2640,47 @@ matrix_parse_function (struct matrix_state *s, const char *token,
   struct matrix_expr *e = xmalloc (sizeof *e);
   *e = (struct matrix_expr) { .op = f->op, .subs = NULL };
 
-  size_t allocated_subs = 0;
-  do
+  if (lex_token (s->lexer) != T_RPAREN)
     {
-      struct matrix_expr *sub = matrix_parse_expr (s);
-      if (!sub)
-        goto error;
+      size_t allocated_subs = 0;
+      do
+        {
+          struct matrix_expr *sub = matrix_parse_expr (s);
+          if (!sub)
+            goto error;
 
-      if (e->n_subs >= allocated_subs)
-        e->subs = x2nrealloc (e->subs, &allocated_subs, sizeof *e->subs);
-      e->subs[e->n_subs++] = sub;
+          if (e->n_subs >= allocated_subs)
+            e->subs = x2nrealloc (e->subs, &allocated_subs, sizeof *e->subs);
+          e->subs[e->n_subs++] = sub;
+        }
+      while (lex_match (s->lexer, T_COMMA));
     }
-  while (lex_match (s->lexer, T_COMMA));
   if (!lex_force_match (s->lexer, T_RPAREN))
     goto error;
 
+  if (e->n_subs < f->min_args || e->n_subs > f->max_args)
+    {
+      if (f->min_args == f->max_args)
+        msg (SE, ngettext ("Matrix function %s requires %zu argument.",
+                           "Matrix function %s requires %zu arguments.",
+                           f->min_args),
+             f->name, f->min_args);
+      else if (f->min_args == 1 && f->max_args == 2)
+        msg (SE, ngettext ("Matrix function %s requires 1 or 2 arguments, "
+                           "but %zu was provided.",
+                           "Matrix function %s requires 1 or 2 arguments, "
+                           "but %zu were provided.",
+                           e->n_subs),
+             f->name, e->n_subs);
+      else if (f->min_args == 1 && f->max_args == INT_MAX)
+        msg (SE, _("Matrix function %s requires at least one argument."),
+             f->name);
+      else
+        NOT_REACHED ();
+
+      goto error;
+    }
+
   *exprp = e;
   return true;