From efe15565cf1bb2224837f35838ee888c0c330c8d Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 21 Nov 2021 13:32:36 -0800 Subject: [PATCH] check number of args to matrix functions --- src/language/stats/matrix.c | 44 +++++++++++++++++++++++++++------- tests/language/stats/matrix.at | 35 ++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/language/stats/matrix.c b/src/language/stats/matrix.c index b507f022fa..c166473e87 100644 --- a/src/language/stats/matrix.c +++ b/src/language/stats/matrix.c @@ -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; diff --git a/tests/language/stats/matrix.at b/tests/language/stats/matrix.at index d8998f6e87..bd81cd7ec9 100644 --- a/tests/language/stats/matrix.at +++ b/tests/language/stats/matrix.at @@ -1434,7 +1434,7 @@ PRINT LN({1, 2; 3, 4})/FORMAT F5.2. PRINT LN(0). END MATRIX. ]) -AT_CHECK([pspp matrix.sps], [0], [dnl +AT_CHECK([pspp matrix.sps], [1], [dnl IDENT(1) 1 @@ -1480,8 +1480,8 @@ LN({1, 2; 3, 4}) .00 .69 1.10 1.39 -LN(0) - -In +error: Argument 1 to matrix function LN has invalid value 0. This argument +must be greater than 0. ]) AT_CLEANUP @@ -1996,6 +1996,35 @@ AT_CHECK([pspp matrix.sps], [0], [dnl ]) AT_CLEANUP +AT_SETUP([MATRIX - invalid number function arguments]) +AT_DATA([matrix.sps], [dnl +MATRIX. +COMPUTE x=ABS(). +COMPUTE x=ABS(1,2). +COMPUTE x=KRONEKER(1,2,3). +COMPUTE x=IDENT(). +COMPUTE x=IDENT(1,2,3). +COMPUTE x=BLOCK(). +END MATRIX. +]) +AT_CHECK([pspp matrix.sps], [1], [dnl +matrix.sps:2: error: COMPUTE: Matrix function ABS requires 1 argument. + +matrix.sps:3: error: COMPUTE: Matrix function ABS requires 1 argument. + +matrix.sps:4: error: COMPUTE: Matrix function KRONEKER requires 2 arguments. + +matrix.sps:5: error: COMPUTE: Matrix function IDENT requires 1 or 2 arguments, +but 0 were provided. + +matrix.sps:6: error: COMPUTE: Matrix function IDENT requires 1 or 2 arguments, +but 3 were provided. + +matrix.sps:7: error: COMPUTE: Matrix function BLOCK requires at least one +argument. +]) +AT_CLEANUP + AT_SETUP([MATRIX - CALL SETDIAG]) AT_DATA([matrix.sps], [dnl MATRIX. -- 2.30.2