pspp-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pspp-cvs] pspp doc/variables.texi src/data/ChangeLog src/...


From: Ben Pfaff
Subject: [Pspp-cvs] pspp doc/variables.texi src/data/ChangeLog src/...
Date: Sun, 10 Dec 2006 03:42:52 +0000

CVSROOT:        /cvsroot/pspp
Module name:    pspp
Changes by:     Ben Pfaff <blp> 06/12/10 03:42:52

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

Log message:
        Finish converting struct variable to an opaque type. In this
        phase, we add remaining setter and getter functions, convert the
        remaining PSPP code to use them, and do a bunch of cleanup. The
        resulting changes are pervasive but mostly trivial, and only the
        notable changes are logged.
        
        This is patch #5629 on Savannah.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pspp/doc/variables.texi?cvsroot=pspp&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/ChangeLog?cvsroot=pspp&r1=1.82&r2=1.83
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/automake.mk?cvsroot=pspp&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/case.c?cvsroot=pspp&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/case.h?cvsroot=pspp&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/casefilter.c?cvsroot=pspp&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/cat-routines.h?cvsroot=pspp&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/category.c?cvsroot=pspp&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/data-in.c?cvsroot=pspp&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/data-out.c?cvsroot=pspp&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/dictionary.c?cvsroot=pspp&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/dictionary.h?cvsroot=pspp&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/format.c?cvsroot=pspp&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/format.h?cvsroot=pspp&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/missing-values.c?cvsroot=pspp&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/missing-values.h?cvsroot=pspp&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/por-file-reader.c?cvsroot=pspp&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/por-file-writer.c?cvsroot=pspp&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/procedure.c?cvsroot=pspp&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/sys-file-reader.c?cvsroot=pspp&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/sys-file-writer.c?cvsroot=pspp&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/value-labels.c?cvsroot=pspp&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/value-labels.h?cvsroot=pspp&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/value.h?cvsroot=pspp&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/variable.c?cvsroot=pspp&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/variable.h?cvsroot=pspp&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/sys-file-private.c?cvsroot=pspp&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/sys-file-private.h?cvsroot=pspp&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/value.c?cvsroot=pspp&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/vardict.h?cvsroot=pspp&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/vector.c?cvsroot=pspp&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/vector.h?cvsroot=pspp&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/control/do-if.c?cvsroot=pspp&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/control/loop.c?cvsroot=pspp&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/ChangeLog?cvsroot=pspp&r1=1.34&r2=1.35
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/data-list.c?cvsroot=pspp&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/get.c?cvsroot=pspp&r1=1.24&r2=1.25
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/inpt-pgm.c?cvsroot=pspp&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/list.q?cvsroot=pspp&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/matrix-data.c?cvsroot=pspp&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/print-space.c?cvsroot=pspp&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/data-io/print.c?cvsroot=pspp&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/ChangeLog?cvsroot=pspp&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/apply-dictionary.c?cvsroot=pspp&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/formats.c?cvsroot=pspp&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/missing-values.c?cvsroot=pspp&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/modify-variables.c?cvsroot=pspp&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/numeric.c?cvsroot=pspp&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/split-file.c?cvsroot=pspp&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/sys-file-info.c?cvsroot=pspp&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/value-labels.c?cvsroot=pspp&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/variable-label.c?cvsroot=pspp&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/dictionary/vector.c?cvsroot=pspp&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/expressions/evaluate.c?cvsroot=pspp&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/expressions/helpers.h?cvsroot=pspp&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/expressions/operations.def?cvsroot=pspp&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/expressions/parse.c?cvsroot=pspp&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/lexer/ChangeLog?cvsroot=pspp&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/lexer/variable-parser.c?cvsroot=pspp&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/lexer/variable-parser.h?cvsroot=pspp&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/ChangeLog?cvsroot=pspp&r1=1.34&r2=1.35
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/aggregate.c?cvsroot=pspp&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/autorecode.c?cvsroot=pspp&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/crosstabs.q?cvsroot=pspp&r1=1.24&r2=1.25
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/descriptives.c?cvsroot=pspp&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/examine.q?cvsroot=pspp&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/flip.c?cvsroot=pspp&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/frequencies.q?cvsroot=pspp&r1=1.24&r2=1.25
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/oneway.q?cvsroot=pspp&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/rank.q?cvsroot=pspp&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/regression.q?cvsroot=pspp&r1=1.40&r2=1.41
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/sort-criteria.c?cvsroot=pspp&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/stats/t-test.q?cvsroot=pspp&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/tests/casefile-test.c?cvsroot=pspp&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/utilities/set.q?cvsroot=pspp&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/xforms/ChangeLog?cvsroot=pspp&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/xforms/compute.c?cvsroot=pspp&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/xforms/count.c?cvsroot=pspp&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/pspp/src/language/xforms/recode.c?cvsroot=pspp&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/pspp/src/libpspp/ChangeLog?cvsroot=pspp&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/pspp/src/libpspp/misc.h?cvsroot=pspp&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/pspp/src/math/design-matrix.c?cvsroot=pspp&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/pspp/src/math/group.c?cvsroot=pspp&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/pspp/src/math/levene.c?cvsroot=pspp&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/pspp/src/math/sort.c?cvsroot=pspp&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/pspp/src/output/table.c?cvsroot=pspp&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/flexifile.c?cvsroot=pspp&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/helper.c?cvsroot=pspp&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/missing-val-dialog.c?cvsroot=pspp&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/psppire-case-file.c?cvsroot=pspp&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/psppire-data-store.c?cvsroot=pspp&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/psppire-var-store.c?cvsroot=pspp&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/psppire-variable.c?cvsroot=pspp&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/psppire-variable.h?cvsroot=pspp&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/val-labs-dialog.c?cvsroot=pspp&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/var-sheet.c?cvsroot=pspp&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/pspp/src/ui/gui/var-type-dialog.c?cvsroot=pspp&r1=1.6&r2=1.7

Patches:
Index: doc/variables.texi
===================================================================
RCS file: /cvsroot/pspp/pspp/doc/variables.texi,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- doc/variables.texi  5 Nov 2006 05:20:53 -0000       1.5
+++ doc/variables.texi  10 Dec 2006 03:42:50 -0000      1.6
@@ -446,7 +446,8 @@
 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: src/data/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/ChangeLog,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -b -r1.82 -r1.83
--- src/data/ChangeLog  10 Dec 2006 02:33:43 -0000      1.82
+++ src/data/ChangeLog  10 Dec 2006 03:42:50 -0000      1.83
@@ -1,3 +1,165 @@
+Sat Dec  9 18:05:59 2006  Ben Pfaff  <address@hidden>
+
+       * data-out.c (output_scientific): Fix bad assumption that "buf" is
+       null-terminated.
+       
+Sat Dec  9 17:23:23 2006  Ben Pfaff  <address@hidden>
+
+       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 <address@hidden>
 
        * casefilter.c (casefilter_variable_missing): Avoided comparision of
@@ -23,10 +185,11 @@
 
 Mon Dec  4 22:20:17 2006  Ben Pfaff  <address@hidden>
 
-       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: src/data/automake.mk
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/automake.mk,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- src/data/automake.mk        29 Nov 2006 02:15:01 -0000      1.9
+++ src/data/automake.mk        10 Dec 2006 03:42:50 -0000      1.10
@@ -60,14 +60,19 @@
        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: src/data/case.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/case.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- src/data/case.c     5 Dec 2006 15:10:21 -0000       1.7
