X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fgnumeric-reader.c;h=acfc3c9064741a7c3550a46cad348b756f56121a;hb=a68ebf8f11b6d584de4188ec5284d12b23f69708;hp=e0e95069b602fb38a3794ca2075d70ed50bf77b5;hpb=7ec18587c5a81ed4cac8d458412c5c08ba68a6b1;p=pspp diff --git a/src/data/gnumeric-reader.c b/src/data/gnumeric-reader.c index e0e95069b6..acfc3c9064 100644 --- a/src/data/gnumeric-reader.c +++ b/src/data/gnumeric-reader.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013, 2016 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 @@ -16,31 +16,8 @@ #include -#include "libpspp/message.h" -#include "libpspp/misc.h" - -#include "gl/minmax.h" -#include "gl/c-strtod.h" - -#include "gettext.h" -#define _(msgid) gettext (msgid) -#define N_(msgid) (msgid) - -#include "spreadsheet-reader.h" - -#if !GNM_READ_SUPPORT - -struct casereader * -gnumeric_open_reader (const struct spreadsheet_read_options *opts, struct dictionary **dict) -{ - msg (ME, _("Support for %s files was not compiled into this installation of PSPP"), "Gnumeric"); - - return NULL; -} - -#else - #include "data/gnumeric-reader.h" +#include "spreadsheet-reader.h" #include #include @@ -48,19 +25,26 @@ gnumeric_open_reader (const struct spreadsheet_read_options *opts, struct dictio #include #include -#include "data/format.h" -#include "data/data-in.h" #include "data/case.h" #include "data/casereader-provider.h" +#include "data/data-in.h" #include "data/dictionary.h" +#include "data/format.h" #include "data/identifier.h" #include "data/value.h" #include "data/variable.h" #include "libpspp/i18n.h" +#include "libpspp/message.h" +#include "libpspp/misc.h" #include "libpspp/str.h" +#include "gl/c-strtod.h" +#include "gl/minmax.h" #include "gl/xalloc.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) (msgid) /* Shamelessly lifted from the Gnumeric sources: https://git.gnome.org/browse/gnumeric/tree/src/value.h @@ -121,7 +105,7 @@ struct sheet_detail int maxrow; }; -struct state_data +struct state_data { /* The libxml reader for this instance */ xmlTextReaderPtr xtr; @@ -157,7 +141,7 @@ struct gnumeric_reader int stop_col; int start_row; int stop_row; - + struct sheet_detail *sheets; const xmlChar *target_sheet; @@ -185,10 +169,15 @@ gnumeric_unref (struct spreadsheet *s) { xmlFree (r->sheets[i].name); } - + + free (r->sheets); state_data_destroy (&r->msd); + dict_unref (r->dict); + + free (s->file_name); + free (r); } } @@ -200,7 +189,7 @@ gnumeric_get_sheet_name (struct spreadsheet *s, int n) struct gnumeric_reader *gr = (struct gnumeric_reader *) s; assert (n < s->n_sheets); - return gr->sheets[n].name; + return gr->sheets[n].name; } @@ -213,14 +202,14 @@ gnumeric_get_sheet_range (struct spreadsheet *s, int n) { int ret; struct gnumeric_reader *gr = (struct gnumeric_reader *) s; - + assert (n < s->n_sheets); - while ( + while ( (gr->sheets[n].stop_col == -1) - && + && (1 == (ret = xmlTextReaderRead (gr->msd.xtr))) - ) + ) { process_node (gr, &gr->msd); } @@ -238,15 +227,15 @@ gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_) { struct gnumeric_reader *r = r_; - if ( r == NULL) + if (r == NULL) return ; state_data_destroy (&r->rsd); - if (r->first_case && ! r->used_first_case ) + if (r->first_case && ! r->used_first_case) case_unref (r->first_case); - if (r->proto) + if (r->proto) caseproto_unref (r->proto); gnumeric_unref (&r->spreadsheet); @@ -296,7 +285,7 @@ process_node (struct gnumeric_reader *r, struct state_data *sd) } else if (XML_READER_TYPE_TEXT == sd->node_type) { - if ( r->sheets [r->spreadsheet.n_sheets - 1].name == NULL) + if (r->sheets [r->spreadsheet.n_sheets - 1].name == NULL) r->sheets [r->spreadsheet.n_sheets - 1].name = CHAR_CAST (char *, xmlTextReaderValue (sd->xtr)); } break; @@ -329,10 +318,10 @@ process_node (struct gnumeric_reader *r, struct state_data *sd) } else if (XML_READER_TYPE_TEXT == sd->node_type) { - if ( r->target_sheet != NULL) + if (r->target_sheet != NULL) { xmlChar *value = xmlTextReaderValue (sd->xtr); - if ( 0 == xmlStrcmp (value, r->target_sheet)) + if (0 == xmlStrcmp (value, r->target_sheet)) sd->state = STATE_SHEET_FOUND; free (value); } @@ -425,7 +414,7 @@ process_node (struct gnumeric_reader *r, struct state_data *sd) if (! xmlTextReaderIsEmptyElement (sd->xtr)) sd->state = STATE_CELL; } - else if ( (0 == xmlStrcasecmp (name, _xml("gnm:Cells"))) && (XML_READER_TYPE_END_ELEMENT == sd->node_type) ) + else if ((0 == xmlStrcasecmp (name, _xml("gnm:Cells"))) && (XML_READER_TYPE_END_ELEMENT == sd->node_type)) { r->sheets[sd->current_sheet].stop_col = sd->col; r->sheets[sd->current_sheet].stop_row = sd->row; @@ -457,7 +446,7 @@ convert_xml_string_to_value (struct ccase *c, const struct variable *var, if (xv == NULL) value_set_missing (v, var_get_width (var)); - else if ( var_is_alpha (var)) + else if (var_is_alpha (var)) value_copy_str_rpad (v, var_get_width (var), xv, ' '); else if (type == VALUE_FLOAT || type == VALUE_INTEGER) { @@ -466,7 +455,7 @@ convert_xml_string_to_value (struct ccase *c, const struct variable *var, errno = 0; v->f = c_strtod (text, &endptr); - if ( errno != 0 || endptr == text) + if (errno != 0 || endptr == text) v->f = SYSMIS; } else @@ -480,13 +469,13 @@ convert_xml_string_to_value (struct ccase *c, const struct variable *var, v, var_get_width (var), "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"), + + msg (MW, _("Cannot convert the value in the spreadsheet cell %s to format (%s): %s"), cell, fmt_to_string (fmt, buf), m); free (cell); } @@ -505,10 +494,11 @@ struct var_spec static void gnumeric_error_handler (void *ctx, const char *mesg, - UNUSED xmlParserSeverities sev, xmlTextReaderLocatorPtr loc) + xmlParserSeverities sev UNUSED, + xmlTextReaderLocatorPtr loc) { struct gnumeric_reader *r = ctx; - + msg (MW, _("There was a problem whilst reading the %s file `%s' (near line %d): `%s'"), "Gnumeric", r->spreadsheet.file_name, @@ -518,7 +508,7 @@ gnumeric_error_handler (void *ctx, const char *mesg, static struct gnumeric_reader * gnumeric_reopen (struct gnumeric_reader *r, const char *filename, bool show_errors) -{ +{ int ret = -1; struct state_data *sd; @@ -543,7 +533,7 @@ gnumeric_reopen (struct gnumeric_reader *r, const char *filename, bool show_erro xtr = xmlReaderForIO ((xmlInputReadCallback) gzread, (xmlInputCloseCallback) gzclose, gz, NULL, NULL, - show_errors ? 0 : (XML_PARSE_NOERROR | XML_PARSE_NOWARNING) ); + show_errors ? 0 : (XML_PARSE_NOERROR | XML_PARSE_NOWARNING)); if (xtr == NULL) { @@ -555,15 +545,15 @@ gnumeric_reopen (struct gnumeric_reader *r, const char *filename, bool show_erro { r = xzalloc (sizeof *r); r->spreadsheet.n_sheets = -1; - r->spreadsheet.file_name = filename; + r->spreadsheet.file_name = strdup (filename); sd = &r->msd; } else { sd = &r->rsd; } - - if (show_errors) + + if (show_errors) xmlTextReaderSetErrorHandler (xtr, gnumeric_error_handler, r); r->target_sheet = NULL; @@ -579,18 +569,17 @@ gnumeric_reopen (struct gnumeric_reader *r, const char *filename, bool show_erro This gives us some confidence that we are actually dealing with a gnumeric spreadsheet. */ - while ( (sd->state != STATE_INIT ) + while ((sd->state != STATE_INIT) && 1 == (ret = xmlTextReaderRead (sd->xtr))) { process_node (r, sd); } - if ( ret != 1) + if (ret != 1) { /* Does not seem to be a gnumeric file */ - xmlFreeTextReader (sd->xtr); - free (r); + gnumeric_unref (&r->spreadsheet); return NULL; } @@ -601,9 +590,9 @@ gnumeric_reopen (struct gnumeric_reader *r, const char *filename, bool show_erro const xmlChar *enc = xmlTextReaderConstEncoding (sd->xtr); xmlCharEncoding xce = xmlParseCharEncoding (CHAR_CAST (const char *, enc)); - if ( XML_CHAR_ENCODING_UTF8 != xce) + if (XML_CHAR_ENCODING_UTF8 != xce) { - /* I have been told that ALL gnumeric files are UTF8 encoded. If that is correct, this + /* I have been told that ALL gnumeric files are UTF8 encoded. If that is correct, this can never happen. */ msg (MW, _("The gnumeric file `%s' is encoded as %s instead of the usual UTF-8 encoding. " "Any non-ascii characters will be incorrectly imported."), @@ -643,9 +632,9 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, r = gnumeric_reopen (r, NULL, true); - if ( opts->cell_range ) + if (opts->cell_range) { - if ( ! convert_cell_ref (opts->cell_range, + if (! convert_cell_ref (opts->cell_range, &r->start_col, &r->start_row, &r->stop_col, &r->stop_row)) { @@ -670,14 +659,14 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, r->proto = NULL; /* Advance to the start of the cells for the target sheet */ - while ( (r->rsd.state != STATE_CELL || r->rsd.row < r->start_row ) + while ((r->rsd.state != STATE_CELL || r->rsd.row < r->start_row) && 1 == (ret = xmlTextReaderRead (r->rsd.xtr))) { xmlChar *value ; process_node (r, &r->rsd); value = xmlTextReaderValue (r->rsd.xtr); - if ( r->rsd.state == STATE_MAXROW && r->rsd.node_type == XML_READER_TYPE_TEXT) + if (r->rsd.state == STATE_MAXROW && r->rsd.node_type == XML_READER_TYPE_TEXT) { n_cases = 1 + _xmlchar_to_int (value) ; } @@ -686,12 +675,12 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, /* If a range has been given, then use that to calculate the number of cases */ - if ( opts->cell_range) + if (opts->cell_range) { n_cases = MIN (n_cases, r->stop_row - r->start_row + 1); } - if ( opts->read_names ) + if (opts->read_names) { r->start_row++; n_cases --; @@ -701,9 +690,9 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, /* Read in the first row of cells, including the headers if read_names was set */ while ( - (( r->rsd.state == STATE_CELLS_START && r->rsd.row <= r->start_row) || r->rsd.state == STATE_CELL ) + ((r->rsd.state == STATE_CELLS_START && r->rsd.row <= r->start_row) || r->rsd.state == STATE_CELL) && (ret = xmlTextReaderRead (r->rsd.xtr)) - ) + ) { int idx; @@ -719,24 +708,24 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, process_node (r, &r->rsd); - if ( r->rsd.row > r->start_row ) + if (r->rsd.row > r->start_row) { xmlChar *attr = xmlTextReaderGetAttribute (r->rsd.xtr, _xml ("ValueType")); - + r->vtype = _xmlchar_to_int (attr); - + xmlFree (attr); break; } - if ( r->rsd.col < r->start_col || + if (r->rsd.col < r->start_col || (r->stop_col != -1 && r->rsd.col > r->stop_col)) continue; idx = r->rsd.col - r->start_col; - if ( idx >= n_var_specs ) + if (idx >= n_var_specs) { int i; var_spec = xrealloc (var_spec, sizeof (*var_spec) * (idx + 1)); @@ -752,14 +741,14 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, var_spec [idx].first_type = type; - if ( r->rsd.node_type == XML_READER_TYPE_TEXT ) + if (r->rsd.node_type == XML_READER_TYPE_TEXT) { xmlChar *value = xmlTextReaderValue (r->rsd.xtr); const char *text = CHAR_CAST (const char *, value); - if ( r->rsd.row < r->start_row) + if (r->rsd.row < r->start_row) { - if ( opts->read_names ) + if (opts->read_names) { var_spec [idx].name = xstrdup (text); } @@ -768,22 +757,22 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, { var_spec [idx].first_value = xmlStrdup (value); - if (-1 == var_spec [idx].width ) + if (-1 == var_spec [idx].width) var_spec [idx].width = (opts->asw == -1) ? ROUND_UP (strlen(text), SPREADSHEET_DEFAULT_WIDTH) : opts->asw; } free (value); } - else if ( r->rsd.node_type == XML_READER_TYPE_ELEMENT + else if (r->rsd.node_type == XML_READER_TYPE_ELEMENT && r->rsd.state == STATE_CELL) { - if ( r->rsd.row == r->start_row ) + if (r->rsd.row == r->start_row) { xmlChar *attr = xmlTextReaderGetAttribute (r->rsd.xtr, _xml ("ValueType")); - if ( NULL == attr || VALUE_STRING != _xmlchar_to_int (attr)) + if (NULL == attr || VALUE_STRING != _xmlchar_to_int (attr)) var_spec [idx].width = 0; free (attr); @@ -793,22 +782,22 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, { const xmlChar *enc = xmlTextReaderConstEncoding (r->rsd.xtr); - if ( enc == NULL) + if (enc == NULL) goto error; /* Create the dictionary and populate it */ spreadsheet->dict = r->dict = dict_create (CHAR_CAST (const char *, enc)); } - for (i = 0 ; i < n_var_specs ; ++i ) + for (i = 0 ; i < n_var_specs ; ++i) { char *name; - if ( (var_spec[i].name == NULL) && (var_spec[i].first_value == NULL)) + if ((var_spec[i].name == NULL) && (var_spec[i].first_value == NULL)) continue; /* Probably no data exists for this variable, so allocate a default width */ - if ( var_spec[i].width == -1 ) + if (var_spec[i].width == -1) var_spec[i].width = SPREADSHEET_DEFAULT_WIDTH; name = dict_make_unique_var_name (r->dict, var_spec[i].name, &vstart); @@ -819,7 +808,7 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, /* Create the first case, and cache it */ r->used_first_case = false; - if ( n_var_specs == 0 ) + if (n_var_specs == 0) { msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."), spreadsheet->file_name); @@ -831,30 +820,30 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, case_set_missing (r->first_case); - for ( i = 0 ; i < n_var_specs ; ++i ) + for (i = 0 ; i < n_var_specs ; ++i) { const struct variable *var; - if ( (var_spec[i].name == NULL) && (var_spec[i].first_value == NULL)) + if ((var_spec[i].name == NULL) && (var_spec[i].first_value == NULL)) continue; var = dict_get_var (r->dict, x++); - + convert_xml_string_to_value (r->first_case, var, - var_spec[i].first_value, + var_spec[i].first_value, var_spec[i].first_type, r->rsd.col + i - 1, r->rsd.row - 1); } - for ( i = 0 ; i < n_var_specs ; ++i ) + for (i = 0 ; i < n_var_specs ; ++i) { free (var_spec[i].first_value); free (var_spec[i].name); } free (var_spec); - + return casereader_create_sequential (NULL, @@ -864,15 +853,13 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, error: - for ( i = 0 ; i < n_var_specs ; ++i ) + for (i = 0 ; i < n_var_specs ; ++i) { free (var_spec[i].first_value); free (var_spec[i].name); } free (var_spec); - dict_destroy (spreadsheet->dict); - spreadsheet->dict = NULL; gnm_file_casereader_destroy (NULL, r); @@ -891,7 +878,7 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_) struct gnumeric_reader *r = r_; int current_row = r->rsd.row; - if ( !r->used_first_case ) + if (!r->used_first_case) { r->used_first_case = true; return r->first_case; @@ -904,7 +891,7 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_) r->start_col = r->rsd.min_col; - while ((r->rsd.state == STATE_CELL || r->rsd.state == STATE_CELLS_START ) + while ((r->rsd.state == STATE_CELL || r->rsd.state == STATE_CELLS_START) && r->rsd.row == current_row && (ret = xmlTextReaderRead (r->rsd.xtr))) { process_node (r, &r->rsd); @@ -919,24 +906,24 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_) xmlFree (attr); } - if ( r->rsd.col < r->start_col || (r->stop_col != -1 && + if (r->rsd.col < r->start_col || (r->stop_col != -1 && r->rsd.col > r->stop_col)) continue; - if ( r->rsd.col - r->start_col >= caseproto_get_n_widths (r->proto)) + if (r->rsd.col - r->start_col >= caseproto_get_n_widths (r->proto)) continue; - if ( r->stop_row != -1 && r->rsd.row > r->stop_row) + if (r->stop_row != -1 && r->rsd.row > r->stop_row) break; - if ( r->rsd.node_type == XML_READER_TYPE_TEXT ) + if (r->rsd.node_type == XML_READER_TYPE_TEXT) { xmlChar *value = xmlTextReaderValue (r->rsd.xtr); const int idx = r->rsd.col - r->start_col; const struct variable *var = dict_get_var (r->dict, idx); - convert_xml_string_to_value (c, var, value, r->vtype, + convert_xml_string_to_value (c, var, value, r->vtype, r->rsd.col, r->rsd.row); xmlFree (value); @@ -951,6 +938,3 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_) return NULL; } } - - -#endif /* GNM_READ_SUPPORT */