From 338fb2a2e84df6427a2fdee6769421f57d5666d8 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 10 Dec 2006 03:42:50 +0000 Subject: [PATCH] Finish converting struct variable to an opaque type. In this phase, we add remaining setter and getter functions, convert the remaining PSPP code to use them, and do a bunch of cleanup. The resulting changes are pervasive but mostly trivial, and only the notable changes are logged. This is patch #5629 on Savannah. --- doc/variables.texi | 3 +- src/data/ChangeLog | 171 +++++- src/data/automake.mk | 7 +- src/data/case.c | 16 +- src/data/case.h | 65 ++- src/data/casefilter.c | 4 +- src/data/cat-routines.h | 2 +- src/data/category.c | 56 +- src/data/data-in.c | 2 +- src/data/data-out.c | 4 +- src/data/dictionary.c | 494 ++++++++-------- src/data/dictionary.h | 2 +- src/data/format.c | 13 +- src/data/format.h | 3 +- src/data/missing-values.c | 2 +- src/data/missing-values.h | 2 +- src/data/por-file-reader.c | 7 +- src/data/por-file-writer.c | 31 +- src/data/procedure.c | 8 +- src/data/sys-file-private.c | 45 ++ src/data/sys-file-private.h | 30 + src/data/sys-file-reader.c | 35 +- src/data/sys-file-writer.c | 59 +- src/data/value-labels.c | 72 +-- src/data/value-labels.h | 8 +- src/data/value.c | 56 ++ src/data/value.h | 35 +- src/data/vardict.h | 39 ++ src/data/variable.c | 641 ++++++++++++++------- src/data/variable.h | 176 +++--- src/data/vector.c | 146 +++++ src/data/vector.h | 42 ++ src/language/control/do-if.c | 2 +- src/language/control/loop.c | 4 +- src/language/data-io/ChangeLog | 4 + src/language/data-io/data-list.c | 16 +- src/language/data-io/get.c | 46 +- src/language/data-io/inpt-pgm.c | 14 +- src/language/data-io/list.q | 24 +- src/language/data-io/matrix-data.c | 37 +- src/language/data-io/print-space.c | 1 + src/language/data-io/print.c | 2 +- src/language/dictionary/ChangeLog | 8 + src/language/dictionary/apply-dictionary.c | 36 +- src/language/dictionary/formats.c | 2 +- src/language/dictionary/missing-values.c | 13 +- src/language/dictionary/modify-variables.c | 8 +- src/language/dictionary/numeric.c | 2 +- src/language/dictionary/split-file.c | 4 +- src/language/dictionary/sys-file-info.c | 36 +- src/language/dictionary/value-labels.c | 4 +- src/language/dictionary/variable-label.c | 11 - src/language/dictionary/vector.c | 2 +- src/language/expressions/evaluate.c | 6 +- src/language/expressions/helpers.h | 1 + src/language/expressions/operations.def | 40 +- src/language/expressions/parse.c | 6 +- src/language/lexer/ChangeLog | 10 + src/language/lexer/variable-parser.c | 46 +- src/language/lexer/variable-parser.h | 3 +- src/language/stats/ChangeLog | 5 + src/language/stats/aggregate.c | 69 +-- src/language/stats/autorecode.c | 10 +- src/language/stats/crosstabs.q | 19 +- src/language/stats/descriptives.c | 24 +- src/language/stats/examine.q | 41 +- src/language/stats/flip.c | 17 +- src/language/stats/frequencies.q | 44 +- src/language/stats/oneway.q | 9 +- src/language/stats/rank.q | 30 +- src/language/stats/regression.q | 47 +- src/language/stats/sort-criteria.c | 2 +- src/language/stats/t-test.q | 29 +- src/language/tests/casefile-test.c | 10 +- src/language/utilities/set.q | 1 + src/language/xforms/ChangeLog | 5 + src/language/xforms/compute.c | 42 +- src/language/xforms/count.c | 6 +- src/language/xforms/recode.c | 28 +- src/libpspp/ChangeLog | 4 + src/libpspp/misc.h | 3 - src/math/design-matrix.c | 7 +- src/math/group.c | 10 +- src/math/levene.c | 8 +- src/math/sort.c | 7 +- src/output/table.c | 2 +- src/ui/flexifile.c | 2 +- src/ui/gui/helper.c | 2 + src/ui/gui/missing-val-dialog.c | 2 +- src/ui/gui/psppire-case-file.c | 6 +- src/ui/gui/psppire-data-store.c | 6 +- src/ui/gui/psppire-var-store.c | 2 +- src/ui/gui/psppire-variable.c | 40 +- src/ui/gui/psppire-variable.h | 2 + src/ui/gui/val-labs-dialog.c | 2 + src/ui/gui/var-sheet.c | 2 +- src/ui/gui/var-type-dialog.c | 4 +- 97 files changed, 1966 insertions(+), 1247 deletions(-) create mode 100644 src/data/sys-file-private.c create mode 100644 src/data/sys-file-private.h create mode 100644 src/data/value.c create mode 100644 src/data/vardict.h create mode 100644 src/data/vector.c create mode 100644 src/data/vector.h diff --git a/doc/variables.texi b/doc/variables.texi index 91b07112..afca8cbf 100644 --- a/doc/variables.texi +++ b/doc/variables.texi @@ -446,7 +446,8 @@ to be created as numeric variables with print and write format F8.2. Variable names including numeric suffixes may not exceed 64 characters in length, and none of the variables may exist prior to @cmd{VECTOR}. -All the variables in a vector must be the same type. +All the variables in a vector must be the same type. String variables +in a vector must all have the same width. Vectors created with @cmd{VECTOR} disappear after any procedure or procedure-like command is executed. The variables contained in the diff --git a/src/data/ChangeLog b/src/data/ChangeLog index d64e8980..e4306829 100644 --- a/src/data/ChangeLog +++ b/src/data/ChangeLog @@ -1,3 +1,165 @@ +Sat Dec 9 18:05:59 2006 Ben Pfaff + + * data-out.c (output_scientific): Fix bad assumption that "buf" is + null-terminated. + +Sat Dec 9 17:23:23 2006 Ben Pfaff + + Finish converting struct variable to an opaque type. In this + phase, we add remaining setter and getter functions, convert the + remaining PSPP code to use them, and do a bunch of cleanup. The + resulting changes are pervasive but mostly trivial, and only the + notable changes are logged. + + * automake.mk (src_data_libdata_a_SOURCES): Add the new source + files. + + * case.c (case_data): Renamed case_data_idx. + (case_num): Renamed case_num_idx. + (case_str): Renamed case_str_idx. + (case_data_rw): Renamed case_data_rw_idx. + + * case.h (case_data): New function with old name and an interface + that takes a variable instead of an index, which is easier to + use. Updated all callers to use the new interface, or to use the + new *_idx function (see above). + (case_num): Ditto. + (case_str): Ditto. + (case_data_rw): Ditto. + + * category.c (cat_stored_values_destroy): Changed interface to + take a struct cat_vals * instead of a struct variable *. + + * dictionary.c (dict_clone): Use new vector_clone function. + (dict_clear) Use new var_destroy function. + (add_var) New function. + (dict_create_var) Rewrite in terms of dict_create_var_assert. + (dict_create_var_assert) Rewrite in terms of add_var. + (dict_clone_var) Rewrite in terms of dict_clone_var_assert. + (dict_clone_var_assert) Rewrite in terms of var_clone, add_var. + (dict_lookup_var) Use new var_create, var_destroy functions. + (dict_contains_var) Rewrite in terms of new vardict functionality. + (set_var_dict_index) New function. + (set_var_case_index) New function. + (reindex_vars) New function. + (dict_delete_var) Rewrite in terms of new vardict functionality. + (dict_reorder_var) Ditto. + (dict_reorder_vars) Ditto. + (rename_var) New function. + (dict_rename_var) Use rename_var. + (dict_rename_vars) Use pool to simplify code. Use rename_var. + (dict_get_compacted_idx_to_fv) Rename + dict_get_compacted_dict_index_to_case_index, update callers. + (dict_create_vector) Use new vector_create function. + (dict_clear_vectors) Use new vector_destroy function. + (set_var_short_name_suffix) Move here from variable.c, renamed + from var_set_short_name_suffix, make static, update caller. + + * sys-file-private.c: New file. + (sfm_width_to_bytes) Moved here from variable.c, renamed from + width_to_bytes, update callers. + + * sys-file-private.h: New file. Later it will supplant + sfm-private.h; for now it supplements it. + (macro MIN_VERY_LONG_STRING) New macro. + (macro EFFECTIVE_LONG_STRING_LENGTH) New macro, from value.h. + + * sys-file-reader.c: Use MIN_VERY_LONG_STRING - 1 where + MAX_LONG_STRING was used before. + + * sys-file-writer.c: Ditto. + + * value-labels.c: Change the paradigm here to be that a null + pointer is OK for a struct val_labs * in most cases; it just + represents an empty set of value labels. + (val_labs_copy) A copy of a null set is a null set. + (val_labs_count) A null set has 0 labels. + (val_labs_replace) Change return type to void. Rewrite for + simplicity. + (val_labs_find) A null set does not contain the value. + (value_to_string) Moved to variable.c, renamed var_get_value_name, + transposed argument order, updated all callers. + + * value.c: New file. + (value_dup) Moved here from variable.c. + (compare_values) Ditto. + (hash_value) Ditto. + + * value.h: (macro MAX_SHORT_STRING) Rewrote for simplicity. + (macro MAX_LONG_STRING) Removed, because it was only interesting + for system files, not for general code. + (macro MAX_VERY_LONG_STRING) Ditto. + (macro EFFECTIVE_LONG_STRING_LENGTH) Moved to sys-file-private.h. + (macro MAX_ELEMS_PER_VALUE) Removed, as it was unused. + + * vardict.h: New file, for an interface between variables and + their dictionaries. + + * variable.c: A lot of functions were moved around, for better + organization. + (struct variable) Move definition here, from variable.h. + (var_type_adj) Removed--makes i18n hard. + (var_type_noun) Ditto. + (var_create) New function. + (var_clone) New function. + (var_destroy) New function. + (var_set_name) Assert that variable is not in a dictionary. + (compare_var_names) Rename compare_vars_by_name and fix a couple + of callers who thought the args were strings. + (hash_var_name) Rename hash_var_by_name. + (compare_var_ptr_names) Rename compare_var_ptrs_by_name. + (hash_var_ptr_name) Rename hash_var_ptr_by_name. + (var_is_very_long_string) Removed, because it was only interesting + to system file code. + (var_set_missing_values) Allow the argument to be the wrong width, + as long as we can resize it. Simplify callers who were doing the + resizing themselves. + (var_get_value_labels) New function. + (var_has_value_labels) New function. + (var_set_value_labels) New function. + (alloc_value_labels) New function. + (var_add_value_label) New function. + (var_replace_value_label) New function. + (var_clear_value_labels) New function. + (var_lookup_value_label) New function. + (var_get_value_name) Moved here from variable.c, renamed from + var_get_value_name, transposed argument order, updated all + callers. + (var_to_string) Moved here, from variable-label.c. + (var_set_leave) New function. + (var_get_leave) New function. + (var_must_leave) New function. + (var_set_short_name_suffix) Moved to dictionary.c, renamed + set_var_short_name_suffix. + (var_get_dict_index) New function. + (var_get_case_index) New function. + (var_get_obs_vals) New function. + (var_set_obs_vals) New function. + (var_has_obs_vals) New function. + (var_get_vardict) New function. + (var_set_vardict) New function. + (var_has_vardict) New function. + (var_clear_vardict) New function. + (value_dup) Moved to value.c. + (compare_values) Ditto. + (hash_value) Ditto. + + * variable.h: (enum NUMERIC) Rename VAR_NUMERIC, update all users. + (enum ALPHA) Rename VAR_STRING, update all users. + + * vector.c: New file. + (struct vector) Moved here, from variable.h. + (check_widths) New function. + (vector_create) New function. + (vector_clone) New function. + (vector_destroy) New function. + (vector_get_name) New function. + (vector_get_var) New function. + (vector_get_var_cnt) New function. + (compare_vector_ptrs_by_name) New function. + + * vector.h: New file. + Sun Dec 10 11:32:56 WST 2006 John Darrington * casefilter.c (casefilter_variable_missing): Avoided comparision of @@ -23,10 +185,11 @@ Thu Dec 7 15:22:38 WST 2006 John Darrington Mon Dec 4 22:20:17 2006 Ben Pfaff - Start converting struct variable to an opaque. In this phase, we - add a bunch of setter and getter functions and convert most of the - PSPP code to use them. The resulting changes are pervasive but - mostly trivial, and only the notable changes are logged. + Start converting struct variable to an opaque type. In this + phase, we add a bunch of setter and getter functions and convert + most of the PSPP code to use them. The resulting changes are + pervasive but mostly trivial, and only the notable changes are + logged. * format.c (fmt_equal): New function. diff --git a/src/data/automake.mk b/src/data/automake.mk index 05276465..48db0f6e 100644 --- a/src/data/automake.mk +++ b/src/data/automake.mk @@ -60,14 +60,19 @@ src_data_libdata_a_SOURCES = \ src/data/sfm-private.h \ src/data/storage-stream.c \ src/data/storage-stream.h \ + src/data/sys-file-private.c \ + src/data/sys-file-private.h \ src/data/sys-file-reader.c \ src/data/sys-file-reader.h \ src/data/sys-file-writer.c \ src/data/sys-file-writer.h \ src/data/transformations.c \ src/data/transformations.h \ + src/data/value.c \ src/data/value.h \ src/data/value-labels.c \ src/data/value-labels.h \ src/data/variable.h \ - src/data/variable.c + src/data/variable.c \ + src/data/vector.c \ + src/data/vector.h diff --git a/src/data/case.c b/src/data/case.c index e41c0e22..20ed8bae 100644 --- a/src/data/case.c +++ b/src/data/case.c @@ -255,7 +255,7 @@ case_from_values (struct ccase *c, const union value *input, element of C numbered IDX. The caller must not modify the returned data. */ const union value * -case_data (const struct ccase *c, size_t idx) +case_data_idx (const struct ccase *c, size_t idx) { assert (c != NULL); assert (c->case_data != NULL); @@ -270,7 +270,7 @@ case_data (const struct ccase *c, size_t idx) /* Returns the numeric value of the `union value' in C numbered IDX. */ double -case_num (const struct ccase *c, size_t idx) +case_num_idx (const struct ccase *c, size_t idx) { assert (c != NULL); assert (c->case_data != NULL); @@ -287,7 +287,7 @@ case_num (const struct ccase *c, size_t idx) (Note that the value is not null-terminated.) The caller must not modify the return value. */ const char * -case_str (const struct ccase *c, size_t idx) +case_str_idx (const struct ccase *c, size_t idx) { assert (c != NULL); assert (c->case_data != NULL); @@ -303,7 +303,7 @@ case_str (const struct ccase *c, size_t idx) element of C numbered IDX. The caller is allowed to modify the returned data. */ union value * -case_data_rw (struct ccase *c, size_t idx) +case_data_rw_idx (struct ccase *c, size_t idx) { assert (c != NULL); assert (c->case_data != NULL); @@ -342,16 +342,16 @@ case_compare_2dict (const struct ccase *ca, const struct ccase *cb, if (var_get_width (va) == 0) { - double af = case_num (ca, va->fv); - double bf = case_num (cb, vb->fv); + double af = case_num (ca, va); + double bf = case_num (cb, vb); if (af != bf) return af > bf ? 1 : -1; } else { - const char *as = case_str (ca, va->fv); - const char *bs = case_str (cb, vb->fv); + const char *as = case_str (ca, va); + const char *bs = case_str (cb, vb); int cmp = memcmp (as, bs, var_get_width (va)); if (cmp != 0) diff --git a/src/data/case.h b/src/data/case.h index df2f0356..23862b06 100644 --- a/src/data/case.h +++ b/src/data/case.h @@ -23,6 +23,7 @@ #include #include #include "value.h" +#include "variable.h" /* Opaque structure that represents a case. Use accessor functions instead of accessing any members directly. Use @@ -68,11 +69,19 @@ CASE_INLINE void case_to_values (const struct ccase *, union value *, size_t); CASE_INLINE void case_from_values (struct ccase *, const union value *, size_t); -CASE_INLINE const union value *case_data (const struct ccase *, size_t idx); -CASE_INLINE double case_num (const struct ccase *, size_t idx); -CASE_INLINE const char *case_str (const struct ccase *, size_t idx); +static inline const union value *case_data (const struct ccase *, + const struct variable *); +static inline double case_num (const struct ccase *, const struct variable *); +static inline const char *case_str (const struct ccase *, + const struct variable *); +static inline union value *case_data_rw (struct ccase *, + const struct variable *); -CASE_INLINE union value *case_data_rw (struct ccase *, size_t idx); +CASE_INLINE const union value *case_data_idx (const struct ccase *, + size_t idx); +CASE_INLINE double case_num_idx (const struct ccase *, size_t idx); +CASE_INLINE const char *case_str_idx (const struct ccase *, size_t idx); +CASE_INLINE union value *case_data_rw_idx (struct ccase *, size_t idx); struct variable; int case_compare (const struct ccase *, const struct ccase *, @@ -161,25 +170,25 @@ case_from_values (struct ccase *c, const union value *input, } static inline const union value * -case_data (const struct ccase *c, size_t idx) +case_data_idx (const struct ccase *c, size_t idx) { return &c->case_data->values[idx]; } static inline double -case_num (const struct ccase *c, size_t idx) +case_num_idx (const struct ccase *c, size_t idx) { return c->case_data->values[idx].f; } static inline const char * -case_str (const struct ccase *c, size_t idx) +case_str_idx (const struct ccase *c, size_t idx) { return c->case_data->values[idx].s; } static inline union value * -case_data_rw (struct ccase *c, size_t idx) +case_data_rw_idx (struct ccase *c, size_t idx) { if (c->case_data->ref_cnt > 1) case_unshare (c); @@ -187,4 +196,44 @@ case_data_rw (struct ccase *c, size_t idx) } #endif /* !DEBUGGING */ +/* Returns a pointer to the `union value' used for the + element of C for variable V. + Case C must be drawn from V's dictionary. + The caller must not modify the returned data. */ +static inline const union value * +case_data (const struct ccase *c, const struct variable *v) +{ + return case_data_idx (c, var_get_case_index (v)); +} + +/* Returns the numeric value of the `union value' in C for + variable V. + Case C must be drawn from V's dictionary. */ +static inline double +case_num (const struct ccase *c, const struct variable *v) +{ + return case_num_idx (c, var_get_case_index (v)); +} + +/* Returns the string value of the `union value' in C for + variable V. + Case C must be drawn from V's dictionary. + (Note that the value is not null-terminated.) + The caller must not modify the return value. */ +static inline const char * +case_str (const struct ccase *c, const struct variable *v) +{ + return case_str_idx (c, var_get_case_index (v)); +} + +/* Returns a pointer to the `union value' used for the + element of C for variable V. + Case C must be drawn from V's dictionary. + The caller is allowed to modify the returned data. */ +static inline union value * +case_data_rw (struct ccase *c, const struct variable *v) +{ + return case_data_rw_idx (c, var_get_case_index (v)); +} + #endif /* case.h */ diff --git a/src/data/casefilter.c b/src/data/casefilter.c index 14941333..9049c517 100644 --- a/src/data/casefilter.c +++ b/src/data/casefilter.c @@ -58,9 +58,9 @@ casefilter_variable_missing (const struct casefilter *filter, const struct ccase *c, const struct variable *var) { - const union value *val = case_data (c, var->fv) ; + const union value *val = case_data (c, var) ; - if ( var_get_type (var) != ALPHA && val->f == SYSMIS ) + if ( var_is_numeric (var) && val->f == SYSMIS ) return true; if ( filter->exclude_user_missing && diff --git a/src/data/cat-routines.h b/src/data/cat-routines.h index 43cfcccd..654ef44d 100644 --- a/src/data/cat-routines.h +++ b/src/data/cat-routines.h @@ -49,5 +49,5 @@ void cat_value_update (struct variable *, const union value *); void cat_create_value_matrix (struct variable *); -void cat_stored_values_destroy (struct variable *); +void cat_stored_values_destroy (struct cat_vals *); #endif diff --git a/src/data/category.c b/src/data/category.c index 21506ed8..d320cea2 100644 --- a/src/data/category.c +++ b/src/data/category.c @@ -42,6 +42,7 @@ #include #include #include "cat-routines.h" +#include "value.h" #include "variable.h" #define N_INITIAL_CATEGORIES 1 @@ -49,30 +50,24 @@ void cat_stored_values_create (struct variable *v) { - if (v->obs_vals == NULL) + if (!var_has_obs_vals (v)) { - v->obs_vals = xmalloc (sizeof (*v->obs_vals)); - v->obs_vals->n_categories = 0; - v->obs_vals->n_allocated_categories = N_INITIAL_CATEGORIES; - v->obs_vals->vals = - xnmalloc (N_INITIAL_CATEGORIES, sizeof *v->obs_vals->vals); + struct cat_vals *obs_vals = xmalloc (sizeof *obs_vals); + obs_vals->n_categories = 0; + obs_vals->n_allocated_categories = N_INITIAL_CATEGORIES; + obs_vals->vals = xnmalloc (N_INITIAL_CATEGORIES, sizeof *obs_vals->vals); + var_set_obs_vals (v, obs_vals); } } void -cat_stored_values_destroy (struct variable *v) +cat_stored_values_destroy (struct cat_vals *obs_vals) { - assert (v != NULL); - - if (v->obs_vals != NULL) + if (obs_vals != NULL) { - if (v->obs_vals->n_allocated_categories > 0) - { - free (v->obs_vals->vals); - v->obs_vals->vals = NULL; - } - free (v->obs_vals); - v->obs_vals = NULL; + if (obs_vals->n_allocated_categories > 0) + free (obs_vals->vals); + free (obs_vals); } } @@ -82,15 +77,13 @@ cat_stored_values_destroy (struct variable *v) size_t cat_value_find (const struct variable *v, const union value *val) { + struct cat_vals *obs_vals = var_get_obs_vals (v); size_t i; const union value *candidate; - assert (val != NULL); - assert (v != NULL); - assert (v->obs_vals != NULL); - for (i = 0; i < v->obs_vals->n_categories; i++) + for (i = 0; i < obs_vals->n_categories; i++) { - candidate = v->obs_vals->vals + i; + candidate = obs_vals->vals + i; assert (candidate != NULL); if (!compare_values (candidate, val, var_get_width (v))) { @@ -106,13 +99,9 @@ cat_value_find (const struct variable *v, const union value *val) void cat_value_update (struct variable *v, const union value *val) { - struct cat_vals *cv; - if (var_is_alpha (v)) { - assert (val != NULL); - assert (v != NULL); - cv = v->obs_vals; + struct cat_vals *cv = var_get_obs_vals (v); if (cat_value_find (v, val) == CAT_VALUE_NOT_FOUND) { if (cv->n_categories >= cv->n_allocated_categories) @@ -131,15 +120,8 @@ cat_value_update (struct variable *v, const union value *val) union value * cat_subscript_to_value (const size_t s, struct variable *v) { - assert (v->obs_vals != NULL); - if (s < v->obs_vals->n_categories) - { - return (v->obs_vals->vals + s); - } - else - { - return NULL; - } + struct cat_vals *obs_vals = var_get_obs_vals (v); + return s < obs_vals->n_categories ? obs_vals->vals + s : NULL; } /* @@ -148,6 +130,6 @@ cat_subscript_to_value (const size_t s, struct variable *v) size_t cat_get_n_categories (const struct variable *v) { - return v->obs_vals->n_categories; + return var_get_obs_vals (v)->n_categories; } diff --git a/src/data/data-in.c b/src/data/data-in.c index 7ecded2f..5fb5d4d3 100644 --- a/src/data/data-in.c +++ b/src/data/data-in.c @@ -34,7 +34,7 @@ #include "calendar.h" #include "identifier.h" #include "settings.h" -#include "variable.h" +#include "value.h" #include #include diff --git a/src/data/data-out.c b/src/data/data-out.c index e7c709f6..544f2a54 100644 --- a/src/data/data-out.c +++ b/src/data/data-out.c @@ -32,7 +32,7 @@ #include "calendar.h" #include "format.h" #include "settings.h" -#include "variable.h" +#include "value.h" #include #include @@ -709,8 +709,8 @@ output_scientific (double number, const struct fmt_spec *format, p = mempset (p, ' ', ss_length (style->neg_suffix)); assert (p == buf + format->w); + memcpy (output, buf, format->w); - buf_copy_str_lpad (output, format->w, buf); return true; } diff --git a/src/data/dictionary.c b/src/data/dictionary.c index 73a9da9a..e312d2e9 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -29,13 +29,16 @@ #include "category.h" #include "settings.h" #include "value-labels.h" +#include "vardict.h" #include "variable.h" +#include "vector.h" #include #include #include #include #include #include +#include #include #include "minmax.h" @@ -69,7 +72,8 @@ dict_create (void) d->var = NULL; d->var_cnt = d->var_cap = 0; - d->name_tab = hsh_create (8, compare_var_names, hash_var_name, NULL, NULL); + d->name_tab = hsh_create (8, compare_vars_by_name, hash_var_by_name, + NULL, NULL); d->next_value_idx = 0; d->split = NULL; d->split_cnt = 0; @@ -125,19 +129,8 @@ dict_clone (const struct dictionary *s) d->vector_cnt = s->vector_cnt; d->vector = xnmalloc (d->vector_cnt, sizeof *d->vector); - for (i = 0; i < s->vector_cnt; i++) - { - struct vector *sv = s->vector[i]; - struct vector *dv = d->vector[i] = xmalloc (sizeof *dv); - int j; - - dv->idx = i; - strcpy (dv->name, sv->name); - dv->cnt = sv->cnt; - dv->var = xnmalloc (dv->cnt, sizeof *dv->var); - for (j = 0; j < dv->cnt; j++) - dv->var[j] = d->var[sv->var[j]->index]; - } + for (i = 0; i < s->vector_cnt; i++) + d->vector[i] = vector_clone (s->vector[i], s, d); return d; } @@ -153,14 +146,10 @@ dict_clear (struct dictionary *d) assert (d != NULL); - for (i = 0; i < d->var_cnt; i++) + for (i = 0; i < d->var_cnt; i++) { - struct variable *v = d->var[i]; - var_clear_aux (v); - val_labs_destroy (v->val_labs); - var_clear_label (v); - free (v->label); - free (v); + var_clear_vardict (d->var[i]); + var_destroy (d->var[i]); } free (d->var); d->var = NULL; @@ -214,9 +203,9 @@ dict_get_var_cnt (const struct dictionary *d) return d->var_cnt; } -/* Returns the variable in D with index IDX, which must be - between 0 and the count returned by dict_get_var_cnt(), - exclusive. */ +/* Returns the variable in D with dictionary index IDX, which + must be between 0 and the count returned by + dict_get_var_cnt(), exclusive. */ struct variable * dict_get_var (const struct dictionary *d, size_t idx) { @@ -264,55 +253,14 @@ dict_get_vars (const struct dictionary *d, struct variable ***vars, assert (*cnt == count); } - -/* Creates and returns a new variable in D with the given NAME - and WIDTH. Returns a null pointer if the given NAME would - duplicate that of an existing variable in the dictionary. */ -struct variable * -dict_create_var (struct dictionary *d, const char *name, int width) +static struct variable * +add_var (struct dictionary *d, struct variable *v) { - struct variable *v; - - assert (d != NULL); - assert (name != NULL); - - assert (width >= 0 && width <= MAX_STRING); - - assert (var_is_plausible_name(name,0)); - - /* Make sure there's not already a variable by that name. */ - if (dict_lookup_var (d, name) != NULL) - return NULL; - - /* Allocate and initialize variable. */ - v = xmalloc (sizeof *v); - var_set_name (v, name); - v->width = width; - v->fv = d->next_value_idx; - v->leave = dict_class_from_id (var_get_name (v)) == DC_SCRATCH; - v->index = d->var_cnt; - mv_init (&v->miss, width); - if (var_is_numeric (v)) - { - v->print = fmt_for_output (FMT_F, 8, 2); - v->alignment = ALIGN_RIGHT; - v->display_width = 8; - v->measure = MEASURE_SCALE; - } - else - { - v->print = fmt_for_output (FMT_A, var_get_width (v), 0); - v->alignment = ALIGN_LEFT; - v->display_width = 8; - v->measure = MEASURE_NOMINAL; - } - v->write = v->print; - v->val_labs = val_labs_create (var_get_width (v)); - v->label = NULL; - var_clear_short_name (v); - v->aux = NULL; - v->aux_dtor = NULL; - v->obs_vals = NULL; + /* Add dictionary info to variable. */ + struct vardict_info vdi; + vdi.case_index = d->next_value_idx; + vdi.dict_index = d->var_cnt; + var_set_vardict (v, &vdi); /* Update dictionary. */ if (d->var_cnt >= d->var_cap) @@ -320,8 +268,7 @@ dict_create_var (struct dictionary *d, const char *name, int width) d->var_cap = 8 + 2 * d->var_cap; d->var = xnrealloc (d->var, d->var_cap, sizeof *d->var); } - d->var[v->index] = v; - d->var_cnt++; + d->var[d->var_cnt++] = v; hsh_force_insert (d->name_tab, v); d->next_value_idx += var_get_value_cnt (v); @@ -329,67 +276,53 @@ dict_create_var (struct dictionary *d, const char *name, int width) return v; } +/* Creates and returns a new variable in D with the given NAME + and WIDTH. Returns a null pointer if the given NAME would + duplicate that of an existing variable in the dictionary. */ +struct variable * +dict_create_var (struct dictionary *d, const char *name, int width) +{ + return (dict_lookup_var (d, name) == NULL + ? dict_create_var_assert (d, name, width) + : NULL); +} + /* Creates and returns a new variable in D with the given NAME and WIDTH. Assert-fails if the given NAME would duplicate that of an existing variable in the dictionary. */ struct variable * dict_create_var_assert (struct dictionary *d, const char *name, int width) { - struct variable *v = dict_create_var (d, name, width); - assert (v != NULL); - return v; + assert (dict_lookup_var (d, name) == NULL); + return add_var (d, var_create (name, width)); } /* Creates and returns a new variable in D with name NAME, as a - copy of existing variable OV, which need not be in D or in any - dictionary. Returns a null pointer if the given NAME would - duplicate that of an existing variable in the dictionary. */ + copy of existing variable OLD_VAR, which need not be in D or + in any dictionary. Returns a null pointer if the given NAME + would duplicate that of an existing variable in the + dictionary. */ struct variable * -dict_clone_var (struct dictionary *d, const struct variable *ov, +dict_clone_var (struct dictionary *d, const struct variable *old_var, const char *name) { - struct variable *nv; - - assert (d != NULL); - assert (ov != NULL); - assert (name != NULL); - - assert (strlen (name) >= 1); - assert (strlen (name) <= LONG_NAME_LEN); - - nv = dict_create_var (d, name, var_get_width (ov)); - if (nv == NULL) - return NULL; - - /* Copy most members not copied via dict_create_var(). - short_name[] is intentionally not copied, because there is - no reason to give a new variable with potentially a new name - the same short name. */ - nv->leave = var_get_leave (ov); - var_set_missing_values (nv, var_get_missing_values (ov)); - var_set_print_format (nv, var_get_print_format (ov)); - var_set_write_format (nv, var_get_write_format (ov)); - val_labs_destroy (nv->val_labs); - nv->val_labs = val_labs_copy (ov->val_labs); - var_set_label (nv, var_get_label (ov)); - var_set_measure (nv, var_get_measure (ov)); - var_set_display_width (nv, var_get_display_width (ov)); - var_set_alignment (nv, var_get_alignment (ov)); - - return nv; + return (dict_lookup_var (d, name) == NULL + ? dict_clone_var_assert (d, old_var, name) + : NULL); } /* Creates and returns a new variable in D with name NAME, as a - copy of existing variable OV, which need not be in D or in any - dictionary. Assert-fails if the given NAME would duplicate - that of an existing variable in the dictionary. */ + copy of existing variable OLD_VAR, which need not be in D or + in any dictionary. Assert-fails if the given NAME would + duplicate that of an existing variable in the dictionary. */ struct variable * -dict_clone_var_assert (struct dictionary *d, const struct variable *ov, +dict_clone_var_assert (struct dictionary *d, const struct variable *old_var, const char *name) { - struct variable *v = dict_clone_var (d, ov, name); - assert (v != NULL); - return v; + struct variable *new_var = var_clone (old_var); + assert (dict_lookup_var (d, name) == NULL); + var_set_name (new_var, name); + return add_var (d, new_var); } /* Returns the variable named NAME in D, or a null pointer if no @@ -397,13 +330,10 @@ dict_clone_var_assert (struct dictionary *d, const struct variable *ov, struct variable * dict_lookup_var (const struct dictionary *d, const char *name) { - struct variable v; - - assert (d != NULL); - assert (name != NULL); - - str_copy_trunc (v.name, sizeof v.name, name); - return hsh_find (d->name_tab, &v); + struct variable *target = var_create (name, 0); + struct variable *result = hsh_find (d->name_tab, target); + var_destroy (target); + return result; } /* Returns the variable named NAME in D. Assert-fails if no @@ -421,10 +351,15 @@ dict_lookup_var_assert (const struct dictionary *d, const char *name) bool dict_contains_var (const struct dictionary *d, const struct variable *v) { - assert (d != NULL); - assert (v != NULL); - - return v->index >= 0 && v->index < d->var_cnt && d->var[v->index] == v; + if (var_has_vardict (v)) + { + const struct vardict_info *vdi = var_get_vardict (v); + return (vdi->dict_index >= 0 + && vdi->dict_index < d->var_cnt + && d->var[vdi->dict_index] == v); + } + else + return false; } /* Compares two double pointers to variables, which should point @@ -438,6 +373,35 @@ compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED) return *a < *b ? -1 : *a > *b; } +/* Sets the dict_index in V's vardict to DICT_INDEX. */ +static void +set_var_dict_index (struct variable *v, int dict_index) +{ + struct vardict_info vdi = *var_get_vardict (v); + vdi.dict_index = dict_index; + var_set_vardict (v, &vdi); +} + +/* Sets the case_index in V's vardict to DICT_INDEX. */ +static void +set_var_case_index (struct variable *v, int case_index) +{ + struct vardict_info vdi = *var_get_vardict (v); + vdi.case_index = case_index; + var_set_vardict (v, &vdi); +} + +/* Re-sets the dict_index in the dictionary variables with + indexes from FROM to TO (exclusive). */ +static void +reindex_vars (struct dictionary *d, size_t from, size_t to) +{ + size_t i; + + for (i = from; i < to; i++) + set_var_dict_index (d->var[i], i); +} + /* Deletes variable V from dictionary D and frees V. This is a very bad idea if there might be any pointers to V @@ -453,10 +417,8 @@ compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED) void dict_delete_var (struct dictionary *d, struct variable *v) { - size_t i; + int dict_index = var_get_dict_index (v); - assert (d != NULL); - assert (v != NULL); assert (dict_contains_var (d, v)); /* Delete aux data. */ @@ -472,21 +434,18 @@ dict_delete_var (struct dictionary *d, struct variable *v) dict_clear_vectors (d); /* Remove V from var array. */ - remove_element (d->var, d->var_cnt, sizeof *d->var, v->index); + remove_element (d->var, d->var_cnt, sizeof *d->var, dict_index); d->var_cnt--; - /* Update index. */ - for (i = v->index; i < d->var_cnt; i++) - d->var[i]->index = i; + /* Update dict_index for each affected variable. */ + reindex_vars (d, dict_index, d->var_cnt); /* Update name hash. */ hsh_force_delete (d->name_tab, v); /* Free memory. */ - val_labs_destroy (v->val_labs); - cat_stored_values_destroy (v); - free (v->label); - free (v); + var_clear_vardict (v); + var_destroy (v); } /* Deletes the COUNT variables listed in VARS from D. This is @@ -525,23 +484,13 @@ dict_delete_scratch_vars (struct dictionary *d) if any, retain their relative positions. Runs in time linear in the distance moved. */ void -dict_reorder_var (struct dictionary *d, struct variable *v, - size_t new_index) +dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index) { - size_t min_idx, max_idx; - size_t i; - - assert (d != NULL); - assert (v != NULL); - assert (dict_contains_var (d, v)); - assert (new_index < d->var_cnt); + size_t old_index = var_get_dict_index (v); - move_element (d->var, d->var_cnt, sizeof *d->var, v->index, new_index); - - min_idx = MIN (v->index, new_index); - max_idx = MAX (v->index, new_index); - for (i = min_idx; i <= max_idx; i++) - d->var[i]->index = i; + assert (new_index < d->var_cnt); + move_element (d->var, d->var_cnt, sizeof *d->var, old_index, new_index); + reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1); } /* Reorders the variables in D, placing the COUNT variables @@ -563,22 +512,37 @@ dict_reorder_vars (struct dictionary *d, memcpy (new_var, order, count * sizeof *new_var); for (i = 0; i < count; i++) { - assert (d->var[order[i]->index] != NULL); - d->var[order[i]->index] = NULL; - order[i]->index = i; + size_t index = var_get_dict_index (order[i]); + assert (d->var[index] == order[i]); + d->var[index] = NULL; + set_var_dict_index (order[i], i); } for (i = 0; i < d->var_cnt; i++) if (d->var[i] != NULL) { assert (count < d->var_cnt); new_var[count] = d->var[i]; - new_var[count]->index = count; + set_var_dict_index (new_var[count], count); count++; } free (d->var); d->var = new_var; } +/* Changes the name of variable V in dictionary D to NEW_NAME. */ +static void +rename_var (struct dictionary *d, struct variable *v, const char *new_name) +{ + struct vardict_info vdi; + + assert (dict_contains_var (d, v)); + + vdi = *var_get_vardict (v); + var_clear_vardict (v); + var_set_name (v, new_name); + var_set_vardict (v, &vdi); +} + /* Changes the name of V in D to name NEW_NAME. Assert-fails if a variable named NEW_NAME is already in D, except that NEW_NAME may be the same as V's existing name. */ @@ -586,16 +550,11 @@ void dict_rename_var (struct dictionary *d, struct variable *v, const char *new_name) { - assert (d != NULL); - assert (v != NULL); - assert (new_name != NULL); - assert (var_is_plausible_name (new_name, false)); - assert (dict_contains_var (d, v)); - assert (!compare_var_names (var_get_name (v), new_name, NULL) + assert (!strcasecmp (var_get_name (v), new_name) || dict_lookup_var (d, new_name) == NULL); hsh_force_delete (d->name_tab, v); - var_set_name (v, new_name); + rename_var (d, v, new_name); hsh_force_insert (d->name_tab, v); if (get_algorithm () == ENHANCED) @@ -610,73 +569,62 @@ dict_rename_var (struct dictionary *d, struct variable *v, is returned. */ bool dict_rename_vars (struct dictionary *d, - struct variable **vars, char **new_names, - size_t count, char **err_name) + struct variable **vars, char **new_names, size_t count, + char **err_name) { + struct pool *pool; char **old_names; size_t i; - bool success = true; - assert (d != NULL); assert (count == 0 || vars != NULL); assert (count == 0 || new_names != NULL); + /* Save the names of the variables to be renamed. */ + pool = pool_create (); + old_names = pool_nalloc (pool, count, sizeof *old_names); + for (i = 0; i < count; i++) + old_names[i] = pool_strdup (pool, var_get_name (vars[i])); + /* Remove the variables to be renamed from the name hash, - save their names, and rename them. */ - old_names = xnmalloc (count, sizeof *old_names); + and rename them. */ for (i = 0; i < count; i++) { - assert (d->var[vars[i]->index] == vars[i]); - assert (var_is_plausible_name (new_names[i], false)); hsh_force_delete (d->name_tab, vars[i]); - old_names[i] = xstrdup (var_get_name (vars[i])); - var_set_name (vars[i], new_names[i]); + rename_var (d, vars[i], new_names[i]); } /* Add the renamed variables back into the name hash, checking for conflicts. */ for (i = 0; i < count; i++) - { - assert (new_names[i] != NULL); - assert (*new_names[i] != '\0'); - assert (strlen (new_names[i]) >= 1); - assert (strlen (new_names[i]) <= LONG_NAME_LEN); - - if (hsh_insert (d->name_tab, vars[i]) != NULL) - { - /* There is a name conflict. - Back out all the name changes that have already - taken place, and indicate failure. */ - size_t fail_idx = i; - if (err_name != NULL) - *err_name = new_names[i]; - - for (i = 0; i < fail_idx; i++) - hsh_force_delete (d->name_tab, vars[i]); + if (hsh_insert (d->name_tab, vars[i]) != NULL) + { + /* There is a name conflict. + Back out all the name changes that have already + taken place, and indicate failure. */ + size_t fail_idx = i; + if (err_name != NULL) + *err_name = new_names[i]; + + for (i = 0; i < fail_idx; i++) + hsh_force_delete (d->name_tab, vars[i]); - for (i = 0; i < count; i++) - { - var_set_name (vars[i], old_names[i]); - hsh_force_insert (d->name_tab, vars[i]); - } - - success = false; - goto done; - } - } + for (i = 0; i < count; i++) + { + rename_var (d, vars[i], old_names[i]); + hsh_force_insert (d->name_tab, vars[i]); + } + + pool_destroy (pool); + return false; + } /* Clear short names. */ if (get_algorithm () == ENHANCED) for (i = 0; i < count; i++) var_clear_short_name (vars[i]); - done: - /* Free the old names we kept around. */ - for (i = 0; i < count; i++) - free (old_names[i]); - free (old_names); - - return success; + pool_destroy (pool); + return true; } /* Returns the weighting variable in dictionary D, or a null @@ -706,7 +654,7 @@ dict_get_case_weight (const struct dictionary *d, const struct ccase *c, return 1.0; else { - double w = case_num (c, d->weight->fv); + double w = case_num (c, d->weight); if (w < 0.0 || var_is_num_missing (d->weight, w)) w = 0.0; if ( w == 0.0 && *warn_on_invalid ) { @@ -773,8 +721,8 @@ dict_set_case_limit (struct dictionary *d, size_t case_limit) d->case_limit = case_limit; } -/* Returns the index of the next value to be added to D. This - value is the number of `union value's that need to be +/* Returns the case index of the next value to be added to D. + This value is the number of `union value's that need to be allocated to store a case for dictionary D. */ int dict_get_next_value_idx (const struct dictionary *d) @@ -808,7 +756,7 @@ dict_compact_values (struct dictionary *d) if (dict_class_from_id (var_get_name (v)) != DC_SCRATCH) { - v->fv = d->next_value_idx; + set_var_case_index (v, d->next_value_idx); d->next_value_idx += var_get_value_cnt (v); i++; } @@ -833,17 +781,18 @@ dict_get_compacted_value_cnt (const struct dictionary *d) } /* Creates and returns an array mapping from a dictionary index - to the `fv' that the corresponding variable will have after - calling dict_compact_values(). Scratch variables receive -1 - for `fv' because dict_compact_values() will delete them. */ + to the case index that the corresponding variable will have + after calling dict_compact_values(). Scratch variables + receive -1 for case index because dict_compact_values() will + delete them. */ int * -dict_get_compacted_idx_to_fv (const struct dictionary *d) +dict_get_compacted_dict_index_to_case_index (const struct dictionary *d) { size_t i; size_t next_value_idx; - int *idx_to_fv; + int *map; - idx_to_fv = xnmalloc (d->var_cnt, sizeof *idx_to_fv); + map = xnmalloc (d->var_cnt, sizeof *map); next_value_idx = 0; for (i = 0; i < d->var_cnt; i++) { @@ -851,13 +800,13 @@ dict_get_compacted_idx_to_fv (const struct dictionary *d) if (dict_class_from_id (var_get_name (v)) != DC_SCRATCH) { - idx_to_fv[i] = next_value_idx; + map[i] = next_value_idx; next_value_idx += var_get_value_cnt (v); } else - idx_to_fv[i] = -1; + map[i] = -1; } - return idx_to_fv; + return map; } /* Returns true if a case for dictionary D would be smaller after @@ -893,7 +842,7 @@ dict_compacting_would_change (const struct dictionary *d) for (i = 0; i < dict_get_var_cnt (d); i++) { struct variable *v = dict_get_var (d, i); - if (v->fv != case_idx) + if (var_get_case_index (v) != case_idx) return true; case_idx += var_get_value_cnt (v); } @@ -943,7 +892,7 @@ dict_make_compactor (const struct dictionary *d) if (dict_class_from_id (var_get_name (v)) == DC_SCRATCH) continue; - if (map != NULL && map->src_idx + map->cnt == v->fv) + if (map != NULL && map->src_idx + map->cnt == var_get_case_index (v)) map->cnt += var_get_value_cnt (v); else { @@ -951,7 +900,7 @@ dict_make_compactor (const struct dictionary *d) compactor->maps = x2nrealloc (compactor->maps, &map_allocated, sizeof *compactor->maps); map = &compactor->maps[compactor->map_cnt++]; - map->src_idx = v->fv; + map->src_idx = var_get_case_index (v); map->dst_idx = value_idx; map->cnt = var_get_value_cnt (v); } @@ -1079,39 +1028,29 @@ dict_set_documents (struct dictionary *d, const char *documents) d->documents = xstrdup (documents); } -/* Creates in D a vector named NAME that contains CNT variables - VAR (see cmd_vector()). Returns true if successful, or - false if a vector named NAME already exists in D. */ +/* Creates in D a vector named NAME that contains the CNT + variables in VAR. Returns true if successful, or false if a + vector named NAME already exists in D. */ bool dict_create_vector (struct dictionary *d, const char *name, struct variable **var, size_t cnt) { - struct vector *vector; size_t i; - assert (d != NULL); - assert (name != NULL); - assert (var_is_plausible_name (name, false)); assert (var != NULL); assert (cnt > 0); - - if (dict_lookup_vector (d, name) != NULL) - return false; - - d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector); - vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector); - vector->idx = d->vector_cnt++; - str_copy_trunc (vector->name, sizeof vector->name, name); - vector->var = xnmalloc (cnt, sizeof *var); for (i = 0; i < cnt; i++) + assert (dict_contains_var (d, var[i])); + + if (dict_lookup_vector (d, name) == NULL) { - assert (dict_contains_var (d, var[i])); - vector->var[i] = var[i]; + d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector); + d->vector[d->vector_cnt++] = vector_create (name, var, cnt); + return true; } - vector->cnt = cnt; - - return true; + else + return false; } /* Returns the vector in D with index IDX, which must be less @@ -1140,12 +1079,8 @@ const struct vector * dict_lookup_vector (const struct dictionary *d, const char *name) { size_t i; - - assert (d != NULL); - assert (name != NULL); - for (i = 0; i < d->vector_cnt; i++) - if (!strcasecmp (d->vector[i]->name, name)) + if (!strcasecmp (vector_get_name (d->vector[i]), name)) return d->vector[i]; return NULL; } @@ -1156,14 +1091,10 @@ dict_clear_vectors (struct dictionary *d) { size_t i; - assert (d != NULL); - - for (i = 0; i < d->vector_cnt; i++) - { - free (d->vector[i]->var); - free (d->vector[i]); - } + for (i = 0; i < d->vector_cnt; i++) + vector_destroy (d->vector[i]); free (d->vector); + d->vector = NULL; d->vector_cnt = 0; } @@ -1182,6 +1113,51 @@ hash_string (const void *s, const void *aux UNUSED) return hsh_hash_string (s); } + +/* Sets V's short name to BASE, followed by a suffix of the form + _A, _B, _C, ..., _AA, _AB, etc. according to the value of + SUFFIX_NUMBER. Truncates BASE as necessary to fit. */ +static void +set_var_short_name_suffix (struct variable *v, const char *base, + int suffix_number) +{ + char suffix[SHORT_NAME_LEN + 1]; + char short_name[SHORT_NAME_LEN + 1]; + char *start, *end; + int len, ofs; + + assert (v != NULL); + assert (suffix_number >= 0); + + /* Set base name. */ + var_set_short_name (v, base); + + /* Compose suffix. */ + start = end = suffix + sizeof suffix - 1; + *end = '\0'; + do + { + *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix_number % 26]; + if (start <= suffix + 1) + msg (SE, _("Variable suffix too large.")); + suffix_number /= 26; + } + while (suffix_number > 0); + *--start = '_'; + + /* Append suffix to V's short name. */ + str_copy_trunc (short_name, sizeof short_name, base); + len = end - start; + if (len + strlen (short_name) > SHORT_NAME_LEN) + ofs = SHORT_NAME_LEN - len; + else + ofs = strlen (short_name); + strcpy (short_name + ofs, start); + + /* Set name. */ + var_set_short_name (v, short_name); +} + /* Assigns a valid, unique short_name[] to each variable in D. Each variable whose actual name is short has highest priority for that short name. Otherwise, variables with an existing @@ -1236,7 +1212,7 @@ dict_assign_short_names (struct dictionary *d) if (trial == 0) var_set_short_name (v, var_get_name (v)); else - var_set_short_name_suffix (v, var_get_name (v), trial - 1); + set_var_short_name_suffix (v, var_get_name (v), trial - 1); trial++; } diff --git a/src/data/dictionary.h b/src/data/dictionary.h index 828b75a9..e0425b85 100644 --- a/src/data/dictionary.h +++ b/src/data/dictionary.h @@ -82,7 +82,7 @@ size_t dict_get_case_size (const struct dictionary *); void dict_compact_values (struct dictionary *); size_t dict_get_compacted_value_cnt (const struct dictionary *); -int *dict_get_compacted_idx_to_fv (const struct dictionary *); +int *dict_get_compacted_dict_index_to_case_index (const struct dictionary *); bool dict_compacting_would_shrink (const struct dictionary *); bool dict_compacting_would_change (const struct dictionary *); diff --git a/src/data/format.c b/src/data/format.c index 8f2d0de9..60c1d0a9 100644 --- a/src/data/format.c +++ b/src/data/format.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -300,15 +301,15 @@ fmt_check_output (const struct fmt_spec *spec) TYPE and returns true if so. Otherwise returns false and emits an error message. */ bool -fmt_check_type_compat (const struct fmt_spec *format, int var_type) +fmt_check_type_compat (const struct fmt_spec *format, enum var_type var_type) { - assert (var_type == NUMERIC || var_type == ALPHA); - if ((var_type == ALPHA) != (fmt_is_string (format->type) != 0)) + assert (var_type_is_valid (var_type)); + if ((var_type == VAR_STRING) != (fmt_is_string (format->type) != 0)) { char str[FMT_STRING_LEN_MAX + 1]; msg (SE, _("%s variables are not compatible with %s format %s."), - var_type == ALPHA ? _("String") : _("Numeric"), - var_type == ALPHA ? _("numeric") : _("string"), + var_type == VAR_STRING ? _("String") : _("Numeric"), + var_type == VAR_STRING ? _("numeric") : _("string"), fmt_to_string (format, str)); return false; } @@ -321,7 +322,7 @@ fmt_check_type_compat (const struct fmt_spec *format, int var_type) bool fmt_check_width_compat (const struct fmt_spec *format, int width) { - if (!fmt_check_type_compat (format, width != 0 ? ALPHA : NUMERIC)) + if (!fmt_check_type_compat (format, var_type_from_width (width))) return false; if (fmt_var_width (format) != width) { diff --git a/src/data/format.h b/src/data/format.h index 67e46f17..089f1ed3 100644 --- a/src/data/format.h +++ b/src/data/format.h @@ -24,6 +24,7 @@ #include #include +#include #include /* Format type categories. */ @@ -82,7 +83,7 @@ struct fmt_spec fmt_default_for_width (int var_width); bool fmt_check (const struct fmt_spec *, bool for_input); bool fmt_check_input (const struct fmt_spec *); bool fmt_check_output (const struct fmt_spec *); -bool fmt_check_type_compat (const struct fmt_spec *, int var_type); +bool fmt_check_type_compat (const struct fmt_spec *, enum var_type); bool fmt_check_width_compat (const struct fmt_spec *, int var_width); /* Working with formats. */ diff --git a/src/data/missing-values.c b/src/data/missing-values.c index 8976abc1..b5f52f5e 100644 --- a/src/data/missing-values.c +++ b/src/data/missing-values.c @@ -303,7 +303,7 @@ can_resize_string (const char *s, int old_width, int new_width) contains only spaces in the characters that will be trimmed. */ bool -mv_is_resizable (struct missing_values *mv, int width) +mv_is_resizable (const struct missing_values *mv, int width) { assert ((width == 0) == (mv->width == 0)); if (width > MAX_SHORT_STRING && mv->type != MV_NONE) diff --git a/src/data/missing-values.h b/src/data/missing-values.h index 5727344d..e6f6a0b2 100644 --- a/src/data/missing-values.h +++ b/src/data/missing-values.h @@ -69,7 +69,7 @@ bool mv_has_range (const struct missing_values *); void mv_pop_range (struct missing_values *, double *low, double *high); void mv_peek_range (const struct missing_values *, double *low, double *high); -bool mv_is_resizable (struct missing_values *, int width); +bool mv_is_resizable (const struct missing_values *, int width); void mv_resize (struct missing_values *, int width); typedef bool mv_is_missing_func (const struct missing_values *, diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c index b6bad0a0..307a5393 100644 --- a/src/data/por-file-reader.c +++ b/src/data/por-file-reader.c @@ -36,6 +36,7 @@ #include "dictionary.h" #include "file-handle-def.h" #include "format.h" +#include "missing-values.h" #include #include #include @@ -663,7 +664,7 @@ read_value_label (struct pfm_reader *r, struct dictionary *dict) { struct variable *var = v[j]; - if (!val_labs_replace (var->val_labs, val, label)) + if (!var_add_value_label (var, &val, label)) continue; if (var_is_numeric (var)) @@ -698,14 +699,14 @@ pfm_read_case (struct pfm_reader *r, struct ccase *c) if (width == 0) { - case_data_rw (c, idx)->f = read_float (r); + case_data_rw_idx (c, idx)->f = read_float (r); idx++; } else { char string[256]; read_string (r, string); - buf_copy_str_rpad (case_data_rw (c, idx)->s, width, string); + buf_copy_str_rpad (case_data_rw_idx (c, idx)->s, width, string); idx += DIV_RND_UP (width, MAX_SHORT_STRING); } } diff --git a/src/data/por-file-writer.c b/src/data/por-file-writer.c index aa8b5e0b..0f5542ce 100644 --- a/src/data/por-file-writer.c +++ b/src/data/por-file-writer.c @@ -19,7 +19,7 @@ #include #include "por-file-writer.h" -#include + #include #include #include @@ -30,18 +30,22 @@ #include #include #include -#include + #include "case.h" #include "dictionary.h" -#include #include "file-handle-def.h" +#include "format.h" +#include "missing-values.h" +#include "stat-macros.h" +#include "value-labels.h" +#include "variable.h" + +#include #include #include +#include #include -#include "stat-macros.h" #include -#include "value-labels.h" -#include "variable.h" #include #include "gettext.h" @@ -134,7 +138,7 @@ pfm_open_writer (struct file_handle *fh, struct dictionary *dict, const struct variable *dv = dict_get_var (dict, i); struct pfm_var *pv = &w->vars[i]; pv->width = var_get_width (dv); - pv->fv = dv->fv; + pv->fv = var_get_case_index (dv); } w->digits = opts.digits; @@ -372,18 +376,19 @@ write_value_labels (struct pfm_writer *w, const struct dictionary *dict) { struct val_labs_iterator *j; struct variable *v = dict_get_var (dict, i); + const struct val_labs *val_labs = var_get_value_labels (v); struct val_lab *vl; - if (!val_labs_count (v->val_labs)) + if (val_labs == NULL) continue; buf_write (w, "D", 1); write_int (w, 1); write_string (w, var_get_short_name (v)); - write_int (w, val_labs_count (v->val_labs)); + write_int (w, val_labs_count (val_labs)); - for (vl = val_labs_first_sorted (v->val_labs, &j); vl != NULL; - vl = val_labs_next (v->val_labs, &j)) + for (vl = val_labs_first_sorted (val_labs, &j); vl != NULL; + vl = val_labs_next (val_labs, &j)) { write_value (w, &vl->value, v); write_string (w, vl->label); @@ -405,11 +410,11 @@ pfm_write_case (struct pfm_writer *w, const struct ccase *c) struct pfm_var *v = &w->vars[i]; if (v->width == 0) - write_float (w, case_num (c, v->fv)); + write_float (w, case_num_idx (c, v->fv)); else { write_int (w, v->width); - buf_write (w, case_str (c, v->fv), v->width); + buf_write (w, case_str_idx (c, v->fv), v->width); } } diff --git a/src/data/procedure.c b/src/data/procedure.c index 7cd34369..422d0ecd 100644 --- a/src/data/procedure.c +++ b/src/data/procedure.c @@ -265,7 +265,7 @@ create_trns_case (struct ccase *trns_case, struct dictionary *dict) for (i = 0; i < var_cnt; i++) { struct variable *v = dict_get_var (dict, i); - union value *value = case_data_rw (trns_case, v->fv); + union value *value = case_data_rw (trns_case, v); if (var_is_numeric (v)) value->f = var_get_leave (v) ? 0.0 : SYSMIS; @@ -398,9 +398,9 @@ clear_case (const struct dataset *ds, struct ccase *c) if (!var_get_leave (v)) { if (var_is_numeric (v)) - case_data_rw (c, v->fv)->f = SYSMIS; + case_data_rw (c, v)->f = SYSMIS; else - memset (case_data_rw (c, v->fv)->s, ' ', var_get_width (v)); + memset (case_data_rw (c, v)->s, ' ', var_get_width (v)); } } } @@ -937,7 +937,7 @@ filter_trns_proc (void *filter_var_, { struct variable *filter_var = filter_var_; - double f = case_num (c, filter_var->fv); + double f = case_num (c, filter_var); return (f != 0.0 && !var_is_num_missing (filter_var, f) ? TRNS_CONTINUE : TRNS_DROP_CASE); } diff --git a/src/data/sys-file-private.c b/src/data/sys-file-private.c new file mode 100644 index 00000000..4c77f879 --- /dev/null +++ b/src/data/sys-file-private.c @@ -0,0 +1,45 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2006 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 the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include "sys-file-private.h" + +#include +#include + +/* Return the number of bytes used when writing case_data for a variable + of WIDTH */ +int +sfm_width_to_bytes (int width) +{ + assert (width >= 0); + + if (width == 0) + return MAX_SHORT_STRING; + else if (width < MIN_VERY_LONG_STRING) + return ROUND_UP (width, MAX_SHORT_STRING); + else + { + int chunks = width / EFFECTIVE_LONG_STRING_LENGTH ; + int remainder = width % EFFECTIVE_LONG_STRING_LENGTH ; + int bytes = remainder + (chunks * MIN_VERY_LONG_STRING); + return ROUND_UP (bytes, MAX_SHORT_STRING); + } +} + + diff --git a/src/data/sys-file-private.h b/src/data/sys-file-private.h new file mode 100644 index 00000000..012ebfee --- /dev/null +++ b/src/data/sys-file-private.h @@ -0,0 +1,30 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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 the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef DATA_SYS_FILE_PRIVATE_H +#define DATA_SYS_FILE_PRIVATE_H 1 + +/* This nonsense is required for SPSS compatibility. */ + +#define MIN_VERY_LONG_STRING 256 +#define EFFECTIVE_LONG_STRING_LENGTH (MIN_VERY_LONG_STRING - 4) + +int sfm_width_to_bytes (int width); + +#endif /* data/sys-file-private.h */ diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c index ccae0577..c1a8292e 100644 --- a/src/data/sys-file-reader.c +++ b/src/data/sys-file-reader.c @@ -19,6 +19,10 @@ #include +#include "sys-file-reader.h" +#include "sfm-private.h" +#include "sys-file-private.h" + #include #include #include @@ -35,16 +39,15 @@ #include #include -#include "sys-file-reader.h" -#include "sfm-private.h" #include "case.h" #include "dictionary.h" #include "file-handle-def.h" #include "file-name.h" #include "format.h" +#include "missing-values.h" #include "value-labels.h" -#include "variable.h" #include "value.h" +#include "variable.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -528,7 +531,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, } /* Identify any duplicates. */ - if ( compare_var_names(short_name, long_name, 0) && + if ( strcasecmp (short_name, long_name) && NULL != dict_lookup_var (*dict, long_name)) lose ((ME, _("%s: Duplicate long variable name `%s' " "within system file."), @@ -635,7 +638,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, else l -= var_get_width (v); - idx = v->index; + idx = var_get_dict_index (v); while ( l > 0 ) { struct variable *v_next; @@ -649,7 +652,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, dict_delete_var(*dict, v_next); } - assert ( length > MAX_LONG_STRING ); + assert ( length >= MIN_VERY_LONG_STRING ); var_set_width (v, length); } @@ -723,7 +726,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, struct variable *v = dict_get_var (*dict, i); struct sfm_var *sv = &r->vars[i]; sv->width = var_get_width (v); - sv->fv = v->fv; + sv->fv = var_get_case_index (v); } } @@ -1413,7 +1416,7 @@ read_value_labels (struct sfm_reader *r, for (j = 0; j < n_labels; j++) { struct label *label = labels + j; - if (!val_labs_replace (v->val_labs, label->value, label->label)) + if (var_add_value_label (v, &label->value, label->label)) continue; if (var_is_numeric (var[0])) @@ -1676,7 +1679,7 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) for (i = 0; i < r->var_cnt; i++) if (r->vars[i].width == 0) - bswap_flt64 (&case_data_rw (c, r->vars[i].fv)->f); + bswap_flt64 (&case_data_rw_idx (c, r->vars[i].fv)->f); } /* Fix up SYSMIS values if needed. @@ -1687,8 +1690,8 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) int i; for (i = 0; i < r->var_cnt; i++) - if (r->vars[i].width == 0 && case_num (c, i) == r->sysmis) - case_data_rw (c, r->vars[i].fv)->f = SYSMIS; + if (r->vars[i].width == 0 && case_num_idx (c, i) == r->sysmis) + case_data_rw_idx (c, r->vars[i].fv)->f = SYSMIS; } } else @@ -1725,7 +1728,7 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) flt64 f = *bounce_cur++; if (r->reverse_endian) bswap_flt64 (&f); - case_data_rw (c, sv->fv)->f = f == r->sysmis ? SYSMIS : f; + case_data_rw_idx (c, sv->fv)->f = f == r->sysmis ? SYSMIS : f; } else { @@ -1733,14 +1736,16 @@ sfm_read_case (struct sfm_reader *r, struct ccase *c) int ofs = 0; while (ofs < sv->width ) { - const int chunk = MIN (MAX_LONG_STRING, sv->width - ofs); - memcpy (case_data_rw (c, sv->fv)->s + ofs, bounce_cur, chunk); + const int chunk = MIN (MIN_VERY_LONG_STRING - 1, + sv->width - ofs); + memcpy (case_data_rw_idx (c, sv->fv)->s + ofs, + bounce_cur, chunk); bounce_cur += DIV_RND_UP (chunk, sizeof (flt64)); ofs += chunk; } - bounce_cur = bc_start + width_to_bytes(sv->width) / sizeof(flt64); + bounce_cur = bc_start + sfm_width_to_bytes (sv->width) / sizeof(flt64); } } diff --git a/src/data/sys-file-writer.c b/src/data/sys-file-writer.c index f4226169..ddfb4ae7 100644 --- a/src/data/sys-file-writer.c +++ b/src/data/sys-file-writer.c @@ -21,6 +21,7 @@ #include "sys-file-writer.h" #include "sfm-private.h" +#include "sys-file-private.h" #include #include @@ -41,6 +42,8 @@ #include "case.h" #include "dictionary.h" #include "file-handle-def.h" +#include "format.h" +#include "missing-values.h" #include "settings.h" #include "value-labels.h" #include "variable.h" @@ -114,7 +117,7 @@ static inline int var_flt64_cnt (const struct variable *v) { assert(sizeof(flt64) == MAX_SHORT_STRING); - return width_to_bytes(var_get_width (v)) / MAX_SHORT_STRING ; + return sfm_width_to_bytes(var_get_width (v)) / MAX_SHORT_STRING ; } static inline int @@ -218,10 +221,10 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d, struct sfm_var *sv = &w->vars[i]; sv->width = var_get_width (dv); /* spss compatibility nonsense */ - if ( var_is_very_long_string (dv) ) + if ( var_get_width (dv) >= MIN_VERY_LONG_STRING ) w->has_vls = true; - sv->fv = dv->fv; + sv->fv = var_get_case_index (dv); sv->flt64_cnt = var_flt64_cnt (dv); } @@ -244,32 +247,34 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d, int wcount = var_get_width (v); do { - struct variable var_cont = *v; + struct variable *var_cont = var_clone (v); + var_set_short_name (var_cont, var_get_short_name (v)); if ( var_is_alpha (v)) { if ( 0 != count ) { - var_clear_missing_values (&var_cont); - var_set_short_name (&var_cont, + var_clear_missing_values (var_cont); + var_set_short_name (var_cont, cont_var_name (var_get_short_name (v), count)); - var_clear_label (&var_cont); + var_clear_label (var_cont); w->var_cnt_vls++; } count++; - if ( wcount > MAX_LONG_STRING ) + if ( wcount >= MIN_VERY_LONG_STRING ) { - var_set_width (&var_cont, MAX_LONG_STRING); + var_set_width (var_cont, MIN_VERY_LONG_STRING - 1); wcount -= EFFECTIVE_LONG_STRING_LENGTH; } else { - var_set_width (&var_cont, wcount); - wcount -= var_get_width (&var_cont); + var_set_width (var_cont, wcount); + wcount -= var_get_width (var_cont); } } - write_variable (w, &var_cont); + write_variable (w, var_cont); + var_destroy (var_cont); } while(wcount > 0); } @@ -458,7 +463,7 @@ write_variable (struct sfm_writer *w, const struct variable *v) const char *label = var_get_label (v); sv.rec_type = 2; - sv.type = MIN(var_get_width (v), MAX_LONG_STRING); + sv.type = MIN (var_get_width (v), MIN_VERY_LONG_STRING - 1); sv.has_var_label = label != NULL; mv_copy (&mv, var_get_missing_values (v)); @@ -524,7 +529,7 @@ write_variable (struct sfm_writer *w, const struct variable *v) memset (&sv.write, 0, sizeof sv.write); memset (&sv.name, 0, sizeof sv.name); - pad_count = DIV_RND_UP (MIN(var_get_width (v), MAX_LONG_STRING), + pad_count = DIV_RND_UP (MIN(var_get_width (v), MIN_VERY_LONG_STRING - 1), (int) sizeof (flt64)) - 1; for (i = 0; i < pad_count; i++) buf_write (w, &sv, sizeof sv); @@ -550,6 +555,7 @@ write_value_labels (struct sfm_writer *w, struct variable *v, int idx) int32_t vars[1] ; } ATTRIBUTE((packed)); + const struct val_labs *val_labs; struct val_labs_iterator *i; struct value_label_rec *vlr; struct var_idx_rec vir; @@ -557,23 +563,24 @@ write_value_labels (struct sfm_writer *w, struct variable *v, int idx) size_t vlr_size; flt64 *loc; - if (!val_labs_count (v->val_labs)) + val_labs = var_get_value_labels (v); + if (val_labs == NULL) return; /* Pass 1: Count bytes. */ vlr_size = (sizeof (struct value_label_rec) - + sizeof (flt64) * (val_labs_count (v->val_labs) - 1)); - for (vl = val_labs_first (v->val_labs, &i); vl != NULL; - vl = val_labs_next (v->val_labs, &i)) + + sizeof (flt64) * (val_labs_count (val_labs) - 1)); + for (vl = val_labs_first (val_labs, &i); vl != NULL; + vl = val_labs_next (val_labs, &i)) vlr_size += ROUND_UP (strlen (vl->label) + 1, sizeof (flt64)); /* Pass 2: Copy bytes. */ vlr = xmalloc (vlr_size); vlr->rec_type = 3; - vlr->n_labels = val_labs_count (v->val_labs); + vlr->n_labels = val_labs_count (val_labs); loc = vlr->labels; - for (vl = val_labs_first_sorted (v->val_labs, &i); vl != NULL; - vl = val_labs_next (v->val_labs, &i)) + for (vl = val_labs_first_sorted (val_labs, &i); vl != NULL; + vl = val_labs_next (val_labs, &i)) { size_t len = strlen (vl->label); @@ -662,7 +669,7 @@ write_variable_display_parameters (struct sfm_writer *w, while (wcount > 0) { - params.width = wcount > MAX_LONG_STRING ? 32 : wcount; + params.width = wcount >= MIN_VERY_LONG_STRING ? 32 : wcount; buf_write (w, ¶ms, sizeof(params)); @@ -699,7 +706,7 @@ write_vls_length_table (struct sfm_writer *w, { const struct variable *v = dict_get_var (dict, i); - if ( var_get_width (v) <= MAX_LONG_STRING ) + if ( var_get_width (v) < MIN_VERY_LONG_STRING ) continue; ds_put_format (&vls_length_map, "%s=%05d", @@ -904,17 +911,17 @@ sfm_write_case (struct sfm_writer *w, const struct ccase *c) if (v->width == 0) { - *bounce_cur = case_num (c, v->fv); + *bounce_cur = case_num_idx (c, v->fv); bounce_cur += v->flt64_cnt; } else { int ofs = 0; while (ofs < v->width) { - int chunk = MIN (MAX_LONG_STRING, v->width - ofs); + int chunk = MIN (MIN_VERY_LONG_STRING - 1, v->width - ofs); int nv = DIV_RND_UP (chunk, sizeof (flt64)); buf_copy_rpad ((char *) bounce_cur, nv * sizeof (flt64), - case_data (c, v->fv)->s + ofs, chunk); + case_data_idx (c, v->fv)->s + ofs, chunk); bounce_cur += nv; ofs += chunk; } diff --git a/src/data/value-labels.c b/src/data/value-labels.c index 357ab4fc..81bb375e 100644 --- a/src/data/value-labels.c +++ b/src/data/value-labels.c @@ -24,6 +24,8 @@ #include #include +#include +#include #include #include #include @@ -72,7 +74,8 @@ val_labs_copy (const struct val_labs *vls) struct val_labs_iterator *i; struct val_lab *vl; - assert (vls != NULL); + if (vls == NULL) + return NULL; copy = val_labs_create (vls->width); for (vl = val_labs_first (vls, &i); vl != NULL; @@ -155,12 +158,7 @@ val_labs_clear (struct val_labs *vls) size_t val_labs_count (const struct val_labs *vls) { - assert (vls != NULL); - - if (vls->labels == NULL) - return 0; - else - return hsh_count (vls->labels); + return vls == NULL || vls->labels == NULL ? 0 : hsh_count (vls->labels); } /* One value label in internal format. */ @@ -222,29 +220,19 @@ val_labs_add (struct val_labs *vls, union value value, const char *label) if there wasn't already a value label for VALUE, or true if there was. Behavior is undefined if VLS's width is greater than MAX_SHORT_STRING. */ -bool +void val_labs_replace (struct val_labs *vls, union value value, const char *label) { - struct int_val_lab *ivl; - - assert (vls != NULL); assert (vls->width <= MAX_SHORT_STRING); - assert (label != NULL); - - if (vls->labels == NULL) + if (vls->labels != NULL) { - val_labs_add (vls, value, label); - return false; + struct int_val_lab *new = create_int_val_lab (vls, value, label); + struct int_val_lab *old = hsh_replace (vls->labels, new); + if (old != NULL) + free_int_val_lab (old, vls); } - - ivl = hsh_replace (vls->labels, create_int_val_lab (vls, value, label)); - if (ivl == NULL) - return false; else - { - free_int_val_lab (ivl, vls); - return true; - } + val_labs_add (vls, value, label); } /* Removes any value label for VALUE within VLS. Returns true @@ -274,12 +262,9 @@ val_labs_remove (struct val_labs *vls, union value value) char * val_labs_find (const struct val_labs *vls, union value value) { - assert (vls != NULL); - - if (vls->width > MAX_SHORT_STRING) - return NULL; - - if (vls->labels != NULL) + if (vls != NULL + && vls->width <= MAX_SHORT_STRING + && vls->labels != NULL) { struct int_val_lab ivl, *vlp; @@ -536,30 +521,3 @@ free_atom (void *atom_, const void *aux UNUSED) free (atom->string); free (atom); } - - -/* Get a string representing the value. - That is, if it has a label, then return that label, - otherwise, if the value is alpha, then return the string for it, - else format it and return the formatted string -*/ -const char * -value_to_string (const union value *val, const struct variable *var) -{ - char *s; - - assert (val != NULL); - assert (var != NULL); - - s = val_labs_find (var->val_labs, *val); - if (s == NULL) - { - static char buf[MAX_STRING + 1]; - const struct fmt_spec *print = var_get_print_format (var); - data_out (val, print, buf); - buf[print->w] = '\0'; - s = buf; - } - - return s; -} diff --git a/src/data/value-labels.h b/src/data/value-labels.h index 1085fe65..bf015824 100644 --- a/src/data/value-labels.h +++ b/src/data/value-labels.h @@ -44,7 +44,7 @@ bool val_labs_can_set_width (const struct val_labs *, int new_width); void val_labs_set_width (struct val_labs *, int new_width); bool val_labs_add (struct val_labs *, union value, const char *); -bool val_labs_replace (struct val_labs *, union value, const char *); +void val_labs_replace (struct val_labs *, union value, const char *); bool val_labs_remove (struct val_labs *, union value); char *val_labs_find (const struct val_labs *, union value); @@ -58,10 +58,4 @@ struct val_lab *val_labs_next (const struct val_labs *, struct val_labs_iterator **); void val_labs_done (struct val_labs_iterator **); -/* Return a string representing this value, in the form most - appropriate from a human factors perspective. - (IE: the label if it has one, otherwise the alpha/numeric ) -*/ -const char *value_to_string(const union value *, const struct variable *); - #endif /* value-labels.h */ diff --git a/src/data/value.c b/src/data/value.c new file mode 100644 index 00000000..2de3adba --- /dev/null +++ b/src/data/value.c @@ -0,0 +1,56 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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 the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include "value.h" + +#include +#include + +#include "xalloc.h" + +/* Duplicate a value. + The caller is responsible for freeing the returned value. */ +union value * +value_dup (const union value *val, int width) +{ + return xmemdup (val, MAX (width, sizeof *val)); +} + +/* Compares A and B, which both have the given WIDTH, and returns + a strcmp()-type result. + Only the short string portion of longer strings are + compared. */ +int +compare_values (const union value *a, const union value *b, int width) +{ + return (width == 0 + ? (a->f < b->f ? -1 : a->f > b->f) + : memcmp (a->s, b->s, MIN (MAX_SHORT_STRING, width))); +} + +/* Create a hash of V, which has the given WIDTH. + Only the short string portion of a longer string is hashed. */ +unsigned +hash_value (const union value *v, int width) +{ + return (width == 0 + ? hsh_hash_double (v->f) + : hsh_hash_bytes (v->s, MIN (MAX_SHORT_STRING, width))); +} diff --git a/src/data/value.h b/src/data/value.h index fccd8a98..d4978989 100644 --- a/src/data/value.h +++ b/src/data/value.h @@ -21,26 +21,17 @@ #define value_h 1 #include - -#include +#include +#include "minmax.h" /* Values. */ -/* Max length of a short string value, generally 8 chars. */ -#define MAX_SHORT_STRING ( (SIZEOF_DOUBLE)>=8 ? (SIZEOF_DOUBLE + 1)/2 * 2 : 8 ) - +/* "Short" strings, which are generally those no more than 8 + characters wide, can participate in more operations than + longer strings. */ +#define MAX_SHORT_STRING (MAX (ROUND_UP (SIZEOF_DOUBLE, 2), 8)) #define MIN_LONG_STRING (MAX_SHORT_STRING + 1) - -/* Max string length. */ -#define MAX_LONG_STRING 255 - -/* This nonsense is required for SPSS compatibility */ -#define EFFECTIVE_LONG_STRING_LENGTH (MAX_LONG_STRING - 3) - -#define MAX_VERY_LONG_STRING 32767 - -#define MAX_STRING MAX_VERY_LONG_STRING - +#define MAX_STRING 32767 /* Special values. */ #define SYSMIS (-DBL_MAX) @@ -55,14 +46,8 @@ union value char s[MAX_SHORT_STRING]; }; -/* Maximum number of `union value's in a single number or string - value. */ -#define MAX_ELEMS_PER_VALUE (MAX_STRING / sizeof (union value) + 1) - -int compare_values (const union value *a, const union value *b, int width); - -unsigned hash_value(const union value *v, int width); - - +union value *value_dup (const union value *, int width); +int compare_values (const union value *, const union value *, int width); +unsigned hash_value (const union value *, int width); #endif /* !value.h */ diff --git a/src/data/vardict.h b/src/data/vardict.h new file mode 100644 index 00000000..dd4f7321 --- /dev/null +++ b/src/data/vardict.h @@ -0,0 +1,39 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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 the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef DATA_VARDICT_H +#define DATA_VARDICT_H 1 + +/* Interface between dictionary and variable code. + This header file should only be included by variable.c and + dictionary.c. */ + +/* Dictionary data stored in variable. */ +struct vardict_info + { + int dict_index; /* Dictionary index containing the variable. */ + int case_index; /* Index into case of variable data. */ + }; + +const struct vardict_info *var_get_vardict (const struct variable *); +void var_set_vardict (struct variable *, const struct vardict_info *); +bool var_has_vardict (const struct variable *); +void var_clear_vardict (struct variable *); + +#endif /* data/vardict.h */ diff --git a/src/data/variable.c b/src/data/variable.c index b43fce7e..5513e5ef 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -19,150 +19,178 @@ #include #include "variable.h" -#include -#include + #include + +#include "cat-routines.h" +#include "category.h" +#include "data-out.h" +#include "dictionary.h" +#include "format.h" +#include "identifier.h" +#include "missing-values.h" +#include "value.h" +#include "value-labels.h" +#include "vardict.h" + #include +#include #include -#include "dictionary.h" #include -#include "identifier.h" +#include #include #include -#include "value-labels.h" #include "minmax.h" #include "gettext.h" #define _(msgid) gettext (msgid) +/* A variable. */ +struct variable + { + /* Dictionary information. */ + char name[LONG_NAME_LEN + 1]; /* Variable name. Mixed case. */ + int width; /* 0 for numeric, otherwise string width. */ + struct missing_values miss; /* Missing values. */ + struct fmt_spec print; /* Default format for PRINT. */ + struct fmt_spec write; /* Default format for WRITE. */ + struct val_labs *val_labs; /* Value labels. */ + char *label; /* Variable label. */ + + /* GUI information. */ + enum measure measure; /* Nominal, ordinal, or continuous. */ + int display_width; /* Width of data editor column. */ + enum alignment alignment; /* Alignment of data in GUI. */ + + /* Case information. */ + bool leave; /* Leave value from case to case? */ + + /* Data for use by containing dictionary. */ + struct vardict_info vardict; + + /* Short name, used only for system and portable file input + and output. Upper case only. There is no index for short + names. Short names are not necessarily unique. Any + variable may have no short name, indicated by an empty + string. */ + char short_name[SHORT_NAME_LEN + 1]; + + /* Each command may use these fields as needed. */ + void *aux; + void (*aux_dtor) (struct variable *); + + /* Values of a categorical variable. Procedures need + vectors with binary entries, so any variable of type ALPHA will + have its values stored here. */ + struct cat_vals *obs_vals; + }; + /* Returns true if VAR_TYPE is a valid variable type. */ bool var_type_is_valid (enum var_type var_type) { - return var_type == NUMERIC || var_type == ALPHA; -} - -/* Returns an adjective describing the given variable TYPE, - suitable for use in phrases like "numeric variable". */ -const char * -var_type_adj (enum var_type type) -{ - return type == NUMERIC ? _("numeric") : _("string"); + return var_type == VAR_NUMERIC || var_type == VAR_STRING; } -/* Returns a noun describing a value of the given variable TYPE, - suitable for use in phrases like "a number". */ -const char * -var_type_noun (enum var_type type) -{ - return type == NUMERIC ? _("number") : _("string"); -} - -/* Returns true if M is a valid variable measurement level, - false otherwise. */ -bool -measure_is_valid (enum measure m) -{ - return m == MEASURE_NOMINAL || m == MEASURE_ORDINAL || m == MEASURE_SCALE; -} - -/* Returns true if A is a valid alignment, - false otherwise. */ -bool -alignment_is_valid (enum alignment a) +/* Returns the variable type for the given width. */ +enum var_type +var_type_from_width (int width) { - return a == ALIGN_LEFT || a == ALIGN_RIGHT || a == ALIGN_CENTRE; + return width != 0 ? VAR_STRING : VAR_NUMERIC; } -/* Assign auxiliary data AUX to variable V, which must not - already have auxiliary data. Before V's auxiliary data is - cleared, AUX_DTOR(V) will be called. */ -void * -var_attach_aux (struct variable *v, - void *aux, void (*aux_dtor) (struct variable *)) -{ - assert (v->aux == NULL); - assert (aux != NULL); - v->aux = aux; - v->aux_dtor = aux_dtor; - return aux; -} - -/* Remove auxiliary data, if any, from V, and returns it, without - calling any associated destructor. */ -void * -var_detach_aux (struct variable *v) -{ - void *aux = v->aux; - assert (aux != NULL); - v->aux = NULL; - return aux; -} - -/* Clears auxiliary data, if any, from V, and calls any - associated destructor. */ -void -var_clear_aux (struct variable *v) -{ - assert (v != NULL); - if (v->aux != NULL) +/* Creates and returns a new variable with the given NAME and + WIDTH and other fields initialized to default values. The + variable is not added to a dictionary; for that, use + dict_create_var instead. */ +struct variable * +var_create (const char *name, int width) +{ + struct variable *v; + + assert (width >= 0 && width <= MAX_STRING); + + v = xmalloc (sizeof *v); + v->vardict.dict_index = v->vardict.case_index = -1; + var_set_name (v, name); + v->width = width; + mv_init (&v->miss, width); + v->leave = var_must_leave (v); + if (var_is_numeric (v)) { - if (v->aux_dtor != NULL) - v->aux_dtor (v); - v->aux = NULL; + v->print = fmt_for_output (FMT_F, 8, 2); + v->alignment = ALIGN_RIGHT; + v->display_width = 8; + v->measure = MEASURE_SCALE; } -} - -/* This function is appropriate for use an auxiliary data - destructor (passed as AUX_DTOR to var_attach_aux()) for the - case where the auxiliary data should be passed to free(). */ -void -var_dtor_free (struct variable *v) -{ - free (v->aux); -} - -/* Duplicate a value. - The caller is responsible for freeing the returned value -*/ -union value * -value_dup (const union value *val, int width) -{ - size_t bytes = MAX(width, sizeof *val); + else + { + v->print = fmt_for_output (FMT_A, var_get_width (v), 0); + v->alignment = ALIGN_LEFT; + v->display_width = 8; + v->measure = MEASURE_NOMINAL; + } + v->write = v->print; + v->val_labs = NULL; + v->label = NULL; + var_clear_short_name (v); + v->aux = NULL; + v->aux_dtor = NULL; + v->obs_vals = NULL; - union value *v = xmalloc (bytes); - memcpy (v, val, bytes); return v; } +/* Creates and returns a clone of OLD_VAR. Most properties of + the new variable are copied from OLD_VAR, except: + - The variable's short name is not copied, because there is + no reason to give a new variable with potentially a new + name the same short name. -/* Compares A and B, which both have the given WIDTH, and returns - a strcmp()-type result. */ -int -compare_values (const union value *a, const union value *b, int width) -{ - if (width == 0) - return a->f < b->f ? -1 : a->f > b->f; - else - return memcmp (a->s, b->s, MIN(MAX_SHORT_STRING, width)); -} + - The new variable is not added to OLD_VAR's dictionary by + default. Use dict_clone_var, instead, to do that. -/* Create a hash of v */ -unsigned -hash_value(const union value *v, int width) + - Auxiliary data and obs_vals are not copied. */ +struct variable * +var_clone (const struct variable *old_var) { - unsigned id_hash; + struct variable *new_var = var_create (var_get_name (old_var), + var_get_width (old_var)); - if ( 0 == width ) - id_hash = hsh_hash_double (v->f); - else - id_hash = hsh_hash_bytes (v->s, MIN(MAX_SHORT_STRING, width)); + var_set_missing_values (new_var, var_get_missing_values (old_var)); + var_set_print_format (new_var, var_get_print_format (old_var)); + var_set_write_format (new_var, var_get_write_format (old_var)); + var_set_value_labels (new_var, var_get_value_labels (old_var)); + var_set_label (new_var, var_get_label (old_var)); + var_set_measure (new_var, var_get_measure (old_var)); + var_set_display_width (new_var, var_get_display_width (old_var)); + var_set_alignment (new_var, var_get_alignment (old_var)); + var_set_leave (new_var, var_get_leave (old_var)); - return id_hash; + return new_var; +} + +/* Destroys variable V. + V must not belong to a dictionary. If it does, use + dict_delete_var instead. */ +void +var_destroy (struct variable *v) +{ + if (v != NULL) + { + assert (!var_has_vardict (v)); + cat_stored_values_destroy (v->obs_vals); + var_clear_aux (v); + val_labs_destroy (v->val_labs); + var_clear_label (v); + free (v); + } } +/* Variable names. */ + /* Return variable V's name. */ const char * var_get_name (const struct variable *v) @@ -170,12 +198,14 @@ var_get_name (const struct variable *v) return v->name; } -/* Sets V's name to NAME. */ +/* Sets V's name to NAME. + Do not use this function for a variable in a dictionary. Use + dict_rename_var instead. */ void var_set_name (struct variable *v, const char *name) { - assert (name[0] != '\0'); - assert (lex_id_to_token (ss_cstr (name)) == T_ID); + assert (v->vardict.dict_index == -1); + assert (var_is_plausible_name (name, false)); str_copy_trunc (v->name, sizeof v->name, name); } @@ -226,8 +256,7 @@ var_is_valid_name (const char *name, bool issue_error) return true; } -/* - Returns true if NAME is an plausible name for a variable, +/* Returns true if NAME is an plausible name for a variable, false otherwise. If ISSUE_ERROR is true, issues an explanatory error message on failure. This function makes no use of LC_CTYPE. @@ -270,27 +299,28 @@ var_is_plausible_name (const char *name, bool issue_error) /* A hsh_compare_func that orders variables A and B by their names. */ int -compare_var_names (const void *a_, const void *b_, const void *aux UNUSED) +compare_vars_by_name (const void *a_, const void *b_, const void *aux UNUSED) { const struct variable *a = a_; const struct variable *b = b_; - return strcasecmp (var_get_name (a), var_get_name (b)); + return strcasecmp (a->name, b->name); } /* A hsh_hash_func that hashes variable V based on its name. */ unsigned -hash_var_name (const void *v_, const void *aux UNUSED) +hash_var_by_name (const void *v_, const void *aux UNUSED) { const struct variable *v = v_; - return hsh_hash_case_string (var_get_name (v)); + return hsh_hash_case_string (v->name); } /* A hsh_compare_func that orders pointers to variables A and B by their names. */ int -compare_var_ptr_names (const void *a_, const void *b_, const void *aux UNUSED) +compare_var_ptrs_by_name (const void *a_, const void *b_, + const void *aux UNUSED) { struct variable *const *a = a_; struct variable *const *b = b_; @@ -301,25 +331,18 @@ compare_var_ptr_names (const void *a_, const void *b_, const void *aux UNUSED) /* A hsh_hash_func that hashes pointer to variable V based on its name. */ unsigned -hash_var_ptr_name (const void *v_, const void *aux UNUSED) +hash_var_ptr_by_name (const void *v_, const void *aux UNUSED) { struct variable *const *v = v_; return hsh_hash_case_string (var_get_name (*v)); } -/* Returns the type of a variable with the given WIDTH. */ -static enum var_type -width_to_type (int width) -{ - return width == 0 ? NUMERIC : ALPHA; -} - /* Returns the type of variable V. */ enum var_type var_get_type (const struct variable *v) { - return width_to_type (v->width); + return var_type_from_width (v->width); } /* Returns the width of variable V. */ @@ -333,7 +356,7 @@ var_get_width (const struct variable *v) void var_set_width (struct variable *v, int new_width) { - enum var_type new_type = width_to_type (new_width); + enum var_type new_type = var_type_from_width (new_width); if (mv_is_resizable (&v->miss, new_width)) mv_resize (&v->miss, new_width); @@ -353,12 +376,12 @@ var_set_width (struct variable *v, int new_width) if (var_get_type (v) != new_type) { - v->print = (new_type == NUMERIC + v->print = (new_type == VAR_NUMERIC ? fmt_for_output (FMT_F, 8, 2) : fmt_for_output (FMT_A, new_width, 0)); v->write = v->print; } - else if (new_type == ALPHA) + else if (new_type == VAR_STRING) { v->print.w = v->print.type == FMT_AHEX ? new_width * 2 : new_width; v->write.w = v->write.type == FMT_AHEX ? new_width * 2 : new_width; @@ -371,7 +394,7 @@ var_set_width (struct variable *v, int new_width) bool var_is_numeric (const struct variable *v) { - return var_get_type (v) == NUMERIC; + return var_get_type (v) == VAR_NUMERIC; } /* Returns true if variable V is a string variable, false @@ -379,7 +402,7 @@ var_is_numeric (const struct variable *v) bool var_is_alpha (const struct variable *v) { - return var_get_type (v) == ALPHA; + return var_get_type (v) == VAR_STRING; } /* Returns true if variable V is a short string variable, false @@ -398,14 +421,14 @@ var_is_long_string (const struct variable *v) return v->width > MAX_SHORT_STRING; } -/* Returns true if variable V is a very long string variable, - false otherwise. */ -bool -var_is_very_long_string (const struct variable *v) +/* Returns the number of "union value"s need to store a value of + variable V. */ +size_t +var_get_value_cnt (const struct variable *v) { - return v->width > MAX_LONG_STRING; + return v->width == 0 ? 1 : DIV_RND_UP (v->width, MAX_SHORT_STRING); } - + /* Returns variable V's missing values. */ const struct missing_values * var_get_missing_values (const struct variable *v) @@ -413,15 +436,18 @@ var_get_missing_values (const struct variable *v) return &v->miss; } -/* Sets variable V's missing values to MISS, which must be of the - correct width. */ +/* Sets variable V's missing values to MISS, which must be of V's + width or at least resizable to V's width. + If MISS is null, then V's missing values, if any, are + cleared. */ void var_set_missing_values (struct variable *v, const struct missing_values *miss) { if (miss != NULL) { - assert (v->width == mv_get_width (miss)); + assert (mv_is_resizable (miss, v->width)); mv_copy (&v->miss, miss); + mv_resize (&v->miss, v->width); } else mv_init (&v->miss, v->width); @@ -502,6 +528,104 @@ var_is_value_system_missing (const struct variable *v, return mv_is_value_system_missing (&v->miss, value); } +/* Returns variable V's value labels, + possibly a null pointer if it has none. */ +const struct val_labs * +var_get_value_labels (const struct variable *v) +{ + return v->val_labs; +} + +/* Returns true if variable V has at least one value label. */ +bool +var_has_value_labels (const struct variable *v) +{ + return val_labs_count (v->val_labs) > 0; +} + +/* Sets variable V's value labels to a copy of VLS, + which must have a width equal to V's width or one that can be + changed to V's width. + If VLS is null, then V's value labels, if any, are removed. */ +void +var_set_value_labels (struct variable *v, const struct val_labs *vls) +{ + val_labs_destroy (v->val_labs); + v->val_labs = NULL; + + if (vls != NULL) + { + assert (val_labs_can_set_width (vls, v->width)); + v->val_labs = val_labs_copy (vls); + val_labs_set_width (v->val_labs, v->width); + } +} + +/* Makes sure that V has a set of value labels, + by assigning one to it if necessary. */ +static void +alloc_value_labels (struct variable *v) +{ + assert (!var_is_long_string (v)); + if (v->val_labs == NULL) + v->val_labs = val_labs_create (v->width); +} + +/* Attempts to add a value label with the given VALUE and LABEL + to V. Returns true if successful, false if VALUE has an + existing label. + V must not be a long string variable. */ +bool +var_add_value_label (struct variable *v, + const union value *value, const char *label) +{ + alloc_value_labels (v); + return val_labs_add (v->val_labs, *value, label); +} + +/* Adds or replaces a value label with the given VALUE and LABEL + to V. + V must not be a long string variable. */ +void +var_replace_value_label (struct variable *v, + const union value *value, const char *label) +{ + alloc_value_labels (v); + val_labs_replace (v->val_labs, *value, label); +} + +/* Removes V's value labels, if any. */ +void +var_clear_value_labels (struct variable *v) +{ + var_set_value_labels (v, NULL); +} + +/* Returns the label associated with VALUE for variable V, + or a null pointer if none. */ +const char * +var_lookup_value_label (const struct variable *v, const union value *value) +{ + return val_labs_find (v->val_labs, *value); +} + +/* Get a string representing VALUE for variable V. + That is, if VALUE has a label, return that label, + otherwise format VALUE and return the formatted string. */ +const char * +var_get_value_name (const struct variable *v, const union value *value) +{ + const char *name = var_lookup_value_label (v, value); + if (name == NULL) + { + static char buf[MAX_STRING + 1]; + data_out (value, &v->print, buf); + buf[v->print.w] = '\0'; + name = buf; + } + return name; +} + /* Print and write formats. */ /* Returns V's print format specification. */ @@ -548,6 +672,15 @@ var_set_both_formats (struct variable *v, const struct fmt_spec *format) var_set_write_format (v, format); } +/* Return a string representing this variable, in the form most + appropriate from a human factors perspective, that is, its + variable label if it has one, otherwise its name. */ +const char * +var_to_string (const struct variable *v) +{ + return v->label != NULL ? v->label : v->name; +} + /* Returns V's variable label, or a null pointer if it has none. */ const char * var_get_label (const struct variable *v) @@ -591,6 +724,14 @@ var_has_label (const struct variable *v) return v->label != NULL; } +/* Returns true if M is a valid variable measurement level, + false otherwise. */ +bool +measure_is_valid (enum measure m) +{ + return m == MEASURE_NOMINAL || m == MEASURE_ORDINAL || m == MEASURE_SCALE; +} + /* Returns V's measurement level. */ enum measure var_get_measure (const struct variable *v) @@ -605,7 +746,7 @@ var_set_measure (struct variable *v, enum measure measure) assert (measure_is_valid (measure)); v->measure = measure; } - + /* Returns V's display width, which applies only to GUIs. */ int var_get_display_width (const struct variable *v) @@ -619,6 +760,14 @@ var_set_display_width (struct variable *v, int display_width) { v->display_width = display_width; } + +/* Returns true if A is a valid alignment, + false otherwise. */ +bool +alignment_is_valid (enum alignment a) +{ + return a == ALIGN_LEFT || a == ALIGN_RIGHT || a == ALIGN_CENTRE; +} /* Returns V's display alignment, which applies only to GUIs. */ enum alignment @@ -635,21 +784,32 @@ var_set_alignment (struct variable *v, enum alignment alignment) v->alignment = alignment; } -/* Returns the number of "union value"s need to store a value of - variable V. */ -size_t -var_get_value_cnt (const struct variable *v) -{ - return v->width == 0 ? 1 : DIV_RND_UP (v->width, MAX_SHORT_STRING); -} +/* Whether variables' values should be preserved from case to + case. */ -/* Return whether variable V's values should be preserved from - case to case. */ +/* Returns true if variable V's value should be left from case to + case, instead of being reset to 0, system-missing, or blanks. */ bool var_get_leave (const struct variable *v) { return v->leave; } + +/* Sets V's leave setting to LEAVE. */ +void +var_set_leave (struct variable *v, bool leave) +{ + assert (leave || !var_must_leave (v)); + v->leave = leave; +} + +/* Returns true if V must be left from case to case, + false if it can be set either way. */ +bool +var_must_leave (const struct variable *v) +{ + return dict_class_from_id (v->name) == DC_SCRATCH; +} /* Returns V's short name, if it has one, or a null pointer otherwise. @@ -692,59 +852,119 @@ var_clear_short_name (struct variable *v) v->short_name[0] = '\0'; } + +/* Relationship with dictionary. */ -/* Sets V's short name to BASE, followed by a suffix of the form - _A, _B, _C, ..., _AA, _AB, etc. according to the value of - SUFFIX_NUMBER. Truncates BASE as necessary to fit. */ -void -var_set_short_name_suffix (struct variable *v, const char *base, - int suffix_number) +/* Returns V's index within its dictionary, the value + for which "dict_get_var (dict, index)" will return V. + V must be in a dictionary. */ +size_t +var_get_dict_index (const struct variable *v) { - char suffix[SHORT_NAME_LEN + 1]; - char short_name[SHORT_NAME_LEN + 1]; - char *start, *end; - int len, ofs; + assert (v->vardict.dict_index != -1); + return v->vardict.dict_index; +} - assert (v != NULL); - assert (suffix_number >= 0); +/* Returns V's index within the case represented by its + dictionary, that is, the value for which "case_data_idx (case, + index)" will return the data for V in that case. + V must be in a dictionary. */ +size_t +var_get_case_index (const struct variable *v) +{ + assert (v->vardict.case_index != -1); + return v->vardict.case_index; +} + +/* Returns V's auxiliary data, or a null pointer if none has been + attached. */ +void * +var_get_aux (const struct variable *v) +{ + return v->aux; +} + +/* Assign auxiliary data AUX to variable V, which must not + already have auxiliary data. Before V's auxiliary data is + cleared, AUX_DTOR(V) will be called. (var_dtor_free, below, + may be appropriate for use as AUX_DTOR.) */ +void * +var_attach_aux (struct variable *v, + void *aux, void (*aux_dtor) (struct variable *)) +{ + assert (v->aux == NULL); + assert (aux != NULL); + v->aux = aux; + v->aux_dtor = aux_dtor; + return aux; +} - /* Set base name. */ - var_set_short_name (v, base); +/* Remove auxiliary data, if any, from V, and return it, without + calling any associated destructor. */ +void * +var_detach_aux (struct variable *v) +{ + void *aux = v->aux; + assert (aux != NULL); + v->aux = NULL; + return aux; +} - /* Compose suffix. */ - start = end = suffix + sizeof suffix - 1; - *end = '\0'; - do +/* Clears auxiliary data, if any, from V, and calls any + associated destructor. */ +void +var_clear_aux (struct variable *v) +{ + assert (v != NULL); + if (v->aux != NULL) { - *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix_number % 26]; - if (start <= suffix + 1) - msg (SE, _("Variable suffix too large.")); - suffix_number /= 26; + if (v->aux_dtor != NULL) + v->aux_dtor (v); + v->aux = NULL; } - while (suffix_number > 0); - *--start = '_'; - - /* Append suffix to V's short name. */ - str_copy_trunc (short_name, sizeof short_name, base); - len = end - start; - if (len + strlen (short_name) > SHORT_NAME_LEN) - ofs = SHORT_NAME_LEN - len; - else - ofs = strlen (short_name); - strcpy (short_name + ofs, start); +} - /* Set name. */ - var_set_short_name (v, short_name); +/* This function is appropriate for use an auxiliary data + destructor (passed as AUX_DTOR to var_attach_aux()) for the + case where the auxiliary data should be passed to free(). */ +void +var_dtor_free (struct variable *v) +{ + free (v->aux); } + +/* Observed categorical values. */ +/* Returns V's observed categorical values, + which V must have. */ +struct cat_vals * +var_get_obs_vals (const struct variable *v) +{ + assert (v->obs_vals != NULL); + return v->obs_vals; +} +/* Sets V's observed categorical values to CAT_VALS. */ +void +var_set_obs_vals (struct variable *v, struct cat_vals *cat_vals) +{ + cat_stored_values_destroy (v->obs_vals); + v->obs_vals = cat_vals; +} + +/* Returns true if V has observed categorical values, + false otherwise. */ +bool +var_has_obs_vals (const struct variable *v) +{ + return v->obs_vals != NULL; +} + /* Returns the dictionary class corresponding to a variable named NAME. */ enum dict_class dict_class_from_id (const char *name) { - assert (name != NULL); - switch (name[0]) { default: @@ -772,25 +992,34 @@ dict_class_to_name (enum dict_class dict_class) NOT_REACHED (); } } - -/* Return the number of bytes used when writing case_data for a variable - of WIDTH */ -int -width_to_bytes(int width) + +/* Returns V's vardict structure. */ +const struct vardict_info * +var_get_vardict (const struct variable *v) { - assert (width >= 0); + assert (var_has_vardict (v)); + return &v->vardict; +} - if ( width == 0 ) - return MAX_SHORT_STRING ; - else if (width <= MAX_LONG_STRING) - return ROUND_UP (width, MAX_SHORT_STRING); - else - { - int chunks = width / EFFECTIVE_LONG_STRING_LENGTH ; - int remainder = width % EFFECTIVE_LONG_STRING_LENGTH ; - int bytes = remainder + (chunks * (MAX_LONG_STRING + 1) ); - return ROUND_UP (bytes, MAX_SHORT_STRING); - } +/* Sets V's vardict data to VARDICT. */ +void +var_set_vardict (struct variable *v, const struct vardict_info *vardict) +{ + assert (vardict->dict_index >= 0); + assert (vardict->case_index >= 0); + v->vardict = *vardict; } +/* Returns true if V has vardict data. */ +bool +var_has_vardict (const struct variable *v) +{ + return v->vardict.dict_index != -1; +} +/* Clears V's vardict data. */ +void +var_clear_vardict (struct variable *v) +{ + v->vardict.dict_index = v->vardict.case_index = -1; +} diff --git a/src/data/variable.h b/src/data/variable.h index 685c5104..0cb20b8f 100644 --- a/src/data/variable.h +++ b/src/data/variable.h @@ -20,101 +20,43 @@ #if !variable_h #define variable_h 1 - #include #include "config.h" #include -#include "category.h" -#include "format.h" -#include "missing-values.h" + +union value; /* Variable type. */ enum var_type { - NUMERIC, /* A numeric variable. */ - ALPHA /* A string variable. */ + VAR_NUMERIC, /* A numeric variable. */ + VAR_STRING /* A string variable. */ }; bool var_type_is_valid (enum var_type); -const char *var_type_adj (enum var_type); -const char *var_type_noun (enum var_type); +enum var_type var_type_from_width (int width); -/* Alignment of data for display. */ -enum alignment - { - ALIGN_LEFT = 0, - ALIGN_RIGHT = 1, - ALIGN_CENTRE = 2, - n_ALIGN - }; +/* Variables. */ +struct variable *var_create (const char *name, int width); +struct variable *var_clone (const struct variable *); +void var_destroy (struct variable *); -bool alignment_is_valid (enum alignment); +/* Variable names. + Long variable names can be used in most contexts, but a few + procedures and file formats are limited to short names. */ +#define SHORT_NAME_LEN 8 +#define LONG_NAME_LEN 64 -/* How data is measured. */ -enum measure - { - MEASURE_NOMINAL = 1, - MEASURE_ORDINAL = 2, - MEASURE_SCALE = 3, - n_MEASURES - }; - -bool measure_is_valid (enum measure); - -/* Maximum lengths of short and long variable names. - Most operations support long variable names, - but some file formats are limited to short names. */ -#define SHORT_NAME_LEN 8 /* Short name length. */ -#define LONG_NAME_LEN 64 /* Long name length. */ - -/* A variable's dictionary entry. */ -struct variable - { - /* Dictionary information. */ - char name[LONG_NAME_LEN + 1]; /* Variable name. Mixed case. */ - int width; /* 0 for numeric, otherwise string width. */ - struct missing_values miss; /* Missing values. */ - struct fmt_spec print; /* Default format for PRINT. */ - struct fmt_spec write; /* Default format for WRITE. */ - struct val_labs *val_labs; /* Value labels. */ - char *label; /* Variable label. */ - - /* GUI information. */ - enum measure measure; /* Nominal, ordinal, or continuous. */ - int display_width; /* Width of data editor column. */ - enum alignment alignment; /* Alignment of data in GUI. */ - - /* Case information. */ - int fv; /* Index into `value's. */ - bool leave; /* Leave value from case to case? */ - - /* Data for use by containing dictionary. */ - int index; /* Dictionary index. */ - - /* Short name, used only for system and portable file input - and output. Upper case only. There is no index for short - names. Short names are not necessarily unique. Any - variable may have no short name, indicated by an empty - string. */ - char short_name[SHORT_NAME_LEN + 1]; - - /* Each command may use these fields as needed. */ - void *aux; - void (*aux_dtor) (struct variable *); - - /* Values of a categorical variable. Procedures need - vectors with binary entries, so any variable of type ALPHA will - have its values stored here. */ - struct cat_vals *obs_vals; - }; - -/* Variable names. */ const char *var_get_name (const struct variable *); void var_set_name (struct variable *, const char *); bool var_is_valid_name (const char *, bool issue_error); bool var_is_plausible_name (const char *name, bool issue_error); -int compare_var_names (const void *, const void *, const void *); -unsigned hash_var_name (const void *, const void *); + +int compare_vars_by_name (const void *, const void *, const void *); +unsigned hash_var_by_name (const void *, const void *); + +int compare_var_ptrs_by_name (const void *, const void *, const void *); +unsigned hash_var_ptr_by_name (const void *, const void *); /* Variable types and widths. */ enum var_type var_get_type (const struct variable *); @@ -124,7 +66,7 @@ bool var_is_numeric (const struct variable *); bool var_is_alpha (const struct variable *); bool var_is_short_string (const struct variable *); bool var_is_long_string (const struct variable *); -bool var_is_very_long_string (const struct variable *); +size_t var_get_value_cnt (const struct variable *); /* Variables' missing values. */ const struct missing_values *var_get_missing_values (const struct variable *); @@ -144,6 +86,19 @@ bool var_is_str_user_missing (const struct variable *, const char[]); bool var_is_value_system_missing (const struct variable *, const union value *); +/* Value labels. */ +const struct val_labs *var_get_value_labels (const struct variable *); +bool var_has_value_labels (const struct variable *); +void var_set_value_labels (struct variable *, const struct val_labs *); +bool var_add_value_label (struct variable *, + const union value *, const char *); +void var_replace_value_label (struct variable *, + const union value *, const char *); +void var_clear_value_labels (struct variable *); +const char *var_lookup_value_label (const struct variable *, + const union value *); +const char *var_get_value_name (const struct variable *, const union value *); + /* Print and write formats. */ const struct fmt_spec *var_get_print_format (const struct variable *); void var_set_print_format (struct variable *, const struct fmt_spec *); @@ -152,45 +107,70 @@ void var_set_write_format (struct variable *, const struct fmt_spec *); void var_set_both_formats (struct variable *, const struct fmt_spec *); /* Variable labels. */ +const char *var_to_string (const struct variable *); const char *var_get_label (const struct variable *); void var_set_label (struct variable *, const char *); void var_clear_label (struct variable *); bool var_has_label (const struct variable *); -/* GUI information. */ +/* How data is measured. */ +enum measure + { + MEASURE_NOMINAL = 1, + MEASURE_ORDINAL = 2, + MEASURE_SCALE = 3, + n_MEASURES + }; + +bool measure_is_valid (enum measure); enum measure var_get_measure (const struct variable *); void var_set_measure (struct variable *, enum measure); +/* GUI display width. */ int var_get_display_width (const struct variable *); void var_set_display_width (struct variable *, int display_width); +/* Alignment of data for display. */ +enum alignment + { + ALIGN_LEFT = 0, + ALIGN_RIGHT = 1, + ALIGN_CENTRE = 2, + n_ALIGN + }; + +bool alignment_is_valid (enum alignment); enum alignment var_get_alignment (const struct variable *); void var_set_alignment (struct variable *, enum alignment); -/* Variable location in cases. */ -size_t var_get_value_cnt (const struct variable *); - /* Whether variables' values should be preserved from case to case. */ bool var_get_leave (const struct variable *); +void var_set_leave (struct variable *, bool leave); +bool var_must_leave (const struct variable *); /* Short names. */ const char *var_get_short_name (const struct variable *); void var_set_short_name (struct variable *, const char *); -void var_set_short_name_suffix (struct variable *, const char *, int suffix); void var_clear_short_name (struct variable *); -/* Pointers to `struct variable', by name. */ -int compare_var_ptr_names (const void *, const void *, const void *); -unsigned hash_var_ptr_name (const void *, const void *); +/* Relationship with dictionary. */ +size_t var_get_dict_index (const struct variable *); +size_t var_get_case_index (const struct variable *); /* Variable auxiliary data. */ +void *var_get_aux (const struct variable *); void *var_attach_aux (struct variable *, void *aux, void (*aux_dtor) (struct variable *)); void var_clear_aux (struct variable *); void *var_detach_aux (struct variable *); void var_dtor_free (struct variable *); +/* Observed categorical values. */ +struct cat_vals *var_get_obs_vals (const struct variable *); +void var_set_obs_vals (struct variable *, struct cat_vals *); +bool var_has_obs_vals (const struct variable *); + /* Classes of variables. */ enum dict_class { @@ -201,27 +181,5 @@ enum dict_class enum dict_class dict_class_from_id (const char *name); const char *dict_class_to_name (enum dict_class dict_class); - -/* Vector of variables. */ -struct vector - { - int idx; /* Index for dict_get_vector(). */ - char name[LONG_NAME_LEN + 1]; /* Name. */ - struct variable **var; /* Vector of variables. */ - int cnt; /* Number of variables. */ - }; - - -/* Return a string representing this variable, in the form most - appropriate from a human factors perspective. - (IE: the label if it has one, otherwise the name ) -*/ -const char * var_to_string(const struct variable *var); - - -int width_to_bytes(int width); - -union value * value_dup (const union value *val, int width); - #endif /* !variable.h */ diff --git a/src/data/vector.c b/src/data/vector.c new file mode 100644 index 00000000..8f3de2f3 --- /dev/null +++ b/src/data/vector.c @@ -0,0 +1,146 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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 the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include "vector.h" + +#include "dictionary.h" + +#include +#include + +#include "xalloc.h" + +/* Vector of variables. */ +struct vector + { + char name[LONG_NAME_LEN + 1]; /* Name. */ + struct variable **vars; /* Set of variables. */ + size_t var_cnt; /* Number of variables. */ + }; + +/* Checks that all the variables in VECTOR have consistent + width. */ +static void +check_widths (const struct vector *vector) +{ + int width = var_get_width (vector->vars[0]); + size_t i; + + for (i = 1; i < vector->var_cnt; i++) + assert (width == var_get_width (vector->vars[i])); +} + +/* Creates and returns a new vector with the given NAME + that contains the VAR_CNT variables in VARS. + All variables in VARS must have the same type and width. */ +struct vector * +vector_create (const char *name, + struct variable **vars, size_t var_cnt) +{ + struct vector *vector = xmalloc (sizeof *vector); + + assert (var_cnt > 0); + assert (var_is_plausible_name (name, false)); + str_copy_trunc (vector->name, sizeof vector->name, name); + + vector->vars = xmemdup (vars, var_cnt * sizeof *vector->vars); + vector->var_cnt = var_cnt; + check_widths (vector); + + return vector; +} + +/* Creates and returns a new vector as a clone of OLD, but that + contains variables from NEW_DICT that are in the same position + as those in OLD are in OLD_DICT. + All variables in the new vector must have the same type and + width. */ +struct vector * +vector_clone (const struct vector *old, + const struct dictionary *old_dict, + const struct dictionary *new_dict) +{ + struct vector *new = xmalloc (sizeof *new); + size_t i; + + strcpy (new->name, old->name); + + new->vars = xnmalloc (old->var_cnt, sizeof *new->vars); + new->var_cnt = old->var_cnt; + for (i = 0; i < new->var_cnt; i++) + { + assert (dict_contains_var (old_dict, old->vars[i])); + new->vars[i] = dict_get_var (new_dict, + var_get_dict_index (old->vars[i])); + } + check_widths (new); + + return new; +} + +/* Destroys VECTOR. */ +void +vector_destroy (struct vector *vector) +{ + free (vector->vars); + free (vector); +} + +/* Returns VECTOR's name. */ +const char * +vector_get_name (const struct vector *vector) +{ + return vector->name; +} + +/* Returns the type of the variables in VECTOR. */ +enum var_type vector_get_type (const struct vector *vector) +{ + return var_get_type (vector->vars[0]); +} + +/* Returns the variable in VECTOR with the given INDEX. */ +struct variable * +vector_get_var (const struct vector *vector, size_t index) +{ + assert (index < vector->var_cnt); + return vector->vars[index]; +} + +/* Returns the number of variables in VECTOR. */ +size_t +vector_get_var_cnt (const struct vector *vector) +{ + return vector->var_cnt; +} + +/* Compares two pointers to vectors represented by A and B and + returns a strcmp()-type result. */ +int +compare_vector_ptrs_by_name (const void *a_, const void *b_) +{ + struct vector *const *pa = a_; + struct vector *const *pb = b_; + struct vector *a = *pa; + struct vector *b = *pb; + + return strcasecmp (a->name, b->name); +} + diff --git a/src/data/vector.h b/src/data/vector.h new file mode 100644 index 00000000..18ac4967 --- /dev/null +++ b/src/data/vector.h @@ -0,0 +1,42 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Ben Pfaff . + + 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 the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef DATA_VECTOR_H +#define DATA_VECTOR_H 1 + +#include +#include + +struct dictionary; + +struct vector *vector_create (const char *name, + struct variable **var, size_t var_cnt); +struct vector *vector_clone (const struct vector *old, + const struct dictionary *old_dict, + const struct dictionary *new_dict); +void vector_destroy (struct vector *); + +const char *vector_get_name (const struct vector *); +enum var_type vector_get_type (const struct vector *); +struct variable *vector_get_var (const struct vector *, size_t idx); +size_t vector_get_var_cnt (const struct vector *); + +int compare_vector_ptrs_by_name (const void *a_, const void *b_); + +#endif /* data/vector.h */ diff --git a/src/language/control/do-if.c b/src/language/control/do-if.c index 51c3ec9f..b02077b5 100644 --- a/src/language/control/do-if.c +++ b/src/language/control/do-if.c @@ -24,7 +24,7 @@ #include "control-stack.h" #include #include -#include +#include #include #include #include diff --git a/src/language/control/loop.c b/src/language/control/loop.c index 01aad6fd..56df4b7a 100644 --- a/src/language/control/loop.c +++ b/src/language/control/loop.c @@ -294,7 +294,7 @@ loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num) /* Even if the loop is never entered, set the index variable to the initial value. */ - case_data_rw (c, loop->index_var->fv)->f = loop->cur; + case_data_rw (c, loop->index_var)->f = loop->cur; /* Throw out pathological cases. */ if (!finite (loop->cur) || !finite (loop->by) || !finite (loop->last) @@ -355,7 +355,7 @@ end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED) if ((loop->by > 0.0 && loop->cur > loop->last) || (loop->by < 0.0 && loop->cur < loop->last)) goto break_out; - case_data_rw (c, loop->index_var->fv)->f = loop->cur; + case_data_rw (c, loop->index_var)->f = loop->cur; } if (loop->loop_condition != NULL diff --git a/src/language/data-io/ChangeLog b/src/language/data-io/ChangeLog index 3c5313a0..5b49843a 100644 --- a/src/language/data-io/ChangeLog +++ b/src/language/data-io/ChangeLog @@ -1,3 +1,7 @@ +Sat Dec 9 18:43:34 2006 Ben Pfaff + + * list.q (cmd_list): Use new var_create, var_destroy functions. + Thu Nov 30 21:51:58 2006 Ben Pfaff * inpt-pgm.c (cmd_reread): Always return error code upon detecting diff --git a/src/language/data-io/data-list.c b/src/language/data-io/data-list.c index 641740fc..0c4caebf 100644 --- a/src/language/data-io/data-list.c +++ b/src/language/data-io/data-list.c @@ -370,7 +370,7 @@ parse_fixed (struct lexer *lexer, struct dictionary *dict, /* Create specifier for parsing the variable. */ spec = pool_alloc (dls->pool, sizeof *spec); spec->input = *f; - spec->fv = v->fv; + spec->fv = var_get_case_index (v); spec->record = record; spec->first_column = column; strcpy (spec->name, var_get_name (v)); @@ -498,7 +498,7 @@ parse_free (struct lexer *lexer, struct dictionary *dict, struct pool *tmp_pool, spec = pool_alloc (dls->pool, sizeof *spec); spec->input = input; - spec->fv = v->fv; + spec->fv = var_get_case_index (v); strcpy (spec->name, var_get_name (v)); ll_push_tail (&dls->specs, &spec->ll); } @@ -679,7 +679,7 @@ read_from_data_list_fixed (const struct data_list_pgm *dls, struct ccase *c) ll_for_each_continue (spec, struct dls_var_spec, ll, &dls->specs) data_in (ss_substr (line, spec->first_column - 1, spec->input.w), spec->input.type, spec->input.d, spec->first_column, - case_data_rw (c, spec->fv), fmt_var_width (&spec->input)); + case_data_rw_idx (c, spec->fv), fmt_var_width (&spec->input)); dfm_forward_record (dls->reader); } @@ -715,7 +715,7 @@ read_from_data_list_free (const struct data_list_pgm *dls, struct ccase *c) data_in (field, spec->input.type, 0, dfm_get_column (dls->reader, ss_data (field)), - case_data_rw (c, spec->fv), fmt_var_width (&spec->input)); + case_data_rw_idx (c, spec->fv), fmt_var_width (&spec->input)); } return true; } @@ -746,16 +746,16 @@ read_from_data_list_list (const struct data_list_pgm *dls, struct ccase *c) { int width = fmt_var_width (&spec->input); if (width == 0) - case_data_rw (c, spec->fv)->f = SYSMIS; + case_data_rw_idx (c, spec->fv)->f = SYSMIS; else - memset (case_data_rw (c, spec->fv)->s, ' ', width); + memset (case_data_rw_idx (c, spec->fv)->s, ' ', width); } break; } data_in (field, spec->input.type, 0, dfm_get_column (dls->reader, ss_data (field)), - case_data_rw (c, spec->fv), fmt_var_width (&spec->input)); + case_data_rw_idx (c, spec->fv), fmt_var_width (&spec->input)); } dfm_forward_record (dls->reader); @@ -794,7 +794,7 @@ data_list_trns_proc (void *dls_, struct ccase *c, casenumber case_num UNUSED) /* If there was an END subcommand handle it. */ if (dls->end != NULL) { - double *end = &case_data_rw (c, dls->end->fv)->f; + double *end = &case_data_rw (c, dls->end)->f; if (retval == TRNS_DROP_CASE) { *end = 1.0; diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index 90c41f2e..6e7206af 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1272,14 +1273,14 @@ mtf_delete_file_in_place (struct mtf_proc *mtf, struct mtf_file **file) *file = f->next; if (f->in_var != NULL) - case_data_rw (&mtf->mtf_case, f->in_var->fv)->f = 0.; + case_data_rw (&mtf->mtf_case, f->in_var)->f = 0.; for (i = 0; i < dict_get_var_cnt (f->dict); i++) { struct variable *v = dict_get_var (f->dict, i); struct variable *mv = get_master (v); if (mv != NULL) { - union value *out = case_data_rw (&mtf->mtf_case, mv->fv); + union value *out = case_data_rw (&mtf->mtf_case, mv); if (var_is_numeric (v)) out->f = SYSMIS; @@ -1427,23 +1428,23 @@ mtf_processing (const struct ccase *c, void *mtf_, const struct dataset *ds UNUS { struct variable *v = dict_get_var (iter->dict, i); struct variable *mv = get_master (v); + size_t mv_index = mv ? var_get_dict_index (mv) : 0; - if (mv != NULL && mtf->seq_nums[mv->index] != mtf->seq_num) + if (mv != NULL && mtf->seq_nums[mv_index] != mtf->seq_num) { const struct ccase *record = case_is_null (&iter->input) ? c : &iter->input; - union value *out = case_data_rw (&mtf->mtf_case, mv->fv); + union value *out = case_data_rw (&mtf->mtf_case, mv); - mtf->seq_nums[mv->index] = mtf->seq_num; + mtf->seq_nums[mv_index] = mtf->seq_num; if (var_is_numeric (v)) - out->f = case_num (record, v->fv); + out->f = case_num (record, v); else - memcpy (out->s, case_str (record, v->fv), - var_get_width (v)); + memcpy (out->s, case_str (record, v), var_get_width (v)); } } if (iter->in_var != NULL) - case_data_rw (&mtf->mtf_case, iter->in_var->fv)->f = 1.; + case_data_rw (&mtf->mtf_case, iter->in_var)->f = 1.; if (iter->type == MTF_FILE && iter->handle == NULL) read_active_file = true; @@ -1461,11 +1462,12 @@ mtf_processing (const struct ccase *c, void *mtf_, const struct dataset *ds UNUS { struct variable *v = dict_get_var (iter->dict, i); struct variable *mv = get_master (v); + size_t mv_index = mv ? var_get_dict_index (mv) : 0; - if (mv != NULL && mtf->seq_nums[mv->index] != mtf->seq_num) + if (mv != NULL && mtf->seq_nums[mv_index] != mtf->seq_num) { - union value *out = case_data_rw (&mtf->mtf_case, mv->fv); - mtf->seq_nums[mv->index] = mtf->seq_num; + union value *out = case_data_rw (&mtf->mtf_case, mv); + mtf->seq_nums[mv_index] = mtf->seq_num; if (var_is_numeric (v)) out->f = SYSMIS; @@ -1474,7 +1476,7 @@ mtf_processing (const struct ccase *c, void *mtf_, const struct dataset *ds UNUS } } if (iter->in_var != NULL) - case_data_rw (&mtf->mtf_case, iter->in_var->fv)->f = 0.; + case_data_rw (&mtf->mtf_case, iter->in_var)->f = 0.; } /* 5. Write the output record. */ @@ -1552,12 +1554,8 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) if (var_get_width (dv) == var_get_width (mv)) { - if (val_labs_count (dv->val_labs) - && !val_labs_count (mv->val_labs)) - { - val_labs_destroy (mv->val_labs); - mv->val_labs = val_labs_copy (dv->val_labs); - } + if (var_has_value_labels (dv) && !var_has_value_labels (mv)) + var_set_value_labels (mv, var_get_value_labels (dv)); if (var_has_missing_values (dv) && !var_has_missing_values (mv)) var_set_missing_values (mv, var_get_missing_values (dv)); } @@ -1584,7 +1582,7 @@ set_master (struct variable *v, struct variable *master) static struct variable * get_master (struct variable *v) { - return v->aux; + return var_get_aux (v); } /* Case map. @@ -1619,7 +1617,7 @@ start_case_map (struct dictionary *d) { struct variable *v = dict_get_var (d, i); int *src_fv = xmalloc (sizeof *src_fv); - *src_fv = v->fv; + *src_fv = var_get_case_index (v); var_attach_aux (v, src_fv, var_dtor_free); } } @@ -1654,13 +1652,13 @@ finish_case_map (struct dictionary *d) int *src_fv = (int *) var_detach_aux (v); size_t idx; - if (v->fv != *src_fv) + if (var_get_case_index (v) != *src_fv) identity_map = 0; for (idx = 0; idx < value_cnt; idx++) { int src_idx = *src_fv + idx; - int dst_idx = v->fv + idx; + int dst_idx = var_get_case_index (v) + idx; assert (map->map[dst_idx] == -1); map->map[dst_idx] = src_idx; @@ -1696,7 +1694,7 @@ map_case (const struct case_map *map, { int src_idx = map->map[dst_idx]; if (src_idx != -1) - *case_data_rw (dst, dst_idx) = *case_data (src, src_idx); + *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx); } } diff --git a/src/language/data-io/inpt-pgm.c b/src/language/data-io/inpt-pgm.c index 24a2e229..d3b04ed9 100644 --- a/src/language/data-io/inpt-pgm.c +++ b/src/language/data-io/inpt-pgm.c @@ -169,7 +169,7 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) value_init |= var_get_leave (var) ? INP_INIT_ONCE : INP_REINIT; for (j = 0; j < value_cnt; j++) - inp->init[j + var->fv] = value_init; + inp->init[j + var_get_case_index (var)] = value_init; } for (i = 0; i < inp->init_cnt; i++) assert (inp->init[i] != -1); @@ -198,14 +198,15 @@ init_case (const struct input_program_pgm *inp, struct ccase *c) switch (inp->init[i]) { case INP_NUMERIC | INP_INIT_ONCE: - case_data_rw (c, i)->f = 0.0; + case_data_rw_idx (c, i)->f = 0.0; break; case INP_NUMERIC | INP_REINIT: - case_data_rw (c, i)->f = SYSMIS; + case_data_rw_idx (c, i)->f = SYSMIS; break; case INP_STRING | INP_INIT_ONCE: case INP_STRING | INP_REINIT: - memset (case_data_rw (c, i)->s, ' ', sizeof case_data_rw (c, i)->s); + memset (case_data_rw_idx (c, i)->s, ' ', + sizeof case_data_rw_idx (c, i)->s); break; default: NOT_REACHED (); @@ -224,12 +225,13 @@ clear_case (const struct input_program_pgm *inp, struct ccase *c) case INP_NUMERIC | INP_INIT_ONCE: break; case INP_NUMERIC | INP_REINIT: - case_data_rw (c, i)->f = SYSMIS; + case_data_rw_idx (c, i)->f = SYSMIS; break; case INP_STRING | INP_INIT_ONCE: break; case INP_STRING | INP_REINIT: - memset (case_data_rw (c, i)->s, ' ', sizeof case_data_rw (c, i)->s); + memset (case_data_rw_idx (c, i)->s, ' ', + sizeof case_data_rw_idx (c, i)->s); break; default: NOT_REACHED (); diff --git a/src/language/data-io/list.q b/src/language/data-io/list.q index b1473fe6..0f6a708f 100644 --- a/src/language/data-io/list.q +++ b/src/language/data-io/list.q @@ -134,7 +134,7 @@ write_line (struct outp_driver *d, const char *s) int cmd_list (struct lexer *lexer, struct dataset *ds) { - struct variable casenum_var; + struct variable *casenum_var = NULL; bool ok; if (!parse_list (lexer, ds, &cmd, NULL)) @@ -215,10 +215,8 @@ cmd_list (struct lexer *lexer, struct dataset *ds) /* Initialize the case-number variable. */ int width = cmd.last == LONG_MAX ? 5 : intlog10 (cmd.last); struct fmt_spec format = fmt_for_output (FMT_F, width, 0); - var_set_name (&casenum_var, "Case#"); - casenum_var.width = 0; - casenum_var.fv = -1; - var_set_both_formats (&casenum_var, &format); + casenum_var = var_create ("Case#", 0); + var_set_both_formats (casenum_var, &format); /* Add the weight variable at the beginning of the variable list. */ cmd.n_variables++; @@ -226,7 +224,7 @@ cmd_list (struct lexer *lexer, struct dataset *ds) cmd.n_variables, sizeof *cmd.v_variables); memmove (&cmd.v_variables[1], &cmd.v_variables[0], (cmd.n_variables - 1) * sizeof *cmd.v_variables); - cmd.v_variables[0] = &casenum_var; + cmd.v_variables[0] = casenum_var; } determine_layout (); @@ -237,6 +235,8 @@ cmd_list (struct lexer *lexer, struct dataset *ds) clean_up (); + var_destroy (casenum_var); + return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE; } @@ -625,7 +625,7 @@ determine_layout (void) /* Writes case C to output. */ static bool -list_cases (const struct ccase *c, void *aux UNUSED, const struct dataset *ds UNUSED) +list_cases (const struct ccase *c, void *aux UNUSED, const struct dataset *ds) { struct outp_driver *d; @@ -681,9 +681,10 @@ list_cases (const struct ccase *c, void *aux UNUSED, const struct dataset *ds UN if (width > print->w) ds_put_char_multiple(&line_buffer, ' ', width - print->w); - if (fmt_is_string (print->type) || v->fv != -1) + if (fmt_is_string (print->type) + || dict_contains_var (dataset_dict (ds), v)) { - data_out (case_data (c, v->fv), print, + data_out (case_data (c, v), print, ds_put_uninit (&line_buffer, print->w)); } else @@ -719,8 +720,9 @@ list_cases (const struct ccase *c, void *aux UNUSED, const struct dataset *ds UN const struct fmt_spec *print = var_get_print_format (v); char buf[256]; - if (fmt_is_string (print->type) || v->fv != -1) - data_out (case_data (c, v->fv), print, buf); + if (fmt_is_string (print->type) + || dict_contains_var (dataset_dict (ds), v)) + data_out (case_data (c, v), print, buf); else { union value case_idx_value; diff --git a/src/language/data-io/matrix-data.c b/src/language/data-io/matrix-data.c index 4898e16f..79023ff3 100644 --- a/src/language/data-io/matrix-data.c +++ b/src/language/data-io/matrix-data.c @@ -351,8 +351,7 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds) for (i = 0; i < split_cnt; i++) { - struct mxd_var *mv = split[i]->aux; - assert (mv != NULL); + struct mxd_var *mv = var_get_aux (split[i]); if (mv->var_type != MXD_CONTINUOUS) { msg (SE, _("Split variable %s is already another type."), @@ -385,8 +384,7 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds) for (i = 0; i < mx->n_factors; i++) { struct variable *v = mx->factors[i]; - struct mxd_var *mv = v->aux; - assert (mv != NULL); + struct mxd_var *mv = var_get_aux (v); if (mv->var_type != MXD_CONTINUOUS) { msg (SE, _("Factor variable %s is already another type."), @@ -606,7 +604,7 @@ cmd_matrix_data (struct lexer *lexer, struct dataset *ds) for (i = 0; i < dict_get_var_cnt (dataset_dict (ds)); i++) { struct variable *v = dict_get_var (dataset_dict (ds), i); - struct mxd_var *mv = v->aux; + struct mxd_var *mv = var_get_aux (v); int type = mv->var_type; assert (type >= 0 && type < MXD_COUNT); @@ -699,8 +697,8 @@ compare_variables_by_mxd_var_type (const void *a_, const void *b_) { struct variable *const *pa = a_; struct variable *const *pb = b_; - const struct mxd_var *a = (*pa)->aux; - const struct mxd_var *b = (*pb)->aux; + const struct mxd_var *a = var_get_aux (*pa); + const struct mxd_var *b = var_get_aux (*pb); if (a->var_type != b->var_type) return a->var_type > b->var_type ? 1 : -1; @@ -715,7 +713,7 @@ attach_mxd_aux (struct variable *v, int var_type, int sub_type) { struct mxd_var *mv; - assert (v->aux == NULL); + assert (var_get_aux (v) == NULL); mv = xmalloc (sizeof *mv); mv->var_type = var_type; mv->sub_type = sub_type; @@ -1232,7 +1230,7 @@ nr_read_splits (struct nr_aux_data *nr, int compare) { if (!compare) { - struct mxd_var *mv = dict_get_split_vars (nr->dict)[0]->aux; + struct mxd_var *mv = var_get_aux (dict_get_split_vars (nr->dict)[0]); nr->split_values[0] = ++mv->sub_type; } return true; @@ -1331,11 +1329,11 @@ dump_cell_content (const struct dictionary *dict, int type = content_type[content]; { - buf_copy_str_rpad (case_data_rw (c, mx->rowtype_->fv)->s, 8, + buf_copy_str_rpad (case_data_rw (c, mx->rowtype_)->s, 8, content_names[content]); if (type != 1) - memset (case_data_rw (c, mx->varname_->fv)->s, ' ', 8); + memset (case_data_rw (c, mx->varname_)->s, ' ', 8); } { @@ -1348,12 +1346,12 @@ dump_cell_content (const struct dictionary *dict, for (j = 0; j < mx->n_continuous; j++) { - int fv = dict_get_var (dict, mx->first_continuous + j)->fv; - case_data_rw (c, fv)->f = *cp; + struct variable *v = dict_get_var (dict, mx->first_continuous + j); + case_data_rw (c, v)->f = *cp; cp++; } if (type == 1) - buf_copy_str_rpad (case_data_rw (c, mx->varname_->fv)->s, 8, + buf_copy_str_rpad (case_data_rw (c, mx->varname_)->s, 8, var_get_name ( dict_get_var (dict, mx->first_continuous + i))); if (!write_case (wc_data)) @@ -1378,7 +1376,7 @@ nr_output_data (struct nr_aux_data *nr, struct ccase *c, split_cnt = dict_get_split_cnt (nr->dict); split = dict_get_split_vars (nr->dict); for (i = 0; i < split_cnt; i++) - case_data_rw (c, split[i]->fv)->f = nr->split_values[i]; + case_data_rw (c, split[i])->f = nr->split_values[i]; } if (mx->n_factors) @@ -1391,7 +1389,7 @@ nr_output_data (struct nr_aux_data *nr, struct ccase *c, size_t factor; for (factor = 0; factor < mx->n_factors; factor++) - case_data_rw (c, mx->factors[factor]->fv)->f + case_data_rw (c, mx->factors[factor])->f = nr->factor_values[factor + cell * mx->n_factors]; } @@ -1420,7 +1418,7 @@ nr_output_data (struct nr_aux_data *nr, struct ccase *c, size_t factor; for (factor = 0; factor < mx->n_factors; factor++) - case_data_rw (c, mx->factors[factor]->fv)->f = SYSMIS; + case_data_rw (c, mx->factors[factor])->f = SYSMIS; } for (content = 0; content <= PROX; content++) @@ -1631,7 +1629,7 @@ wr_output_data (struct wr_aux_data *wr, split_cnt = dict_get_split_cnt (wr->dict); split = dict_get_split_vars (wr->dict); for (i = 0; i < split_cnt; i++) - case_data_rw (c, split[i]->fv)->f = wr->split_values[i]; + case_data_rw (c, split[i])->f = wr->split_values[i]; } /* Sort the wr->data list. */ @@ -1665,8 +1663,7 @@ wr_output_data (struct wr_aux_data *wr, size_t factor; for (factor = 0; factor < mx->n_factors; factor++) - case_data_rw (c, mx->factors[factor]->fv)->f - = iter->factors[factor]; + case_data_rw (c, mx->factors[factor])->f = iter->factors[factor]; } { diff --git a/src/language/data-io/print-space.c b/src/language/data-io/print-space.c index 8ddd0be5..f26e1f25 100644 --- a/src/language/data-io/print-space.c +++ b/src/language/data-io/print-space.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include diff --git a/src/language/data-io/print.c b/src/language/data-io/print.c index 374415b5..cb344193 100644 --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@ -460,7 +460,7 @@ print_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED) ds_set_length (&trns->line, spec->first_column, ' '); if (spec->type == PRT_VAR) { - const union value *input = case_data (c, spec->var->fv); + const union value *input = case_data (c, spec->var); char *output = ds_put_uninit (&trns->line, spec->format.w); if (!spec->sysmis_as_spaces || input->f != SYSMIS) data_out (input, &spec->format, output); diff --git a/src/language/dictionary/ChangeLog b/src/language/dictionary/ChangeLog index a1d42607..e2d7d80f 100644 --- a/src/language/dictionary/ChangeLog +++ b/src/language/dictionary/ChangeLog @@ -1,3 +1,11 @@ +Sat Dec 9 18:44:26 2006 Ben Pfaff + + * variable-label.c: Move to src/data/variable.c. + + * vector.c (cmd_vector): Use PV_SAME_WIDTH in parse_variables + call, because string variables in a vector must have the same + width. + Thu Nov 30 22:06:21 2006 Ben Pfaff * value-labels.c (get_label): Allow commas between values and diff --git a/src/language/dictionary/apply-dictionary.c b/src/language/dictionary/apply-dictionary.c index da9a9731..4a2b9cb6 100644 --- a/src/language/dictionary/apply-dictionary.c +++ b/src/language/dictionary/apply-dictionary.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -86,32 +87,27 @@ cmd_apply_dictionary (struct lexer *lexer, struct dataset *ds) var_set_label (t, label); } - if (val_labs_count (s->val_labs) && var_is_long_string (t)) - msg (SW, _("Cannot add value labels from source file to " - "long string variable %s."), - var_get_name (s)); - else if (val_labs_count (s->val_labs)) - { - if (val_labs_can_set_width (s->val_labs, var_get_width (t))) + if (var_has_value_labels (s)) + { + if (!var_is_long_string (t)) { - val_labs_destroy (t->val_labs); - t->val_labs = s->val_labs; - val_labs_set_width (t->val_labs, var_get_width (t)); - s->val_labs = val_labs_create (var_get_width (s)); + const struct val_labs *value_labels = var_get_value_labels (s); + if (val_labs_can_set_width (value_labels, var_get_width (t))) + var_set_value_labels (s, value_labels); } - } - + else + msg (SW, _("Cannot add value labels from source file to " + "long string variable %s."), + var_get_name (s)); + } + if (var_has_missing_values (s)) { if (!var_is_long_string (t)) { - struct missing_values miss; - mv_copy (&miss, var_get_missing_values (s)); - if (mv_is_resizable (&miss, var_get_width (t))) - { - mv_resize (&miss, var_get_width (t)); - var_set_missing_values (t, &miss); - } + const struct missing_values *miss = var_get_missing_values (s); + if (mv_is_resizable (miss, var_get_width (t))) + var_set_missing_values (t, miss); } else msg (SW, _("Cannot apply missing values from source file to " diff --git a/src/language/dictionary/formats.c b/src/language/dictionary/formats.c index 34599e6b..b7fa47b8 100644 --- a/src/language/dictionary/formats.c +++ b/src/language/dictionary/formats.c @@ -94,7 +94,7 @@ internal_cmd_formats (struct lexer *lexer, struct dataset *ds, int which) } if (!parse_format_specifier (lexer, &f) || !fmt_check_output (&f) - || !fmt_check_type_compat (&f, NUMERIC)) + || !fmt_check_type_compat (&f, VAR_NUMERIC)) goto fail; if (!lex_match (lexer, ')')) diff --git a/src/language/dictionary/missing-values.c b/src/language/dictionary/missing-values.c index 99018c3f..af7eeec9 100644 --- a/src/language/dictionary/missing-values.c +++ b/src/language/dictionary/missing-values.c @@ -22,7 +22,9 @@ #include #include +#include #include +#include #include #include #include @@ -133,20 +135,15 @@ cmd_missing_values (struct lexer *lexer, struct dataset *ds) for (i = 0; i < nv; i++) { - if (!mv_is_resizable (&mv, var_get_width (v[i]))) + if (mv_is_resizable (&mv, var_get_width (v[i]))) + var_set_missing_values (v[i], &mv); + else { msg (SE, _("Missing values provided are too long to assign " "to variable of width %d."), var_get_width (v[i])); deferred_errors = true; } - else - { - struct missing_values tmp; - mv_copy (&tmp, &mv); - mv_resize (&tmp, var_get_width (v[i])); - var_set_missing_values (v[i], &tmp); - } } } diff --git a/src/language/dictionary/modify-variables.c b/src/language/dictionary/modify-variables.c index 1e42cb6d..5322c2e3 100644 --- a/src/language/dictionary/modify-variables.c +++ b/src/language/dictionary/modify-variables.c @@ -354,8 +354,12 @@ compare_variables_given_ordering (const void *a_, const void *b_, const struct ordering *ordering = ordering_; int result; - if (ordering->positional) - result = a->index < b->index ? -1 : a->index > b->index; + if (ordering->positional) + { + size_t a_index = var_get_dict_index (a); + size_t b_index = var_get_dict_index (b); + result = a_index < b_index ? -1 : a_index > b_index; + } else result = strcasecmp (var_get_name (a), var_get_name (b)); if (!ordering->forward) diff --git a/src/language/dictionary/numeric.c b/src/language/dictionary/numeric.c index 29155961..aa6794d3 100644 --- a/src/language/dictionary/numeric.c +++ b/src/language/dictionary/numeric.c @@ -185,7 +185,7 @@ cmd_leave (struct lexer *lexer, struct dataset *ds) if (!parse_variables (lexer, dataset_dict (ds), &v, &nv, PV_NONE)) return CMD_CASCADING_FAILURE; for (i = 0; i < nv; i++) - v[i]->leave = true; + var_set_leave (v[i], true); free (v); return lex_end_of_command (lexer); diff --git a/src/language/dictionary/split-file.c b/src/language/dictionary/split-file.c index 05b39bc0..6944792f 100644 --- a/src/language/dictionary/split-file.c +++ b/src/language/dictionary/split-file.c @@ -96,12 +96,12 @@ output_split_file_values (const struct dataset *ds, const struct ccase *c) tab_text (t, 0, i + 1, TAB_LEFT | TAT_PRINTF, "%s", var_get_name (v)); - data_out (case_data (c, v->fv), print, temp_buf); + data_out (case_data (c, v), print, temp_buf); temp_buf[print->w] = 0; tab_text (t, 1, i + 1, TAT_PRINTF, "%.*s", print->w, temp_buf); - val_lab = val_labs_find (v->val_labs, *case_data (c, v->fv)); + val_lab = var_lookup_value_label (v, case_data (c, v)); if (val_lab) tab_text (t, 2, i + 1, TAB_LEFT, val_lab); } diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index 220faa3b..47d151ee 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -24,10 +24,13 @@ #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -151,7 +154,7 @@ cmd_sysfile_info (struct lexer *lexer, struct dataset *ds UNUSED) for (r = 1, i = 0; i < dict_get_var_cnt (d); i++) { struct variable *v = dict_get_var (d, i); - const int nvl = val_labs_count (v->val_labs); + const int nvl = val_labs_count (var_get_value_labels (v)); if (r + 10 + nvl > nr) { @@ -275,7 +278,7 @@ cmd_display (struct lexer *lexer, struct dataset *ds) } if (sorted) - sort (vl, n, sizeof *vl, compare_var_ptr_names, NULL); + sort (vl, n, sizeof *vl, compare_var_ptrs_by_name, NULL); display_variables (vl, n, as); @@ -399,7 +402,7 @@ display_variables (struct variable **vl, size_t n, int as) if (as == AS_DICTIONARY || as == AS_VARIABLES) { - int nvl = val_labs_count (v->val_labs); + int nvl = val_labs_count (var_get_value_labels (v)); if (r + 10 + nvl > nr) { @@ -419,7 +422,8 @@ display_variables (struct variable **vl, size_t n, int as) } if (as != AS_NAMES) { - tab_text (t, pc, r, TAT_PRINTF, "%d", v->index + 1); + tab_text (t, pc, r, TAT_PRINTF, "%d", + (int) var_get_dict_index (v) + 1); tab_hline (t, TAL_1, 0, nc - 1, r); } r++; @@ -451,7 +455,7 @@ describe_variable (struct variable *v, struct tab_table *t, int r, int as) /* Put the name, var label, and position into the first row. */ tab_text (t, 0, r, TAB_LEFT, var_get_name (v)); - tab_text (t, 3, r, TAT_PRINTF, "%d", v->index + 1); + tab_text (t, 3, r, TAT_PRINTF, "%d", (int) var_get_dict_index (v) + 1); if (as == AS_DICTIONARY && var_has_label (v)) { @@ -524,8 +528,9 @@ describe_variable (struct variable *v, struct tab_table *t, int r, int as) } /* Value labels. */ - if (as == AS_DICTIONARY && val_labs_count (v->val_labs)) + if (as == AS_DICTIONARY && var_has_value_labels (v)) { + const struct val_labs *val_labs = var_get_value_labels (v); struct val_labs_iterator *i; struct val_lab *vl; int orig_r = r; @@ -537,8 +542,8 @@ describe_variable (struct variable *v, struct tab_table *t, int r, int as) #endif tab_hline (t, TAL_1, 1, 2, r); - for (vl = val_labs_first_sorted (v->val_labs, &i); vl != NULL; - vl = val_labs_next (v->val_labs, &i)) + for (vl = val_labs_first_sorted (val_labs, &i); vl != NULL; + vl = val_labs_next (val_labs, &i)) { char buf[128]; @@ -564,17 +569,6 @@ describe_variable (struct variable *v, struct tab_table *t, int r, int as) return r; } -static int -compare_vectors_by_name (const void *a_, const void *b_) -{ - struct vector *const *pa = a_; - struct vector *const *pb = b_; - struct vector *a = *pa; - struct vector *b = *pb; - - return strcasecmp (a->name, b->name); -} - /* Display a list of vectors. If SORTED is nonzero then they are sorted alphabetically. */ static void @@ -596,7 +590,7 @@ display_vectors (const struct dictionary *dict, int sorted) for (i = 0; i < nvec; i++) vl[i] = dict_get_vector (dict, i); if (sorted) - qsort (vl, nvec, sizeof *vl, compare_vectors_by_name); + qsort (vl, nvec, sizeof *vl, compare_vector_ptrs_by_name); t = tab_create (1, nvec + 1, 0); tab_headers (t, 0, 0, 1, 0); @@ -606,7 +600,7 @@ display_vectors (const struct dictionary *dict, int sorted) tab_text (t, 0, 0, TAT_TITLE | TAB_LEFT, _("Vector")); tab_flags (t, SOMF_NO_TITLE); for (i = 0; i < nvec; i++) - tab_text (t, 0, i + 1, TAB_LEFT, vl[i]->name); + tab_text (t, 0, i + 1, TAB_LEFT, vector_get_name (vl[i])); tab_submit (t); free (vl); diff --git a/src/language/dictionary/value-labels.c b/src/language/dictionary/value-labels.c index 5ac8fb52..0259d69b 100644 --- a/src/language/dictionary/value-labels.c +++ b/src/language/dictionary/value-labels.c @@ -136,7 +136,7 @@ erase_labels (struct variable **vars, size_t var_cnt) /* Erase old value labels if desired. */ for (i = 0; i < var_cnt; i++) - val_labs_clear (vars[i]->val_labs); + var_clear_value_labels (vars[i]); } /* Parse all the labels for the VAR_CNT variables in VARS and add @@ -188,7 +188,7 @@ get_label (struct lexer *lexer, struct variable **vars, size_t var_cnt) } for (i = 0; i < var_cnt; i++) - val_labs_replace (vars[i]->val_labs, value, ds_cstr (&label)); + var_replace_value_label (vars[i], &value, ds_cstr (&label)); ds_destroy (&label); diff --git a/src/language/dictionary/variable-label.c b/src/language/dictionary/variable-label.c index 857c783c..3cb6f596 100644 --- a/src/language/dictionary/variable-label.c +++ b/src/language/dictionary/variable-label.c @@ -76,14 +76,3 @@ cmd_variable_labels (struct lexer *lexer, struct dataset *ds) -const char * -var_to_string(const struct variable *var) -{ - const char *label; - - if ( !var ) - return 0; - - label = var_get_label (var); - return label ? label : var_get_name (var); -} diff --git a/src/language/dictionary/vector.c b/src/language/dictionary/vector.c index 7492015c..ac8d74d5 100644 --- a/src/language/dictionary/vector.c +++ b/src/language/dictionary/vector.c @@ -107,7 +107,7 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) } if (!parse_variables (lexer, dict, &v, &nv, - PV_SAME_TYPE | PV_DUPLICATE)) + PV_SAME_WIDTH | PV_DUPLICATE)) goto fail; dict_create_vector (dict, vecnames, v, nv); diff --git a/src/language/expressions/evaluate.c b/src/language/expressions/evaluate.c index 1cf73ed7..93f724ff 100644 --- a/src/language/expressions/evaluate.c +++ b/src/language/expressions/evaluate.c @@ -180,9 +180,9 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED) case_resize (c, old_value_cnt, dict_get_next_value_idx (d)); if (lex_is_number (lexer)) - case_data_rw (c, v->fv)->f = lex_tokval (lexer); + case_data_rw (c, v)->f = lex_tokval (lexer); else - memcpy (case_data_rw (c, v->fv)->s, ds_data (lex_tokstr (lexer)), + memcpy (case_data_rw (c, v)->s, ds_data (lex_tokstr (lexer)), var_get_width (v)); lex_get (lexer); @@ -312,7 +312,7 @@ expr_debug_print_postfix (const struct expression *e) fprintf (stderr, "v<%s>", var_get_name (op->variable)); break; case OP_vector: - fprintf (stderr, "vec<%s>", op->vector->name); + fprintf (stderr, "vec<%s>", vector_get_name (op->vector)); break; case OP_integer: fprintf (stderr, "i<%d>", op->integer); diff --git a/src/language/expressions/helpers.h b/src/language/expressions/helpers.h index 124868cc..46ed5e4a 100644 --- a/src/language/expressions/helpers.h +++ b/src/language/expressions/helpers.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src/language/expressions/operations.def b/src/language/expressions/operations.def index 5f0b938a..03861021 100644 --- a/src/language/expressions/operations.def +++ b/src/language/expressions/operations.def @@ -892,22 +892,22 @@ absorb_miss boolean function SYSMIS (x) = x == SYSMIS || !finite (x); no_opt boolean function SYSMIS (num_var v) case c; { - return case_num (c, v->fv) == SYSMIS; + return case_num (c, v) == SYSMIS; } no_opt boolean function VALUE (num_var v) case c; { - return case_num (c, v->fv); + return case_num (c, v); } no_opt operator VEC_ELEM_NUM (idx) vector v; case c; { - if (idx >= 1 && idx <= v->cnt) + if (idx >= 1 && idx <= vector_get_var_cnt (v)) { - const struct variable *var = v->var[(int) idx - 1]; - double value = case_num (c, var->fv); + const struct variable *var = vector_get_var (v, (size_t) idx - 1); + double value = case_num (c, var); return !var_is_num_user_missing (var, value) ? value : SYSMIS; } else @@ -915,11 +915,11 @@ no_opt operator VEC_ELEM_NUM (idx) if (idx == SYSMIS) msg (SE, _("SYSMIS is not a valid index value for vector " "%s. The result will be set to SYSMIS."), - v->name); + vector_get_name (v)); else msg (SE, _("%g is not a valid index value for vector %s. " "The result will be set to SYSMIS."), - idx, v->name); + idx, vector_get_name (v)); return SYSMIS; } } @@ -929,21 +929,21 @@ absorb_miss no_opt string operator VEC_ELEM_STR (idx) vector v; case c; { - if (idx >= 1 && idx <= v->cnt) + if (idx >= 1 && idx <= vector_get_var_cnt (v)) { - struct variable *var = v->var[(int) idx - 1]; - return copy_string (e, case_str (c, var->fv), var_get_width (var)); + struct variable *var = vector_get_var (v, (size_t) idx - 1); + return copy_string (e, case_str (c, var), var_get_width (var)); } else { if (idx == SYSMIS) msg (SE, _("SYSMIS is not a valid index value for vector " "%s. The result will be set to the empty string."), - v->name); + vector_get_name (v)); else msg (SE, _("%g is not a valid index value for vector %s. " "The result will be set to the empty string."), - idx, v->name); + idx, vector_get_name (v)); return empty_string; } } @@ -954,7 +954,7 @@ no_opt operator NUM_VAR () case c; num_var v; { - double d = case_num (c, v->fv); + double d = case_num (c, v); return !var_is_num_user_missing (v, d) ? d : SYSMIS; } @@ -964,7 +964,7 @@ no_opt string operator STR_VAR () str_var v; { struct substring s = alloc_string (e, var_get_width (v)); - memcpy (s.string, case_str (c, v->fv), var_get_width (v)); + memcpy (s.string, case_str (c, v), var_get_width (v)); return s; } @@ -974,7 +974,7 @@ no_opt perm_only function LAG (num_var v, pos_int n_before) struct ccase *c = lagged_case (ds, n_before); if (c != NULL) { - double x = case_num (c, v->fv); + double x = case_num (c, v); return !var_is_num_user_missing (v, x) ? x : SYSMIS; } else @@ -987,7 +987,7 @@ no_opt perm_only function LAG (num_var v) struct ccase *c = lagged_case (ds, 1); if (c != NULL) { - double x = case_num (c, v->fv); + double x = case_num (c, v); return !var_is_num_user_missing (v, x) ? x : SYSMIS; } else @@ -1000,7 +1000,7 @@ no_opt perm_only string function LAG (str_var v, pos_int n_before) { struct ccase *c = lagged_case (ds, n_before); if (c != NULL) - return copy_string (e, case_str (c, v->fv), var_get_width (v)); + return copy_string (e, case_str (c, v), var_get_width (v)); else return empty_string; } @@ -1011,7 +1011,7 @@ no_opt perm_only string function LAG (str_var v) { struct ccase *c = lagged_case (ds, 1); if (c != NULL) - return copy_string (e, case_str (c, v->fv), var_get_width (v)); + return copy_string (e, case_str (c, v), var_get_width (v)); else return empty_string; } @@ -1020,14 +1020,14 @@ no_opt operator NUM_SYS () case c; num_var v; { - return case_num (c, v->fv) == SYSMIS; + return case_num (c, v) == SYSMIS; } no_opt operator NUM_VAL () case c; num_var v; { - return case_num (c, v->fv); + return case_num (c, v); } no_opt operator CASENUM () diff --git a/src/language/expressions/parse.c b/src/language/expressions/parse.c index 6489ed83..7c5ea4cf 100644 --- a/src/language/expressions/parse.c +++ b/src/language/expressions/parse.c @@ -358,7 +358,7 @@ type_coercion_core (struct expression *e, msg_disable (); if ((*node)->type == OP_format && fmt_check_input (&(*node)->format.f) - && fmt_check_type_compat (&(*node)->format.f, NUMERIC)) + && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC)) { msg_enable (); if (do_coercion) @@ -372,7 +372,7 @@ type_coercion_core (struct expression *e, msg_disable (); if ((*node)->type == OP_format && fmt_check_output (&(*node)->format.f) - && fmt_check_type_compat (&(*node)->format.f, NUMERIC)) + && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC)) { msg_enable (); if (do_coercion) @@ -901,7 +901,7 @@ parse_vector_element (struct lexer *lexer, struct expression *e) || !lex_match (lexer, ')')) return NULL; - return expr_allocate_binary (e, (var_is_numeric (vector->var[0]) + return expr_allocate_binary (e, (vector_get_type (vector) == VAR_NUMERIC ? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR), element, expr_allocate_vector (e, vector)); } diff --git a/src/language/lexer/ChangeLog b/src/language/lexer/ChangeLog index db33299a..cfa344d2 100644 --- a/src/language/lexer/ChangeLog +++ b/src/language/lexer/ChangeLog @@ -1,3 +1,13 @@ +Sat Dec 9 18:46:11 2006 Ben Pfaff + + * variable-parser.h: New PV_SAME_WIDTH variable parsing option. + + * variable-parser.c (add_variable): Implement new PV_SAME_WIDTH + option. + (parse_var_set_vars) Ditto. + (array_var_set_lookup_var_idx) Use new var_create, var_destroy + functions. + Sat Dec 2 21:19:50 2006 Ben Pfaff General clean-up. diff --git a/src/language/lexer/variable-parser.c b/src/language/lexer/variable-parser.c index 2cb54f7a..d9eae524 100644 --- a/src/language/lexer/variable-parser.c +++ b/src/language/lexer/variable-parser.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -175,11 +176,17 @@ add_variable (struct variable ***v, size_t *nv, size_t *mv, && dict_class_from_id (add_name) == DC_SCRATCH) msg (SE, _("Scratch variables (such as %s) are not allowed " "here."), add_name); - else if ((pv_opts & PV_SAME_TYPE) && *nv + else if ((pv_opts & (PV_SAME_TYPE | PV_SAME_WIDTH)) && *nv && var_get_type (add) != var_get_type ((*v)[0])) msg (SE, _("%s and %s are not the same type. All variables in " "this variable list must be of the same type. %s " - "will be omitted from list."), + "will be omitted from the list."), + var_get_name ((*v)[0]), add_name, add_name); + else if ((pv_opts & PV_SAME_WIDTH) && *nv + && var_get_width (add) != var_get_width ((*v)[0])) + msg (SE, _("%s and %s are string variables with different widths. " + "All variables in this variable list must have the " + "same width. %s will be omttied from the list."), var_get_name ((*v)[0]), add_name, add_name); else if ((pv_opts & PV_NO_DUPLICATE) && included[idx]) msg (SE, _("Variable %s appears twice in variable list."), add_name); @@ -229,11 +236,12 @@ parse_var_set_vars (struct lexer *lexer, const struct var_set *vs, assert (v != NULL); assert (nv != NULL); - /* At most one of PV_NUMERIC, PV_STRING, PV_SAME_TYPE may be - specified. */ - assert ((((pv_opts & PV_NUMERIC) != 0) - + ((pv_opts & PV_STRING) != 0) - + ((pv_opts & PV_SAME_TYPE) != 0)) <= 1); + /* At most one of PV_NUMERIC, PV_STRING, PV_SAME_TYPE, + PV_SAME_WIDTH may be specified. */ + assert (((pv_opts & PV_NUMERIC) != 0) + + ((pv_opts & PV_STRING) != 0) + + ((pv_opts & PV_SAME_TYPE) != 0) + + ((pv_opts & PV_SAME_WIDTH) != 0) <= 1); /* PV_DUPLICATE and PV_NO_DUPLICATE are incompatible. */ assert (!(pv_opts & PV_DUPLICATE) || !(pv_opts & PV_NO_DUPLICATE)); @@ -252,8 +260,13 @@ parse_var_set_vars (struct lexer *lexer, const struct var_set *vs, size_t i; included = xcalloc (var_set_get_cnt (vs), sizeof *included); - for (i = 0; i < *nv; i++) - included[(*v)[i]->index] = 1; + for (i = 0; i < *nv; i++) + { + size_t index; + if (!var_set_lookup_var_idx (vs, var_get_name ((*v)[i]), &index)) + NOT_REACHED (); + included[index] = 1; + } } else included = NULL; @@ -687,7 +700,7 @@ dict_var_set_lookup_var_idx (const struct var_set *vs, const char *name, struct variable *v = dict_lookup_var (d, name); if (v != NULL) { - *idx = v->index; + *idx = var_get_dict_index (v); return true; } else @@ -748,11 +761,12 @@ array_var_set_lookup_var_idx (const struct var_set *vs, const char *name, size_t *idx) { struct array_var_set *avs = vs->aux; - struct variable v, *vp, *const *vpp; + struct variable *v, *const *vpp; - strcpy (v.name, name); - vp = &v; - vpp = hsh_find (avs->name_tab, &vp); + v = var_create (name, 0); + vpp = hsh_find (avs->name_tab, &v); + var_destroy (v); + if (vpp != NULL) { *idx = vpp - avs->var; @@ -791,8 +805,8 @@ var_set_create_from_array (struct variable *const *var, size_t var_cnt) avs->var = var; avs->var_cnt = var_cnt; avs->name_tab = hsh_create (2 * var_cnt, - compare_var_ptr_names, hash_var_ptr_name, NULL, - NULL); + compare_var_ptrs_by_name, hash_var_ptr_by_name, + NULL, NULL); for (i = 0; i < var_cnt; i++) if (hsh_insert (avs->name_tab, (void *) &var[i]) != NULL) { diff --git a/src/language/lexer/variable-parser.h b/src/language/lexer/variable-parser.h index 0a204844..1e626f33 100644 --- a/src/language/lexer/variable-parser.h +++ b/src/language/lexer/variable-parser.h @@ -53,7 +53,8 @@ enum PV_NUMERIC = 0020, /* Vars must be numeric. */ PV_STRING = 0040, /* Vars must be string. */ PV_SAME_TYPE = 00100, /* All vars must be the same type. */ - PV_NO_SCRATCH = 00200 /* Disallow scratch variables. */ + PV_SAME_WIDTH = 00200, /* All vars must be the same type and width. */ + PV_NO_SCRATCH = 00400 /* Disallow scratch variables. */ }; struct variable *parse_variable (struct lexer *, const struct dictionary *); diff --git a/src/language/stats/ChangeLog b/src/language/stats/ChangeLog index fdfa62d7..95e24640 100644 --- a/src/language/stats/ChangeLog +++ b/src/language/stats/ChangeLog @@ -1,3 +1,8 @@ +Sat Dec 9 18:47:51 2006 Ben Pfaff + + * regression.q (is_depvar): Compare variable pointers instead of + variable names. + Thu Dec 7 15:26:25 WST 2006 John Darrington * examine.q: Allocated the categorical values for the dependent and diff --git a/src/language/stats/aggregate.c b/src/language/stats/aggregate.c index 4a441716..5e4be3bc 100644 --- a/src/language/stats/aggregate.c +++ b/src/language/stats/aggregate.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -93,36 +94,36 @@ struct agr_func { const char *name; /* Aggregation function name. */ size_t n_args; /* Number of arguments. */ - int alpha_type; /* When given ALPHA arguments, output type. */ + enum var_type alpha_type; /* When given ALPHA arguments, output type. */ struct fmt_spec format; /* Format spec if alpha_type != ALPHA. */ }; /* Attributes of aggregation functions. */ static const struct agr_func agr_func_tab[] = { - {"", 0, -1, {0, 0, 0}}, - {"SUM", 0, -1, {FMT_F, 8, 2}}, - {"MEAN", 0, -1, {FMT_F, 8, 2}}, - {"SD", 0, -1, {FMT_F, 8, 2}}, - {"MAX", 0, ALPHA, {-1, -1, -1}}, - {"MIN", 0, ALPHA, {-1, -1, -1}}, - {"PGT", 1, NUMERIC, {FMT_F, 5, 1}}, - {"PLT", 1, NUMERIC, {FMT_F, 5, 1}}, - {"PIN", 2, NUMERIC, {FMT_F, 5, 1}}, - {"POUT", 2, NUMERIC, {FMT_F, 5, 1}}, - {"FGT", 1, NUMERIC, {FMT_F, 5, 3}}, - {"FLT", 1, NUMERIC, {FMT_F, 5, 3}}, - {"FIN", 2, NUMERIC, {FMT_F, 5, 3}}, - {"FOUT", 2, NUMERIC, {FMT_F, 5, 3}}, - {"N", 0, NUMERIC, {FMT_F, 7, 0}}, - {"NU", 0, NUMERIC, {FMT_F, 7, 0}}, - {"NMISS", 0, NUMERIC, {FMT_F, 7, 0}}, - {"NUMISS", 0, NUMERIC, {FMT_F, 7, 0}}, - {"FIRST", 0, ALPHA, {-1, -1, -1}}, - {"LAST", 0, ALPHA, {-1, -1, -1}}, - {NULL, 0, -1, {-1, -1, -1}}, - {"N", 0, NUMERIC, {FMT_F, 7, 0}}, - {"NU", 0, NUMERIC, {FMT_F, 7, 0}}, + {"", 0, -1, {0, 0, 0}}, + {"SUM", 0, -1, {FMT_F, 8, 2}}, + {"MEAN", 0, -1, {FMT_F, 8, 2}}, + {"SD", 0, -1, {FMT_F, 8, 2}}, + {"MAX", 0, VAR_STRING, {-1, -1, -1}}, + {"MIN", 0, VAR_STRING, {-1, -1, -1}}, + {"PGT", 1, VAR_NUMERIC, {FMT_F, 5, 1}}, + {"PLT", 1, VAR_NUMERIC, {FMT_F, 5, 1}}, + {"PIN", 2, VAR_NUMERIC, {FMT_F, 5, 1}}, + {"POUT", 2, VAR_NUMERIC, {FMT_F, 5, 1}}, + {"FGT", 1, VAR_NUMERIC, {FMT_F, 5, 3}}, + {"FLT", 1, VAR_NUMERIC, {FMT_F, 5, 3}}, + {"FIN", 2, VAR_NUMERIC, {FMT_F, 5, 3}}, + {"FOUT", 2, VAR_NUMERIC, {FMT_F, 5, 3}}, + {"N", 0, VAR_NUMERIC, {FMT_F, 7, 0}}, + {"NU", 0, VAR_NUMERIC, {FMT_F, 7, 0}}, + {"NMISS", 0, VAR_NUMERIC, {FMT_F, 7, 0}}, + {"NUMISS", 0, VAR_NUMERIC, {FMT_F, 7, 0}}, + {"FIRST", 0, VAR_STRING, {-1, -1, -1}}, + {"LAST", 0, VAR_STRING, {-1, -1, -1}}, + {NULL, 0, -1, {-1, -1, -1}}, + {"N", 0, VAR_NUMERIC, {FMT_F, 7, 0}}, + {"NU", 0, VAR_NUMERIC, {FMT_F, 7, 0}}, }; /* Missing value types. */ @@ -494,13 +495,15 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, s if (lex_token (lexer) == T_STRING) { arg[i].c = ds_xstrdup (lex_tokstr (lexer)); - type = ALPHA; + type = VAR_STRING; } else if (lex_is_number (lexer)) { arg[i].f = lex_tokval (lexer); - type = NUMERIC; - } else { + type = VAR_NUMERIC; + } + else + { msg (SE, _("Missing argument %d to %s."), i + 1, function->name); goto error; @@ -587,12 +590,12 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, s v->string = xmalloc (var_get_width (src[i])); } - if (function->alpha_type == ALPHA) + if (function->alpha_type == VAR_STRING) destvar = dict_clone_var (agr->dict, v->src, dest[i]); else { assert (var_is_numeric (v->src) - || function->alpha_type == NUMERIC); + || function->alpha_type == VAR_NUMERIC); destvar = dict_create_var (agr->dict, dest[i], 0); if (destvar != NULL) { @@ -771,7 +774,7 @@ accumulate_aggregate_info (struct agr_proc *agr, for (iter = agr->agr_vars; iter; iter = iter->next) if (iter->src) { - const union value *v = case_data (input, iter->src->fv); + const union value *v = case_data (input, iter->src); int src_width = var_get_width (iter->src); if (iter->include_missing @@ -944,8 +947,8 @@ dump_aggregate_info (struct agr_proc *agr, struct ccase *output) { struct variable *v = agr->break_vars[i]; size_t value_cnt = var_get_value_cnt (v); - memcpy (case_data_rw (output, value_idx), - case_data (&agr->break_case, v->fv), + memcpy (case_data_rw_idx (output, value_idx), + case_data (&agr->break_case, v), sizeof (union value) * value_cnt); value_idx += value_cnt; } @@ -956,7 +959,7 @@ dump_aggregate_info (struct agr_proc *agr, struct ccase *output) for (i = agr->agr_vars; i; i = i->next) { - union value *v = case_data_rw (output, i->dest->fv); + union value *v = case_data_rw (output, i->dest); if (agr->missing == COLUMNWISE && i->missing != 0 && (i->function & FUNC) != N && (i->function & FUNC) != NU diff --git a/src/language/stats/autorecode.c b/src/language/stats/autorecode.c index fe1150a3..048db119 100644 --- a/src/language/stats/autorecode.c +++ b/src/language/stats/autorecode.c @@ -285,12 +285,12 @@ autorecode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED) union arc_value v; if (var_is_numeric (spec->src)) - v.f = case_num (c, spec->src->fv); + v.f = case_num (c, spec->src); else - v.c = (char *) case_str (c, spec->src->fv); + v.c = (char *) case_str (c, spec->src); item = hsh_force_find (spec->items, &v); - case_data_rw (c, spec->dest->fv)->f = item->to; + case_data_rw (c, spec->dest)->f = item->to; } return TRNS_CONTINUE; } @@ -357,9 +357,9 @@ autorecode_proc_func (const struct ccase *c, void *arc_, const struct dataset *d union arc_value v, *vp, **vpp; if (var_is_numeric (arc->src_vars[i])) - v.f = case_num (c, arc->src_vars[i]->fv); + v.f = case_num (c, arc->src_vars[i]); else - v.c = (char *) case_str (c, arc->src_vars[i]->fv); + v.c = (char *) case_str (c, arc->src_vars[i]); vpp = (union arc_value **) hsh_probe (arc->src_values[i], &v); if (*vpp == NULL) diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index fc8571c4..cd12ab98 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -131,9 +132,7 @@ struct var_range static inline struct var_range * get_var_range (struct variable *v) { - assert (v != NULL); - assert (v->aux != NULL); - return v->aux; + return var_get_aux (v); } /* Indexes into crosstab.v. */ @@ -592,7 +591,7 @@ calc_general (const struct ccase *c, void *aux UNUSED, const struct dataset *ds) assert (x != NULL); for (j = 0; j < x->nvar; j++) { - const union value *v = case_data (c, x->vars[j]->fv); + const union value *v = case_data (c, x->vars[j]); if ((cmd.miss == CRS_TABLE && var_is_value_missing (x->vars[j], v)) || (cmd.miss == CRS_INCLUDE && var_is_value_system_missing (x->vars[j], v))) @@ -602,10 +601,10 @@ calc_general (const struct ccase *c, void *aux UNUSED, const struct dataset *ds) } if (var_is_numeric (x->vars[j])) - te->values[j].f = case_num (c, x->vars[j]->fv); + te->values[j].f = case_num (c, x->vars[j]); else { - memcpy (te->values[j].s, case_str (c, x->vars[j]->fv), + memcpy (te->values[j].s, case_str (c, x->vars[j]), var_get_width (x->vars[j])); /* Necessary in order to simplify comparisons. */ @@ -661,7 +660,7 @@ calc_integer (const struct ccase *c, void *aux UNUSED, const struct dataset *ds) { struct variable *const v = x->vars[i]; struct var_range *vr = get_var_range (v); - double value = case_num (c, v->fv); + double value = case_num (c, v); /* Note that the first test also rules out SYSMIS. */ if ((value < vr->min || value >= vr->max) @@ -680,10 +679,10 @@ calc_integer (const struct ccase *c, void *aux UNUSED, const struct dataset *ds) { struct variable *row_var = x->vars[ROW_VAR]; - const int row = case_num (c, row_var->fv) - get_var_range (row_var)->min; + const int row = case_num (c, row_var) - get_var_range (row_var)->min; struct variable *col_var = x->vars[COL_VAR]; - const int col = case_num (c, col_var->fv) - get_var_range (col_var)->min; + const int col = case_num (c, col_var) - get_var_range (col_var)->min; const int col_dim = get_var_range (col_var)->count; @@ -1667,7 +1666,7 @@ table_value_missing (struct tab_table *table, int c, int r, unsigned char opt, struct substring s; const struct fmt_spec *print = var_get_print_format (var); - const char *label = val_labs_find (var->val_labs, *v); + const char *label = var_lookup_value_label (var, v); if (label) { tab_text (table, c, r, TAB_LEFT, label); diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index 598752ca..ccab1931 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -64,11 +64,10 @@ enum dsc_missing_type calculating a Z-score. */ struct dsc_z_score { - int src_idx; /* Source index into case data. */ - int dst_idx; /* Destination index into case data. */ + struct variable *src_var; /* Variable on which z-score is based. */ + struct variable *z_var; /* New z-score variable. */ double mean; /* Distribution mean. */ double std_dev; /* Distribution standard deviation. */ - struct variable *v; /* Variable on which z-score is based. */ }; /* DESCRIPTIVES transformation (for calculating Z-scores). */ @@ -596,7 +595,7 @@ descriptives_trns_proc (void *trns_, struct ccase * c, assert(t->vars); for (vars = t->vars; vars < t->vars + t->var_cnt; vars++) { - double score = case_num (c, (*vars)->fv); + double score = case_num (c, *vars); if ( score == SYSMIS || (!t->include_user_missing && var_is_num_user_missing (*vars, score))) @@ -609,13 +608,13 @@ descriptives_trns_proc (void *trns_, struct ccase * c, for (z = t->z_scores; z < t->z_scores + t->z_score_cnt; z++) { - double input = case_num (c, z->src_idx); - double *output = &case_data_rw (c, z->dst_idx)->f; + double input = case_num (c, z->src_var); + double *output = &case_data_rw (c, z->z_var)->f; if (z->mean == SYSMIS || z->std_dev == SYSMIS || all_sysmis || input == SYSMIS || (!t->include_user_missing - && var_is_num_user_missing (z->v, input))) + && var_is_num_user_missing (z->src_var, input))) *output = SYSMIS; else *output = (input - z->mean) / z->std_dev; @@ -677,11 +676,10 @@ setup_z_trns (struct dsc_proc *dsc, struct dataset *ds) var_to_string (dv->v))); z = &t->z_scores[cnt++]; - z->src_idx = dv->v->fv; - z->dst_idx = dst_var->fv; + z->src_var = dv->v; + z->z_var = dst_var; z->mean = dv->stats[DSC_MEAN]; z->std_dev = dv->stats[DSC_STDDEV]; - z->v = dv->v; } } @@ -741,7 +739,7 @@ calc_descriptives (const struct ccase *first, for (i = 0; i < dsc->var_cnt; i++) { struct dsc_var *dv = &dsc->vars[i]; - double x = case_num (&c, dv->v->fv); + double x = case_num (&c, dv->v); if (dsc->missing_type != DSC_LISTWISE && (x == SYSMIS @@ -783,7 +781,7 @@ calc_descriptives (const struct ccase *first, for (i = 0; i < dsc->var_cnt; i++) { struct dsc_var *dv = &dsc->vars[i]; - double x = case_num (&c, dv->v->fv); + double x = case_num (&c, dv->v); if (dsc->missing_type != DSC_LISTWISE && (x == SYSMIS @@ -850,7 +848,7 @@ listwise_missing (struct dsc_proc *dsc, const struct ccase *c) for (i = 0; i < dsc->var_cnt; i++) { struct dsc_var *dv = &dsc->vars[i]; - double x = case_num (c, dv->v->fv); + double x = case_num (c, dv->v); if (x == SYSMIS || (!dsc->include_user_missing diff --git a/src/language/stats/examine.q b/src/language/stats/examine.q index b337131c..9a55c9f3 100644 --- a/src/language/stats/examine.q +++ b/src/language/stats/examine.q @@ -649,13 +649,13 @@ factor_calc (const struct ccase *c, int case_no, double weight, union value *indep_vals[2] ; indep_vals[0] = value_dup ( - case_data (c, fctr->indep_var[0]->fv), + case_data (c, fctr->indep_var[0]), var_get_width (fctr->indep_var[0]) ); if ( fctr->indep_var[1] ) indep_vals[1] = value_dup ( - case_data (c, fctr->indep_var[1]->fv), + case_data (c, fctr->indep_var[1]), var_get_width (fctr->indep_var[1]) ); else @@ -692,7 +692,7 @@ factor_calc (const struct ccase *c, int case_no, double weight, { const struct variable *var = dependent_vars[v]; union value *val = value_dup ( - case_data (c, var->fv), + case_data (c, var), var_get_width (var) ); @@ -759,7 +759,7 @@ run_examine (const struct ccase *first, const struct casefile *cf, { const struct variable *var = dependent_vars[v]; union value *val = value_dup ( - case_data (&c, var->fv), + case_data (&c, var), var_get_width (var) ); @@ -774,7 +774,7 @@ run_examine (const struct ccase *first, const struct casefile *cf, { const struct variable *var = dependent_vars[v]; union value *val = value_dup ( - case_data (&c, var->fv), + case_data (&c, var), var_get_width (var) ); @@ -1059,8 +1059,8 @@ show_summary (struct variable **dependent_var, int n_dep_var, (i * n_factors ) + count + heading_rows, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[0], - fctr->indep_var[0]) + var_get_value_name (fctr->indep_var[0], + (*fs)->id[0]) ); if (fctr->indep_var[1] && count > 0 ) @@ -1078,7 +1078,7 @@ show_summary (struct variable **dependent_var, int n_dep_var, (i * n_factors ) + count + heading_rows, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[1], fctr->indep_var[1]) + var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) ); populate_summary (tbl, heading_columns, @@ -1234,7 +1234,8 @@ show_extremes (struct variable **dependent_var, int n_dep_var, tab_text (tbl, 1, row, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[0], fctr->indep_var[0]) + var_get_value_name (fctr->indep_var[0], + (*fs)->id[0]) ); } @@ -1246,7 +1247,7 @@ show_extremes (struct variable **dependent_var, int n_dep_var, if ( fctr->indep_var[1]) tab_text (tbl, 2, row, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[1], fctr->indep_var[1]) + var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) ); populate_extremes (tbl, heading_columns - 2, @@ -1471,7 +1472,8 @@ show_descriptives (struct variable **dependent_var, tab_text (tbl, 1, row, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[0], fctr->indep_var[0]) + var_get_value_name (fctr->indep_var[0], + (*fs)->id[0]) ); } @@ -1483,7 +1485,7 @@ show_descriptives (struct variable **dependent_var, if ( fctr->indep_var[1]) tab_text (tbl, 2, row, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[1], fctr->indep_var[1]) + var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) ); populate_descriptives (tbl, heading_columns - 2, @@ -2097,7 +2099,8 @@ show_percentiles (struct variable **dependent_var, tab_text (tbl, 1, row, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[0], fctr->indep_var[0]) + var_get_value_name (fctr->indep_var[0], + (*fs)->id[0]) ); @@ -2111,7 +2114,7 @@ show_percentiles (struct variable **dependent_var, if ( fctr->indep_var[1]) tab_text (tbl, 2, row, TAB_LEFT | TAT_TITLE, - value_to_string ((*fs)->id[1], fctr->indep_var[1]) + var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) ); @@ -2213,7 +2216,7 @@ factor_to_string (const struct factor *fctr, snprintf (buf2, 100, "%s = %s", var_to_string (fctr->indep_var[0]), - value_to_string (fs->id[0], fctr->indep_var[0])); + var_get_value_name (fctr->indep_var[0], fs->id[0])); strcat (buf1, buf2); @@ -2221,8 +2224,7 @@ factor_to_string (const struct factor *fctr, { sprintf (buf2, "; %s = %s)", var_to_string (fctr->indep_var[1]), - value_to_string (fs->id[1], - fctr->indep_var[1])); + var_get_value_name (fctr->indep_var[1], fs->id[1])); strcat (buf1, buf2); } else @@ -2247,11 +2249,12 @@ factor_to_string_concise (const struct factor *fctr, char buf2[100]; snprintf (buf, 100, "%s", - value_to_string (fs->id[0], fctr->indep_var[0])); + var_get_value_name (fctr->indep_var[0], fs->id[0])); if ( fctr->indep_var[1] ) { - sprintf (buf2, ",%s)", value_to_string (fs->id[1], fctr->indep_var[1]) ); + sprintf (buf2, ",%s)", var_get_value_name (fctr->indep_var[1], + fs->id[1]) ); strcat (buf, buf2); } diff --git a/src/language/stats/flip.c b/src/language/stats/flip.c index a8f13580..c28de460 100644 --- a/src/language/stats/flip.c +++ b/src/language/stats/flip.c @@ -104,7 +104,7 @@ cmd_flip (struct lexer *lexer, struct dataset *ds) flip = pool_create_container (struct flip_pgm, pool); flip->var = NULL; - flip->idx_to_fv = dict_get_compacted_idx_to_fv (dict); + flip->idx_to_fv = dict_get_compacted_dict_index_to_case_index (dict); pool_register (flip->pool, free, flip->idx_to_fv); flip->var_cnt = 0; flip->case_cnt = 0; @@ -327,10 +327,11 @@ flip_sink_write (struct case_sink *sink, const struct ccase *c) if (flip->new_names != NULL) { struct varname *v = pool_alloc (flip->pool, sizeof *v); + int fv = flip->idx_to_fv[var_get_dict_index (flip->new_names)]; v->next = NULL; if (var_is_numeric (flip->new_names)) { - double f = case_num (c, flip->idx_to_fv[flip->new_names->index]); + double f = case_num_idx (c, fv); if (f == SYSMIS) strcpy (v->name, "VSYSMIS"); @@ -344,8 +345,7 @@ flip_sink_write (struct case_sink *sink, const struct ccase *c) else { int width = MIN (var_get_width (flip->new_names), MAX_SHORT_STRING); - memcpy (v->name, case_str (c, flip->idx_to_fv[flip->new_names->index]), - width); + memcpy (v->name, case_str_idx (c, fv), width); v->name[width] = 0; } @@ -361,8 +361,11 @@ flip_sink_write (struct case_sink *sink, const struct ccase *c) { double out; - if (var_is_numeric (flip->var[i])) - out = case_num (c, flip->idx_to_fv[flip->var[i]->index]); + if (var_is_numeric (flip->var[i])) + { + int fv = flip->idx_to_fv[var_get_dict_index (flip->var[i])]; + out = case_num_idx (c, fv); + } else out = SYSMIS; flip->output_buf[i].f = out; @@ -547,7 +550,7 @@ flip_source_read (struct case_source *source, } for (j = 0; j < flip->case_cnt; j++) - case_data_rw (c, j)->f = input_buf[j].f; + case_data_rw_idx (c, j)->f = input_buf[j].f; ok = write_case (wc_data); } free (input_buf); diff --git a/src/language/stats/frequencies.q b/src/language/stats/frequencies.q index 8256f3d8..f614bcf9 100644 --- a/src/language/stats/frequencies.q +++ b/src/language/stats/frequencies.q @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -269,9 +270,7 @@ struct var_freqs static inline struct var_freqs * get_var_freqs (const struct variable *v) { - assert (v != NULL); - assert (v->aux != NULL); - return v->aux; + return var_get_aux (v); } static void determine_charts (void); @@ -516,7 +515,7 @@ calc (const struct ccase *c, void *aux UNUSED, const struct dataset *ds) for (i = 0; i < n_variables; i++) { const struct variable *v = v_variables[i]; - const union value *val = case_data (c, v->fv); + const union value *val = case_data (c, v); struct var_freqs *vf = get_var_freqs (v); struct freq_tab *ft = &vf->tab; @@ -695,23 +694,22 @@ postcalc (void *aux UNUSED, const struct dataset *ds UNUSED) sorting a frequency table by FRQ_SORT using VAR_TYPE variables. */ static hsh_compare_func * -get_freq_comparator (int frq_sort, int var_type) +get_freq_comparator (int frq_sort, enum var_type var_type) { - /* Note that q2c generates tags beginning with 1000. */ - switch (frq_sort | (var_type << 16)) + bool is_numeric = var_type == VAR_NUMERIC; + switch (frq_sort) { - case FRQ_AVALUE | (NUMERIC << 16): return compare_value_numeric_a; - case FRQ_AVALUE | (ALPHA << 16): return compare_value_alpha_a; - case FRQ_DVALUE | (NUMERIC << 16): return compare_value_numeric_d; - case FRQ_DVALUE | (ALPHA << 16): return compare_value_alpha_d; - case FRQ_AFREQ | (NUMERIC << 16): return compare_freq_numeric_a; - case FRQ_AFREQ | (ALPHA << 16): return compare_freq_alpha_a; - case FRQ_DFREQ | (NUMERIC << 16): return compare_freq_numeric_d; - case FRQ_DFREQ | (ALPHA << 16): return compare_freq_alpha_d; - default: NOT_REACHED (); + case FRQ_AVALUE: + return is_numeric ? compare_value_numeric_a : compare_value_alpha_a; + case FRQ_DVALUE: + return is_numeric ? compare_value_numeric_d : compare_value_alpha_d; + case FRQ_AFREQ: + return is_numeric ? compare_freq_numeric_a : compare_freq_alpha_a; + case FRQ_DFREQ: + return is_numeric ? compare_freq_numeric_d : compare_freq_alpha_d; + default: + NOT_REACHED (); } - - return 0; } /* Returns true iff the value in struct freq F is non-missing @@ -840,7 +838,7 @@ frq_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_freque struct variable *v = v_variables[i]; struct var_freqs *vf; - if (v->aux != NULL) + if (var_get_aux (v) != NULL) { msg (SE, _("Variable %s specified multiple times on VARIABLES " "subcommand."), var_get_name (v)); @@ -933,7 +931,7 @@ frq_custom_grouped (struct lexer *lexer, struct dataset *ds, struct cmd_frequenc } for (i = 0; i < n; i++) - if (v[i]->aux == NULL) + if (var_get_aux (v[i]) == NULL) msg (SE, _("Variables %s specified on GROUPED but not on " "VARIABLES."), var_get_name (v[i])); else @@ -1217,7 +1215,7 @@ dump_full (struct variable *v) if (lab) { - const char *label = val_labs_find (v->val_labs, f->v[0]); + const char *label = var_lookup_value_label (v, &f->v[0]); if (label != NULL) tab_text (t, 0, r, TAB_LEFT, label); } @@ -1235,7 +1233,7 @@ dump_full (struct variable *v) if (lab) { - const char *label = val_labs_find (v->val_labs, f->v[0]); + const char *label = var_lookup_value_label (v, &f->v[0]); if (label != NULL) tab_text (t, 0, r, TAB_LEFT, label); } @@ -1643,7 +1641,7 @@ freq_tab_to_slice_array(const struct freq_tab *frq_tab, { const struct freq *frq = &frq_tab->valid[i]; - slices[i].label = value_to_string(frq->v, var); + slices[i].label = var_get_value_name (var, frq->v); slices[i].magnetude = frq->c; } diff --git a/src/language/stats/oneway.q b/src/language/stats/oneway.q index ea4ed328..9b5ed83d 100644 --- a/src/language/stats/oneway.q +++ b/src/language/stats/oneway.q @@ -435,7 +435,8 @@ show_descriptives(void) gs = gs_array[count]; tab_text (t, 1, row + count, - TAB_LEFT | TAT_TITLE ,value_to_string(&gs->id,indep_var)); + TAB_LEFT | TAT_TITLE, var_get_value_name(indep_var, + &gs->id)); /* Now fill in the numbers ... */ @@ -621,7 +622,7 @@ show_contrast_coeffs (short *bad_contrast) group_value = group_values[count]; tab_text (t, count + 2, 1, TAB_CENTER | TAT_TITLE, - value_to_string(group_value, indep_var)); + var_get_value_name (indep_var, group_value)); for (i = 0 ; i < cmd.sbc_contrast ; ++i ) { @@ -917,7 +918,7 @@ run_oneway(const struct ccase *first, const struct casefile *cf, if ( casefilter_variable_missing (filter, &c, indep_var)) continue; - indep_val = case_data (&c, indep_var->fv); + indep_val = case_data (&c, indep_var); hsh_insert ( global_group_hash, (void *) indep_val ); @@ -925,7 +926,7 @@ run_oneway(const struct ccase *first, const struct casefile *cf, { const struct variable *v = vars[i]; - const union value *val = case_data (&c, v->fv); + const union value *val = case_data (&c, v); struct group_proc *gp = group_proc_get (vars[i]); struct hsh_table *group_hash = gp->group_hash; diff --git a/src/language/stats/rank.q b/src/language/stats/rank.q index 12024239..f64778ae 100644 --- a/src/language/stats/rank.q +++ b/src/language/stats/rank.q @@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA #include "sort-criteria.h" #include +#include +#include #include #include #include @@ -247,13 +249,13 @@ rank_cmd (struct dataset *ds, const struct sort_criteria *sc, for (i = 0; i < n_splits ; i++) { struct variable *v = dict_get_split_vars (dataset_dict (ds))[i]; - criteria.crits[i].fv = v->fv; + criteria.crits[i].fv = var_get_case_index (v); criteria.crits[i].width = var_get_width (v); criteria.crits[i].dir = SRT_ASCEND; } for (i = 0; i < n_group_vars; i++) { - criteria.crits[i + n_splits].fv = group_vars[i]->fv; + criteria.crits[i + n_splits].fv = var_get_case_index (group_vars[i]); criteria.crits[i + n_splits].width = var_get_width (group_vars[i]); criteria.crits[i + n_splits].dir = SRT_ASCEND; } @@ -273,7 +275,7 @@ rank_cmd (struct dataset *ds, const struct sort_criteria *sc, /* Sort CF into SORTED_CF. */ reader = casefile_get_destructive_reader (cf) ; criteria.crits[criteria.crit_cnt - 1] = sc->crits[i]; - assert ( sc->crits[i].fv == src_vars[i]->fv ); + assert ( sc->crits[i].fv == var_get_case_index (src_vars[i]) ); sorted_cf = sort_execute (reader, &criteria); casefile_destroy (cf); @@ -519,7 +521,7 @@ rank_cases (struct casereader *cr, if (!casereader_read_xfer (cr, &this_case)) break; - this_value = case_data (&this_case, fv); + this_value = case_data_idx (&this_case, fv); c = dict_get_case_weight (dict, &this_case, &warn); lookahead = casereader_clone (cr); @@ -527,7 +529,7 @@ rank_cases (struct casereader *cr, while (casereader_cnum (lookahead) < end && casereader_read_xfer (lookahead, &lookahead_case)) { - const union value *lookahead_value = case_data (&lookahead_case, fv); + const union value *lookahead_value = case_data_idx (&lookahead_case, fv); int diff = compare_values (this_value, lookahead_value, width); if (diff != 0) @@ -553,12 +555,12 @@ rank_cases (struct casereader *cr, { for (i = 0; i < n_rank_specs; ++i) { - const int dest_idx = rs[i].destvars[dest_var_index]->fv; + const struct variable *dst_var = rs[i].destvars[dest_var_index]; if ( value_is_missing (mv, this_value) ) - case_data_rw (&this_case, dest_idx)->f = SYSMIS; + case_data_rw (&this_case, dst_var)->f = SYSMIS; else - case_data_rw (&this_case, dest_idx)->f = + case_data_rw (&this_case, dst_var)->f = rank_func[rs[i].rfunc](c, cc, cc_1, iter, w); } casefile_append_xfer (dest, &this_case); @@ -582,8 +584,8 @@ same_group (const struct ccase *a, const struct ccase *b, for (i = 0; i < crit->crit_cnt - 1; i++) { struct sort_criterion *c = &crit->crits[i]; - if (compare_values (case_data (a, c->fv), case_data (b, c->fv), - c->width) != 0) + if (compare_values (case_data_idx (a, c->fv), + case_data_idx (b, c->fv), c->width) != 0) return false; } @@ -612,7 +614,7 @@ rank_sorted_casefile (struct casefile *cf, struct ccase this_case; const union value *this_value ; double w = 0.0; - this_value = case_data( &group_case, ultimate_crit->fv); + this_value = case_data_idx( &group_case, ultimate_crit->fv); if ( !value_is_missing(mv, this_value) ) w = dict_get_case_weight (dict, &group_case, &warn); @@ -620,7 +622,7 @@ rank_sorted_casefile (struct casefile *cf, while (casereader_read (lookahead, &this_case)) { const union value *this_value = - case_data(&this_case, ultimate_crit->fv); + case_data_idx(&this_case, ultimate_crit->fv); double c = dict_get_case_weight (dict, &this_case, &warn); if (!same_group (&group_case, &this_case, crit)) { @@ -661,7 +663,7 @@ create_resort_key (void *key_var_, struct ccase *cc, casenumber case_num) { struct variable *key_var = key_var_; - case_data_rw(cc, key_var->fv)->f = case_num; + case_data_rw(cc, key_var)->f = case_num; return TRNS_CONTINUE; } @@ -907,7 +909,7 @@ cmd_rank (struct lexer *lexer, struct dataset *ds) { struct sort_criteria criteria; struct sort_criterion restore_criterion ; - restore_criterion.fv = order->fv; + restore_criterion.fv = var_get_case_index (order); restore_criterion.width = 0; restore_criterion.dir = SRT_ASCEND; diff --git a/src/language/stats/regression.q b/src/language/stats/regression.q index 77f577a5..c779ae1e 100644 --- a/src/language/stats/regression.q +++ b/src/language/stats/regression.q @@ -239,7 +239,7 @@ reg_stats_coeff (pspp_linreg_cache * c) */ val = pspp_coeff_get_value (c->coeff[j], v); - val_s = value_to_string (val, v); + val_s = var_get_value_name (v, val); strncat (tmp, val_s, MAX_STRING); } @@ -566,12 +566,12 @@ regression_trns_pred_proc (void *t_, struct ccase *c, n_vals = (*model->get_vars) (model, vars); vals = xnmalloc (n_vals, sizeof (*vals)); - output = case_data_rw (c, model->pred->fv); + output = case_data_rw (c, model->pred); assert (output != NULL); for (i = 0; i < n_vals; i++) { - vals[i] = case_data (c, vars[i]->fv); + vals[i] = case_data (c, vars[i]); } output->f = (*model->predict) ((const struct variable **) vars, vals, model, n_vals); @@ -606,14 +606,14 @@ regression_trns_resid_proc (void *t_, struct ccase *c, n_vals = (*model->get_vars) (model, vars); vals = xnmalloc (n_vals, sizeof (*vals)); - output = case_data_rw (c, model->resid->fv); + output = case_data_rw (c, model->resid); assert (output != NULL); for (i = 0; i < n_vals; i++) { - vals[i] = case_data (c, vars[i]->fv); + vals[i] = case_data (c, vars[i]); } - obs = case_data (c, model->depvar->fv); + obs = case_data (c, model->depvar); output->f = (*model->residual) ((const struct variable **) vars, vals, obs, model, n_vals); free (vals); @@ -734,20 +734,16 @@ static void reg_print_categorical_encoding (FILE * fp, pspp_linreg_cache * c) { int i; - size_t j; int n_vars = 0; struct variable **varlist; - struct pspp_coeff *coeff; - const struct variable *v; - union value *val; fprintf (fp, "%s", reg_export_categorical_encode_1); varlist = xnmalloc (c->n_indeps, sizeof (*varlist)); for (i = 1; i < c->n_indeps; i++) /* c->coeff[0] is the intercept. */ { - coeff = c->coeff[i]; - v = pspp_coeff_get_var (coeff, 0); + struct pspp_coeff *coeff = c->coeff[i]; + const struct variable *v = pspp_coeff_get_var (coeff, 0); if (var_is_alpha (v)) { if (!reg_inserted (v, varlist, n_vars)) @@ -770,20 +766,22 @@ reg_print_categorical_encoding (FILE * fp, pspp_linreg_cache * c) for (i = 0; i < n_vars; i++) { - coeff = c->coeff[i]; + size_t n_categories = cat_get_n_categories (varlist[i]); + size_t j; + fprintf (fp, "%s.name = \"%s\";\n\t", var_get_name (varlist[i]), var_get_name (varlist[i])); fprintf (fp, "%s.n_vals = %d;\n\t", var_get_name (varlist[i]), - varlist[i]->obs_vals->n_categories); + n_categories); - for (j = 0; j < varlist[i]->obs_vals->n_categories; j++) + for (j = 0; j < n_categories; j++) { - val = cat_subscript_to_value ((const size_t) j, varlist[i]); + union value *val = cat_subscript_to_value (j, varlist[i]); fprintf (fp, "%s.values[%d] = \"%s\";\n\t", var_get_name (varlist[i]), j, - value_to_string (val, varlist[i])); + var_get_value_name (varlist[i], val)); } } fprintf (fp, "%s", reg_export_categorical_encode_2); @@ -959,14 +957,7 @@ cmd_regression (struct lexer *lexer, struct dataset *ds) static bool is_depvar (size_t k, const struct variable *v) { - /* - compare_var_names returns 0 if the variable - names match. - */ - if (!compare_var_names (v, v_variables[k], NULL)) - return true; - - return false; + return v == v_variables[k]; } /* @@ -986,7 +977,7 @@ mark_missing_cases (const struct casefile *cf, struct variable *v, { row = casereader_cnum (r) - 1; - val = case_data (&c, v->fv); + val = case_data (&c, v); cat_value_update (v, val); if (var_is_value_missing (v, val)) { @@ -1199,7 +1190,7 @@ run_regression (const struct ccase *first, current case. */ { - val = case_data (&c, v_variables[i]->fv); + val = case_data (&c, v_variables[i]); /* Independent/dependent variable separation. The 'variables' subcommand specifies a varlist which contains @@ -1222,7 +1213,7 @@ run_regression (const struct ccase *first, } } } - val = case_data (&c, cmd.v_dependent[k]->fv); + val = case_data (&c, cmd.v_dependent[k]); gsl_vector_set (Y, row, val->f); row++; } diff --git a/src/language/stats/sort-criteria.c b/src/language/stats/sort-criteria.c index 6e8bada4..87dc6b4f 100644 --- a/src/language/stats/sort-criteria.c +++ b/src/language/stats/sort-criteria.c @@ -115,7 +115,7 @@ sort_parse_criteria (struct lexer *lexer, const struct dictionary *dict, for (; prev_var_cnt < criteria->crit_cnt; prev_var_cnt++) { struct sort_criterion *c = &criteria->crits[prev_var_cnt]; - c->fv = (*vars)[prev_var_cnt]->fv; + c->fv = var_get_case_index ((*vars)[prev_var_cnt]); c->width = var_get_width ((*vars)[prev_var_cnt]); c->dir = direction; } diff --git a/src/language/stats/t-test.q b/src/language/stats/t-test.q index 7748676a..5c902dfd 100644 --- a/src/language/stats/t-test.q +++ b/src/language/stats/t-test.q @@ -154,7 +154,7 @@ struct pair static struct pair *pairs=0; -static int parse_value (struct lexer *lexer, union value * v, int type) ; +static int parse_value (struct lexer *lexer, union value * v, enum var_type); /* Structures and Functions for the Statistics Summary Box */ struct ssbox; @@ -309,7 +309,8 @@ cmd_t_test (struct lexer *lexer, struct dataset *ds) struct hsh_table *hash; struct variable *v; - hash = hsh_create (n_pairs, compare_var_names, hash_var_name, 0, 0); + hash = hsh_create (n_pairs, compare_vars_by_name, hash_var_by_name, + 0, 0); for (i=0; i < n_pairs; ++i) { @@ -565,9 +566,9 @@ tts_custom_pairs (struct lexer *lexer, struct dataset *ds, struct cmd_t_test *cm /* Parses the current token (numeric or string, depending on type) value v and returns success. */ static int -parse_value (struct lexer *lexer, union value * v, int type ) +parse_value (struct lexer *lexer, union value * v, enum var_type type) { - if (type == NUMERIC) + if (type == VAR_NUMERIC) { if (!lex_force_num (lexer)) return 0; @@ -716,16 +717,16 @@ ssbox_independent_samples_populate(struct ssbox *ssb, { int i; - char *val_lab0=0; - char *val_lab1=0; + const char *val_lab0; + const char *val_lab1; double indep_value[2]; char prefix[2][3]={"",""}; if ( var_is_numeric (indep_var) ) { - val_lab0 = val_labs_find( indep_var->val_labs,gp.v.g_value[0]); - val_lab1 = val_labs_find( indep_var->val_labs,gp.v.g_value[1]); + val_lab0 = var_lookup_value_label (indep_var, &gp.v.g_value[0]); + val_lab1 = var_lookup_value_label (indep_var, &gp.v.g_value[1]); } else { @@ -1435,7 +1436,7 @@ common_calc (const struct dictionary *dict, if (! casefilter_variable_missing (filter, c, v) ) { struct group_statistics *gs; - const union value *val = case_data (c, v->fv); + const union value *val = case_data (c, v); gs = &group_proc_get (cmd->v_variables[i])->ugs; gs->n += weight; @@ -1507,7 +1508,7 @@ one_sample_calc (const struct dictionary *dict, { struct group_statistics *gs; struct variable *v = cmd->v_variables[i]; - const union value *val = case_data (c, v->fv); + const union value *val = case_data (c, v); gs= &group_proc_get (cmd->v_variables[i])->ugs; @@ -1582,8 +1583,8 @@ paired_calc (const struct dictionary *dict, const struct ccase *c, struct variable *v0 = pairs[i].v[0]; struct variable *v1 = pairs[i].v[1]; - const union value *val0 = case_data (c, v0->fv); - const union value *val1 = case_data (c, v1->fv); + const union value *val0 = case_data (c, v0); + const union value *val1 = case_data (c, v1); if ( ! casefilter_variable_missing (filter, c, v0) && ! casefilter_variable_missing (filter, c, v1) ) @@ -1708,12 +1709,12 @@ group_calc (const struct dictionary *dict, if ( casefilter_variable_missing (filter, c, indep_var)) return 0; - gv = case_data (c, indep_var->fv); + gv = case_data (c, indep_var); for(i=0; i< cmd->n_variables ; ++i) { struct variable *var = cmd->v_variables[i]; - const union value *val = case_data (c, var->fv); + const union value *val = case_data (c, var); struct hsh_table *grp_hash = group_proc_get (var)->group_hash; struct group_statistics *gs; diff --git a/src/language/tests/casefile-test.c b/src/language/tests/casefile-test.c index 0bafe5ef..33b15cb6 100644 --- a/src/language/tests/casefile-test.c +++ b/src/language/tests/casefile-test.c @@ -160,8 +160,8 @@ test_casefile (int pattern, size_t value_cnt, size_t case_cnt) fail_test ("Premature end of casefile."); for (j = 0; j < value_cnt; j++) { - double a = case_num (&read_case, j); - double b = case_num (&expected_case, j); + double a = case_num_idx (&read_case, j); + double b = case_num_idx (&expected_case, j); if (a != b) fail_test ("Case %lu fails comparison.", (unsigned long) i); } @@ -180,7 +180,7 @@ get_random_case (struct ccase *c, size_t value_cnt, size_t case_idx) int i; case_create (c, value_cnt); for (i = 0; i < value_cnt; i++) - case_data_rw (c, i)->f = case_idx % 257 + i; + case_data_rw_idx (c, i)->f = case_idx % 257 + i; } static void @@ -205,8 +205,8 @@ read_and_verify_random_case (struct casefile *cf, fail_test ("Premature end of casefile."); for (i = 0; i < value_cnt; i++) { - double a = case_num (&read_case, i); - double b = case_num (&expected_case, i); + double a = case_num_idx (&read_case, i); + double b = case_num_idx (&expected_case, i); if (a != b) fail_test ("Case %lu fails comparison.", (unsigned long) case_idx); } diff --git a/src/language/utilities/set.q b/src/language/utilities/set.q index efafcc8f..b0fad473 100644 --- a/src/language/utilities/set.q +++ b/src/language/utilities/set.q @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/src/language/xforms/ChangeLog b/src/language/xforms/ChangeLog index 4c79eeff..8e099a96 100644 --- a/src/language/xforms/ChangeLog +++ b/src/language/xforms/ChangeLog @@ -1,3 +1,8 @@ +Sat Dec 9 18:48:20 2006 Ben Pfaff + + * compute.c (struct compute_trns): Remove `fv' member, which was + redundant with `variable'. + Thu Nov 30 22:46:50 2006 Ben Pfaff * compute.c: Fix bug #17422, which reports that a variable created diff --git a/src/language/xforms/compute.c b/src/language/xforms/compute.c index 03e38c75..4d90f982 100644 --- a/src/language/xforms/compute.c +++ b/src/language/xforms/compute.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -58,7 +59,6 @@ struct compute_trns /* Variable lvalue, if variable != NULL. */ struct variable *variable; /* Destination variable, if any. */ - int fv; /* `value' index of destination variable. */ int width; /* Lvalue string width; 0=numeric. */ /* Vector lvalue, if vector != NULL. */ @@ -120,8 +120,8 @@ compute_num (void *compute_, struct ccase *c, casenumber case_num) if (compute->test == NULL || expr_evaluate_num (compute->test, c, case_num) == 1.0) - case_data_rw (c, compute->fv)->f = expr_evaluate_num (compute->rvalue, c, - case_num); + case_data_rw (c, compute->variable)->f + = expr_evaluate_num (compute->rvalue, c, case_num); return TRNS_CONTINUE; } @@ -141,18 +141,20 @@ compute_num_vec (void *compute_, struct ccase *c, casenumber case_num) index = expr_evaluate_num (compute->element, c, case_num); rindx = floor (index + EPSILON); - if (index == SYSMIS || rindx < 1 || rindx > compute->vector->cnt) + if (index == SYSMIS + || rindx < 1 || rindx > vector_get_var_cnt (compute->vector)) { if (index == SYSMIS) - msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value as " - "an index into vector %s."), compute->vector->name); + msg (SW, _("When executing COMPUTE: SYSMIS is not a valid value " + "as an index into vector %s."), + vector_get_name (compute->vector)); else msg (SW, _("When executing COMPUTE: %g is not a valid value as " "an index into vector %s."), - index, compute->vector->name); + index, vector_get_name (compute->vector)); return TRNS_CONTINUE; } - case_data_rw (c, compute->vector->var[rindx - 1]->fv)->f + case_data_rw (c, vector_get_var (compute->vector, rindx - 1))->f = expr_evaluate_num (compute->rvalue, c, case_num); } @@ -168,7 +170,7 @@ compute_str (void *compute_, struct ccase *c, casenumber case_num) if (compute->test == NULL || expr_evaluate_num (compute->test, c, case_num) == 1.0) expr_evaluate_str (compute->rvalue, c, case_num, - case_data_rw (c, compute->fv)->s, compute->width); + case_data_rw (c, compute->variable)->s, compute->width); return TRNS_CONTINUE; } @@ -193,20 +195,21 @@ compute_str_vec (void *compute_, struct ccase *c, casenumber case_num) { msg (SW, _("When executing COMPUTE: SYSMIS is not a valid " "value as an index into vector %s."), - compute->vector->name); + vector_get_name (compute->vector)); return TRNS_CONTINUE; } - else if (rindx < 1 || rindx > compute->vector->cnt) + else if (rindx < 1 || rindx > vector_get_var_cnt (compute->vector)) { msg (SW, _("When executing COMPUTE: %g is not a valid value as " "an index into vector %s."), - index, compute->vector->name); + index, vector_get_name (compute->vector)); return TRNS_CONTINUE; } - vr = compute->vector->var[rindx - 1]; + vr = vector_get_var (compute->vector, rindx - 1); expr_evaluate_str (compute->rvalue, c, case_num, - case_data_rw (c, vr->fv)->s, var_get_width (vr)); + case_data_rw (c, vr)->s, + var_get_width (vr)); } return TRNS_CONTINUE; @@ -257,7 +260,7 @@ cmd_if (struct lexer *lexer, struct dataset *ds) static trns_proc_func * get_proc_func (const struct lvalue *lvalue) { - bool is_numeric = lvalue_get_type (lvalue) == NUMERIC; + bool is_numeric = lvalue_get_type (lvalue) == VAR_NUMERIC; bool is_vector = lvalue_is_vector (lvalue); return (is_numeric @@ -271,7 +274,7 @@ static struct expression * parse_rvalue (struct lexer *lexer, const struct lvalue *lvalue, struct dataset *ds) { - bool is_numeric = lvalue_get_type (lvalue) == NUMERIC; + bool is_numeric = lvalue_get_type (lvalue) == VAR_NUMERIC; return expr_parse (lexer, ds, is_numeric ? EXPR_NUMBER : EXPR_STRING); } @@ -380,7 +383,7 @@ lvalue_get_type (const struct lvalue *lvalue) { return (lvalue->variable != NULL ? var_get_type (lvalue->variable) - : var_get_type (lvalue->vector->var[0])); + : vector_get_type (lvalue->vector)); } /* Returns true if LVALUE has a vector as its target. */ @@ -400,12 +403,11 @@ lvalue_finalize (struct lvalue *lvalue, if (lvalue->vector == NULL) { compute->variable = lvalue->variable; - compute->fv = compute->variable->fv; compute->width = var_get_width (compute->variable); /* Goofy behavior, but compatible: Turn off LEAVE. */ - if (dict_class_from_id (var_get_name (compute->variable)) != DC_SCRATCH) - compute->variable->leave = false; + if (!var_must_leave (compute->variable)) + var_set_leave (compute->variable, false); /* Prevent lvalue_destroy from deleting variable. */ lvalue->is_new_variable = false; diff --git a/src/language/xforms/count.c b/src/language/xforms/count.c index 8afab355..80854d31 100644 --- a/src/language/xforms/count.c +++ b/src/language/xforms/count.c @@ -277,7 +277,7 @@ count_numeric (struct criteria *crit, struct ccase *c) for (i = 0; i < crit->var_cnt; i++) { - double x = case_num (c, crit->vars[i]->fv); + double x = case_num (c, crit->vars[i]); if (x == SYSMIS) counter += crit->count_system_missing; else if (crit->count_user_missing @@ -311,7 +311,7 @@ count_string (struct criteria *crit, struct ccase *c) { char **v; for (v = crit->values.str; v < crit->values.str + crit->value_cnt; v++) - if (!memcmp (case_str (c, crit->vars[i]->fv), *v, + if (!memcmp (case_str (c, crit->vars[i]), *v, var_get_width (crit->vars[i]))) { counter++; @@ -341,7 +341,7 @@ count_trns_proc (void *trns_, struct ccase *c, counter += count_numeric (crit, c); else counter += count_string (crit, c); - case_data_rw (c, dv->var->fv)->f = counter; + case_data_rw (c, dv->var)->f = counter; } return TRNS_CONTINUE; } diff --git a/src/language/xforms/recode.c b/src/language/xforms/recode.c index 0c2a7529..54ae90ff 100644 --- a/src/language/xforms/recode.c +++ b/src/language/xforms/recode.c @@ -157,7 +157,7 @@ cmd_recode (struct lexer *lexer, struct dataset *ds) /* Ensure that all the output strings are at least as wide as the widest destination variable. */ - if (trns->dst_type == ALPHA) + if (trns->dst_type == VAR_STRING) enlarge_dst_widths (trns); /* Create destination variables, if needed. @@ -243,7 +243,7 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns) if (!parse_map_out (lexer, trns->pool, &out)) return false; - dst_type = out.width == 0 ? NUMERIC : ALPHA; + dst_type = var_type_from_width (out.width); if (have_dst_type && dst_type != trns->dst_type) { msg (SE, _("Inconsistent target variable types. " @@ -262,9 +262,9 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns) set_map_in_generic (&in, MAP_CONVERT); add_mapping (trns, &map_allocated, &in); - dst_type = NUMERIC; - if (trns->src_type != ALPHA - || (have_dst_type && trns->dst_type != NUMERIC)) + dst_type = VAR_NUMERIC; + if (trns->src_type != VAR_STRING + || (have_dst_type && trns->dst_type != VAR_NUMERIC)) { msg (SE, _("CONVERT requires string input values and " "numeric output values.")); @@ -293,7 +293,7 @@ parse_map_in (struct lexer *lexer, struct map_in *in, struct pool *pool, { if (lex_match_id (lexer, "ELSE")) set_map_in_generic (in, MAP_ELSE); - else if (src_type == NUMERIC) + else if (src_type == VAR_NUMERIC) { if (lex_match_id (lexer, "MISSING")) set_map_in_generic (in, MAP_MISSING); @@ -446,7 +446,7 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns, { struct variable *v; v = trns->dst_vars[i] = dict_lookup_var (dict, trns->dst_names[i]); - if (v == NULL && trns->dst_type == ALPHA) + if (v == NULL && trns->dst_type == VAR_STRING) { msg (SE, _("There is no variable named " "%s. (All string variables specified " @@ -465,8 +465,8 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns, { msg (SE, _("INTO is required with %s input values " "and %s output values."), - var_type_adj (trns->src_type), - var_type_adj (trns->dst_type)); + trns->src_type == VAR_NUMERIC ? _("numeric") : _("string"), + trns->dst_type == VAR_NUMERIC ? _("numeric") : _("string")); return false; } } @@ -478,7 +478,7 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns, { msg (SE, _("Type mismatch. Cannot store %s data in " "%s variable %s."), - trns->dst_type == ALPHA ? _("string") : _("numeric"), + trns->dst_type == VAR_STRING ? _("string") : _("numeric"), var_is_alpha (v) ? _("string") : _("numeric"), var_get_name (v)); return false; @@ -628,17 +628,17 @@ recode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED) struct variable *src_var = trns->src_vars[i]; struct variable *dst_var = trns->dst_vars[i]; - const union value *src_data = case_data (c, src_var->fv); - union value *dst_data = case_data_rw (c, dst_var->fv); + const union value *src_data = case_data (c, src_var); + union value *dst_data = case_data_rw (c, dst_var); const struct map_out *out; - if (trns->src_type == NUMERIC) + if (trns->src_type == VAR_NUMERIC) out = find_src_numeric (trns, src_data->f, src_var); else out = find_src_string (trns, src_data->s, var_get_width (src_var)); - if (trns->dst_type == NUMERIC) + if (trns->dst_type == VAR_NUMERIC) { if (out != NULL) dst_data->f = !out->copy_input ? out->value.f : src_data->f; diff --git a/src/libpspp/ChangeLog b/src/libpspp/ChangeLog index 8e197d99..1a6c7c33 100644 --- a/src/libpspp/ChangeLog +++ b/src/libpspp/ChangeLog @@ -1,3 +1,7 @@ +Sat Dec 9 18:48:55 2006 Ben Pfaff + + * misc.h (macro range): Removed, as it was unused. + Sat Dec 9 07:19:01 WST 2006 John Darrington * array.c: Removed gratuitous #include diff --git a/src/libpspp/misc.h b/src/libpspp/misc.h index 16f16b97..fea0e28e 100644 --- a/src/libpspp/misc.h +++ b/src/libpspp/misc.h @@ -43,9 +43,6 @@ #include /* Declares finite() under Solaris. */ #endif -/* Clamps A to be between B and C. */ -#define range(A, B, C) ((A) < (B) ? (B) : ((A) > (C) ? (C) : (A))) - /* Divides nonnegative X by positive Y, rounding up. */ #define DIV_RND_UP(X, Y) (((X) + ((Y) - 1)) / (Y)) diff --git a/src/math/design-matrix.c b/src/math/design-matrix.c index 01fdb085..0f5242d5 100644 --- a/src/math/design-matrix.c +++ b/src/math/design-matrix.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -122,10 +123,10 @@ design_matrix_create (int n_variables, } else if (var_is_alpha (v)) { - assert (v->obs_vals != NULL); + struct cat_vals *obs_vals = var_get_obs_vals (v); (dm->vars + i)->last_column = - (dm->vars + i)->first_column + v->obs_vals->n_categories - 2; - n_cols += v->obs_vals->n_categories - 1; + (dm->vars + i)->first_column + obs_vals->n_categories - 2; + n_cols += obs_vals->n_categories - 1; } } dm->m = gsl_matrix_calloc (n_data, n_cols); diff --git a/src/math/group.c b/src/math/group.c index c3dcbaad..87ba02bb 100644 --- a/src/math/group.c +++ b/src/math/group.c @@ -63,7 +63,11 @@ struct group_proc * group_proc_get (struct variable *v) { /* This is not ideal, obviously. */ - if (v->aux == NULL) - var_attach_aux (v, xmalloc (sizeof (struct group_proc)), var_dtor_free); - return v->aux; + struct group_proc *group = var_get_aux (v); + if (group == NULL) + { + group = xmalloc (sizeof (struct group_proc)); + var_attach_aux (v, group, var_dtor_free); + } + return group; } diff --git a/src/math/levene.c b/src/math/levene.c index f5ed0568..c6a33e22 100644 --- a/src/math/levene.c +++ b/src/math/levene.c @@ -187,7 +187,7 @@ levene_calc (const struct dictionary *dict, const struct ccase *c, { size_t i; bool warn = false; - const union value *gv = case_data (c, l->v_indep->fv); + const union value *gv = case_data (c, l->v_indep); struct group_statistics key; double weight = dict_get_case_weight (dict, c, &warn); @@ -198,7 +198,7 @@ levene_calc (const struct dictionary *dict, const struct ccase *c, struct variable *var = l->v_dep[i]; struct group_proc *gp = group_proc_get (var); double levene_z; - const union value *v = case_data (c, var->fv); + const union value *v = case_data (c, var); struct group_statistics *gs; gs = hsh_find(gp->group_hash,(void *) &key ); @@ -278,7 +278,7 @@ levene2_calc (const struct dictionary *dict, const struct ccase *c, double weight = dict_get_case_weight (dict, c, &warn); - const union value *gv = case_data (c, l->v_indep->fv); + const union value *gv = case_data (c, l->v_indep); struct group_statistics key; key.id = *gv; @@ -287,7 +287,7 @@ levene2_calc (const struct dictionary *dict, const struct ccase *c, { double levene_z; struct variable *var = l->v_dep[i] ; - const union value *v = case_data (c, var->fv); + const union value *v = case_data (c, var); struct group_statistics *gs; gs = hsh_find(group_proc_get (var)->group_hash,(void *) &key ); diff --git a/src/math/sort.c b/src/math/sort.c index 7d2469a8..fbd40d9b 100644 --- a/src/math/sort.c +++ b/src/math/sort.c @@ -463,13 +463,14 @@ compare_record (const struct ccase *a, const struct ccase *b, if (c->width == 0) { - double af = case_num (a, c->fv); - double bf = case_num (b, c->fv); + double af = case_num_idx (a, c->fv); + double bf = case_num_idx (b, c->fv); result = af < bf ? -1 : af > bf; } else - result = memcmp (case_str (a, c->fv), case_str (b, c->fv), c->width); + result = memcmp (case_str_idx (a, c->fv), + case_str_idx (b, c->fv), c->width); if (result != 0) return c->dir == SRT_ASCEND ? result : -result; diff --git a/src/output/table.c b/src/output/table.c index a8624488..3f1672a5 100644 --- a/src/output/table.c +++ b/src/output/table.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/ui/flexifile.c b/src/ui/flexifile.c index 9ab6cb98..3d781468 100644 --- a/src/ui/flexifile.c +++ b/src/ui/flexifile.c @@ -331,7 +331,7 @@ impl_resize (struct flexifile *ff, int n_values, int posn) case_copy (&c, 0, &ff->cases[i], 0, posn); if ( n_values > 0 ) - memset (case_data_rw(&c, posn), ' ', n_values * MAX_SHORT_STRING) ; + memset (case_data_rw_idx(&c, posn), ' ', n_values * MAX_SHORT_STRING) ; case_copy (&c, posn + n_values, &ff->cases[i], posn, ff->value_cnt - posn); diff --git a/src/ui/gui/helper.c b/src/ui/gui/helper.c index 2b3c637a..d60a01ac 100644 --- a/src/ui/gui/helper.c +++ b/src/ui/gui/helper.c @@ -1,3 +1,5 @@ +#include + #include "helper.h" #include #include diff --git a/src/ui/gui/missing-val-dialog.c b/src/ui/gui/missing-val-dialog.c index 4e166545..945cebe3 100644 --- a/src/ui/gui/missing-val-dialog.c +++ b/src/ui/gui/missing-val-dialog.c @@ -279,7 +279,7 @@ missing_val_dialog_show(struct missing_val_dialog *dialog) gtk_widget_set_sensitive(dialog->discrete, FALSE); gtk_widget_set_sensitive(GTK_WIDGET(dialog->button_range), - psppire_variable_get_type(dialog->pv) == NUMERIC); + psppire_variable_get_type(dialog->pv) == VAR_NUMERIC); for(i = 0 ; i < 3 ; ++i ) { diff --git a/src/ui/gui/psppire-case-file.c b/src/ui/gui/psppire-case-file.c index 7e16087e..35db14ef 100644 --- a/src/ui/gui/psppire-case-file.c +++ b/src/ui/gui/psppire-case-file.c @@ -247,7 +247,7 @@ psppire_case_file_get_value(const PsppireCaseFile *cf, gint casenum, gint idx) flexifile_get_case(FLEXIFILE(cf->flexifile), casenum, &c); - v = case_data(&c, idx); + v = case_data_idx(&c, idx); case_destroy(&c); @@ -284,7 +284,7 @@ psppire_case_file_set_value(PsppireCaseFile *cf, gint casenum, gint idx, bytes = DIV_RND_UP(width, MAX_SHORT_STRING) * MAX_SHORT_STRING ; /* Cast away const in flagrant abuse of the casefile */ - memcpy((union value *)case_data(&cc, idx), v, bytes); + memcpy((union value *)case_data_idx(&cc, idx), v, bytes); g_signal_emit(cf, signal[CASE_CHANGED], 0, casenum); @@ -310,7 +310,7 @@ psppire_case_file_data_in(PsppireCaseFile *cf, gint casenum, gint idx, /* Cast away const in flagrant abuse of the casefile */ if (!data_in (input, fmt->type, 0, 0, - (union value *) case_data(&cc, idx), fmt_var_width (fmt))) + (union value *) case_data_idx(&cc, idx), fmt_var_width (fmt))) g_warning("Cant set value\n"); g_signal_emit(cf, signal[CASE_CHANGED], 0, casenum); diff --git a/src/ui/gui/psppire-data-store.c b/src/ui/gui/psppire-data-store.c index 0466a97b..65a4391d 100644 --- a/src/ui/gui/psppire-data-store.c +++ b/src/ui/gui/psppire-data-store.c @@ -442,10 +442,10 @@ psppire_data_store_insert_new_case(PsppireDataStore *ds, gint posn) for (v = 0 ; v < psppire_dict_get_var_cnt (ds->dict) ; ++v) { const struct PsppireVariable *pv = psppire_dict_get_variable(ds->dict, v); - if (ALPHA == psppire_variable_get_type(pv) ) + if (VAR_STRING == psppire_variable_get_type(pv) ) continue; - case_data_rw (&cc, psppire_variable_get_fv (pv))->f = SYSMIS; + case_data_rw_idx (&cc, psppire_variable_get_fv (pv))->f = SYSMIS; } result = psppire_case_file_insert_case (ds->case_file, &cc, posn); @@ -530,7 +530,7 @@ psppire_data_store_clear_datum (GSheetModel *model, const gint index = psppire_variable_get_fv(pv) ; - if ( psppire_variable_get_type(pv) == NUMERIC) + if ( psppire_variable_get_type(pv) == VAR_NUMERIC) v.f = SYSMIS; else memcpy(v.s, "", MAX_SHORT_STRING); diff --git a/src/ui/gui/psppire-var-store.c b/src/ui/gui/psppire-var-store.c index eb97401e..daeeb23e 100644 --- a/src/ui/gui/psppire-var-store.c +++ b/src/ui/gui/psppire-var-store.c @@ -156,7 +156,7 @@ psppire_var_store_item_editable(PsppireVarStore *var_store, gint row, gint colum if ( !pv ) return TRUE; - if ( ALPHA == psppire_variable_get_type(pv) && column == COL_DECIMALS ) + if ( VAR_STRING == psppire_variable_get_type(pv) && column == COL_DECIMALS ) return FALSE; write_spec = psppire_variable_get_write_spec(pv); diff --git a/src/ui/gui/psppire-variable.c b/src/ui/gui/psppire-variable.c index 6195a16b..70c69a7e 100644 --- a/src/ui/gui/psppire-variable.c +++ b/src/ui/gui/psppire-variable.c @@ -18,6 +18,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include + #include #include @@ -51,7 +53,7 @@ psppire_variable_set_name(struct PsppireVariable *pv, const gchar *text) dict_rename_var(pv->dict->dict, pv->v, text); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -66,7 +68,7 @@ psppire_variable_set_columns(struct PsppireVariable *pv, gint columns) var_set_display_width (pv->v, columns); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -80,7 +82,7 @@ psppire_variable_set_label(struct PsppireVariable *pv, const gchar *label) var_set_label (pv->v, label); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -124,7 +126,7 @@ psppire_variable_set_width(struct PsppireVariable *pv, gint width) old_var_cnt = DIV_RND_UP(var_get_width (pv->v), MAX_SHORT_STRING); new_var_cnt = DIV_RND_UP(width, MAX_SHORT_STRING); - pv->v->width = width; + var_set_width (pv->v, width); psppire_dict_resize_variable(pv->dict, pv, old_var_cnt, new_var_cnt); @@ -148,10 +150,7 @@ psppire_variable_set_type(struct PsppireVariable *pv, int type) else old_var_cnt = DIV_RND_UP (var_get_width (pv->v), MAX_SHORT_STRING); - if ( type == NUMERIC ) - pv->v->width = 0; - else if (var_get_width (pv->v)) - pv->v->width = 1; + var_set_width (pv->v, type == VAR_NUMERIC ? 0 : 1); if ( var_get_width (pv->v) == 0 ) new_var_cnt = 1; @@ -161,7 +160,7 @@ psppire_variable_set_type(struct PsppireVariable *pv, int type) psppire_dict_resize_variable(pv->dict, pv, old_var_cnt, new_var_cnt); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -180,7 +179,7 @@ psppire_variable_set_format(struct PsppireVariable *pv, struct fmt_spec *fmt) { msg_enable (); var_set_both_formats (pv->v, fmt); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } msg_enable (); @@ -197,10 +196,9 @@ psppire_variable_set_value_labels(const struct PsppireVariable *pv, g_return_val_if_fail(pv->dict, FALSE); g_return_val_if_fail(pv->v, FALSE); - val_labs_destroy(pv->v->val_labs); - pv->v->val_labs = val_labs_copy(vls); + var_set_value_labels (pv->v, vls); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -214,7 +212,7 @@ psppire_variable_set_missing(const struct PsppireVariable *pv, var_set_missing_values (pv->v, miss); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -226,7 +224,7 @@ psppire_variable_set_write_spec(const struct PsppireVariable *pv, struct fmt_spe var_set_write_format (pv->v, &fmt); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -238,7 +236,7 @@ psppire_variable_set_print_spec(const struct PsppireVariable *pv, struct fmt_spe var_set_print_format (pv->v, &fmt); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -253,7 +251,7 @@ psppire_variable_set_alignment(struct PsppireVariable *pv, gint align) var_set_alignment (pv->v, align); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -267,7 +265,7 @@ psppire_variable_set_measure(struct PsppireVariable *pv, gint measure) var_set_measure (pv->v, measure + 1); - psppire_dict_var_changed(pv->dict, pv->v->index); + psppire_dict_var_changed(pv->dict, var_get_dict_index (pv->v)); return TRUE; } @@ -329,7 +327,7 @@ psppire_variable_get_value_labels(const struct PsppireVariable *pv) g_return_val_if_fail(pv, NULL); g_return_val_if_fail(pv->v, NULL); - return pv->v->val_labs; + return var_get_value_labels (pv->v); } @@ -379,7 +377,7 @@ psppire_variable_get_fv(const struct PsppireVariable *pv) g_return_val_if_fail(pv, -1); g_return_val_if_fail(pv->v, -1); - return pv->v->fv; + return var_get_case_index (pv->v); } @@ -390,6 +388,6 @@ psppire_variable_get_index(const struct PsppireVariable *pv) g_return_val_if_fail(pv, -1); g_return_val_if_fail(pv->v, -1); - return pv->v->index; + return var_get_dict_index (pv->v); } diff --git a/src/ui/gui/psppire-variable.h b/src/ui/gui/psppire-variable.h index 248844eb..2b06336d 100644 --- a/src/ui/gui/psppire-variable.h +++ b/src/ui/gui/psppire-variable.h @@ -28,6 +28,8 @@ #include #include "psppire-dict.h" +struct val_labs; + /* Don't use any of these members. Use accessor functions instead. */ diff --git a/src/ui/gui/val-labs-dialog.c b/src/ui/gui/val-labs-dialog.c index a17d8e10..ff78347c 100644 --- a/src/ui/gui/val-labs-dialog.c +++ b/src/ui/gui/val-labs-dialog.c @@ -22,6 +22,8 @@ /* This module describes the behaviour of the Value Labels dialog box, used for input of the value labels in the variable sheet */ +#include + #include #include "helper.h" diff --git a/src/ui/gui/var-sheet.c b/src/ui/gui/var-sheet.c index 3145f13d..2cf12f58 100644 --- a/src/ui/gui/var-sheet.c +++ b/src/ui/gui/var-sheet.c @@ -372,7 +372,7 @@ var_sheet_cell_change_entry (GtkSheet * sheet, gint row, gint column, { case COL_WIDTH: r_min = fmt->d + 1; - r_max = (psppire_variable_get_type(pv) == ALPHA) ? MAX_STRING : 40; + r_max = (psppire_variable_get_type(pv) == VAR_STRING) ? MAX_STRING : 40; break; case COL_DECIMALS: r_min = 0 ; diff --git a/src/ui/gui/var-type-dialog.c b/src/ui/gui/var-type-dialog.c index 12180433..a4b66cc2 100644 --- a/src/ui/gui/var-type-dialog.c +++ b/src/ui/gui/var-type-dialog.c @@ -819,14 +819,14 @@ on_var_type_ok_clicked(GtkWidget *w, gpointer data) gint decimals = atoi(gtk_entry_get_text (GTK_ENTRY(dialog->entry_decimals))); - gint new_type = NUMERIC; + gint new_type = VAR_NUMERIC; gint new_width = 0; bool result = false; struct fmt_spec spec; switch (dialog->active_button) { case BUTTON_STRING: - new_type = ALPHA; + new_type = VAR_STRING; new_width = width; result = make_output_format_try(&spec, FMT_A, width, 0); break; -- 2.30.2