Finish converting struct variable to an opaque type. In this
authorBen Pfaff <blp@gnu.org>
Sun, 10 Dec 2006 03:42:50 +0000 (03:42 +0000)
committerBen Pfaff <blp@gnu.org>
Sun, 10 Dec 2006 03:42:50 +0000 (03:42 +0000)
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.

97 files changed:
doc/variables.texi
src/data/ChangeLog
src/data/automake.mk
src/data/case.c
src/data/case.h
src/data/casefilter.c
src/data/cat-routines.h
src/data/category.c
src/data/data-in.c
src/data/data-out.c
src/data/dictionary.c
src/data/dictionary.h
src/data/format.c
src/data/format.h
src/data/missing-values.c
src/data/missing-values.h
src/data/por-file-reader.c
src/data/por-file-writer.c
src/data/procedure.c
src/data/sys-file-private.c [new file with mode: 0644]
src/data/sys-file-private.h [new file with mode: 0644]
src/data/sys-file-reader.c
src/data/sys-file-writer.c
src/data/value-labels.c
src/data/value-labels.h
src/data/value.c [new file with mode: 0644]
src/data/value.h
src/data/vardict.h [new file with mode: 0644]
src/data/variable.c
src/data/variable.h
src/data/vector.c [new file with mode: 0644]
src/data/vector.h [new file with mode: 0644]
src/language/control/do-if.c
src/language/control/loop.c
src/language/data-io/ChangeLog
src/language/data-io/data-list.c
src/language/data-io/get.c
src/language/data-io/inpt-pgm.c
src/language/data-io/list.q
src/language/data-io/matrix-data.c
src/language/data-io/print-space.c
src/language/data-io/print.c
src/language/dictionary/ChangeLog
src/language/dictionary/apply-dictionary.c
src/language/dictionary/formats.c
src/language/dictionary/missing-values.c
src/language/dictionary/modify-variables.c
src/language/dictionary/numeric.c
src/language/dictionary/split-file.c
src/language/dictionary/sys-file-info.c
src/language/dictionary/value-labels.c
src/language/dictionary/variable-label.c
src/language/dictionary/vector.c
src/language/expressions/evaluate.c
src/language/expressions/helpers.h
src/language/expressions/operations.def
src/language/expressions/parse.c
src/language/lexer/ChangeLog
src/language/lexer/variable-parser.c
src/language/lexer/variable-parser.h
src/language/stats/ChangeLog
src/language/stats/aggregate.c
src/language/stats/autorecode.c
src/language/stats/crosstabs.q
src/language/stats/descriptives.c
src/language/stats/examine.q
src/language/stats/flip.c
src/language/stats/frequencies.q
src/language/stats/oneway.q
src/language/stats/rank.q
src/language/stats/regression.q
src/language/stats/sort-criteria.c
src/language/stats/t-test.q
src/language/tests/casefile-test.c
src/language/utilities/set.q
src/language/xforms/ChangeLog
src/language/xforms/compute.c
src/language/xforms/count.c
src/language/xforms/recode.c
src/libpspp/ChangeLog
src/libpspp/misc.h
src/math/design-matrix.c
src/math/group.c
src/math/levene.c
src/math/sort.c
src/output/table.c
src/ui/flexifile.c
src/ui/gui/helper.c
src/ui/gui/missing-val-dialog.c
src/ui/gui/psppire-case-file.c
src/ui/gui/psppire-data-store.c
src/ui/gui/psppire-var-store.c
src/ui/gui/psppire-variable.c
src/ui/gui/psppire-variable.h
src/ui/gui/val-labs-dialog.c
src/ui/gui/var-sheet.c
src/ui/gui/var-type-dialog.c

index 91b07112fbfa9b463854dd062b3d324c4cd34bdf..afca8cbfc90c95a6e8658628023ec56b76efa25b 100644 (file)
@@ -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
index d64e89807698ec41e6950b6e295db6d1928318d1..e4306829c42d15e51328d2ac63470f8a7f223da3 100644 (file)
@@ -1,3 +1,165 @@
+Sat Dec  9 18:05:59 2006  Ben Pfaff  <blp@gnu.org>
+
+       * data-out.c (output_scientific): Fix bad assumption that "buf" is
+       null-terminated.
+       
+Sat Dec  9 17:23:23 2006  Ben Pfaff  <blp@gnu.org>
+
+       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 <john@darrington.wattle.id.au>
 
        * casefilter.c (casefilter_variable_missing): Avoided comparision of
