lexer: New function lex_force_int_range().
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 22 Mar 2021 19:50:23 +0000 (12:50 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 22 Mar 2021 19:51:52 +0000 (12:51 -0700)
This simplifies parsing code that needs an integer in a particular range.

28 files changed:
src/language/command.c
src/language/control/repeat.c
src/language/data-io/data-list.c
src/language/data-io/file-handle.c
src/language/data-io/get-data.c
src/language/data-io/matrix-data.c
src/language/data-io/placement-parser.c
src/language/data-io/print.c
src/language/data-io/save.c
src/language/dictionary/attributes.c
src/language/dictionary/variable-display.c
src/language/dictionary/vector.c
src/language/lexer/lexer.c
src/language/lexer/lexer.h
src/language/stats/crosstabs.c
src/language/stats/examine.c
src/language/stats/factor.c
src/language/stats/frequencies.c
src/language/stats/glm.c
src/language/stats/logistic.c
src/language/stats/quick-cluster.c
src/language/stats/rank.c
src/language/stats/sort-cases.c
src/language/utilities/set.c
src/language/xforms/sample.c
tests/language/data-io/data-list.at
tests/language/lexer/lexer.at
tests/language/stats/rank.at

index 7c0c9bc413d58c4ddd34bfc32524e5e1eaa3ce4a..068ae0ea631a7f19da70898336a2414052205c55 100644 (file)
@@ -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;
 }
index c73d02827149290d9af9dd05dbf5992000e2600b..7341f0760bcf48960a01ca3f378cc18f666c9abe 100644 (file)
@@ -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
index 58224baa2de01b6b3920e7947cb25cd528de9be7..f689c99711d0626143f2026fc230d468d75beed0 100644 (file)
@@ -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"))
index 8d65418db75b0a30078c2600730404b3adfeb5ff..49669a565a74db4157267901914196df03d4aa29 100644 (file)
@@ -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;
     }
index af44f03a2a8253ed53b4462143f6439cc12501ea..a37e3f0326119808e49075542f89afbe6241ba9e 100644 (file)
@@ -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);
         }
index 50a34642be79cebb749cc07ff0cc7932618d3f50..b41f47216b32a2d86e46345aaca5e3d757be74f3 100644 (file)
@@ -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"))
index 8a08208b8a0d68a41d544a859be1be8dc3619f80..6fa4e20388b02d7c6d03442ec0a790e557d6c26c 100644 (file)
@@ -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
index cc6971ded25938b53a3a1eba5609fe97dff08eb6..9e4d8a294dfee4c88d58f42f44c946df50ee189f 100644 (file)
@@ -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);
index f43aba7a46abc986d6f335a053d9b811e37ef7de..a5848e59f5ce12f08b5de428df5fb7154cc9ed09 100644 (file)
@@ -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);
index 2fdc11e2a1ad3744f8551a29c360b8a8cd769a5f..88832fd501f641ebcc041c1558fa3d214047c454 100644 (file)
@@ -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))
index 1fa17017e09556c662bf8ab7d0da5a7cd398eb71..461648557a05eaf017ffd1e67f8280c0a99fd3e6 100644 (file)
@@ -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)
index 28e97b15d8aa9643475dfdbbcd1d964d164ebc3c..e7e70cecb28a288549b22fdbf9641b2b4b8cd009 100644 (file)
@@ -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)
                 {
index b69bc9a5d0df1c12772afa777b4fb43a4d10bb1c..6d3549a82782134f62c8603e76ac207f54fe6fef 100644 (file)
@@ -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,
index e98dac00f59e45b01455f5f0d2b46a378205bdb2..efb909baca1d04a597202fe848ff8c07e7543565 100644 (file)
@@ -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;
index b6a5de51110d02fb360bfd0c84ae634002261ffa..0b9d1519517b100f6e0376110ab3a91813a44a9d 100644 (file)
@@ -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);
index 6b2f68a31dc5feff89372bbddde345085c37484b..ad8a9baa767d525fdf645c1a8ec07d3dba312885 100644 (file)
@@ -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;
index f9156b7de059e597c1e77f12e300d16b5c44e716..4ec49010c9dcf6fc44a2ca934ef6ec4e942ce644 100644 (file)
@@ -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);
index a6ef914b03be4f34a17fabfb2c50b4fa954ef5a3..484ce1af1e7095bf2f18e8eef0d6c0ebee16607b 100644 (file)
@@ -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;
index d7b9b0f084e2de4fc04a5a75d6cd1fbe42e01e60..d0dc4bc83ca9d2a926593c233cabdba58755070f 100644 (file)
@@ -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))
index 2cf440c31f8829f34ee0416a26feea1ea12adf0f..dbf54c6b0b483093d7b6a2de692801accd987581 100644 (file)
@@ -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;
index 23f67b00b0d6cf5df21c870a51ca8d4008e68251..8b2432ac455fec61a7fe8a56043ba035e5991c3d 100644 (file)
@@ -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;
index 64c44a1e1ca2a108540d07e5f3471c16690738d3..fe277c7de3824fd9e6287d513ae6223de1deb5cb 100644 (file)
@@ -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);
index 603a341d6ef53c23a6e87c50bd53a0010f12e08f..069451510d532ad5b76a3b771dbef500d370d90e 100644 (file)
@@ -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);
     }
index 89a70526003b89e201df4288b3b9c5f3f6d5e780..11b3dac914db6d9a6cd7da97ac3b7a4606d4445c 100644 (file)
@@ -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;
 }
 \f
index 260841a6029b541ddd97dc3ca811391dfee68471..7184562ef2943fd060357450adee5f600658c529 100644 (file)
@@ -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);
index 8637ff7c6a348c4f4afa318109ee8e23e314c062..ee576ae474451670fde52863d16de6bc96951422 100644 (file)
@@ -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.
 ])
index 25ced0d9ab199a4fd59a7935a419117aed9f4b3b..e664ac2ad7c209925558c732176d1873eb2ef446 100644 (file)
@@ -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
index eb0b71b10752abd728fc894088e124bfdf8bb9d8..e314071338fa5990467e6ab239a17a5a32be8207 100644 (file)
@@ -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.