+++ src/data/case.c     10 Dec 2006 03:42:50 -0000      1.8
@@ -255,7 +255,7 @@
    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 @@
 /* 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 @@
    (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 @@
    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 @@
       
       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: src/data/case.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/case.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- src/data/case.h     14 Oct 2006 00:25:20 -0000      1.6
+++ src/data/case.h     10 Dec 2006 03:42:50 -0000      1.7
@@ -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_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);
-
-CASE_INLINE union value *case_data_rw (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 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 @@
 }
 
 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 @@
 }
 #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: src/data/casefilter.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/casefilter.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- src/data/casefilter.c       10 Dec 2006 02:33:43 -0000      1.3
+++ src/data/casefilter.c       10 Dec 2006 03:42:50 -0000      1.4
@@ -58,9 +58,9 @@
                             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: src/data/cat-routines.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/cat-routines.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- src/data/cat-routines.h     4 Mar 2006 01:11:57 -0000       1.1
+++ src/data/cat-routines.h     10 Dec 2006 03:42:50 -0000      1.2
@@ -49,5 +49,5 @@
 
 void cat_create_value_matrix (struct variable *);
 
-void cat_stored_values_destroy (struct variable *);
+void cat_stored_values_destroy (struct cat_vals *);
 #endif

Index: src/data/category.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/category.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- src/data/category.c 5 Dec 2006 15:10:21 -0000       1.5
+++ src/data/category.c 10 Dec 2006 03:42:50 -0000      1.6
@@ -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
@@ -49,30 +50,24 @@
 void
 cat_stored_values_create (struct variable *v)
 {
-  if (v->obs_vals == NULL)
+  if (!var_has_obs_vals (v))
     {
-      v->obs_vals = xmalloc (sizeof (*v->obs_vals));
-      v->obs_vals->n_categories = 0;
-      v->obs_vals->n_allocated_categories = N_INITIAL_CATEGORIES;
-      v->obs_vals->vals =
-       xnmalloc (N_INITIAL_CATEGORIES, sizeof *v->obs_vals->vals);
+      struct cat_vals *obs_vals = xmalloc (sizeof *obs_vals);
+      obs_vals->n_categories = 0;
+      obs_vals->n_allocated_categories = N_INITIAL_CATEGORIES;
+      obs_vals->vals = xnmalloc (N_INITIAL_CATEGORIES, sizeof *obs_vals->vals);
+      var_set_obs_vals (v, obs_vals);
     }
 }
 
 void
-cat_stored_values_destroy (struct variable *v)
+cat_stored_values_destroy (struct cat_vals *obs_vals)
 {
-  assert (v != NULL);
-
-  if (v->obs_vals != NULL)
-    {
-      if (v->obs_vals->n_allocated_categories > 0)
+  if (obs_vals != NULL) 
        {
-         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 @@
 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 @@
 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 @@
 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 @@
 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: src/data/data-in.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/data-in.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- src/data/data-in.c  22 Nov 2006 04:24:02 -0000      1.17
+++ src/data/data-in.c  10 Dec 2006 03:42:50 -0000      1.18
@@ -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: src/data/data-out.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/data-out.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- src/data/data-out.c 8 Dec 2006 01:41:21 -0000       1.13
+++ src/data/data-out.c 10 Dec 2006 03:42:50 -0000      1.14
@@ -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 @@
     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;
 }
 

Index: src/data/dictionary.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/dictionary.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- src/data/dictionary.c       5 Dec 2006 15:10:21 -0000       1.20
+++ src/data/dictionary.c       10 Dec 2006 03:42:50 -0000      1.21
@@ -29,13 +29,16 @@
 #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 @@
   
   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;
@@ -126,18 +130,7 @@
   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];
-    }
+    d->vector[i] = vector_clone (s->vector[i], s, d);
 
   return d;
 }
@@ -155,12 +148,8 @@
 
   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 @@
   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 @@
   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 @@
       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);
@@ -330,66 +277,52 @@
 }
 
 /* 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 @@
 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 @@
 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 @@
   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 @@
 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_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 @@
    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;
+  size_t old_index = var_get_dict_index (v);
   
-  assert (d != NULL);
-  assert (v != NULL);
-  assert (dict_contains_var (d, v));
   assert (new_index < d->var_cnt);
-
-  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;
+  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 @@
   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 @@
 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,38 +569,33 @@
    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.
@@ -656,13 +610,12 @@
           
           for (i = 0; i < count; i++)
             {
-              var_set_name (vars[i], old_names[i]);
+            rename_var (d, vars[i], old_names[i]);
               hsh_force_insert (d->name_tab, vars[i]);
             }
 
-          success = false;
-          goto done;
-        }
+        pool_destroy (pool);
+        return false;
     }
 
   /* Clear short names. */
@@ -670,13 +623,8 @@
     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 @@
     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 @@
   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 @@
 
       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 @@
 }
 
 /* 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 @@
 
       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 @@
   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 @@
 
       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 @@
             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 @@
     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]));
-      vector->var[i] = var[i];
-    }
-  vector->cnt = cnt;
   
+  if (dict_lookup_vector (d, name) == NULL)
+    {
+      d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
+      d->vector[d->vector_cnt++] = vector_create (name, var, cnt);
   return true;
+    }
+  else
+    return false;
 }
 
 /* Returns the vector in D with index IDX, which must be less
@@ -1140,12 +1079,8 @@
 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 @@
 {
   size_t i;
   
-  assert (d != NULL);
-
   for (i = 0; i < d->vector_cnt; i++) 
-    {
-      free (d->vector[i]->var);
-      free (d->vector[i]);
-    }
+    vector_destroy (d->vector[i]);
   free (d->vector);
+
   d->vector = NULL;
   d->vector_cnt = 0;
 }
@@ -1182,6 +1113,51 @@
   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 @@
               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: src/data/dictionary.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/dictionary.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- src/data/dictionary.h       23 Sep 2006 00:15:58 -0000      1.4
+++ src/data/dictionary.h       10 Dec 2006 03:42:50 -0000      1.5
@@ -82,7 +82,7 @@
 
 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: src/data/format.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/format.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- src/data/format.c   5 Dec 2006 15:10:21 -0000       1.15
+++ src/data/format.c   10 Dec 2006 03:42:50 -0000      1.16
@@ -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 @@
    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 @@
 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: src/data/format.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/format.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- src/data/format.h   5 Dec 2006 15:10:21 -0000       1.10
+++ src/data/format.h   10 Dec 2006 03:42:50 -0000      1.11
@@ -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 @@
 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: src/data/missing-values.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/missing-values.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- src/data/missing-values.c   5 Dec 2006 15:10:21 -0000       1.5
+++ src/data/missing-values.c   10 Dec 2006 03:42:50 -0000      1.6
@@ -303,7 +303,7 @@
    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: src/data/missing-values.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/missing-values.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- src/data/missing-values.h   5 Dec 2006 15:10:21 -0000       1.2
+++ src/data/missing-values.h   10 Dec 2006 03:42:50 -0000      1.3
@@ -69,7 +69,7 @@
 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: src/data/por-file-reader.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/por-file-reader.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- src/data/por-file-reader.c  5 Dec 2006 15:10:21 -0000       1.13
+++ src/data/por-file-reader.c  10 Dec 2006 03:42:50 -0000      1.14
@@ -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 @@
        {
          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 @@
       
       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: src/data/por-file-writer.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/por-file-writer.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- src/data/por-file-writer.c  5 Dec 2006 15:10:21 -0000       1.6
+++ src/data/por-file-writer.c  10 Dec 2006 03:42:50 -0000      1.7
@@ -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>
@@ -30,18 +30,22 @@
 #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 @@
       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 @@
     {
       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 @@
       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: src/data/procedure.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/procedure.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- src/data/procedure.c        5 Dec 2006 15:10:21 -0000       1.16
+++ src/data/procedure.c        10 Dec 2006 03:42:50 -0000      1.17
@@ -265,7 +265,7 @@
   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 @@
       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 @@
   
 {
   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);
 }

Index: src/data/sys-file-reader.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/sys-file-reader.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- src/data/sys-file-reader.c  5 Dec 2006 15:10:21 -0000       1.27
+++ src/data/sys-file-reader.c  10 Dec 2006 03:42:50 -0000      1.28
@@ -19,6 +19,10 @@
 
 #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>
@@ -35,16 +39,15 @@
 #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 @@
                         }
 
                       /* 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 @@
                              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 @@
                                  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 @@
         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 @@
       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 @@
           
           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 @@
           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 @@
               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 @@
              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: src/data/sys-file-writer.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/sys-file-writer.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- src/data/sys-file-writer.c  5 Dec 2006 15:10:21 -0000       1.17
+++ src/data/sys-file-writer.c  10 Dec 2006 03:42:50 -0000      1.18
@@ -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 @@
 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 @@
       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 @@
       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 @@
   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 @@
       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 @@
       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 @@
   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 @@
 
          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 @@
     {
       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 @@
 
           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: src/data/value-labels.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/value-labels.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- src/data/value-labels.c     8 Dec 2006 22:24:08 -0000       1.11
+++ src/data/value-labels.c     10 Dec 2006 03:42:50 -0000      1.12
@@ -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 @@
   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 @@
 size_t
 val_labs_count (const struct val_labs *vls) 
 {
-  assert (vls != NULL);
-
-  if (vls->labels == NULL)
-    return 0;
-  else
-    return hsh_count (vls->labels);
+  return vls == NULL || vls->labels == NULL ? 0 : hsh_count (vls->labels);
 }
 
 /* One value label in internal format. */
