Respect the case_cnt field from sys file header. Closes patch #6092
[pspp-builds.git] / src / data / sys-file-reader.c
index fe17bd2865d22d6a7f420f7cc34022f826cad831..6d2a982db9dbe3aedc8661ed403db3fa2e9d5cb6 100644 (file)
@@ -1,20 +1,18 @@
-/* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
 
@@ -79,6 +77,7 @@ struct sfm_reader
     int flt64_cnt;             /* Number of 8-byte units per case. */
     struct sfm_var *vars;       /* Variables. */
     size_t var_cnt;             /* Number of variables. */
+    int32_t case_cnt;           /* Number of cases */
     bool has_long_var_names;    /* File has a long variable name map */
     bool has_vls;               /* File has one or more very long strings? */
 
@@ -310,7 +309,9 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
 
   pool_free (r->pool, var_by_value_idx);
   r->value_cnt = dict_get_next_value_idx (*dict);
-  return casereader_create_sequential (NULL, r->value_cnt, CASENUMBER_MAX,
+  return casereader_create_sequential
+    (NULL, r->value_cnt,
+     r->case_cnt == -1 ? CASENUMBER_MAX: r->case_cnt,
                                        &sys_file_casereader_class, r);
 }
 
@@ -383,7 +384,6 @@ read_header (struct sfm_reader *r, struct dictionary *dict,
   char rec_type[5];
   char eye_catcher[61];
   uint8_t raw_layout_code[4];
-  int case_cnt;
   uint8_t raw_bias[8];
   char creation_date[10];
   char creation_time[9];
@@ -414,9 +414,10 @@ read_header (struct sfm_reader *r, struct dictionary *dict,
 
   *weight_idx = read_int32 (r);
 
-  case_cnt = read_int32 (r);
-  if (case_cnt < -1 || case_cnt > INT_MAX / 2)
-    case_cnt = -1;
+  r->case_cnt = read_int32 (r);
+  if ( r->case_cnt > INT_MAX / 2)
+    r->case_cnt = -1;
+
 
   /* Identify floating-point format and obtain compression bias. */
   read_bytes (r, raw_bias, sizeof raw_bias);
@@ -455,7 +456,7 @@ read_header (struct sfm_reader *r, struct dictionary *dict,
       info->integer_format = r->integer_format;
       info->float_format = r->float_format;
       info->compressed = r->compressed;
-      info->case_cnt = case_cnt;
+      info->case_cnt = r->case_cnt;
 
       product = ss_cstr (eye_catcher);
       ss_match_string (&product, ss_cstr ("@(#) SPSS DATA FILE"));
@@ -1124,6 +1125,10 @@ read_value_labels (struct sfm_reader *r,
 
 static void partial_record (struct sfm_reader *r)
      NO_RETURN;
+
+static void read_error (struct casereader *, const struct sfm_reader *);
+
+
 static bool read_case_number (struct sfm_reader *, double *);
 static bool read_case_string (struct sfm_reader *, char *, size_t);
 static int read_opcode (struct sfm_reader *);
@@ -1156,6 +1161,7 @@ sys_file_casereader_read (struct casereader *reader, void *r_,
                            sizeof (union value) * r->flt64_cnt))
         {
           case_destroy (c);
+         read_error (reader, r);
           return false;
         }
 
@@ -1231,6 +1237,7 @@ sys_file_casereader_read (struct casereader *reader, void *r_,
       case_destroy (c);
       if (i != 0)
         partial_record (r);
+      read_error (reader, r);
       return false;
     }
 }
@@ -1242,6 +1249,13 @@ partial_record (struct sfm_reader *r)
   sys_error (r, _("File ends in partial case."));
 }
 
+static void
+read_error (struct casereader *r, const struct sfm_reader *sfm)
+{
+  msg (ME, _("Error reading case from file %s"), fh_get_name (sfm->fh));
+  casereader_force_error (r);
+}
+
 /* Reads a number from R and stores its value in *D.
    If R is compressed, reads a compressed number;
    otherwise, reads a number in the regular way.