dataset: Fix memory leak destroying a dataset that has a permanent_dict.
[pspp] / src / data / por-file-reader.c
index 4fb6c5fb452de7fbf64a00cf3001124594d85d0e..b5cc35b825ba73c27ae015971fd249afdf9e749e 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2015 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
@@ -43,7 +43,6 @@
 #include "libpspp/pool.h"
 #include "libpspp/str.h"
 
-#include "gl/intprops.h"
 #include "gl/minmax.h"
 #include "gl/xalloc.h"
 #include "gl/xmemdup0.h"
@@ -103,7 +102,6 @@ error (struct pfm_reader *r, const char *msg,...)
 static void
 error (struct pfm_reader *r, const char *msg, ...)
 {
-  struct msg m;
   struct string text;
   va_list args;
 
@@ -114,16 +112,13 @@ error (struct pfm_reader *r, const char *msg, ...)
   ds_put_vformat (&text, msg, args);
   va_end (args);
 
-  m.category = MSG_C_GENERAL;
-  m.severity = MSG_S_ERROR;
-  m.file_name = NULL;
-  m.first_line = 0;
-  m.last_line = 0;
-  m.first_column = 0;
-  m.last_column = 0;
-  m.text = ds_cstr (&text);
-
-  msg_emit (&m);
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
+    .category = MSG_C_GENERAL,
+    .severity = MSG_S_ERROR,
+    .text = ds_steal_cstr (&text),
+  };
+  msg_emit (m);
 
   r->ok = false;
 
@@ -135,7 +130,6 @@ error (struct pfm_reader *r, const char *msg, ...)
 static void
 warning (struct pfm_reader *r, const char *msg, ...)
 {
-  struct msg m;
   struct string text;
   va_list args;
 
@@ -146,16 +140,13 @@ warning (struct pfm_reader *r, const char *msg, ...)
   ds_put_vformat (&text, msg, args);
   va_end (args);
 
-  m.category = MSG_C_GENERAL;
-  m.severity = MSG_S_WARNING;
-  m.file_name = NULL;
-  m.first_line = 0;
-  m.last_line = 0;
-  m.first_column = 0;
-  m.last_column = 0;
-  m.text = ds_cstr (&text);
-
-  msg_emit (&m);
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
+    .category = MSG_C_GENERAL,
+    .severity = MSG_S_WARNING,
+    .text = ds_steal_cstr (&text),
+  };
+  msg_emit (m);
 }
 
 /* Close and destroy R.
@@ -166,11 +157,11 @@ pfm_close (struct any_reader *r_)
   struct pfm_reader *r = pfm_reader_cast (r_);
   bool ok;
 
-  dict_destroy (r->dict);
+  dict_unref (r->dict);
   any_read_info_destroy (&r->info);
   if (r->file)
     {
-      if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
+      if (fn_close (r->fh, r->file) == EOF)
         {
           msg (ME, _("Error closing portable file `%s': %s."),
                fh_get_file_name (r->fh), strerror (errno));
@@ -255,7 +246,7 @@ static void read_documents (struct pfm_reader *, struct dictionary *);
 /* Reads the dictionary from file with handle H, and returns it in a
    dictionary structure.  This dictionary may be modified in order to
    rename, reorder, and delete variables, etc. */
-struct any_reader *
+static struct any_reader *
 pfm_open (struct file_handle *fh)
 {
   struct pool *volatile pool = NULL;
@@ -288,7 +279,7 @@ pfm_open (struct file_handle *fh)
     goto error;
 
   /* Open file. */
-  r->file = fn_open (fh_get_file_name (r->fh), "rb");
+  r->file = fn_open (r->fh, "rb");
   if (r->file == NULL)
     {
       msg (ME, _("An error occurred while opening `%s' for reading "
@@ -322,7 +313,7 @@ pfm_open (struct file_handle *fh)
   return NULL;
 }
 
-struct casereader *
+static struct casereader *
 pfm_decode (struct any_reader *r_, const char *encoding UNUSED,
             struct dictionary **dictp, struct any_read_info *info)
 {
@@ -739,9 +730,9 @@ read_variables (struct pfm_reader *r, struct dictionary *dict)
           unsigned long int i;
           for (i = 1; ; i++)
             {
-              char try_name[8 + 1 + INT_STRLEN_BOUND (i) + 1];
-              sprintf (try_name, "%s_%lu", name, i);
+              char *try_name = xasprintf ("%s_%lu", name, i);
               v = dict_create_var (dict, try_name, width);
+              free (try_name);
               if (v != NULL)
                 break;
             }
@@ -910,7 +901,7 @@ por_file_casereader_read (struct casereader *reader, void *r_)
       int width = caseproto_get_width (r->proto, i);
 
       if (width == 0)
-        case_data_rw_idx (c, i)->f = read_float (r);
+        *case_num_rw_idx (c, i) = read_float (r);
       else
         {
           uint8_t buf[256];
@@ -922,9 +913,9 @@ por_file_casereader_read (struct casereader *reader, void *r_)
   return c;
 }
 
-/* Returns true if FILE is an SPSS portable file,
-   false otherwise. */
-int
+/* Detects whether FILE is an SPSS portable file.  Returns 1 if so, 0 if not,
+   and a negative errno value if there is an error reading FILE. */
+static int
 pfm_detect (FILE *file)
 {
   unsigned char header[464];
@@ -938,7 +929,7 @@ pfm_detect (FILE *file)
     {
       int c = getc (file);
       if (c == EOF || raw_cnt++ > 512)
-        return 0;
+        return ferror (file) ? -errno : 0;
       else if (c == '\n')
         {
           while (line_len < 80 && cooked_cnt < sizeof header)