@@ -222,29 +220,19 @@
    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 @@
 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->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: src/data/value-labels.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/value-labels.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- src/data/value-labels.h     14 Oct 2006 00:25:20 -0000      1.4
+++ src/data/value-labels.h     10 Dec 2006 03:42:50 -0000      1.5
@@ -44,7 +44,7 @@
 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_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 */

Index: src/data/value.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/value.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- src/data/value.h    6 May 2006 23:04:05 -0000       1.4
+++ src/data/value.h    10 Dec 2006 03:42:50 -0000      1.5
@@ -21,26 +21,17 @@
 #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 @@
     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 */

Index: src/data/variable.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/variable.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- src/data/variable.c 7 Dec 2006 06:31:04 -0000       1.15
+++ src/data/variable.c 10 Dec 2006 03:42:50 -0000      1.16
@@ -19,149 +19,177 @@
 
 #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;
+  return var_type == VAR_NUMERIC || var_type == VAR_STRING;
 }
 
-/* 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) 
+/* Returns the variable type for the given width. */
+enum var_type
+var_type_from_width (int width) 
 {
-  return type == NUMERIC ? _("numeric") : _("string");
+  return width != 0 ? VAR_STRING : VAR_NUMERIC;
 }
 
-/* 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");
-}
+/* 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))
+    {
+      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 = NULL;
+  v->label = NULL;
+  var_clear_short_name (v);
+  v->aux = NULL;
+  v->aux_dtor = NULL;
+  v->obs_vals = NULL;
 
-/* Returns true if M is a valid variable measurement level,
-   false otherwise. */
-bool
-measure_is_valid (enum measure m)
-{
-  return m == MEASURE_NOMINAL || m == MEASURE_ORDINAL || m == MEASURE_SCALE;
+  return v;
 }
 
-/* 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;
-}
+/* Creates and returns a clone of OLD_VAR.  Most properties of
+   the new variable are copied from OLD_VAR, except:
 
-/* 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;
-}
+    - 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.
 
-/* 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;
-}
+    - The new variable is not added to OLD_VAR's dictionary by
+      default.  Use dict_clone_var, instead, to do that.
 
-/* Clears auxiliary data, if any, from V, and calls any
-   associated destructor. */
-void
-var_clear_aux (struct variable *v) 
+    - Auxiliary data and obs_vals are not copied. */
+struct variable *
+var_clone (const struct variable *old_var)
 {
-  assert (v != NULL);
-  if (v->aux != NULL) 
-    {
-      if (v->aux_dtor != NULL)
-        v->aux_dtor (v);
-      v->aux = NULL;
-    }
-}
-
-/* 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);
-}
+  struct variable *new_var = var_create (var_get_name (old_var),
+                                         var_get_width (old_var));
 
-/* 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);
+  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));
 
-  union value *v = xmalloc (bytes);
-  memcpy (v, val, bytes);
-  return v;
+  return new_var;
 }
 
-
-
-/* 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) 
+/* 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 (width == 0) 
-    return a->f < b->f ? -1 : a->f > b->f;
-  else
-    return memcmp (a->s, b->s, MIN(MAX_SHORT_STRING, width));
+  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); 
+    }
 }
 
-/* Create a hash of v */
-unsigned 
-hash_value(const union value  *v, int width)
-{
-  unsigned id_hash;
-
-  if ( 0 == width ) 
-    id_hash = hsh_hash_double (v->f);
-  else
-    id_hash = hsh_hash_bytes (v->s, MIN(MAX_SHORT_STRING, width));
-
-  return id_hash;
-}
+/* Variable names. */
 
 /* Return variable V's name. */
 const char *
@@ -170,12 +198,14 @@
   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 @@
   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 @@
 /* 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 @@
 /* A hsh_hash_func that hashes pointer to variable V based on its
    name. */
 unsigned
-hash_var_ptr_name (const void *v_, const void *aux UNUSED) 
+hash_var_ptr_by_name (const void *v_, const void *aux UNUSED) 
 {
   struct variable *const *v = v_;
 
   return hsh_hash_case_string (var_get_name (*v));
 }
 
-/* Returns the type of a variable with the given WIDTH. */
-static enum var_type
-width_to_type (int width) 
-{
-  return width == 0 ? NUMERIC : ALPHA;
-}
-
 /* Returns the type of variable V. */
 enum var_type
 var_get_type (const struct variable *v) 
 {
-  return width_to_type (v->width);
+  return var_type_from_width (v->width);
 }
 
 /* Returns the width of variable V. */
@@ -333,7 +356,7 @@
 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 @@
   
   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 @@
 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 @@
 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,12 +421,12 @@
   return v->width > MAX_SHORT_STRING;
 }
 
-/* Returns true if variable V is a very long string variable,
-   false otherwise. */
-bool
-var_is_very_long_string (const struct variable *v) 
+/* Returns the number of "union value"s need to store a value of
+   variable V. */
+size_t
+var_get_value_cnt (const struct variable *v) 
 {
-  return v->width > MAX_LONG_STRING;
+  return v->width == 0 ? 1 : DIV_RND_UP (v->width, MAX_SHORT_STRING);
 }
 
 /* Returns variable V's missing values. */
@@ -413,15 +436,18 @@
   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 @@
   return mv_is_value_system_missing (&v->miss, value);
 }
 
