From 24c5f7c629e68801492d7ca1766953a2a954a820 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 16 Mar 2014 10:22:34 -0700 Subject: [PATCH] Allow variable labels longer than 255 bytes. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reported by Andre Müller. Bug #41863. --- NEWS | 3 + doc/dev/system-file-format.texi | 2 +- perl-module/PSPP.xs | 2 +- src/data/por-file-reader.c | 4 +- src/data/sys-file-reader.c | 2 +- src/data/variable.c | 65 +++++----------------- src/data/variable.h | 4 +- src/language/data-io/combine-files.c | 4 +- src/language/dictionary/apply-dictionary.c | 4 +- src/language/dictionary/variable-label.c | 4 +- src/language/stats/aggregate.c | 4 +- src/language/stats/descriptives.c | 2 +- src/language/stats/rank.c | 4 +- src/ui/gui/psppire-var-sheet.c | 2 +- 14 files changed, 35 insertions(+), 71 deletions(-) diff --git a/NEWS b/NEWS index fba979bee6..5a0202d844 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,9 @@ Changes since 0.8.2: - SYSFILE INFO now accepts an ENCODING subcommand to specify the character encoding of string data in the system file. + - Variable labels over 255 bytes long are now accepted without + truncation (bug #41863). + - System files that contain duplicate variable names may now be read successfully (bug #41475). diff --git a/doc/dev/system-file-format.texi b/doc/dev/system-file-format.texi index 2d57673308..0f0940b58f 100644 --- a/doc/dev/system-file-format.texi +++ b/doc/dev/system-file-format.texi @@ -328,7 +328,7 @@ This field is present only if @code{has_var_label} is set to 1. It is set to the length, in characters, of the variable label. The documented maximum length varies from 120 to 255 based on SPSS version, but some files have been seen with longer labels. PSPP -accepts longer labels and truncates them to 255 bytes on input. +accepts labels of any length. @item char label[]; This field is present only if @code{has_var_label} is set to 1. It has diff --git a/perl-module/PSPP.xs b/perl-module/PSPP.xs index 0f0d16b343..e600f7b45d 100644 --- a/perl-module/PSPP.xs +++ b/perl-module/PSPP.xs @@ -424,7 +424,7 @@ set_label (var, label) struct variable *var; char *label CODE: - var_set_label (var, label, false); + var_set_label (var, label); void diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c index a4d13ec7bc..0897d77aa2 100644 --- a/src/data/por-file-reader.c +++ b/src/data/por-file-reader.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -750,7 +750,7 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) { char label[256]; read_string (r, label); - var_set_label (v, label, false); /* XXX */ + var_set_label (v, label); /* XXX */ } } diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c index 98af300312..99e8caa6a7 100644 --- a/src/data/sys-file-reader.c +++ b/src/data/sys-file-reader.c @@ -1439,7 +1439,7 @@ parse_variable_records (struct sfm_reader *r, struct dictionary *dict, utf8_label = recode_string_pool ("UTF-8", dict_encoding, rec->label, -1, r->pool); - var_set_label (var, utf8_label, false); + var_set_label (var, utf8_label); } /* Set missing values. */ diff --git a/src/data/variable.c b/src/data/variable.c index c4bab00fc3..8758af35b4 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -80,7 +80,7 @@ struct variable static void var_set_print_format_quiet (struct variable *v, const struct fmt_spec *print); static void var_set_write_format_quiet (struct variable *v, const struct fmt_spec *write); -static bool var_set_label_quiet (struct variable *v, const char *label, bool issue_warning); +static void var_set_label_quiet (struct variable *v, const char *label); static void var_set_name_quiet (struct variable *v, const char *name); /* Creates and returns a new variable with the given NAME and @@ -124,7 +124,7 @@ var_destroy (struct variable *v) mv_destroy (&v->miss); var_clear_short_names (v); val_labs_destroy (v->val_labs); - var_set_label_quiet (v, NULL, false); + var_set_label_quiet (v, NULL); attrset_destroy (var_get_attributes (v)); free (v->name); ds_destroy (&v->name_and_label); @@ -715,49 +715,18 @@ var_get_label (const struct variable *v) /* Sets V's variable label to UTF-8 encoded string LABEL, stripping off leading and trailing white space. If LABEL is a null pointer or if LABEL is an empty string (after stripping white space), then V's variable label (if any) - is removed. - - Variable labels are limited to 255 bytes in V's encoding (as returned by - var_get_encoding()). If LABEL fits within this limit, this function returns - true. Otherwise, the variable label is set to a truncated value, this - function returns false and, if ISSUE_WARNING is true, issues a warning. */ -static bool -var_set_label_quiet (struct variable *v, const char *label, bool issue_warning) + is removed. */ +static void +var_set_label_quiet (struct variable *v, const char *label) { - bool truncated = false; - free (v->label); v->label = NULL; if (label != NULL && label[strspn (label, CC_SPACES)]) - { - const char *dict_encoding = var_get_encoding (v); - struct substring s = ss_cstr (label); - size_t trunc_len; - - if (dict_encoding != NULL) - { - enum { MAX_LABEL_LEN = 255 }; - - trunc_len = utf8_encoding_trunc_len (label, dict_encoding, - MAX_LABEL_LEN); - if (ss_length (s) > trunc_len) - { - if (issue_warning) - msg (SW, _("Truncating variable label for variable `%s' to %d " - "bytes."), var_get_name (v), MAX_LABEL_LEN); - ss_truncate (&s, trunc_len); - truncated = true; - } - } - - v->label = ss_xstrdup (s); - } + v->label = xstrdup (label); ds_destroy (&v->name_and_label); ds_init_empty (&v->name_and_label); - - return truncated; } @@ -765,21 +734,13 @@ var_set_label_quiet (struct variable *v, const char *label, bool issue_warning) /* Sets V's variable label to UTF-8 encoded string LABEL, stripping off leading and trailing white space. If LABEL is a null pointer or if LABEL is an empty string (after stripping white space), then V's variable label (if any) - is removed. - - Variable labels are limited to 255 bytes in V's encoding (as returned by - var_get_encoding()). If LABEL fits within this limit, this function returns - true. Otherwise, the variable label is set to a truncated value, this - function returns false and, if ISSUE_WARNING is true, issues a warning. */ -bool -var_set_label (struct variable *v, const char *label, bool issue_warning) + is removed. */ +void +var_set_label (struct variable *v, const char *label) { struct variable *ov = var_clone (v); - bool truncated = var_set_label_quiet (v, label, issue_warning); - + var_set_label_quiet (v, label); dict_var_changed (v, VAR_TRAIT_LABEL, ov); - - return truncated; } @@ -787,7 +748,7 @@ var_set_label (struct variable *v, const char *label, bool issue_warning) void var_clear_label (struct variable *v) { - var_set_label (v, NULL, false); + var_set_label (v, NULL); } /* Returns true if V has a variable V, @@ -1298,7 +1259,7 @@ var_clone (const struct variable *old_var) var_set_print_format_quiet (new_var, var_get_print_format (old_var)); var_set_write_format_quiet (new_var, var_get_write_format (old_var)); var_set_value_labels_quiet (new_var, var_get_value_labels (old_var)); - var_set_label_quiet (new_var, var_get_label (old_var), false); + var_set_label_quiet (new_var, var_get_label (old_var)); var_set_measure_quiet (new_var, var_get_measure (old_var)); var_set_role_quiet (new_var, var_get_role (old_var)); var_set_display_width_quiet (new_var, var_get_display_width (old_var)); diff --git a/src/data/variable.h b/src/data/variable.h index d77a289afa..25596ad368 100644 --- a/src/data/variable.h +++ b/src/data/variable.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -120,7 +120,7 @@ struct fmt_spec var_default_formats (int width); /* Variable labels. */ const char *var_to_string (const struct variable *); const char *var_get_label (const struct variable *); -bool var_set_label (struct variable *, const char *label, bool issue_warning); +void var_set_label (struct variable *, const char *label); void var_clear_label (struct variable *); bool var_has_label (const struct variable *); diff --git a/src/language/data-io/combine-files.c b/src/language/data-io/combine-files.c index 9d353c81a1..6eb9a3181a 100644 --- a/src/language/data-io/combine-files.c +++ b/src/language/data-io/combine-files.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -590,7 +590,7 @@ merge_dictionary (struct dictionary *const m, struct comb_file *f) if (var_has_missing_values (dv) && !var_has_missing_values (mv)) var_set_missing_values (mv, var_get_missing_values (dv)); if (var_get_label (dv) && !var_get_label (mv)) - var_set_label (mv, var_get_label (dv), false); + var_set_label (mv, var_get_label (dv)); } else mv = dict_clone_var_assert (m, dv); diff --git a/src/language/dictionary/apply-dictionary.c b/src/language/dictionary/apply-dictionary.c index 8531ba56d2..05143fcd58 100644 --- a/src/language/dictionary/apply-dictionary.c +++ b/src/language/dictionary/apply-dictionary.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012, 2014 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 @@ -80,7 +80,7 @@ cmd_apply_dictionary (struct lexer *lexer, struct dataset *ds) } if (var_has_label (s)) - var_set_label (t, var_get_label (s), false); + var_set_label (t, var_get_label (s)); if (var_has_value_labels (s)) { diff --git a/src/language/dictionary/variable-label.c b/src/language/dictionary/variable-label.c index bceb84994e..c4e0df69fe 100644 --- a/src/language/dictionary/variable-label.c +++ b/src/language/dictionary/variable-label.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2010, 2011, 2014 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 @@ -54,7 +54,7 @@ cmd_variable_labels (struct lexer *lexer, struct dataset *ds) } for (i = 0; i < nv; i++) - var_set_label (v[i], lex_tokcstr (lexer), i == 0); + var_set_label (v[i], lex_tokcstr (lexer)); lex_get (lexer); while (lex_token (lexer) == T_SLASH) diff --git a/src/language/stats/aggregate.c b/src/language/stats/aggregate.c index 4d95e62e64..678ea5334a 100644 --- a/src/language/stats/aggregate.c +++ b/src/language/stats/aggregate.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2008, 2009, 2010, 2011, 2012, 2014 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 @@ -639,7 +639,7 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, free (dest[i]); if (dest_label[i]) - var_set_label (destvar, dest_label[i], true); + var_set_label (destvar, dest_label[i]); v->dest = destvar; } diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index f80965616f..a35878b75a 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -748,7 +748,7 @@ setup_z_trns (struct dsc_proc *dsc, struct dataset *ds) dst_var = dict_create_var_assert (dataset_dict (ds), dv->z_name, 0); label = xasprintf (_("Z-score of %s"),var_to_string (dv->v)); - var_set_label (dst_var, label, false); + var_set_label (dst_var, label); free (label); z = &t->z_scores[cnt++]; diff --git a/src/language/stats/rank.c b/src/language/stats/rank.c index 5a849b8cf8..cef51df08c 100644 --- a/src/language/stats/rank.c +++ b/src/language/stats/rank.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc + Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -1123,7 +1123,7 @@ rank_cmd (struct dataset *ds, const struct rank *cmd) var = dict_create_var_assert (d, rs->dest_names[i], 0); var_set_both_formats (var, &dest_format[rs->rfunc]); - var_set_label (var, rs->dest_labels[i], false); + var_set_label (var, rs->dest_labels[i]); iv->output_vars[j] = var; } diff --git a/src/ui/gui/psppire-var-sheet.c b/src/ui/gui/psppire-var-sheet.c index 6fc42c1a36..733a6450c6 100644 --- a/src/ui/gui/psppire-var-sheet.c +++ b/src/ui/gui/psppire-var-sheet.c @@ -252,7 +252,7 @@ on_var_column_edited (GtkCellRendererText *cell, break; case VS_LABEL: - var_set_label (var, new_text, false); + var_set_label (var, new_text); break; case VS_VALUES: -- 2.30.2