@@ -23,10 +185,11 @@ Thu Dec  7 15:22:38 WST 2006 John Darrington <john@darrington.wattle.id.au>
 
 Mon Dec  4 22:20:17 2006  Ben Pfaff  <blp@gnu.org>
 
-       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.
        
index 05276465a73fb23e6b1a59e059da0416216fdd11..48db0f6e4cb411f3bd4af6c7c510f699d2799af6 100644 (file)
@@ -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
index e41c0e2235945a64a0ff2867827e7baf203913fc..20ed8bae2810ac6bbf8b2a3766358a776598a8c4 100644 (file)
@@ -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)
index df2f03560f3205106e4e60c7daa0d76e31b9c698..23862b067215d98be695ecb022076b4f64b4c33c 100644 (file)
@@ -23,6 +23,7 @@
 #include <stddef.h>
 #include <stdbool.h>
 #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 */
index 1494133359d2b3aaa3608269316f82190f215953..9049c5173ed9a833daae7af6f6d8c1e14e2e7df2 100644 (file)
@@ -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 &&
index 43cfcccd3dcf8ec019043e07d6443f4d4825803d..654ef44deaf777f3ed6fc1d9f4983f3e2426e98a 100644 (file)
@@ -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
index 21506ed8b5d0af64b2d2dc0e538776d9db27a78e..d320cea2a108f955475b413fd0cabbe54173691a 100644 (file)
@@ -42,6 +42,7 @@
 #include <libpspp/alloc.h>
 #include <libpspp/message.h>
 #include "cat-routines.h"
+#include "value.h"
 #include "variable.h"
 
 #define N_INITIAL_CATEGORIES 1
 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;
 }
 
index 7ecded2f9333f8235488c8f676692c57ba44b5fd..5fb5d4d3907367fc3ec093b879ad54277c493365 100644 (file)
@@ -34,7 +34,7 @@
 #include "calendar.h"
 #include "identifier.h"
 #include "settings.h"
-#include "variable.h"
+#include "value.h"
 
 #include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
index e7c709f678bfc1eaa49b331fabb6dfe2b278c525..544f2a54a3f86ad76c766a4c9afee5bcb8fa80e1 100644 (file)
@@ -32,7 +32,7 @@
 #include "calendar.h"
 #include "format.h"
 #include "settings.h"
-#include "variable.h"
+#include "value.h"
 
 #include <libpspp/assertion.h>
 #include <libpspp/float-format.h>
@@ -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;
 }
 \f
index 73a9da9a60a8079493b95da846f8dcdb28da8235..e312d2e9abd2d5fce35f4b49b4ddc478c93926b9 100644 (file)
 #include "category.h"
 #include "settings.h"
 #include "value-labels.h"
+#include "vardict.h"
 #include "variable.h"
+#include "vector.h"
 #include <libpspp/alloc.h>
 #include <libpspp/array.h>
 #include <libpspp/compiler.h>
 #include <libpspp/hash.h>
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
+#include <libpspp/pool.h>
 #include <libpspp/str.h>
 
 #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++;
             }
index 828b75a9bd5b8b139fec17747d043fa441caa50c..e0425b8552129b0f48bd3b7b6ef0f686bf88b703 100644 (file)
@@ -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 *);
 
index 8f2d0de98ed44215d84dcbd0ef5526950466a3a9..60c1d0a9133b98fc33e4411e6b1b7d39e73824db 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <data/identifier.h>
 #include <data/settings.h>
+#include <data/value.h>
 #include <data/variable.h>
 #include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