+/* Returns variable V's value labels,
+   possibly a null pointer if it has none. */
+const struct val_labs *
+var_get_value_labels (const struct variable *v) 
+{
+  return v->val_labs;
+}
+
+/* Returns true if variable V has at least one value label. */
+bool
+var_has_value_labels (const struct variable *v) 
+{
+  return val_labs_count (v->val_labs) > 0;
+}
+
+/* Sets variable V's value labels to a copy of VLS,
+   which must have a width equal to V's width or one that can be
+   changed to V's width.
+   If VLS is null, then V's value labels, if any, are removed. */
+void
+var_set_value_labels (struct variable *v, const struct val_labs *vls) 
+{
+  val_labs_destroy (v->val_labs);
+  v->val_labs = NULL;
+
+  if (vls != NULL)
+    {
+      assert (val_labs_can_set_width (vls, v->width));
+      v->val_labs = val_labs_copy (vls);
+      val_labs_set_width (v->val_labs, v->width);
+    }
+}
+
+/* Makes sure that V has a set of value labels,
+   by assigning one to it if necessary. */
+static void
+alloc_value_labels (struct variable *v) 
+{
+  assert (!var_is_long_string (v));
+  if (v->val_labs == NULL)
+    v->val_labs = val_labs_create (v->width);
+}
+
+/* Attempts to add a value label with the given VALUE and LABEL
+   to V.  Returns true if successful, false if VALUE has an
+   existing label.
+   V must not be a long string variable. */
+bool
+var_add_value_label (struct variable *v,
+                     const union value *value, const char *label) 
+{
+  alloc_value_labels (v);
+  return val_labs_add (v->val_labs, *value, label);
+}
+
+/* Adds or replaces a value label with the given VALUE and LABEL
+   to V.
+   V must not be a long string variable. */
+void
+var_replace_value_label (struct variable *v,
+                         const union value *value, const char *label)
+{
+  alloc_value_labels (v);
+  val_labs_replace (v->val_labs, *value, label);
+}
+
+/* Removes V's value labels, if any. */
+void
+var_clear_value_labels (struct variable *v) 
+{
+  var_set_value_labels (v, NULL);
+}
+
+/* Returns the label associated with VALUE for variable V,
+   or a null pointer if none. */
+const char *
+var_lookup_value_label (const struct variable *v, const union value *value) 
+{
+  return val_labs_find (v->val_labs, *value);
+}
+
+/* Get a string representing VALUE for variable V.
+   That is, if VALUE has a label, return that label,
+   otherwise format VALUE and return the formatted string. */
+const char *
+var_get_value_name (const struct variable *v, const union value *value)
+{
+  const char *name = var_lookup_value_label (v, value);
+  if (name == NULL) 
+    {
+      static char buf[MAX_STRING + 1];
+      data_out (value, &v->print, buf);
+      buf[v->print.w] = '\0';
+      name = buf;
+    }
+  return name;
+}
+
 /* Print and write formats. */
 
 /* Returns V's print format specification. */
@@ -548,6 +672,15 @@
   var_set_write_format (v, format);
 }
 
+/* Return a string representing this variable, in the form most
+   appropriate from a human factors perspective, that is, its
+   variable label if it has one, otherwise its name. */
+const char *
+var_to_string (const struct variable *v)
+{
+  return v->label != NULL ? v->label : v->name;
+}
+
 /* Returns V's variable label, or a null pointer if it has none. */
 const char *
 var_get_label (const struct variable *v) 
@@ -591,6 +724,14 @@
   return v->label != NULL;
 }
 
+/* Returns true if M is a valid variable measurement level,
+   false otherwise. */
+bool
+measure_is_valid (enum measure m)
+{
+  return m == MEASURE_NOMINAL || m == MEASURE_ORDINAL || m == MEASURE_SCALE;
+}
+
 /* Returns V's measurement level. */
 enum measure
 var_get_measure (const struct variable *v) 
@@ -620,6 +761,14 @@
   v->display_width = display_width;
 }
 
+/* Returns true if A is a valid alignment,
+   false otherwise. */
+bool
+alignment_is_valid (enum alignment a)
+{
+  return a == ALIGN_LEFT || a == ALIGN_RIGHT || a == ALIGN_CENTRE;
+}
+
 /* Returns V's display alignment, which applies only to GUIs. */
 enum alignment
 var_get_alignment (const struct variable *v) 
@@ -635,22 +784,33 @@
   v->alignment = alignment;
 }
 
-/* Returns the number of "union value"s need to store a value of
-   variable V. */
-size_t
-var_get_value_cnt (const struct variable *v) 
-{
-  return v->width == 0 ? 1 : DIV_RND_UP (v->width, MAX_SHORT_STRING);
-}
+/* Whether variables' values should be preserved from case to
+   case. */
 
-/* Return whether variable V's values should be preserved from
-   case to case. */
+/* Returns true if variable V's value should be left from case to
+   case, instead of being reset to 0, system-missing, or blanks. */
 bool
 var_get_leave (const struct variable *v) 
 {
   return v->leave;
 }
 
+/* Sets V's leave setting to LEAVE. */
+void
+var_set_leave (struct variable *v, bool leave) 
+{
+  assert (leave || !var_must_leave (v));
+  v->leave = leave;
+}
+
+/* Returns true if V must be left from case to case,
+   false if it can be set either way. */
+bool
+var_must_leave (const struct variable *v) 
+{
+  return dict_class_from_id (v->name) == DC_SCRATCH;
+}
+
 /* Returns V's short name, if it has one, or a null pointer
    otherwise.
 
@@ -693,58 +853,118 @@
   v->short_name[0] = '\0';
 }
 
-/* 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)
+/* Relationship with dictionary. */
+
+/* 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;
+}
 
+/* Returns V's index within the case represented by its
+   dictionary, that is, the value for which "case_data_idx (case,
+   index)" will return the data for V in that case.
+   V must be in a dictionary. */
+size_t
+var_get_case_index (const struct variable *v) 
+{
+  assert (v->vardict.case_index != -1);
+  return v->vardict.case_index;
+}
+
+/* Returns V's auxiliary data, or a null pointer if none has been
+   attached. */
+void *
+var_get_aux (const struct variable *v) 
+{
+  return v->aux;
+}
+
+/* Assign auxiliary data AUX to variable V, which must not
+   already have auxiliary data.  Before V's auxiliary data is
+   cleared, AUX_DTOR(V) will be called.  (var_dtor_free, below,
+   may be appropriate for use as AUX_DTOR.) */
+void *
+var_attach_aux (struct variable *v,
+                void *aux, void (*aux_dtor) (struct variable *)) 
+{
+  assert (v->aux == NULL);
+  assert (aux != NULL);
+  v->aux = aux;
+  v->aux_dtor = aux_dtor;
+  return aux;
+}
+
+/* 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;
+}
+
+/* Clears auxiliary data, if any, from V, and calls any
+   associated destructor. */
+void
+var_clear_aux (struct variable *v) 
+{
   assert (v != NULL);
-  assert (suffix_number >= 0);
+  if (v->aux != NULL) 
+    {
+      if (v->aux_dtor != NULL)
+        v->aux_dtor (v);
+      v->aux = NULL;
+    }
+}
 
-  /* Set base name. */
-  var_set_short_name (v, base);
+/* 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);
+}
 
-  /* 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);
+/* Observed categorical values. */
 
-  /* Set name. */
-  var_set_short_name (v, short_name);
+/* Returns V's observed categorical values,
+   which V must have. */
+struct cat_vals *
+var_get_obs_vals (const struct variable *v) 
+{
+  assert (v->obs_vals != NULL);
+  return v->obs_vals;
 }
 
+/* Sets V's observed categorical values to CAT_VALS. */
+void
+var_set_obs_vals (struct variable *v, struct cat_vals *cat_vals) 
+{
+  cat_stored_values_destroy (v->obs_vals);
+  v->obs_vals = cat_vals;
+}
+
+/* Returns true if V has observed categorical values,
+   false otherwise. */
+bool
+var_has_obs_vals (const struct variable *v) 
+{
+  return v->obs_vals != NULL;
+}
 
 /* Returns the dictionary class corresponding to a variable named
    NAME. */
 enum dict_class
 dict_class_from_id (const char *name) 
 {
-  assert (name != NULL);
-
   switch (name[0]) 
     {
     default:
@@ -773,24 +993,33 @@
     }
 }
 
-/* Return the number of bytes used when writing case_data for a variable 
-   of WIDTH */
-int
-width_to_bytes(int width)
+/* Returns V's vardict structure. */
+const struct vardict_info *
+var_get_vardict (const struct variable *v) 
 {
-  assert (width >= 0);
+  assert (var_has_vardict (v));
+  return &v->vardict;
+}
 
