From: Ben Pfaff Date: Mon, 22 Mar 2021 19:50:23 +0000 (-0700) Subject: lexer: New function lex_force_int_range(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=cd221d80fafb54e550398c6de105d4c1b7f02ba0 lexer: New function lex_force_int_range(). This simplifies parsing code that needs an integer in a particular range. --- diff --git a/src/language/command.c b/src/language/command.c index 7c0c9bc413..068ae0ea63 100644 --- a/src/language/command.c +++ b/src/language/command.c @@ -496,15 +496,12 @@ cmd_finish (struct lexer *lexer UNUSED, struct dataset *ds UNUSED) int cmd_n_of_cases (struct lexer *lexer, struct dataset *ds) { - /* Value for N. */ - int x; - - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "N OF CASES", 1, LONG_MAX)) return CMD_FAILURE; - x = lex_integer (lexer); + long n = lex_integer (lexer); lex_get (lexer); if (!lex_match_id (lexer, "ESTIMATED")) - dict_set_case_limit (dataset_dict (ds), x); + dict_set_case_limit (dataset_dict (ds), n); return CMD_SUCCESS; } diff --git a/src/language/control/repeat.c b/src/language/control/repeat.c index c73d028271..7341f0760b 100644 --- a/src/language/control/repeat.c +++ b/src/language/control/repeat.c @@ -371,23 +371,20 @@ parse_numbers (struct lexer *lexer, struct dummy_var *dv) if (lex_next_token (lexer, 1) == T_TO) { - long int a, b; - long int i; - if (!lex_is_integer (lexer)) { msg (SE, _("Ranges may only have integer bounds.")); return false; } - a = lex_integer (lexer); + long a = lex_integer (lexer); lex_get (lexer); lex_get (lexer); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, NULL, a, LONG_MAX)) return false; - b = lex_integer (lexer); + long b = lex_integer (lexer); if (b < a) { msg (SE, _("%ld TO %ld is an invalid range."), a, b); @@ -395,7 +392,7 @@ parse_numbers (struct lexer *lexer, struct dummy_var *dv) } lex_get (lexer); - for (i = a; i <= b; i++) + for (long i = a; i <= b; i++) add_replacement (dv, xasprintf ("%ld", i), &allocated); } else diff --git a/src/language/data-io/data-list.c b/src/language/data-io/data-list.c index 58224baa2d..f689c99711 100644 --- a/src/language/data-io/data-list.c +++ b/src/language/data-io/data-list.c @@ -120,31 +120,18 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) { lex_match (lexer, T_EQUALS); lex_match (lexer, T_LPAREN); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "RECORDS", 0, INT_MAX)) goto error; - - int records = lex_integer (lexer); - if (records < 0) - { - msg (SE, _("The %s value must be non-negative."), "RECORDS"); - goto error; - } - data_parser_set_records (parser, records); + data_parser_set_records (parser, lex_integer (lexer)); lex_get (lexer); lex_match (lexer, T_RPAREN); } else if (lex_match_id (lexer, "SKIP")) { lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "SKIP", 0, INT_MAX)) goto error; - int skip = lex_integer (lexer); - if (skip < 0) - { - msg (SE, _("The %s value must be non-negative."), "SKIP"); - goto error; - } - data_parser_set_skip (parser, skip); + data_parser_set_skip (parser, lex_integer (lexer)); lex_get (lexer); } else if (lex_match_id (lexer, "END")) diff --git a/src/language/data-io/file-handle.c b/src/language/data-io/file-handle.c index 8d65418db7..49669a565a 100644 --- a/src/language/data-io/file-handle.c +++ b/src/language/data-io/file-handle.c @@ -94,7 +94,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED) } lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "LRECL", 1, (1UL << 31) - 1)) goto exit; lrecl = lex_integer (lexer); lex_get (lexer); @@ -108,7 +108,7 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED) } lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "TABWIDTH", 1, INT_MAX)) goto exit; tabwidth = lex_integer (lexer); lex_get (lexer); @@ -252,10 +252,6 @@ cmd_file_handle (struct lexer *lexer, struct dataset *ds UNUSED) msg (SE, _("The specified file mode requires LRECL. " "Assuming %zu-character records."), properties.record_width); - else if (lrecl < 1 || lrecl >= (1UL << 31)) - msg (SE, _("Record length (%d) must be between 1 and %lu bytes. " - "Assuming %zu-character records."), - lrecl, (1UL << 31) - 1, properties.record_width); else properties.record_width = lrecl; } diff --git a/src/language/data-io/get-data.c b/src/language/data-io/get-data.c index af44f03a2a..a37e3f0326 100644 --- a/src/language/data-io/get-data.c +++ b/src/language/data-io/get-data.c @@ -164,7 +164,7 @@ parse_get_psql (struct lexer *lexer, struct dataset *ds) if (lex_match_id (lexer, "ASSUMEDSTRWIDTH")) { lex_match (lexer, T_EQUALS); - if (lex_force_int (lexer)) + if (lex_force_int_range (lexer, "ASSUMEDSTRWIDTH", 1, 32767)) { psql.str_width = lex_integer (lexer); lex_get (lexer); @@ -173,7 +173,7 @@ parse_get_psql (struct lexer *lexer, struct dataset *ds) else if (lex_match_id (lexer, "BSIZE")) { lex_match (lexer, T_EQUALS); - if (lex_force_int (lexer)) + if (lex_force_int_range (lexer, "BSIZE", 1, INT_MAX)) { psql.bsize = lex_integer (lexer); lex_get (lexer); @@ -248,7 +248,7 @@ parse_spreadsheet (struct lexer *lexer, char **filename, if (lex_match_id (lexer, "ASSUMEDSTRWIDTH")) { lex_match (lexer, T_EQUALS); - if (lex_force_int (lexer)) + if (lex_force_int_range (lexer, "ASSUMEDSTRWIDTH", 1, 32767)) { opts->asw = lex_integer (lexer); lex_get (lexer); @@ -269,15 +269,9 @@ parse_spreadsheet (struct lexer *lexer, char **filename, } else if (lex_match_id (lexer, "INDEX")) { - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "INDEX", 1, INT_MAX)) goto error; - opts->sheet_index = lex_integer (lexer); - if (opts->sheet_index <= 0) - { - msg (SE, _("The sheet index must be greater than or equal to 1")); - goto error; - } lex_get (lexer); } else @@ -434,13 +428,8 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds) else if (lex_match_id (lexer, "FIRSTCASE")) { lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "FIRSTCASE", 1, INT_MAX)) goto error; - if (lex_integer (lexer) < 1) - { - msg (SE, _("Value of %s must be 1 or greater."), "FIRSTCASE"); - goto error; - } data_parser_set_skip (parser, lex_integer (lexer) - 1); lex_get (lexer); } @@ -472,13 +461,8 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds) if (!set_type (parser, "FIXCASE", DP_FIXED, &has_type)) goto error; lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "FIXCASE", 1, INT_MAX)) goto error; - if (lex_integer (lexer) < 1) - { - msg (SE, _("Value of %s must be 1 or greater."), "FIXCASE"); - goto error; - } data_parser_set_records (parser, lex_integer (lexer)); lex_get (lexer); } @@ -576,25 +560,9 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds) while (type == DP_FIXED && lex_match (lexer, T_SLASH)) { - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, NULL, record, + data_parser_get_records (parser))) goto error; - if (lex_integer (lexer) < record) - { - msg (SE, _("The record number specified, %ld, is at or " - "before the previous record, %d. Data " - "fields must be listed in order of " - "increasing record number."), - lex_integer (lexer), record); - goto error; - } - if (lex_integer (lexer) > data_parser_get_records (parser)) - { - msg (SE, _("The record number specified, %ld, exceeds " - "the number of records per case specified " - "on FIXCASE, %d."), - lex_integer (lexer), data_parser_get_records (parser)); - goto error; - } record = lex_integer (lexer); lex_get (lexer); } diff --git a/src/language/data-io/matrix-data.c b/src/language/data-io/matrix-data.c index 50a34642be..b41f47216b 100644 --- a/src/language/data-io/matrix-data.c +++ b/src/language/data-io/matrix-data.c @@ -479,15 +479,10 @@ cmd_matrix (struct lexer *lexer, struct dataset *ds) { lex_match (lexer, T_EQUALS); - if (! lex_force_int (lexer)) + if (! lex_force_int_range (lexer, "N", 0, INT_MAX)) goto error; mformat.n = lex_integer (lexer); - if (mformat.n < 0) - { - msg (SE, _("%s must not be negative."), "N"); - goto error; - } lex_get (lexer); } else if (lex_match_id (lexer, "FORMAT")) diff --git a/src/language/data-io/placement-parser.c b/src/language/data-io/placement-parser.c index 8a08208b8a..6fa4e20388 100644 --- a/src/language/data-io/placement-parser.c +++ b/src/language/data-io/placement-parser.c @@ -401,19 +401,9 @@ parse_record_placement (struct lexer *lexer, int *record, int *column) { if (lex_is_number (lexer)) { - double orignum = lex_number (lexer); - long n = (lex_is_integer (lexer)?lex_integer (lexer):*record); - bool out_of_range = orignum > INT_MAX || orignum < INT_MIN; - if (n <= *record || out_of_range) - { - msg (SE, _("The record number specified, %.0f, is at or " - "before the previous record, %d. Data " - "fields must be listed in order of " - "increasing record number."), - orignum, *record); - return false; - } - *record = n; + if (!lex_force_int_range (lexer, NULL, *record + 1, INT_MAX)) + return false; + *record = lex_integer (lexer); lex_get (lexer); } else diff --git a/src/language/data-io/print.c b/src/language/data-io/print.c index cc6971ded2..9e4d8a294d 100644 --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@ -175,7 +175,7 @@ internal_cmd_print (struct lexer *lexer, struct dataset *ds, { lex_match (lexer, T_EQUALS); lex_match (lexer, T_LPAREN); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "RECORDS", 0, INT_MAX)) goto error; trns->record_cnt = lex_integer (lexer); lex_get (lexer); diff --git a/src/language/data-io/save.c b/src/language/data-io/save.c index f43aba7a46..a5848e59f5 100644 --- a/src/language/data-io/save.c +++ b/src/language/data-io/save.c @@ -269,7 +269,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, && lex_match_id (lexer, "VERSION")) { lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "VERSION", 2, 3)) goto error; sysfile_opts.version = lex_integer (lexer); lex_get (lexer); @@ -290,7 +290,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS")) { lex_match (lexer, T_EQUALS); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "DIGITS", 1, INT_MAX)) goto error; porfile_opts.digits = lex_integer (lexer); lex_get (lexer); diff --git a/src/language/dictionary/attributes.c b/src/language/dictionary/attributes.c index 2fdc11e2a1..88832fd501 100644 --- a/src/language/dictionary/attributes.c +++ b/src/language/dictionary/attributes.c @@ -97,13 +97,8 @@ parse_attribute_name (struct lexer *lexer, const char *dict_encoding, if (lex_match (lexer, T_LBRACK)) { - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, NULL, 1, 65535)) goto error; - if (lex_integer (lexer) < 1 || lex_integer (lexer) > 65535) - { - msg (SE, _("Attribute array index must be between 1 and 65535.")); - goto error; - } *index = lex_integer (lexer); lex_get (lexer); if (!lex_force_match (lexer, T_RBRACK)) diff --git a/src/language/dictionary/variable-display.c b/src/language/dictionary/variable-display.c index 1fa17017e0..461648557a 100644 --- a/src/language/dictionary/variable-display.c +++ b/src/language/dictionary/variable-display.c @@ -103,7 +103,8 @@ cmd_variable_width (struct lexer *lexer, struct dataset *ds) if (!parse_variables (lexer, dataset_dict (ds), &v, &nv, PV_NONE)) return CMD_FAILURE; - if (!lex_force_match (lexer, T_LPAREN) || !lex_force_int (lexer)) + if (!lex_force_match (lexer, T_LPAREN) + || !lex_force_int_range (lexer, NULL, 1, INT_MAX)) { free (v); return CMD_FAILURE; @@ -116,12 +117,6 @@ cmd_variable_width (struct lexer *lexer, struct dataset *ds) return CMD_FAILURE; } - if (width < 0) - { - msg (SE, _("Variable display width must be a positive integer.")); - free (v); - return CMD_FAILURE; - } width = MIN (width, 2 * MAX_STRING); for(i = 0 ; i < nv ; ++i) diff --git a/src/language/dictionary/vector.c b/src/language/dictionary/vector.c index 28e97b15d8..e7e70cecb2 100644 --- a/src/language/dictionary/vector.c +++ b/src/language/dictionary/vector.c @@ -124,13 +124,10 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) { if (lex_is_integer (lexer) && var_cnt == 0) { + if (!lex_force_int_range (lexer, NULL, 1, INT_MAX)) + goto fail; var_cnt = lex_integer (lexer); lex_get (lexer); - if (var_cnt <= 0) - { - msg (SE, _("Vectors must have at least one element.")); - goto fail; - } } else if (lex_token (lexer) == T_ID && !seen_format) { diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index b69bc9a5d0..6d3549a827 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -679,6 +679,96 @@ lex_force_int (struct lexer *lexer) } } +/* If the current token is an integer in the range MIN...MAX (inclusive), does + nothing and returns true. Otherwise, reports an error and returns false. + If NAME is nonnull, then it is used in the error message. */ +bool +lex_force_int_range (struct lexer *lexer, const char *name, long min, long max) +{ + bool is_integer = lex_is_integer (lexer); + bool too_small = is_integer && lex_integer (lexer) < min; + bool too_big = is_integer && lex_integer (lexer) > max; + if (is_integer && !too_small && !too_big) + return true; + + if (min > max) + { + /* Weird, maybe a bug in the caller. Just report that we needed an + integer. */ + if (name) + lex_error (lexer, _("Integer expected for %s."), name); + else + lex_error (lexer, _("Integer expected.")); + } + else if (min == max) + { + if (name) + lex_error (lexer, _("Expected %ld for %s."), min, name); + else + lex_error (lexer, _("Expected %ld."), min); + } + else if (min + 1 == max) + { + if (name) + lex_error (lexer, _("Expected %ld or %ld for %s."), min, min + 1, name); + else + lex_error (lexer, _("Expected %ld or %ld."), min, min + 1); + } + else + { + bool report_lower_bound = (min > INT_MIN / 2) || too_small; + bool report_upper_bound = (max < INT_MAX / 2) || too_big; + + if (report_lower_bound && report_upper_bound) + { + if (name) + lex_error (lexer, + _("Expected integer between %ld and %ld for %s."), + min, max, name); + else + lex_error (lexer, _("Expected integer between %ld and %ld."), + min, max); + } + else if (report_lower_bound) + { + if (min == 0) + { + if (name) + lex_error (lexer, _("Expected non-negative integer for %s."), + name); + else + lex_error (lexer, _("Expected non-negative integer.")); + } + else if (min == 1) + { + if (name) + lex_error (lexer, _("Expected positive integer for %s."), + name); + else + lex_error (lexer, _("Expected positive integer.")); + } + } + else if (report_upper_bound) + { + if (name) + lex_error (lexer, + _("Expected integer less than or equal to %ld for %s."), + max, name); + else + lex_error (lexer, _("Expected integer less than or equal to %ld."), + max); + } + else + { + if (name) + lex_error (lexer, _("Integer expected for %s."), name); + else + lex_error (lexer, _("Integer expected.")); + } + } + return false; +} + /* If the current token is a number, does nothing and returns true. Otherwise, reports an error and returns false. */ bool @@ -1306,7 +1396,8 @@ lex_source_error_valist (struct lex_source *src, int n0, int n1, ds_put_cstr (&s, ": "); ds_put_vformat (&s, format, args); } - ds_put_byte (&s, '.'); + if (ds_last (&s) != '.') + ds_put_byte (&s, '.'); struct msg m = { .category = MSG_C_SYNTAX, diff --git a/src/language/lexer/lexer.h b/src/language/lexer/lexer.h index e98dac00f5..efb909baca 100644 --- a/src/language/lexer/lexer.h +++ b/src/language/lexer/lexer.h @@ -129,6 +129,8 @@ bool lex_match_phrase (struct lexer *, const char *s); bool lex_force_match (struct lexer *, enum token_type) WARN_UNUSED_RESULT; bool lex_force_match_id (struct lexer *, const char *) WARN_UNUSED_RESULT; bool lex_force_int (struct lexer *) WARN_UNUSED_RESULT; +bool lex_force_int_range (struct lexer *, const char *name, + long min, long max) WARN_UNUSED_RESULT; bool lex_force_num (struct lexer *) WARN_UNUSED_RESULT; bool lex_force_id (struct lexer *) WARN_UNUSED_RESULT; bool lex_force_string (struct lexer *) WARN_UNUSED_RESULT; diff --git a/src/language/stats/crosstabs.c b/src/language/stats/crosstabs.c index b6a5de5111..0b9d151951 100644 --- a/src/language/stats/crosstabs.c +++ b/src/language/stats/crosstabs.c @@ -664,9 +664,6 @@ parse_crosstabs_variables (struct lexer *lexer, struct dataset *ds, for (;;) { size_t orig_nv = proc->n_variables; - size_t i; - - long min, max; if (!parse_variables_const (lexer, dataset_dict (ds), &proc->variables, &proc->n_variables, @@ -679,26 +676,20 @@ parse_crosstabs_variables (struct lexer *lexer, struct dataset *ds, if (!lex_force_int (lexer)) goto error; - min = lex_integer (lexer); + long min = lex_integer (lexer); lex_get (lexer); lex_match (lexer, T_COMMA); - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, NULL, min, LONG_MAX)) goto error; - max = lex_integer (lexer); - if (max < min) - { - msg (SE, _("Maximum value (%ld) less than minimum value (%ld)."), - max, min); - goto error; - } + long max = lex_integer (lexer); lex_get (lexer); if (!lex_force_match (lexer, T_RPAREN)) goto error; - for (i = orig_nv; i < proc->n_variables; i++) + for (size_t i = orig_nv; i < proc->n_variables; i++) { const struct variable *var = proc->variables[i]; struct var_range *vr = xmalloc (sizeof *vr); diff --git a/src/language/stats/examine.c b/src/language/stats/examine.c index 6b2f68a31d..ad8a9baa76 100644 --- a/src/language/stats/examine.c +++ b/src/language/stats/examine.c @@ -1536,16 +1536,10 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) int extr = 5; if (lex_match (lexer, T_LPAREN)) { - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "EXTREME", 0, INT_MAX)) goto error; extr = lex_integer (lexer); - if (extr < 0) - { - msg (MW, _("%s may not be negative. Using default value (%g)."), "EXTREME", 5.0); - extr = 5; - } - lex_get (lexer); if (! lex_force_match (lexer, T_RPAREN)) goto error; diff --git a/src/language/stats/factor.c b/src/language/stats/factor.c index f9156b7de0..4ec49010c9 100644 --- a/src/language/stats/factor.c +++ b/src/language/stats/factor.c @@ -1314,7 +1314,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds) else if (lex_match_id (lexer, "ITERATE")) { if (lex_force_match (lexer, T_LPAREN) - && lex_force_int (lexer)) + && lex_force_int_range (lexer, "ITERATE", 0, INT_MAX)) { n_iterations = lex_integer (lexer); lex_get (lexer); diff --git a/src/language/stats/frequencies.c b/src/language/stats/frequencies.c index a6ef914b03..484ce1af1e 100644 --- a/src/language/stats/frequencies.c +++ b/src/language/stats/frequencies.c @@ -797,7 +797,7 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) else if (lex_match_id (lexer, "LIMIT")) { if (!lex_force_match (lexer, T_LPAREN) - || !lex_force_int (lexer)) + || !lex_force_int_range (lexer, "LIMIT", 0, INT_MAX)) goto error; frq.max_categories = lex_integer (lexer); @@ -833,12 +833,11 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) { lex_match (lexer, T_EQUALS); - if (lex_force_int (lexer)) + if (lex_force_int_range (lexer, "NTILES", 0, INT_MAX)) { - int i; int n = lex_integer (lexer); lex_get (lexer); - for (i = 0; i < n + 1; ++i) + for (int i = 0; i < n + 1; ++i) { frq.percentiles = xrealloc (frq.percentiles, @@ -896,13 +895,9 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) hi_scale = FRQ_FREQ; if (lex_match (lexer, T_LPAREN)) { - if (lex_force_int (lexer)) + if (lex_force_int_range (lexer, "FREQ", 1, INT_MAX)) { hi_freq = lex_integer (lexer); - if (hi_freq <= 0) - { - lex_error (lexer, _("Histogram frequency must be greater than zero.")); - } lex_get (lexer); if (! lex_force_match (lexer, T_RPAREN)) goto error; @@ -914,13 +909,9 @@ cmd_frequencies (struct lexer *lexer, struct dataset *ds) hi_scale = FRQ_PERCENT; if (lex_match (lexer, T_LPAREN)) { - if (lex_force_int (lexer)) + if (lex_force_int_range (lexer, "PERCENT", 1, INT_MAX)) { hi_pcnt = lex_integer (lexer); - if (hi_pcnt <= 0) - { - lex_error (lexer, _("Histogram percentage must be greater than zero.")); - } lex_get (lexer); if (! lex_force_match (lexer, T_RPAREN)) goto error; diff --git a/src/language/stats/glm.c b/src/language/stats/glm.c index d7b9b0f084..d0dc4bc83c 100644 --- a/src/language/stats/glm.c +++ b/src/language/stats/glm.c @@ -262,19 +262,13 @@ cmd_glm (struct lexer *lexer, struct dataset *ds) goto error; } - if (! lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "SSTYPE", 1, 3)) { lex_error (lexer, NULL); goto error; } glm.ss_type = lex_integer (lexer); - if (1 > glm.ss_type || 3 < glm.ss_type) - { - msg (ME, _("Only types 1, 2 & 3 sums of squares are currently implemented")); - goto error; - } - lex_get (lexer); if (! lex_force_match (lexer, T_RPAREN)) diff --git a/src/language/stats/logistic.c b/src/language/stats/logistic.c index 2cf440c31f..dbf54c6b0b 100644 --- a/src/language/stats/logistic.c +++ b/src/language/stats/logistic.c @@ -928,7 +928,7 @@ cmd_logistic (struct lexer *lexer, struct dataset *ds) { if (lex_force_match (lexer, T_LPAREN)) { - if (! lex_force_int (lexer)) + if (! lex_force_int_range (lexer, "ITERATE", 0, INT_MAX)) { lex_error (lexer, NULL); goto error; diff --git a/src/language/stats/quick-cluster.c b/src/language/stats/quick-cluster.c index 23f67b00b0..8b2432ac45 100644 --- a/src/language/stats/quick-cluster.c +++ b/src/language/stats/quick-cluster.c @@ -920,14 +920,9 @@ quick_cluster_parse (struct lexer *lexer, struct qc *qc) if (lex_match_id (lexer, "CLUSTERS")) { if (lex_force_match (lexer, T_LPAREN) && - lex_force_int (lexer)) + lex_force_int_range (lexer, "CLUSTERS", 1, INT_MAX)) { qc->ngroups = lex_integer (lexer); - if (qc->ngroups <= 0) - { - lex_error (lexer, _("The number of clusters must be positive")); - return false; - } lex_get (lexer); if (!lex_force_match (lexer, T_RPAREN)) return false; @@ -952,14 +947,9 @@ quick_cluster_parse (struct lexer *lexer, struct qc *qc) else if (lex_match_id (lexer, "MXITER")) { if (lex_force_match (lexer, T_LPAREN) && - lex_force_int (lexer)) + lex_force_int_range (lexer, "MXITER", 1, INT_MAX)) { qc->maxiter = lex_integer (lexer); - if (qc->maxiter <= 0) - { - lex_error (lexer, _("The number of iterations must be positive")); - return false; - } lex_get (lexer); if (!lex_force_match (lexer, T_RPAREN)) return false; diff --git a/src/language/stats/rank.c b/src/language/stats/rank.c index 64c44a1e1c..fe277c7de3 100644 --- a/src/language/stats/rank.c +++ b/src/language/stats/rank.c @@ -290,7 +290,7 @@ parse_into (struct lexer *lexer, struct rank *cmd, if (!lex_force_match (lexer, T_LPAREN)) return false; - if (! lex_force_int (lexer)) + if (! lex_force_int_range (lexer, "NTILES", 1, INT_MAX)) return false; cmd->k_ntiles = lex_integer (lexer); diff --git a/src/language/stats/sort-cases.c b/src/language/stats/sort-cases.c index 603a341d6e..069451510d 100644 --- a/src/language/stats/sort-cases.c +++ b/src/language/stats/sort-cases.c @@ -54,15 +54,10 @@ cmd_sort_cases (struct lexer *lexer, struct dataset *ds) if (settings_get_testing_mode () && lex_match (lexer, T_SLASH)) { if (!lex_force_match_id (lexer, "BUFFERS") || !lex_match (lexer, T_EQUALS) - || !lex_force_int (lexer)) + || !lex_force_int_range (lexer, "BUFFERS", 2, INT_MAX)) goto done; min_buffers = max_buffers = lex_integer (lexer); - if (max_buffers < 2) - { - msg (SE, _("Buffer limit must be at least 2.")); - goto done; - } lex_get (lexer); } diff --git a/src/language/utilities/set.c b/src/language/utilities/set.c index 89a7052600..11b3dac914 100644 --- a/src/language/utilities/set.c +++ b/src/language/utilities/set.c @@ -51,6 +51,7 @@ #include "output/journal.h" #include "output/pivot-table.h" +#include "gl/minmax.h" #include "gl/xalloc.h" #include "gettext.h" @@ -344,14 +345,10 @@ parse_EPOCH (struct lexer *lexer) settings_set_epoch (-1); else if (lex_is_integer (lexer)) { - int new_epoch = lex_integer (lexer); + if (!lex_force_int_range (lexer, "EPOCH", 1500, INT_MAX)) + return false; + settings_set_epoch (lex_integer (lexer)); lex_get (lexer); - if (new_epoch < 1500) - { - msg (SE, _("%s must be 1500 or later."), "EPOCH"); - return false; - } - settings_set_epoch (new_epoch); } else { @@ -397,15 +394,10 @@ parse_FORMAT (struct lexer *lexer) static bool parse_FUZZBITS (struct lexer *lexer) { - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "FUZZITS", 0, 20)) return false; - int fuzzbits = lex_integer (lexer); + settings_set_fuzzbits (lex_integer (lexer)); lex_get (lexer); - - if (fuzzbits >= 0 && fuzzbits <= 20) - settings_set_fuzzbits (fuzzbits); - else - msg (SE, _("%s must be between 0 and 20."), "FUZZBITS"); return true; } @@ -457,13 +449,8 @@ parse_LENGTH (struct lexer *lexer) page_length = -1; else { - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "LENGTH", 1, INT_MAX)) return false; - if (lex_integer (lexer) < 1) - { - msg (SE, _("%s must be at least %d."), "LENGTH", 1); - return false; - } page_length = lex_integer (lexer); lex_get (lexer); } @@ -715,34 +702,25 @@ parse_WIDTH (struct lexer *lexer) settings_set_viewwidth (131); else { - if (!lex_force_int (lexer)) - return 0; - if (lex_integer (lexer) < 40) - { - msg (SE, _("%s must be at least %d."), "WIDTH", 40); - return 0; - } + if (!lex_force_int_range (lexer, "WIDTH", 40, INT_MAX)) + return false; settings_set_viewwidth (lex_integer (lexer)); lex_get (lexer); } - return 1; + return true; } static bool parse_WORKSPACE (struct lexer *lexer) { - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "WORKSPACE", + settings_get_testing_mode () ? 1 : 1024, + INT_MAX)) return false; int workspace = lex_integer (lexer); lex_get (lexer); - - if (workspace < 1024 && !settings_get_testing_mode ()) - msg (SE, _("%s must be at least 1MB"), "WORKSPACE"); - else if (workspace <= 0) - msg (SE, _("%s must be positive"), "WORKSPACE"); - else - settings_set_workspace (workspace * 1024L); + settings_set_workspace (MIN (workspace, INT_MAX / 1024) * 1024); return true; } diff --git a/src/language/xforms/sample.c b/src/language/xforms/sample.c index 260841a602..7184562ef2 100644 --- a/src/language/xforms/sample.c +++ b/src/language/xforms/sample.c @@ -88,17 +88,9 @@ cmd_sample (struct lexer *lexer, struct dataset *ds) lex_get (lexer); if (!lex_force_match_id (lexer, "FROM")) return CMD_FAILURE; - if (!lex_force_int (lexer)) + if (!lex_force_int_range (lexer, "FROM", a + 1, INT_MAX)) return CMD_FAILURE; b = lex_integer (lexer); - if (a >= b) - { - msg (SE, _("Cannot sample %d observations from a population of " - "%d."), - a, b); - return CMD_FAILURE; - } - frac = 0; } lex_get (lexer); diff --git a/tests/language/data-io/data-list.at b/tests/language/data-io/data-list.at index 8637ff7c6a..ee576ae474 100644 --- a/tests/language/data-io/data-list.at +++ b/tests/language/data-io/data-list.at @@ -410,7 +410,7 @@ EXECUTE. ]) AT_CHECK([pspp -O format=csv data-list.sps], [1], [dnl -data-list.sps:1: error: DATA LIST: The SKIP value must be non-negative. +data-list.sps:1.41-1.42: error: DATA LIST: Syntax error at `-1': Expected non-negative integer for SKIP. data-list.sps:3: error: Stopping syntax file processing here to avoid a cascade of dependent command failures. ]) @@ -426,7 +426,7 @@ EXECUTE. ]) AT_CHECK([pspp -O format=csv data-list.sps], [1], [dnl -data-list.sps:1: error: DATA LIST: The RECORDS value must be non-negative. +data-list.sps:1.44-1.45: error: DATA LIST: Syntax error at `-1': Expected non-negative integer for RECORDS. data-list.sps:3: error: Stopping syntax file processing here to avoid a cascade of dependent command failures. ]) diff --git a/tests/language/lexer/lexer.at b/tests/language/lexer/lexer.at index 25ced0d9ab..e664ac2ad7 100644 --- a/tests/language/lexer/lexer.at +++ b/tests/language/lexer/lexer.at @@ -103,7 +103,7 @@ AT_SETUP([lexer crash due to overflow]) printf "DATA LIST/5555555555555555." > lexer.sps AT_CHECK([pspp -O format=csv lexer.sps], [1], [dnl -"lexer.sps:1: error: DATA LIST: The record number specified, 5555555555555555, is at or before the previous record, 0. Data fields must be listed in order of increasing record number." +lexer.sps:1.11-1.27: error: DATA LIST: Syntax error at `5555555555555555.': Expected integer between 1 and 2147483647. ]) AT_CLEANUP diff --git a/tests/language/stats/rank.at b/tests/language/stats/rank.at index eb0b71b107..e314071338 100644 --- a/tests/language/stats/rank.at +++ b/tests/language/stats/rank.at @@ -597,7 +597,7 @@ RANK x AT_CHECK([pspp -O format=csv rank.sps], [1], [dnl rank.sps:15.1: error: RANK: Syntax error at end of command: expecting `@{:@'. -rank.sps:19.11: error: RANK: Syntax error at `d': expecting integer. +rank.sps:19.11: error: RANK: Syntax error at `d': Expected positive integer for NTILES. rank.sps:25: error: RANK: Variable x already exists.