Make cases simpler, faster, and easier to understand.
[pspp-builds.git] / src / data / por-file-reader.c
index 4636d5fb806cf82b81124f0515c96a9f89feb965..7e65c28bdf51c11b54f1f6ddd9eced26670b6197 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009 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
@@ -33,6 +33,7 @@
 #include <data/file-name.h>
 #include <data/format.h>
 #include <data/missing-values.h>
+#include <data/short-names.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 #include <libpspp/compiler.h>
@@ -46,6 +47,7 @@
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
+#define N_(msgid) (msgid)
 
 /* portable_to_local[PORTABLE] translates the given portable
    character into the local character set. */
@@ -65,6 +67,7 @@ struct pfm_reader
     jmp_buf bail_out;           /* longjmp() target for error handling. */
 
     struct file_handle *fh;     /* File handle. */
+    struct fh_lock *lock;       /* Read lock for file. */
     FILE *file;                        /* File stream. */
     int line_length;            /* Number of characters so far on this line. */
     char cc;                   /* Current character. */
@@ -76,7 +79,7 @@ struct pfm_reader
     bool ok;                    /* Set false on I/O error. */
   };
 
-static struct casereader_class por_file_casereader_class;
+static const struct casereader_class por_file_casereader_class;
 
 static void
 error (struct pfm_reader *r, const char *msg,...)
@@ -157,8 +160,8 @@ close_reader (struct pfm_reader *r)
       r->file = NULL;
     }
 
-  if (r->fh != NULL)
-    fh_close (r->fh, "portable file", "rs");
+  fh_unlock (r->lock);
+  fh_unref (r->fh);
 
   ok = r->ok;
   pool_destroy (r->pool);
@@ -241,15 +244,14 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   struct pfm_reader *volatile r = NULL;
 
   *dict = dict_create ();
-  if (!fh_open (fh, FH_REF_FILE, "portable file", "rs"))
-    goto error;
 
   /* Create and initialize reader. */
   pool = pool_create ();
   r = pool_alloc (pool, sizeof *r);
   r->pool = pool;
-  r->fh = fh;
-  r->file = fn_open (fh_get_file_name (r->fh), "rb");
+  r->fh = fh_ref (fh);
+  r->lock = NULL;
+  r->file = NULL;
   r->line_length = 0;
   r->weight_index = -1;
   r->trans = NULL;
@@ -257,11 +259,18 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   r->widths = NULL;
   r->value_cnt = 0;
   r->ok = true;
-
   if (setjmp (r->bail_out))
     goto error;
 
-  /* Check that file open succeeded. */
+  /* Lock file. */
+  /* TRANSLATORS: this fragment will be interpolated into
+     messages in fh_lock() that identify types of files. */
+  r->lock = fh_lock (fh, FH_REF_FILE, N_("portable file"), FH_ACC_READ, false);
+  if (r->lock == NULL)
+    goto error;
+
+  /* Open file. */
+  r->file = fn_open (fh_get_file_name (r->fh), "rb");
   if (r->file == NULL)
     {
       msg (ME, _("An error occurred while opening \"%s\" for reading "
@@ -500,8 +509,9 @@ read_header (struct pfm_reader *r)
 static void
 read_version_data (struct pfm_reader *r, struct pfm_read_info *info)
 {
-  static char empty_string[] = "";
-  char *date, *time, *product, *author, *subproduct;
+  static const char empty_string[] = "";
+  char *date, *time;
+  const char *product, *author, *subproduct;
   int i;
 
   /* Read file. */
@@ -515,9 +525,9 @@ read_version_data (struct pfm_reader *r, struct pfm_read_info *info)
 
   /* Validate file. */
   if (strlen (date) != 8)
-    error (r, _("Bad date string length %d."), (int) strlen (date));
+    error (r, _("Bad date string length %zu."), strlen (date));
   if (strlen (time) != 6)
-    error (r, _("Bad time string length %d."), (int) strlen (time));
+    error (r, _("Bad time string length %zu."), strlen (time));
 
   /* Save file info. */
   if (info != NULL)
@@ -661,8 +671,8 @@ read_variables (struct pfm_reader *r, struct dictionary *dict)
           int i;
           for (i = 1; i < 100000; i++)
             {
-              char try_name[LONG_NAME_LEN + 1];
-              sprintf (try_name, "%.*s_%d", LONG_NAME_LEN - 6, name, i);
+              char try_name[VAR_NAME_LEN + 1];
+              sprintf (try_name, "%.*s_%d", VAR_NAME_LEN - 6, name, i);
               v = dict_create_var (dict, try_name, width);
               if (v != NULL)
                 break;
@@ -684,12 +694,12 @@ read_variables (struct pfm_reader *r, struct dictionary *dict)
         {
           double x = read_float (r);
           double y = read_float (r);
-          mv_add_num_range (&miss, x, y);
+          mv_add_range (&miss, x, y);
         }
       else if (match (r, 'A'))
-        mv_add_num_range (&miss, read_float (r), HIGHEST);
+        mv_add_range (&miss, read_float (r), HIGHEST);
       else if (match (r, '9'))
-        mv_add_num_range (&miss, LOWEST, read_float (r));
+        mv_add_range (&miss, LOWEST, read_float (r));
 
       /* Single missing values. */
       while (match (r, '8'))
@@ -804,28 +814,30 @@ read_documents (struct pfm_reader *r, struct dictionary *dict)
     }
 }
 
-/* Reads one case from portable file R into C. */
-static bool
-por_file_casereader_read (struct casereader *reader, void *r_, struct ccase *c)
+/* Reads and returns one case from portable file R.  Returns a
+   null pointer on failure. */
+static struct ccase *
+por_file_casereader_read (struct casereader *reader, void *r_)
 {
   struct pfm_reader *r = r_;
+  struct ccase *volatile c;
   size_t i;
   size_t idx;
 
-  case_create (c, casereader_get_value_cnt (reader));
+  c = case_create (casereader_get_value_cnt (reader));
   setjmp (r->bail_out);
   if (!r->ok)
     {
       casereader_force_error (reader);
-      case_destroy (c);
-      return false;
+      case_unref (c);
+      return NULL;
     }
 
   /* Check for end of file. */
   if (r->cc == 'Z')
     {
-      case_destroy (c);
-      return false;
+      case_unref (c);
+      return NULL;
     }
 
   idx = 0;
@@ -847,7 +859,7 @@ por_file_casereader_read (struct casereader *reader, void *r_, struct ccase *c)
         }
     }
 
-  return true;
+  return c;
 }
 
 /* Returns true if FILE is an SPSS portable file,
@@ -885,7 +897,7 @@ pfm_detect (FILE *file)
   return true;
 }
 
-static struct casereader_class por_file_casereader_class =
+static const struct casereader_class por_file_casereader_class =
   {
     por_file_casereader_read,
     por_file_casereader_destroy,