-  if ( width == 0 ) 
-    return MAX_SHORT_STRING ;
-  else if (width <= MAX_LONG_STRING) 
-    return ROUND_UP (width, MAX_SHORT_STRING);
-  else 
-    {
-      int chunks = width / EFFECTIVE_LONG_STRING_LENGTH ;
-      int remainder = width % EFFECTIVE_LONG_STRING_LENGTH ;
-      int bytes = remainder + (chunks * (MAX_LONG_STRING + 1) );
-      return ROUND_UP (bytes, MAX_SHORT_STRING); 
-    }
+/* Sets V's vardict data to VARDICT. */
+void
+var_set_vardict (struct variable *v, const struct vardict_info *vardict) 
+{
+  assert (vardict->dict_index >= 0);
+  assert (vardict->case_index >= 0);
+  v->vardict = *vardict;
 }
 
+/* Returns true if V has vardict data. */
+bool
+var_has_vardict (const struct variable *v) 
+{
+  return v->vardict.dict_index != -1;
+}
 
+/* Clears V's vardict data. */
+void
+var_clear_vardict (struct variable *v) 
+{
+  v->vardict.dict_index = v->vardict.case_index = -1;
+}

Index: src/data/variable.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/variable.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- src/data/variable.h 7 Dec 2006 06:31:04 -0000       1.15
+++ src/data/variable.h 10 Dec 2006 03:42:51 -0000      1.16
@@ -20,101 +20,43 @@
 #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);
-
-/* Alignment of data for display. */
-enum alignment 
-  {
-    ALIGN_LEFT = 0,
-    ALIGN_RIGHT = 1,
-    ALIGN_CENTRE = 2,
-    n_ALIGN
-  };
-
-bool alignment_is_valid (enum alignment);
-
-/* How data is measured. */
-enum measure
-  {
-    MEASURE_NOMINAL = 1,
-    MEASURE_ORDINAL = 2,
-    MEASURE_SCALE = 3,
-    n_MEASURES
-  };
-
-bool measure_is_valid (enum measure);
+enum var_type var_type_from_width (int width);
 
-/* 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. */
+/* Variables. */
+struct variable *var_create (const char *name, int width);
+struct variable *var_clone (const struct variable *);
+void var_destroy (struct variable *);
+
+/* 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
 
-/* 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_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_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_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 
   {
@@ -202,26 +182,4 @@
 enum dict_class dict_class_from_id (const char *name);
 const char *dict_class_to_name (enum dict_class dict_class);
 
-/* Vector of variables. */
-struct vector
-  {
-    int idx;                    /* Index for dict_get_vector(). */
-    char name[LONG_NAME_LEN + 1]; /* Name. */
-    struct variable **var;     /* Vector of variables. */
-    int cnt;                   /* Number of variables. */
-  };
-
-
-/* Return a string representing this variable, in the form most 
-   appropriate from a human factors perspective.
-   (IE: the label if it has one, otherwise the name )
-*/
-const char * var_to_string(const struct variable *var);
-
-
-int width_to_bytes(int width);
-
-union value * value_dup (const union value *val, int width);
-
-
 #endif /* !variable.h */

