session: Fix two memory leaks.
[pspp] / src / data / ods-reader.c
index 5883395d0d7e4b7042bac7dbb32485ee51059552..8504c14cca545033de0d074a29f45659c47258c0 100644 (file)
@@ -117,7 +117,10 @@ static void
 state_data_destroy (struct state_data *sd)
 {
   xmlFree (sd->current_sheet_name);
+  sd->current_sheet_name = NULL;
+
   xmlFreeTextReader (sd->xtr);
+  sd->xtr = NULL;
 }
 
 struct ods_reader
@@ -149,6 +152,8 @@ struct ods_reader
   bool read_names;
 
   struct string ods_errs;
+
+  struct string zip_errs;
 };
 
 void
@@ -238,7 +243,7 @@ ods_get_sheet_range (struct spreadsheet *s, int n)
       process_node (r, or);
     }
 
-  return create_cell_ref (
+  return create_cell_range (
                          r->sheets[n].start_col,
                          r->sheets[n].start_row,
                          r->sheets[n].stop_col,
@@ -260,12 +265,16 @@ ods_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
 
   ds_destroy (&r->ods_errs);
 
-  if ( ! r->used_first_case )
+  if ( r->first_case && ! r->used_first_case )
     case_unref (r->first_case);
 
+
   caseproto_unref (r->proto);
+  r->proto = NULL;
 
   xmlFree (r->target_sheet_name);
+  r->target_sheet_name = NULL;
+
 
   ods_destroy (&r->spreadsheet);
 }
@@ -468,7 +477,7 @@ xmv_to_width (const struct xml_value *xmv, int fallback)
  */
 static void
 convert_xml_to_value (struct ccase *c, const struct variable *var,
-                     const struct xml_value *xmv)
+                     const struct xml_value *xmv, int col, int row)
 {
   union value *v = case_data_rw (c, var);
 
@@ -494,12 +503,22 @@ convert_xml_to_value (struct ccase *c, const struct variable *var,
          const char *text = xmv->value ?
            CHAR_CAST (const char *, xmv->value) : CHAR_CAST (const char *, xmv->text);
 
-
-         free (data_in (ss_cstr (text), "UTF-8",
+         char *m = data_in (ss_cstr (text), "UTF-8",
                         fmt->type,
                         v,
                         var_get_width (var),
-                        "UTF-8"));
+                        "UTF-8");
+
+         if (m)
+           {
+             char buf [FMT_STRING_LEN_MAX + 1];
+             char *cell = create_cell_ref (col, row);
+
+             msg (MW, _("Cannot convert the value in the spreadsheet cell %s to format (%s): %s"), 
+                  cell, fmt_to_string (fmt, buf), m);
+             free (cell);
+           }
+         free (m);
        }
     }
 }
@@ -585,28 +604,33 @@ init_reader (struct ods_reader *r, bool report_errors)
 }
 
 
+
 struct spreadsheet *
 ods_probe (const char *filename, bool report_errors)
 {
-  struct ods_reader *r;
-  struct string errs = DS_EMPTY_INITIALIZER;
   int sheet_count;
-  struct zip_reader *zr = zip_reader_create (filename, &errs);
-  xmlTextReaderPtr xtr;
+  struct ods_reader *r = xzalloc (sizeof *r);
+  xmlTextReaderPtr xtr;  
+  struct zip_reader *zr;
+
+  ds_init_empty (&r->zip_errs);
+
+  zr = zip_reader_create (filename, &r->zip_errs);
 
   if (zr == NULL)
     {
       if (report_errors)
        {
          msg (ME, _("Cannot open %s as a OpenDocument file: %s"),
-              filename, ds_cstr (&errs));
+              filename, ds_cstr (&r->zip_errs));
        }
+      ds_destroy (&r->zip_errs);
+      free (r);
       return NULL;
     }
 
   sheet_count = get_sheet_count (zr);
 
-  r = xzalloc (sizeof *r);
   r->zreader = zr;
   r->ref_cnt = 1;
 
@@ -626,14 +650,12 @@ ods_probe (const char *filename, bool report_errors)
   r->n_allocated_sheets = 0;
   r->sheets = NULL;
 
-  ds_destroy (&errs);
-
   r->spreadsheet.file_name = filename;
   return &r->spreadsheet;
 
  error:
+  ds_destroy (&r->zip_errs);
   zip_reader_destroy (r->zreader);
-  ds_destroy (&errs);
   free (r);
   return NULL;
 }
@@ -669,6 +691,8 @@ ods_make_reader (struct spreadsheet *spreadsheet,
   r->rsd.current_sheet = 0;
   r->rsd.state = STATE_INIT;
 
+  r->used_first_case = false;
+  r->first_case = NULL;
 
   if (opts->cell_range)
     {
@@ -711,7 +735,7 @@ ods_make_reader (struct spreadsheet *spreadsheet,
 
   if ( opts->read_names)
     {
-      while (1 == (ret = xmlTextReaderRead (r->rsd.xtr)))
+      while (1 == xmlTextReaderRead (r->rsd.xtr))
        {
          int idx;
 
@@ -835,9 +859,6 @@ ods_make_reader (struct spreadsheet *spreadsheet,
       var_set_both_formats (var, &fmt);
     }
 
-  /* Create the first case, and cache it */
-  r->used_first_case = false;
-
   if ( n_var_specs ==  0 )
     {
       msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
@@ -845,6 +866,7 @@ ods_make_reader (struct spreadsheet *spreadsheet,
       goto error;
     }
 
+  /* Create the first case, and cache it */
   r->proto = caseproto_ref (dict_get_proto (r->dict));
   r->first_case = case_create (r->proto);
   case_set_missing (r->first_case);
@@ -853,7 +875,9 @@ ods_make_reader (struct spreadsheet *spreadsheet,
     {
       const struct variable *var = dict_get_var (r->dict, i);
 
-      convert_xml_to_value (r->first_case, var,  &var_spec[i].firstval);
+      convert_xml_to_value (r->first_case, var,  &var_spec[i].firstval,
+                           r->rsd.col - n_var_specs + i,
+                           r->rsd.row - 1);
     }
 
   /* Read in the first row of data */
@@ -911,6 +935,9 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_)
   struct ccase *c = NULL;
   struct ods_reader *r = r_;
 
+  xmlChar *val_string = NULL;
+  xmlChar *type = NULL;
+
   if (!r->used_first_case)
     {
       r->used_first_case = true;
@@ -938,9 +965,6 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_)
   c = case_create (r->proto);
   case_set_missing (c);
   
-  xmlChar *val_string = NULL;
-  xmlChar *type = NULL;
-
   while (1 == xmlTextReaderRead (r->rsd.xtr))
     {
       process_node (r, &r->rsd);
@@ -977,7 +1001,7 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_)
                break;
 
               var = dict_get_var (r->dict, idx);
-             convert_xml_to_value (c, var, xmv);
+             convert_xml_to_value (c, var, xmv, idx + r->start_col, r->rsd.row - 1);
            }
 
          xmlFree (xmv->text);