@@ -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)
     {
index 67e46f17b18e50894069733766c9fdca31835e83..089f1ed3d1638d8e940614c32943928313bc0cee 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <stdbool.h>
 #include <stddef.h>
+#include <data/variable.h>
 #include <libpspp/str.h>
 
 /* 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. */
index 8976abc16eb41d1e345ed89e988b3ea84fd4ec08..b5f52f5e6985301b27066df9f7ab41b751ae69cf 100644 (file)
@@ -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)
index 5727344df6a47c57b8d2ddb539c4df74d58ae7e5..e6f6a0b2926ffc77403bfc082ff3783c3f85b6f5 100644 (file)
@@ -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 *,
index b6bad0a00ae974f5e6c26a24f0c835887eb6502c..307a5393063f49ec84d7e4fafa4b20d573afbc93 100644 (file)
@@ -36,6 +36,7 @@
 #include "dictionary.h"
 #include "file-handle-def.h"
 #include "format.h"
+#include "missing-values.h"
 #include <libpspp/hash.h>
 #include <libpspp/magic.h>
 #include <libpspp/misc.h>
@@ -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);
         }
     }
index aa8b5e0bc0139152dba4ae97dc546c1930429ee1..0f5542ce42bd1703723573e88d563b0fbcef6a38 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <config.h>
 #include "por-file-writer.h"
-#include <libpspp/message.h>
+
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <time.h>
 #include <unistd.h>
-#include <libpspp/alloc.h>
+
 #include "case.h"
 #include "dictionary.h"
-#include <libpspp/message.h>
 #include "file-handle-def.h"
+#include "format.h"
+#include "missing-values.h"
+#include "stat-macros.h"
+#include "value-labels.h"
+#include "variable.h"
+
+#include <libpspp/alloc.h>
 #include <libpspp/hash.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include "stat-macros.h"
 #include <libpspp/str.h>
-#include "value-labels.h"
-#include "variable.h"
 #include <libpspp/version.h>
 
 #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);
        }
     }
 
index 7cd34369a122824751245023f4b03e9b1340db22..422d0ecdc9b8b3e48483bb4216825c5a88fe99b9 100644 (file)
@@ -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 (file)
index 0000000..4c77f87
--- /dev/null
@@ -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 <config.h>
+#include "sys-file-private.h"
+
+#include <data/value.h>
+#include <libpspp/assertion.h>
+
+/* 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 (file)
index 0000000..012ebfe
--- /dev/null
@@ -0,0 +1,30 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   Written by Ben Pfaff <blp@gnu.org>.
+
+   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 */
index ccae0577b4d919c050a7fcf702841c97d0570c82..c1a8292eaae19fb01e2c09384a85fc83c536ed6f 100644 (file)
 
 #include <config.h>
 
+#include "sys-file-reader.h"
+#include "sfm-private.h"
+#include "sys-file-private.h"
+
 #include <stdlib.h>
 #include <errno.h>
 #include <float.h>
 #include <libpspp/hash.h>
 #include <libpspp/array.h>
 
-#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);
             }
         }
 
index f4226169646d8118ea4d118b3405b475e0464d1b..ddfb4ae75c47288ec4d4ff2683c89ed76c2091fd 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "sys-file-writer.h"
 #include "sfm-private.h"
+#include "sys-file-private.h"
 
 #include <ctype.h>
 #include <errno.h>
@@ -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, &params, 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;
              }
index 357ab4fcb2b5f7f06fc059e0748aeb00b275e374..81bb375eeca5538fa27c71e5b33735c5368fc762 100644 (file)
@@ -24,6 +24,8 @@
 #include <stdlib.h>
 
 #include <data/data-out.h>
+#include <data/format.h>
+#include <data/value.h>
 #include <data/variable.h>
 #include <libpspp/alloc.h>
 #include <libpspp/compiler.h>