Index: src/language/control/do-if.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/control/do-if.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- src/language/control/do-if.c        11 Nov 2006 23:10:00 -0000      1.10
+++ src/language/control/do-if.c        10 Dec 2006 03:42:51 -0000      1.11
@@ -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: src/language/control/loop.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/control/loop.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- src/language/control/loop.c 11 Nov 2006 23:10:00 -0000      1.11
+++ src/language/control/loop.c 10 Dec 2006 03:42:51 -0000      1.12
@@ -294,7 +294,7 @@
 
       /* 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 @@
       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: src/language/data-io/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/ChangeLog,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -b -r1.34 -r1.35
--- src/language/data-io/ChangeLog      1 Dec 2006 05:52:59 -0000       1.34
+++ src/language/data-io/ChangeLog      10 Dec 2006 03:42:51 -0000      1.35
@@ -1,3 +1,7 @@
+Sat Dec  9 18:43:34 2006  Ben Pfaff  <address@hidden>
+
+       * list.q (cmd_list): Use new var_create, var_destroy functions.
+
 Thu Nov 30 21:51:58 2006  Ben Pfaff  <address@hidden>
 
        * inpt-pgm.c (cmd_reread): Always return error code upon detecting

Index: src/language/data-io/data-list.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/data-list.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- src/language/data-io/data-list.c    5 Dec 2006 15:10:21 -0000       1.27
+++ src/language/data-io/data-list.c    10 Dec 2006 03:42:51 -0000      1.28
@@ -370,7 +370,7 @@
             /* 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 @@
 
           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 @@
       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 @@
       
       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 @@
             {
               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 @@
   /* 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: src/language/data-io/get.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/get.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- src/language/data-io/get.c  7 Dec 2006 05:41:11 -0000       1.24
+++ src/language/data-io/get.c  10 Dec 2006 03:42:51 -0000      1.25
@@ -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 @@
   *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 @@
            {
              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 @@
            {
              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 @@
                 }
             }
           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 @@
         
           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 @@
 static struct variable *
 get_master (struct variable *v) 
 {
-  return v->aux;
+  return var_get_aux (v);
 }
 
 /* Case map.
@@ -1619,7 +1617,7 @@
     {
       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 @@
       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 @@
     {
       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: src/language/data-io/inpt-pgm.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/inpt-pgm.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- src/language/data-io/inpt-pgm.c     5 Dec 2006 15:10:21 -0000       1.19
+++ src/language/data-io/inpt-pgm.c     10 Dec 2006 03:42:51 -0000      1.20
@@ -169,7 +169,7 @@
       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 @@
     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 @@
       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: src/language/data-io/list.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/list.q,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- src/language/data-io/list.q 5 Dec 2006 15:10:21 -0000       1.22
+++ src/language/data-io/list.q 10 Dec 2006 03:42:51 -0000      1.23
@@ -134,7 +134,7 @@
 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 @@
       /* 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.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 @@
 
   clean_up ();
 
+  var_destroy (casenum_var);    
+
   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
 }
 
@@ -625,7 +625,7 @@
 
 /* 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 @@
            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 @@
             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: src/language/data-io/matrix-data.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/matrix-data.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- src/language/data-io/matrix-data.c  5 Dec 2006 15:10:21 -0000       1.20
+++ src/language/data-io/matrix-data.c  10 Dec 2006 03:42:51 -0000      1.21
@@ -351,8 +351,7 @@
 
             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 @@
            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 @@
     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 @@
 {
   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 @@
 {
   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 @@
     {
       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 @@
   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 @@
 
        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 @@
     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 @@
            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 @@
       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 @@
     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 @@
          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: src/language/data-io/print-space.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/print-space.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- src/language/data-io/print-space.c  11 Nov 2006 23:10:00 -0000      1.7
+++ src/language/data-io/print-space.c  10 Dec 2006 03:42:51 -0000      1.8
@@ -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: src/language/data-io/print.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/data-io/print.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- src/language/data-io/print.c        5 Dec 2006 15:10:21 -0000       1.21
+++ src/language/data-io/print.c        10 Dec 2006 03:42:51 -0000      1.22
@@ -460,7 +460,7 @@
       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: src/language/dictionary/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/ChangeLog,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- src/language/dictionary/ChangeLog   1 Dec 2006 06:06:52 -0000       1.6
+++ src/language/dictionary/ChangeLog   10 Dec 2006 03:42:51 -0000      1.7
@@ -1,3 +1,11 @@
+Sat Dec  9 18:44:26 2006  Ben Pfaff  <address@hidden>
+
+       * 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  <address@hidden>
 
        * value-labels.c (get_label): Allow commas between values and

Index: src/language/dictionary/apply-dictionary.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/apply-dictionary.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- src/language/dictionary/apply-dictionary.c  5 Dec 2006 15:10:21 -0000       
1.11
+++ src/language/dictionary/apply-dictionary.c  10 Dec 2006 03:42:51 -0000      
1.12
@@ -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 @@
             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 (var_has_value_labels (s))
        {
-          if (val_labs_can_set_width (s->val_labs, var_get_width (t)))
+          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: src/language/dictionary/formats.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/formats.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- src/language/dictionary/formats.c   5 Dec 2006 15:10:21 -0000       1.14
+++ src/language/dictionary/formats.c   10 Dec 2006 03:42:51 -0000      1.15
@@ -94,7 +94,7 @@
        }
       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: src/language/dictionary/missing-values.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/missing-values.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- src/language/dictionary/missing-values.c    5 Dec 2006 15:10:21 -0000       
1.13
+++ src/language/dictionary/missing-values.c    10 Dec 2006 03:42:51 -0000      
1.14
@@ -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 @@
           
           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: src/language/dictionary/modify-variables.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/modify-variables.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- src/language/dictionary/modify-variables.c  5 Dec 2006 15:10:21 -0000       
1.13
+++ src/language/dictionary/modify-variables.c  10 Dec 2006 03:42:51 -0000      
1.14
@@ -355,7 +355,11 @@
 
   int result;
   if (ordering->positional)
-    result = a->index < b->index ? -1 : a->index > b->index;
+    {
+      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: src/language/dictionary/numeric.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/numeric.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- src/language/dictionary/numeric.c   5 Dec 2006 15:10:21 -0000       1.17
+++ src/language/dictionary/numeric.c   10 Dec 2006 03:42:51 -0000      1.18
@@ -185,7 +185,7 @@
   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: src/language/dictionary/split-file.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/split-file.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- src/language/dictionary/split-file.c        5 Dec 2006 15:10:21 -0000       
1.12
+++ src/language/dictionary/split-file.c        10 Dec 2006 03:42:51 -0000      
1.13
@@ -96,12 +96,12 @@
 
       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: src/language/dictionary/sys-file-info.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/sys-file-info.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- src/language/dictionary/sys-file-info.c     5 Dec 2006 15:10:21 -0000       
1.17
+++ src/language/dictionary/sys-file-info.c     10 Dec 2006 03:42:51 -0000      
1.18
@@ -24,10 +24,13 @@
 
 #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 @@
   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 @@
        }
 
       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 @@
 
       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 @@
             }
          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 @@
 
   /* 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 @@
     }
 
   /* 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 @@
 #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 @@
   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 @@
   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 @@
   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: src/language/dictionary/value-labels.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/value-labels.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- src/language/dictionary/value-labels.c      5 Dec 2006 15:10:21 -0000       
1.13
+++ src/language/dictionary/value-labels.c      10 Dec 2006 03:42:51 -0000      
1.14
@@ -136,7 +136,7 @@
 
   /* 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 @@
        }
 
       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: src/language/dictionary/variable-label.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/variable-label.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- src/language/dictionary/variable-label.c    5 Dec 2006 15:10:21 -0000       
1.12
+++ src/language/dictionary/variable-label.c    10 Dec 2006 03:42:51 -0000      
1.13
@@ -76,14 +76,3 @@
 
 
 
-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: src/language/dictionary/vector.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/dictionary/vector.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- src/language/dictionary/vector.c    11 Nov 2006 23:10:00 -0000      1.10
+++ src/language/dictionary/vector.c    10 Dec 2006 03:42:51 -0000      1.11
@@ -107,7 +107,7 @@
            }
 
          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: src/language/expressions/evaluate.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/expressions/evaluate.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- src/language/expressions/evaluate.c 5 Dec 2006 15:10:21 -0000       1.12
+++ src/language/expressions/evaluate.c 10 Dec 2006 03:42:51 -0000      1.13
@@ -180,9 +180,9 @@
             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 @@
           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: src/language/expressions/helpers.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/expressions/helpers.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- src/language/expressions/helpers.h  5 Nov 2006 05:20:53 -0000       1.7
+++ src/language/expressions/helpers.h  10 Dec 2006 03:42:51 -0000      1.8
@@ -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: src/language/expressions/operations.def
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/expressions/operations.def,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- src/language/expressions/operations.def     5 Dec 2006 15:10:21 -0000       
1.10
+++ src/language/expressions/operations.def     10 Dec 2006 03:42:51 -0000      
1.11
@@ -892,22 +892,22 @@
 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 @@
       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 @@
      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 @@
      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 @@
      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 @@
   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 @@
   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 @@
 {
   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 @@
 {
   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 @@
      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: src/language/expressions/parse.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/expressions/parse.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- src/language/expressions/parse.c    5 Dec 2006 15:10:21 -0000       1.19
+++ src/language/expressions/parse.c    10 Dec 2006 03:42:51 -0000      1.20
@@ -358,7 +358,7 @@
       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 @@
       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 @@
       || !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: src/language/lexer/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/lexer/ChangeLog,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- src/language/lexer/ChangeLog        3 Dec 2006 22:16:45 -0000       1.19
+++ src/language/lexer/ChangeLog        10 Dec 2006 03:42:51 -0000      1.20
@@ -1,3 +1,13 @@
+Sat Dec  9 18:46:11 2006  Ben Pfaff  <address@hidden>
+
+       * 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  <address@hidden>
 
        General clean-up.

Index: src/language/lexer/variable-parser.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/lexer/variable-parser.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- src/language/lexer/variable-parser.c        5 Dec 2006 15:10:21 -0000       
1.12
+++ src/language/lexer/variable-parser.c        10 Dec 2006 03:42:51 -0000      
1.13
@@ -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 @@
            && 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 @@
   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)
+  /* 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)) <= 1);
+          + ((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));
@@ -253,7 +261,12 @@
       
       included = xcalloc (var_set_get_cnt (vs), sizeof *included);
       for (i = 0; i < *nv; i++)
-        included[(*v)[i]->index] = 1;
+        {
+          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 @@
   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 @@
                               size_t *idx) 
 {
   struct array_var_set *avs = vs->aux;
-  struct variable v, *vp, *const *vpp;
+  struct variable *v, *const *vpp;
+
+  v = var_create (name, 0);
+  vpp = hsh_find (avs->name_tab, &v);
+  var_destroy (v);
 
-  strcpy (v.name, name);
-  vp = &v;
-  vpp = hsh_find (avs->name_tab, &vp);
   if (vpp != NULL) 
     {
       *idx = vpp - avs->var;
@@ -791,8 +805,8 @@
   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: src/language/lexer/variable-parser.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/lexer/variable-parser.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- src/language/lexer/variable-parser.h        11 Nov 2006 23:10:00 -0000      
1.5
+++ src/language/lexer/variable-parser.h        10 Dec 2006 03:42:51 -0000      
1.6
@@ -53,7 +53,8 @@
     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: src/language/stats/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/ChangeLog,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -b -r1.34 -r1.35
--- src/language/stats/ChangeLog        7 Dec 2006 06:31:04 -0000       1.34
+++ src/language/stats/ChangeLog        10 Dec 2006 03:42:51 -0000      1.35
@@ -1,3 +1,8 @@
+Sat Dec  9 18:47:51 2006  Ben Pfaff  <address@hidden>
+
+       * regression.q (is_depvar): Compare variable pointers instead of
+       variable names.
+
 Thu Dec  7 15:26:25 WST 2006 John Darrington <address@hidden>
 
        * examine.q: Allocated the categorical values for the dependent and 

Index: src/language/stats/aggregate.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/aggregate.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- src/language/stats/aggregate.c      5 Dec 2006 15:10:21 -0000       1.21
+++ src/language/stats/aggregate.c      10 Dec 2006 03:42:51 -0000      1.22
@@ -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,7 +94,7 @@
   {
     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. */
   };
 