@@ -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);
 }
 \f
 /* 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;
-}
index 1085fe65f7be60e665e627e54020575bbf88529e..bf015824fa22925df0b917702deba5fefa6b3d05 100644 (file)
@@ -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 (file)
index 0000000..2de3adb
--- /dev/null
@@ -0,0 +1,56 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Written by Ben Pfaff <blp@gnu.org>.
+
+   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 <config.h>
+#include "value.h"
+
+#include <libpspp/hash.h>
+#include <libpspp/str.h>
+
+#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)));
+}
index fccd8a98cd4e0093928f1bf5178aa4f42ea5f9ff..d4978989044040933f328fd02e4fd9829d485285 100644 (file)
 #define value_h 1
 
 #include <float.h>
-
-#include <config.h>
+#include <libpspp/misc.h>
+#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 (file)
index 0000000..dd4f732
--- /dev/null
@@ -0,0 +1,39 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Written by Ben Pfaff <blp@gnu.org>.
+
+   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 */
index b43fce7e41d6f844ff74c35c183225af1827962b..5513e5ef89a27a8dad7f8c16814a6384e07c4a85 100644 (file)
 
 #include <config.h>
 #include "variable.h"
-#include <libpspp/assertion.h>
-#include <libpspp/message.h>
+
 #include <stdlib.h>
+
+#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 <libpspp/alloc.h>
+#include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
-#include "dictionary.h"
 #include <libpspp/hash.h>
-#include "identifier.h"
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
-#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");
-}
-\f
-/* 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;
 }
 \f
-/* 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); 
+    }
 }
 \f
+/* 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));
 }
 \f
-/* 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);
 }
-
+\f
 /* 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);
 }
 \f
+/* 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;
+}
+\f
 /* 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);
 }
 \f
+/* 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;
 }
 \f
+/* 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;
 }
-
+\f
 /* 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;
 }
+\f
+/* 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;
 }
 \f
-/* 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;
+}
 \f
 /* 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';
 }
+\f
+/* 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;
+}
+\f
+/* 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);
 }
+\f
+/* 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;
+}
+\f
 /* 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)
+\f
+/* 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;
+}
index 685c5104a22a4dbd8f21497fa99383c9d961bb80..0cb20b8fec3dd9204f3281e012462aa17335391b 100644 (file)
 #if !variable_h
 #define variable_h 1
 
-
 #include <stddef.h>
 #include "config.h"
 #include <stdbool.h>
-#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);
-\f
-/* 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 (file)
index 0000000..8f3de2f
--- /dev/null
@@ -0,0 +1,146 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2006  Free Software Foundation, Inc.
+   Written by Ben Pfaff <blp@gnu.org>.
+
+   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 <config.h>
+#include "vector.h"
+
+#include "dictionary.h"
+
+#include <libpspp/assertion.h>
+#include <libpspp/str.h>
+
+#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 (file)
index 0000000..18ac496
--- /dev/null
@@ -0,0 +1,42 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2006  Free Software Foundation, Inc.
+   Written by Ben Pfaff <blp@gnu.org>.
+
+   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 <stddef.h>
+#include <data/variable.h>
+
+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 */
index 51c3ec9fa3b636308be4c15c6a349f6e8473399d..b02077b5e2210a2e9ed06e9ecbfb0b76399b7f4d 100644 (file)
@@ -24,7 +24,7 @@
 #include "control-stack.h"
 #include <data/procedure.h>
 #include <data/transformations.h>
-#include <data/variable.h>
+#include <data/value.h>
 #include <language/command.h>
 #include <language/expressions/public.h>
 #include <language/lexer/lexer.h>
index 01aad6fdaad36ae9d414c9b30127d9fdb8b4e5d1..56df4b7a9273be6337986af9809ca32eae7b737e 100644 (file)
@@ -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
index 3c5313a0db7fc77c890bc2c929fd4cfb045a9725..5b49843a61cbbf554a2204046490d55b2e6483d2 100644 (file)
@@ -1,3 +1,7 @@
+Sat Dec  9 18:43:34 2006  Ben Pfaff  <blp@gnu.org>
+
+       * list.q (cmd_list): Use new var_create, var_destroy functions.
+
 Thu Nov 30 21:51:58 2006  Ben Pfaff  <blp@gnu.org>
 
        * inpt-pgm.c (cmd_reread): Always return error code upon detecting