@@ -104,25 +105,25 @@
     {"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}},
+    {"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, NUMERIC, {FMT_F, 7, 0}},
-    {"NU",      0, NUMERIC, {FMT_F, 7, 0}},
+    {"N",       0, VAR_NUMERIC, {FMT_F, 7, 0}},
+    {"NU",      0, VAR_NUMERIC, {FMT_F, 7, 0}},
   };
 
 /* Missing value types. */
@@ -494,13 +495,15 @@
                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 @@
                    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 @@
   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 @@
       {
         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 @@
   
     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: src/language/stats/autorecode.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/autorecode.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- src/language/stats/autorecode.c     5 Dec 2006 15:10:21 -0000       1.15
+++ src/language/stats/autorecode.c     10 Dec 2006 03:42:51 -0000      1.16
@@ -285,12 +285,12 @@
       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 @@
       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: src/language/stats/crosstabs.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/crosstabs.q,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- src/language/stats/crosstabs.q      5 Dec 2006 15:10:21 -0000       1.24
+++ src/language/stats/crosstabs.q      10 Dec 2006 03:42:51 -0000      1.25
@@ -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 @@
 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 @@
        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 @@
              }
              
            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 @@
        {
          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 @@
       
       {
         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 @@
   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: src/language/stats/descriptives.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/descriptives.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- src/language/stats/descriptives.c   5 Dec 2006 15:10:21 -0000       1.18
+++ src/language/stats/descriptives.c   10 Dec 2006 03:42:51 -0000      1.19
@@ -64,11 +64,10 @@
    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 @@
       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 @@
       
   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 @@
                                              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 @@
       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 @@
           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 @@
   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: src/language/stats/examine.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/examine.q,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- src/language/stats/examine.q        7 Dec 2006 06:31:04 -0000       1.19
+++ src/language/stats/examine.q        10 Dec 2006 03:42:51 -0000      1.20
@@ -649,13 +649,13 @@
       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 @@
        {
          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 @@
            {
              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 @@
        {
          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 @@
                            (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 @@
                          (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 @@
                  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 @@
              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 @@
                  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 @@
              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 @@
                  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 @@
              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 @@
 
   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 @@
     {
       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 @@
   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: src/language/stats/flip.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/flip.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- src/language/stats/flip.c   5 Dec 2006 15:10:21 -0000       1.16
+++ src/language/stats/flip.c   10 Dec 2006 03:42:51 -0000      1.17
@@ -104,7 +104,7 @@
 
   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 @@
   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 @@
       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;
        }
       
@@ -362,7 +362,10 @@
       double out;
       
       if (var_is_numeric (flip->var[i]))
-        out = case_num (c, flip->idx_to_fv[flip->var[i]->index]);
+        {
+          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 @@
         }
 
       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: src/language/stats/frequencies.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/frequencies.q,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- src/language/stats/frequencies.q    5 Dec 2006 15:10:21 -0000       1.24
+++ src/language/stats/frequencies.q    10 Dec 2006 03:42:51 -0000      1.25
@@ -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 @@
 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 @@
   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 @@
    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 @@
       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 @@
           }
 
        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 @@
 
       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 @@
 
       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 @@
     {
       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: src/language/stats/oneway.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/oneway.q,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- src/language/stats/oneway.q 5 Dec 2006 15:10:21 -0000       1.16
+++ src/language/stats/oneway.q 10 Dec 2006 03:42:51 -0000      1.17
@@ -435,7 +435,8 @@
          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 @@
       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 @@
       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 @@
        {
          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: src/language/stats/rank.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/rank.q,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- src/language/stats/rank.q   5 Dec 2006 15:10:21 -0000       1.20
+++ src/language/stats/rank.q   10 Dec 2006 03:42:51 -0000      1.21
@@ -24,6 +24,8 @@
 #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 @@
   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 @@
       /* 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 @@
       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 @@
       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 @@
         {
           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 @@
   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 @@
       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 @@
       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 @@
 {
   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 @@
   {
     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: src/language/stats/regression.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/regression.q,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -b -r1.40 -r1.41
--- src/language/stats/regression.q     7 Dec 2006 05:16:33 -0000       1.40
+++ src/language/stats/regression.q     10 Dec 2006 03:42:51 -0000      1.41
@@ -239,7 +239,7 @@
           */
 
          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 @@
   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 @@
   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 @@
 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 @@
 
   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 @@
 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 @@
     {
       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 @@
                                                   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 @@
                        }
                    }
                }
-             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: src/language/stats/sort-criteria.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/sort-criteria.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- src/language/stats/sort-criteria.c  5 Dec 2006 15:10:21 -0000       1.5
+++ src/language/stats/sort-criteria.c  10 Dec 2006 03:42:51 -0000      1.6
@@ -115,7 +115,7 @@
       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: src/language/stats/t-test.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/t-test.q,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- src/language/stats/t-test.q 5 Dec 2006 15:10:21 -0000       1.16
+++ src/language/stats/t-test.q 10 Dec 2006 03:42:51 -0000      1.17
@@ -154,7 +154,7 @@
 
 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 @@
          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 @@
 /* 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 @@
 {
   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 @@
       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 @@
     {
       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 @@
       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 @@
   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: src/language/tests/casefile-test.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/tests/casefile-test.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- src/language/tests/casefile-test.c  11 Nov 2006 23:10:00 -0000      1.9
+++ src/language/tests/casefile-test.c  10 Dec 2006 03:42:51 -0000      1.10
@@ -160,8 +160,8 @@
             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 @@
   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 @@
     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: src/language/utilities/set.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/utilities/set.q,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- src/language/utilities/set.q        5 Dec 2006 15:10:21 -0000       1.23
+++ src/language/utilities/set.q        10 Dec 2006 03:42:51 -0000      1.24
@@ -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: src/language/xforms/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/xforms/ChangeLog,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- src/language/xforms/ChangeLog       1 Dec 2006 06:51:08 -0000       1.7
+++ src/language/xforms/ChangeLog       10 Dec 2006 03:42:51 -0000      1.8
@@ -1,3 +1,8 @@
+Sat Dec  9 18:48:20 2006  Ben Pfaff  <address@hidden>
+
+       * compute.c (struct compute_trns): Remove `fv' member, which was
+       redundant with `variable'.
+
 Thu Nov 30 22:46:50 2006  Ben Pfaff  <address@hidden>
 
        * compute.c: Fix bug #17422, which reports that a variable created

Index: src/language/xforms/compute.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/xforms/compute.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- src/language/xforms/compute.c       5 Dec 2006 15:10:21 -0000       1.12
+++ src/language/xforms/compute.c       10 Dec 2006 03:42:51 -0000      1.13
@@ -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 @@
 
     /* 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 @@
 
   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 @@
 
       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 @@
   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 @@
         {
           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 @@
 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 @@
 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 @@
 {
   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 @@
   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: src/language/xforms/count.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/xforms/count.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- src/language/xforms/count.c 5 Dec 2006 15:10:21 -0000       1.12
+++ src/language/xforms/count.c 10 Dec 2006 03:42:51 -0000      1.13
@@ -277,7 +277,7 @@
 
   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 @@
     {
       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 @@
          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: src/language/xforms/recode.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/xforms/recode.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- src/language/xforms/recode.c        5 Dec 2006 15:10:21 -0000       1.15
+++ src/language/xforms/recode.c        10 Dec 2006 03:42:51 -0000      1.16
@@ -157,7 +157,7 @@
 
       /* 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 @@
 
           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 @@
           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 @@
 {
   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 @@
         {
           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 @@
         {
           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 @@
         {
           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 @@
       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: src/libpspp/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/libpspp/ChangeLog,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- src/libpspp/ChangeLog       8 Dec 2006 22:24:08 -0000       1.44
+++ src/libpspp/ChangeLog       10 Dec 2006 03:42:51 -0000      1.45
@@ -1,3 +1,7 @@
+Sat Dec  9 18:48:55 2006  Ben Pfaff  <address@hidden>
+
+       * misc.h (macro range): Removed, as it was unused.
+
 Sat Dec  9 07:19:01 WST 2006 John Darrington <address@hidden>
 
        * array.c: Removed gratuitous #include

Index: src/libpspp/misc.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/libpspp/misc.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- src/libpspp/misc.h  25 Nov 2006 02:15:01 -0000      1.2
+++ src/libpspp/misc.h  10 Dec 2006 03:42:51 -0000      1.3
@@ -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: src/math/design-matrix.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/design-matrix.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- src/math/design-matrix.c    7 Dec 2006 05:16:33 -0000       1.5
+++ src/math/design-matrix.c    10 Dec 2006 03:42:51 -0000      1.6
@@ -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 @@
        }
       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: src/math/group.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/group.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- src/math/group.c    15 Mar 2006 03:29:11 -0000      1.3
+++ src/math/group.c    10 Dec 2006 03:42:51 -0000      1.4
@@ -63,7 +63,11 @@
 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: src/math/levene.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/levene.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- src/math/levene.c   5 Nov 2006 00:35:44 -0000       1.7
+++ src/math/levene.c   10 Dec 2006 03:42:51 -0000      1.8
@@ -187,7 +187,7 @@
 {
   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 @@
       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 @@
 
   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 @@
     {
       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: src/math/sort.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/sort.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- src/math/sort.c     7 Dec 2006 06:31:04 -0000       1.19
+++ src/math/sort.c     10 Dec 2006 03:42:51 -0000      1.20
@@ -463,13 +463,14 @@
       
       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: src/output/table.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/output/table.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- src/output/table.c  25 Nov 2006 02:15:01 -0000      1.17
+++ src/output/table.c  10 Dec 2006 03:42:51 -0000      1.18
@@ -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: src/ui/flexifile.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/flexifile.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- src/ui/flexifile.c  29 Nov 2006 11:50:31 -0000      1.4
+++ src/ui/flexifile.c  10 Dec 2006 03:42:52 -0000      1.5
@@ -331,7 +331,7 @@
 
       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: src/ui/gui/helper.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/helper.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- src/ui/gui/helper.c 22 Nov 2006 04:24:03 -0000      1.8
+++ src/ui/gui/helper.c 10 Dec 2006 03:42:52 -0000      1.9
@@ -1,3 +1,5 @@
+#include <config.h>
+
 #include "helper.h"
 #include <data/data-in.h>
 #include <data/data-out.h>

Index: src/ui/gui/missing-val-dialog.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/missing-val-dialog.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- src/ui/gui/missing-val-dialog.c     27 May 2006 08:36:10 -0000      1.4
+++ src/ui/gui/missing-val-dialog.c     10 Dec 2006 03:42:52 -0000      1.5
@@ -279,7 +279,7 @@
   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: src/ui/gui/psppire-case-file.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/psppire-case-file.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- src/ui/gui/psppire-case-file.c      22 Nov 2006 04:24:03 -0000      1.7
+++ src/ui/gui/psppire-case-file.c      10 Dec 2006 03:42:52 -0000      1.8
@@ -247,7 +247,7 @@
 
   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 @@
     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 @@
 
   /* 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: src/ui/gui/psppire-data-store.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/psppire-data-store.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- src/ui/gui/psppire-data-store.c     22 Nov 2006 04:24:03 -0000      1.20
+++ src/ui/gui/psppire-data-store.c     10 Dec 2006 03:42:52 -0000      1.21
@@ -442,10 +442,10 @@
   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 @@
 
   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: src/ui/gui/psppire-var-store.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/psppire-var-store.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- src/ui/gui/psppire-var-store.c      3 Nov 2006 04:53:52 -0000       1.13
+++ src/ui/gui/psppire-var-store.c      10 Dec 2006 03:42:52 -0000      1.14
@@ -156,7 +156,7 @@
   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: src/ui/gui/psppire-variable.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/psppire-variable.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- src/ui/gui/psppire-variable.c       5 Dec 2006 15:10:22 -0000       1.8
+++ src/ui/gui/psppire-variable.c       10 Dec 2006 03:42:52 -0000      1.9
@@ -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 @@
 
   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 @@
 
   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 @@
 
   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 @@
        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 @@
   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_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 @@
     {
       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 @@
   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 @@
 
   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 @@
 
   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 @@
 
   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 @@
 
   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 @@
 
   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 @@
   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 @@
   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 @@
   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: src/ui/gui/psppire-variable.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/psppire-variable.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- src/ui/gui/psppire-variable.h       24 Jun 2006 09:08:50 -0000      1.3
+++ src/ui/gui/psppire-variable.h       10 Dec 2006 03:42:52 -0000      1.4
@@ -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: src/ui/gui/val-labs-dialog.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/val-labs-dialog.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- src/ui/gui/val-labs-dialog.c        31 May 2006 07:38:03 -0000      1.4
+++ src/ui/gui/val-labs-dialog.c        10 Dec 2006 03:42:52 -0000      1.5
@@ -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: src/ui/gui/var-sheet.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/var-sheet.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- src/ui/gui/var-sheet.c      29 Jul 2006 09:37:18 -0000      1.8
+++ src/ui/gui/var-sheet.c      10 Dec 2006 03:42:52 -0000      1.9
@@ -372,7 +372,7 @@
                {
                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: src/ui/gui/var-type-dialog.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/var-type-dialog.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- src/ui/gui/var-type-dialog.c        3 Nov 2006 04:53:52 -0000       1.6
+++ src/ui/gui/var-type-dialog.c        10 Dec 2006 03:42:52 -0000      1.7
@@ -819,14 +819,14 @@
     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;

Index: src/data/sys-file-private.c
===================================================================
RCS file: src/data/sys-file-private.c
diff -N src/data/sys-file-private.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/data/sys-file-private.c 10 Dec 2006 03:42:50 -0000      1.1
@@ -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); 
+    }
+}
+
+

Index: src/data/sys-file-private.h
===================================================================
RCS file: src/data/sys-file-private.h
diff -N src/data/sys-file-private.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/data/sys-file-private.h 10 Dec 2006 03:42:50 -0000      1.1
@@ -0,0 +1,30 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   Written by Ben Pfaff <address@hidden>.
+
+   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: src/data/value.c
===================================================================
RCS file: src/data/value.c
diff -N src/data/value.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/data/value.c    10 Dec 2006 03:42:50 -0000      1.1
@@ -0,0 +1,56 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Written by Ben Pfaff <address@hidden>.
+
+   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: src/data/vardict.h
===================================================================
RCS file: src/data/vardict.h
diff -N src/data/vardict.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/data/vardict.h  10 Dec 2006 03:42:50 -0000      1.1
@@ -0,0 +1,39 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Written by Ben Pfaff <address@hidden>.
+
+   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: src/data/vector.c
===================================================================
RCS file: src/data/vector.c
diff -N src/data/vector.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/data/vector.c   10 Dec 2006 03:42:51 -0000      1.1
@@ -0,0 +1,146 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2006  Free Software Foundation, Inc.
+   Written by Ben Pfaff <address@hidden>.
+
+   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);
+}
+

Index: src/data/vector.h
===================================================================
RCS file: src/data/vector.h
diff -N src/data/vector.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/data/vector.h   10 Dec 2006 03:42:51 -0000      1.1
@@ -0,0 +1,42 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2006  Free Software Foundation, Inc.
+   Written by Ben Pfaff <address@hidden>.
+
+   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 */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]