index 641740fc6c29c66f97e583d21df58de39b298aea..0c4caebfe53643917321ea05cde91a017c8c8c6c 100644 (file)
@@ -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;
index 90c41f2ecd40a820c8d4f908eeeacbb1d013c860..6e7206afc7fbf09d059a8a1c7b2a395044ee25d5 100644 (file)
@@ -28,6 +28,7 @@
 #include <data/case.h>
 #include <data/casefile.h>
 #include <data/fastfile.h>
+#include <data/format.h>
 #include <data/dictionary.h>
 #include <data/por-file-writer.h>
 #include <data/procedure.h>
@@ -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);
 }
 \f
 /* 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);
     }
 }
 
index 24a2e22968f1eccc0a3a23f9f0275f898470c228..d3b04ed9448ef03dc0f0d3808ea85aead2fa4ae7 100644 (file)
@@ -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 ();
index b1473fe693ff53a4cae6932725cc83682534240a..0f6a708feeb794c7ecead70a0913f920d100e369 100644 (file)
@@ -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;
index 4898e16ff250040855eb7aef1d68ce3e6e99a2d2..79023ff372b769b43cfad8e583724479643ffd49 100644 (file)
@@ -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];
        }
        
        {
index 8ddd0be5d9c93df9e13a9326aa67ff8ae021d244..f26e1f25111648634e720a3f97ec0593317b2246 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 
 #include <data/procedure.h>
+#include <data/value.h>
 #include <language/command.h>
 #include <language/data-io/data-writer.h>
 #include <language/data-io/file-handle.h>
index 374415b531fb860f662621a08604cb2d598445e8..cb3441937819f56c61e65bbf1d8e9e306c69ce02 100644 (file)
@@ -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);
index a1d42607e290b47d497d68a6f3e4a224f708c9bb..e2d7d80f72222bdf0d80707fb3c64e07618f9f0c 100644 (file)
@@ -1,3 +1,11 @@
+Sat Dec  9 18:44:26 2006  Ben Pfaff  <blp@gnu.org>
+
+       * 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  <blp@gnu.org>
 
        * value-labels.c (get_label): Allow commas between values and
index da9a9731a553bb6e45c9212a2289c6123f72db42..4a2b9cb64cde5d41303f5f11ef51ae39d6e7c0c9 100644 (file)
@@ -24,6 +24,7 @@
 #include <data/any-reader.h>
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
+#include <data/missing-values.h>
 #include <data/procedure.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
@@ -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 "
index 34599e6b22463195d1e661611b5f9e6d3a9cf141..b7fa47b82b54a5f9ff372a9a5918f76605dd1099 100644 (file)
@@ -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, ')'))
index 99018c3f4fe381ded138ccc0add09aa89df6cd51..af7eeec9afdc95a55899ff5439b416e8f5835784 100644 (file)
@@ -22,7 +22,9 @@
 #include <stdlib.h>
 
 #include <data/data-in.h>
+#include <data/missing-values.h>
 #include <data/procedure.h>
+#include <data/value.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
@@ -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);
-                }
             }
         }
 
index 1e42cb6de0a90caaee4f2d03a28cced19d996965..5322c2e31b70234391357e4f1f47def46693893d 100644 (file)
@@ -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)
index 29155961b1daf6dc8fd2e8b1c0c74876f127225b..aa6794d39f7308eb6cfda619c1af5eb8b7daf357 100644 (file)
@@ -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);
index 05b39bc02306c6594a55ff32f2f03fadb9dbbcbb..6944792f4d845f017766b032dc6426e0e83cc37e 100644 (file)
@@ -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);
     }
index 220faa3b2a97c0684f1159e4ee2b64722a3c71fc..47d151ee23c1659f2337873059324f9dad97f9a6 100644 (file)
 
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
+#include <data/format.h>
+#include <data/missing-values.h>
 #include <data/procedure.h>
 #include <data/sys-file-reader.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
+#include <data/vector.h>
 #include <language/command.h>
 #include <language/data-io/file-handle.h>
 #include <language/lexer/lexer.h>
@@ -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);
index 5ac8fb52a2ca4e11dd0b436a2c71e301e7864a80..0259d69b3ee8b32847afd2fa9245e6eac69ead3f 100644 (file)
@@ -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);
 
index 857c783c45b979a4f24b99f7ea202780b19bcac0..3cb6f5963f7fdea8ecc4f43bc63faa03891cd61c 100644 (file)
@@ -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);
-}
index 7492015c7c868d3fd875722f8ac0d64150be4074..ac8d74d5dabbb5bc14db93ed095b9cc2a2542694 100644 (file)
@@ -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);
index 1cf73ed713096011b0e2b36d483fa4d7f07dd119..93f724ff9b77916c16f3577adb816d6a3a1da842 100644 (file)
@@ -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);
index 124868cc6b50d70a65a493331da029692542f554..46ed5e4a79e03b4a698b87475ce8275b70061793 100644 (file)
@@ -19,6 +19,7 @@
 #include <data/settings.h>
 #include <data/value.h>
 #include <data/variable.h>
+#include <data/vector.h>
 #include <gsl-extras/gsl-extras.h>
 #include <language/expressions/public.h>
 #include <libpspp/compiler.h>
index 5f0b938a0974a1a1e92a948d961ce7bd9cd1f523..03861021c4f4863ebcf5976710c8e893a53ebfe9 100644 (file)
@@ -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 ()
index 6489ed8381c0eacd3273268000c93b697be812be..7c5ea4cfda7acd08316caef515fd8a216cf1831c 100644 (file)
@@ -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));
 }
index db33299a4cd473398effd2f2ac0ac9d5415ac79b..cfa344d2f84bfd0589479992c746368d77b997b9 100644 (file)
@@ -1,3 +1,13 @@
+Sat Dec  9 18:46:11 2006  Ben Pfaff  <blp@gnu.org>
+
+       * 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  <blp@gnu.org>
 
        General clean-up.
index 2cb54f7a542eae4cb7c486dc899c9b62d168951d..d9eae5247c3dc833a5f105861e6179354567797d 100644 (file)
@@ -30,6 +30,7 @@
 #include <data/procedure.h>
 #include <data/variable.h>
 #include <libpspp/alloc.h>
+#include <libpspp/assertion.h>
 #include <libpspp/bit-vector.h>
 #include <libpspp/hash.h>
 #include <libpspp/message.h>
@@ -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) 
       {
index 0a204844549c367bd430a409b0ae8ddfd58f8728..1e626f33880d4e19dd1b3eef53f3a0272a14ecd9 100644 (file)
@@ -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 *);
index fdfa62d764dbebd409ed165c32f52883cb7e40ed..95e24640ef13b5906b7d1dd087989281839a0953 100644 (file)
@@ -1,3 +1,8 @@
+Sat Dec  9 18:47:51 2006  Ben Pfaff  <blp@gnu.org>
+
+       * regression.q (is_depvar): Compare variable pointers instead of
+       variable names.
+
 Thu Dec  7 15:26:25 WST 2006 John Darrington <john@darrington.wattle.id.au>
 
        * examine.q: Allocated the categorical values for the dependent and 
index 4a4417165f5aa6a0b1b4b4b6f778d20400b1a128..5e4be3bcd9643bb4ae3014c46c4caee454b4e254 100644 (file)
@@ -27,6 +27,7 @@
 #include <data/casefile.h>
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
+#include <data/format.h>
 #include <data/procedure.h>
 #include <data/settings.h>
 #include <data/storage-stream.h>
@@ -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[] = 
   {
-    {"<NONE>",  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}},
+    {"<NONE>",  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
index fe1150a3bb456a92e23e507d4245d509a04a02c7..048db1191cbecffe1a8dd055e126c9ceb1e71192 100644 (file)
@@ -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)
index fc8571c46aee0f8c59c9066c27f94b085b728de9..cd12ab988e2e859652da7e50e134a99ecb0e7d3b 100644 (file)
@@ -39,6 +39,7 @@
 #include <data/case.h>
 #include <data/data-out.h>
 #include <data/dictionary.h>
+#include <data/format.h>
 #include <data/procedure.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
@@ -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);
index 598752caf1deba6011feb81044af5db7adc98f45..ccab1931e18d063877afdc0007c4f0a143bdb4ad 100644 (file)
@@ -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
index b337131c9ef3ff32802c370a64f351d4140fae2e..9a55c9f3e5915787f5d28a4e45542ddfe9205870 100644 (file)
@@ -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);
     }
 
index a8f135806640ffb7888fccdcb0e04ea57c96ef70..c28de4600ac055247c9dcd58ea0859ef8e642dc5 100644 (file)
@@ -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);
index 8256f3d8a450f3261ab741cfc0d4417475fd1a85..f614bcf9970c0219b21e59e874db61862a9afed3 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <data/case.h>
 #include <data/dictionary.h>
+#include <data/format.h>
 #include <data/procedure.h>
 #include <data/settings.h>
 #include <data/value-labels.h>
@@ -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;
     }
index ea4ed328c6ab8e3d5c60297e1867332743d55802..9b5ed83dc3ca400b4cea8e539f5b780993ae8925 100644 (file)
@@ -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;
index 12024239f09ca5666739986d98acf1892a96b0ad..f64778ae78fa4add452f969b64505220f25a198a 100644 (file)
@@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 #include "sort-criteria.h"
 
 #include <data/dictionary.h>
+#include <data/format.h>
+#include <data/missing-values.h>
 #include <data/procedure.h>
 #include <data/variable.h>
 #include <data/case.h>
@@ -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;
 
index 77f577a565672a9e1971155e4ab2375122155f14..c779ae1e43a8e407c353728887843e9d3fcd9132 100644 (file)
@@ -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++;
            }
index 6e8bada48e01653f7d6d08b53ca714e66a6d30ae..87dc6b4fd5875ecb21e3684d09a77fbed88fdbac 100644 (file)
@@ -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;
         }
index 7748676ab0c338663f9995bcd50d7845352b9f20..5c902dfd225038c42ad584c5bd560deaa53c3ffa 100644 (file)
@@ -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;
 
index 0bafe5ef13aceb08c38537018afd3463f7788cf0..33b15cb6eb00ef0eb93e7ae312859b79c458e576 100644 (file)
@@ -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); 
     }
index efafcc8fc0886bf681703abbf58cd9c63b720d38..b0fad473b372f75526f70eedcb209d2eb499cb4a 100644 (file)
@@ -30,6 +30,7 @@
 #include <data/format.h>
 #include <data/procedure.h>
 #include <data/settings.h>
+#include <data/value.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/format-parser.h>
index 4c79eeff4e279e4749c5df1e6624cb2c83c295d2..8e099a969e06cc72b1375ea12908900857415c06 100644 (file)
@@ -1,3 +1,8 @@
+Sat Dec  9 18:48:20 2006  Ben Pfaff  <blp@gnu.org>
+
+       * compute.c (struct compute_trns): Remove `fv' member, which was
+       redundant with `variable'.
+
 Thu Nov 30 22:46:50 2006  Ben Pfaff  <blp@gnu.org>
 
        * compute.c: Fix bug #17422, which reports that a variable created
index 03e38c75f6f9afd0191e84d37e7fad5936fbcea0..4d90f9823fd9a907d7862554133a00095299a7a8 100644 (file)
@@ -26,6 +26,7 @@
 #include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
+#include <data/vector.h>
 #include <language/command.h>
 #include <language/expressions/public.h>
 #include <language/lexer/lexer.h>
@@ -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;
index 8afab3554ff99ff768fbcbf590c9dc3d95113637..80854d3100661cb81715adfa402f915288b5a13e 100644 (file)
@@ -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;
 }
index 0c2a7529c5b79d91eb1ce320795956415f560601..54ae90ffb8b2e4cb7fb7ab56ff948be94567714e 100644 (file)
@@ -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; 
index 8e197d991b1289f84a78284c7764658d0c506240..1a6c7c3322d38cd14de506b7010e6073756790cc 100644 (file)
@@ -1,3 +1,7 @@
+Sat Dec  9 18:48:55 2006  Ben Pfaff  <blp@gnu.org>
+
+       * misc.h (macro range): Removed, as it was unused.
+
 Sat Dec  9 07:19:01 WST 2006 John Darrington <john@darrington.wattle.id.au>
 
        * array.c: Removed gratuitous #include
index 16f16b97ae4309c64b9aa141004915480e893335..fea0e28e5e64a98b2037dd0dc97fc6adcfb299f0 100644 (file)
@@ -43,9 +43,6 @@
 #include <ieeefp.h>            /* 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))
 
index 01fdb0851aca937aeefe1d7d4fbf98f6d0017b9d..0f5242d5d138a1e85ed7c022c732777d80fb286b 100644 (file)
@@ -33,6 +33,7 @@
 #include <libpspp/message.h>
 #include <data/variable.h>
 #include <data/category.h>
+#include <data/value.h>
 
 #include <gsl/gsl_machine.h>
 #include <gsl/gsl_vector.h>
@@ -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);
index c3dcbaadda5f8c8eccfd307294e782d1f2a9f65c..87ba02bbff22fdbdf09119d73a1c8a54d83371c8 100644 (file)
@@ -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;
 }
index f5ed0568f1721558204c63f230103ff3d5bd51b0..c6a33e223c4725e1917465d0134c95cb252e2f9a 100644 (file)
@@ -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 );
index 7d2469a88b8519aaceb6465c4c10368f4ee7d6c7..fbd40d9b966897ec4df1afd7e53e7916e8dec022 100644 (file)
@@ -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;
index a8624488e7775cc4aac93025ae0d05ddf0ae2ec8..3f1672a5f56707e14b5e7c1c8a977d59df613ae6 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <data/data-out.h>
 #include <data/format.h>
-#include <data/variable.h>
+#include <data/value.h>
 #include <libpspp/alloc.h>
 #include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
index 9ab6cb98257591b27187015e2c6e3793201312dc..3d781468bb1d20a773ba7f4ce1dc519e77a3172b 100644 (file)
@@ -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);
 
index 2b3c637ab02b3cdab634e6ff1abdc682edfc2055..d60a01ac12fce9092228675a20bedcce8fd837b1 100644 (file)
@@ -1,3 +1,5 @@
+#include <config.h>
+
 #include "helper.h"
 #include <data/data-in.h>
 #include <data/data-out.h>
index 4e1665456288cdd3581f2feab06680ceb3b268e2..945cebe3aa55d93d18e228642feac7fdfcc2985a 100644 (file)
@@ -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 ) 
     {
index 7e16087eb93ae7bfe2057d72fdc49cb3d9e48136..35db14ef9b6b2aa0eaf374700322afba56454d2b 100644 (file)
@@ -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);
index 0466a97becda12095be792137cb9e9f4701d9842..65a4391d224402e353648de7795607c57e03366b 100644 (file)
@@ -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);
index eb97401eb793a608ea8d86f69b3036ac135b7de8..daeeb23e56569427825ff1d4cd362b9129605550 100644 (file)
@@ -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);
index 6195a16b2ce1c1b421880a2d9e031d2f426dc684..70c69a7ee768b3bdcbee3cd02a67b287dc31a50d 100644 (file)
@@ -18,6 +18,8 @@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     02110-1301, USA. */
 
+#include <config.h>
+
 #include <string.h>
 #include <stdlib.h>
 
@@ -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);
 }
 
index 248844eb84a77d4036a5bbbfb0c552797b541330..2b06336d33375be9f479a4147e1c413c4082fd24 100644 (file)
@@ -28,6 +28,8 @@
 #include <data/variable.h>
 #include "psppire-dict.h"
 
+struct val_labs;
+
 /* Don't use any of these members.
    Use accessor functions instead.
 */
index a17d8e10f059101f1168d79521013d08f4a2fa97..ff78347c5a5426cf0e686386ead008d1bbb2066f 100644 (file)
@@ -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 <config.h>
+
 #include <string.h>
 
 #include "helper.h"
index 3145f13dc7159cc7d754dddbd91fcc9f8b240e97..2cf12f58703f96e1ac2cfa1b8ae8d9da891d744d 100644 (file)
@@ -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 ; 
index 121804331b84afb5c842b4dff24869143ddffc06..a4b66cc2917d61c43e244721b53568da7d4146de 100644 (file)
@@ -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;