Patch #6262. New developers guide and resulting fixes and cleanups.
authorBen Pfaff <blp@gnu.org>
Sun, 11 Nov 2007 05:51:38 +0000 (05:51 +0000)
committerBen Pfaff <blp@gnu.org>
Sun, 11 Nov 2007 05:51:38 +0000 (05:51 +0000)
* automake.mk (src_data_libdata_a_SOURCES): Add new files.

* dict-class.c: New file.
(dict_class_from_id): Move here.
(dict_class_to_name): Move here.

* dict-class.h: New file.
(enum dict_class): Move here.  Change from consecutive integers to
consecutive bits, to make testing for any of multiple values
easier.  Add new DC_ALL constant.

* dictionary.c (struct dictionary): Change `case_limit' from
size_t to casenumber.
(dict_get_vars): Make final argument an enum dict_class.
(dict_get_vars_mutable): Ditto.
(dict_get_case_limit): Change return value to casenumber.
(dict_set_case_limit): Change final argument to a casenumber.
(dict_unset_split_var): Add assertion.  Rephrase slightly.
(dict_set_label): Use xstrndup to simplify.

* format.c (fmt_step_width): AHEX format also needs 2-byte
stepping.
(fmt_set_style): Simplify assertions.

* missing-values.c (mv_add_num_range): Rename mv_add_range.
Simplify implementation.
(mv_has_value): Simplify implementation.
(mv_pop_value): Remove the first value, not the last, to avoid
having GET followed by SAVE reverse the order of missing values.
(mv_peek_value): Rename mv_get_value.  Simplify assertion.
(mv_has_range): Simplify implementation.
(mv_peek_range): Rename mv_get_range.
(can_resize_string): Removed.
(mv_is_resizable): Use value_is_resizable.
(mv_resize): Use value_resize.

* short-names.h (SHORT_NAME_LEN): Move here.

* val-type.h: New file, for definitions related to type and width
of abstract values.  Before, these definitions were mixed among
those related to "union value" and those related to variables.
(macro SYSMIS): Move here.
(macro LOWEST): Move here.
(macro HIGHEST): Move here.
(macro MAX_STRING); Move here.
(enum val_type): New enum with values VAL_NUMERIC and VAL_STRING.
Replaces enum var_type that had values VAR_NUMERIC and VAR_STRING.
All references updated.
(val_type_is_valid): New function.  Replaces var_type_is_valid.
All references updated.
(val_type_from_width): New function.  Replaces
var_type_from_width.  All references updated.

* value-labels.c (val_labs_copy): Renamed val_labs_clone.  All
references updated.
(val_labs_can_set_width): Use value_is_resizable.
(val_labs_add): Simply return false if the value labels set is too
wide, instead of having undefined behavior.
(val_labs_replace): Ditto.
(val_labs_replace): Ditto.
(val_labs_first): Set iterator to null if iteration is complete.
(val_labs_first_sorted): Ditto.
(val_labs_done): Become a no-op if the iterator is null.

* value.c (value_is_resizable): New function.
(value_resize): New function.

* variable.c (var_get_dict_class): New function.

* variable.h (macro LONG_NAME_LEN): Rename VAR_NAME_LEN.  Update
all references.

* not-implemented.texi: Fix @include command so that it works
consistently, by using a file name relative to Makefile.am's
srcdir instead of relative to doc.

79 files changed:
doc/.cvsignore
doc/ChangeLog
doc/automake.mk
doc/data-file-format.texi [deleted file]
doc/dev/concepts.texi [new file with mode: 0644]
doc/dev/data.texi [new file with mode: 0644]
doc/dev/intro.texi [new file with mode: 0644]
doc/dev/output.texi [new file with mode: 0644]
doc/dev/portable-file-format.texi [new file with mode: 0644]
doc/dev/q2c.texi [new file with mode: 0644]
doc/dev/syntax.texi [new file with mode: 0644]
doc/dev/system-file-format.texi [new file with mode: 0644]
doc/not-implemented.texi
doc/portable-file-format.texi [deleted file]
doc/pspp-dev.texinfo [new file with mode: 0644]
doc/pspp.texinfo
doc/q2c.texi [deleted file]
doc/utilities.texi
doc/variables.texi
po/de.po
po/en_GB.po
src/data/ChangeLog
src/data/automake.mk
src/data/calendar.c
src/data/case.h
src/data/data-in.h
src/data/data-out.c
src/data/dict-class.c [new file with mode: 0644]
src/data/dict-class.h [new file with mode: 0644]
src/data/dictionary.c
src/data/dictionary.h
src/data/format.c
src/data/format.h
src/data/missing-values.c
src/data/missing-values.h
src/data/por-file-reader.c
src/data/procedure.c
src/data/short-names.h
src/data/sys-file-reader.c
src/data/sys-file-writer.c
src/data/val-type.h [new file with mode: 0644]
src/data/value-labels.c
src/data/value-labels.h
src/data/value.c
src/data/value.h
src/data/vardict.h
src/data/variable.c
src/data/variable.h
src/data/vector.c
src/data/vector.h
src/language/data-io/data-list.c
src/language/data-io/file-handle.q
src/language/data-io/get.c
src/language/data-io/list.q
src/language/dictionary/formats.c
src/language/dictionary/missing-values.c
src/language/dictionary/modify-variables.c
src/language/dictionary/vector.c
src/language/expressions/evaluate.c
src/language/expressions/parse.c
src/language/lexer/lexer.c
src/language/lexer/variable-parser.c
src/language/stats/aggregate.c
src/language/stats/descriptives.c
src/language/stats/flip.c
src/language/stats/frequencies.q
src/language/stats/rank.q
src/language/stats/regression.q
src/language/stats/t-test.q
src/language/xforms/compute.c
src/language/xforms/recode.c
src/libpspp/model-checker.c
src/math/factor-stats.c
src/math/moments.c
src/math/percentiles.c
src/ui/gui/missing-val-dialog.c
src/ui/gui/val-labs-dialog.c
src/ui/gui/var-display.c
src/ui/gui/var-type-dialog.c

index 6d2576feb9f8ef70064afdde2f8bae9b90d4c248..06eb3bb18a49b17bb6a488f2c2a259d95e6be159 100644 (file)
@@ -1,6 +1,9 @@
 Makefile
 Makefile.in
 ni.texi
 Makefile
 Makefile.in
 ni.texi
+pspp-dev.info
 pspp.info*
 pspp.info*
+stamp-1
 stamp-vti
 stamp-vti
+version-dev.texi
 version.texi
 version.texi
index 8a52b3d8de1383f7c9f505f0ce77089b6ae24a49..c1fa40eb6c587b759847e7ef36a59b5dbf42a6b1 100644 (file)
@@ -1,3 +1,36 @@
+2007-11-10  Ben Pfaff  <blp@gnu.org>
+
+       * not-implemented.texi: Fix @include command so that it works
+       consistently, by using a file name relative to Makefile.am's
+       srcdir instead of relative to doc.
+
+2007-11-10  Ben Pfaff  <blp@gnu.org>
+
+       Patch #6262: New developers guide (currently incomplete).
+
+       * automake.mk: Add definitions for new manual.
+
+       * pspp.texinfo: Now this is the PSPP Users Guide instead of just
+       the PSPP manual.  Remove development chapters.
+
+       * pspp-dev.texinfo: New file.
+
+       * data-file-format.texi: Move to dev/system-file-format.texi.
+
+       * portable-file-format.texi: Move to dev/.
+
+       * q2c.texi: Move to dev/
+
+       * dev/concepts.texi: New file.
+
+       * dev/data.texi: New file.
+
+       * dev/intro.texi: New file.
+
+       * dev/output.texi: New file.
+
+       * dev/syntax.texi: New file.
+
 2007-10-19 John Darrington <john@darrington.wattle.id.au>
 
        * statistics.texi: Changed /CONTRASTS to /CONTRAST in ONEWAY which
 2007-10-19 John Darrington <john@darrington.wattle.id.au>
 
        * statistics.texi: Changed /CONTRASTS to /CONTRAST in ONEWAY which
index 301757c8b71f105e159bbea2d24c29ee4eef5c7f..9c73d344bffbeef2489fd3eb4ea166e3c6fd4ecb 100644 (file)
@@ -1,13 +1,12 @@
 ## Process this file with automake to produce Makefile.in  -*- makefile -*-
 
 ## Process this file with automake to produce Makefile.in  -*- makefile -*-
 
-info_TEXINFOS = doc/pspp.texinfo 
+info_TEXINFOS = doc/pspp.texinfo doc/pspp-dev.texinfo
 
 doc_pspp_TEXINFOS = doc/version.texi \
        doc/bugs.texi \
        doc/command-index.texi \
        doc/concept-index.texi \
        doc/configuring.texi \
 
 doc_pspp_TEXINFOS = doc/version.texi \
        doc/bugs.texi \
        doc/command-index.texi \
        doc/concept-index.texi \
        doc/configuring.texi \
-       doc/data-file-format.texi \
        doc/data-io.texi \
        doc/data-selection.texi \
        doc/expressions.texi \
        doc/data-io.texi \
        doc/data-selection.texi \
        doc/expressions.texi \
@@ -21,8 +20,6 @@ doc_pspp_TEXINFOS = doc/version.texi \
        doc/license.texi \
        doc/ni.texi \
        doc/not-implemented.texi \
        doc/license.texi \
        doc/ni.texi \
        doc/not-implemented.texi \
-       doc/portable-file-format.texi \
-       doc/q2c.texi \
        doc/statistics.texi \
        doc/transformation.texi \
        doc/regression.texi \
        doc/statistics.texi \
        doc/transformation.texi \
        doc/regression.texi \
@@ -30,9 +27,18 @@ doc_pspp_TEXINFOS = doc/version.texi \
        doc/variables.texi \
        doc/fdl.texi 
 
        doc/variables.texi \
        doc/fdl.texi 
 
+doc_pspp_dev_TEXINFOS = doc/version-dev.texi \
+       doc/dev/intro.texi \
+       doc/dev/concepts.texi \
+       doc/dev/syntax.texi \
+       doc/dev/data.texi \
+       doc/dev/output.texi \
+       doc/dev/system-file-format.texi \
+       doc/dev/portable-file-format.texi \
+       doc/dev/q2c.texi
+
 EXTRA_DIST += doc/pspp.man \
 EXTRA_DIST += doc/pspp.man \
-       doc/get-commands.pl \
-       $(doc_pspp_TEXINFOS)
+       doc/get-commands.pl
 
 doc/ni.texi: $(top_srcdir)/src/language/command.def doc/get-commands.pl
        @$(MKDIR_P)  doc
 
 doc/ni.texi: $(top_srcdir)/src/language/command.def doc/get-commands.pl
        @$(MKDIR_P)  doc
diff --git a/doc/data-file-format.texi b/doc/data-file-format.texi
deleted file mode 100644 (file)
index c2fdacd..0000000
+++ /dev/null
@@ -1,906 +0,0 @@
-@node System File Format
-@appendix System File Format
-
-A system file encapsulates a set of cases and dictionary information
-that describes how they may be interpreted.  This chapter describes
-the format of a system file.
-
-System files use three data types: 8-bit characters, 32-bit integers,
-and 64-bit floating points, called here @code{char}, @code{int32}, and
-@code{flt64}, respectively.  Data is not necessarily aligned on a word
-or double-word boundary: the long variable name record (@pxref{Long
-Variable Names Record}) and very long string records (@pxref{Very Long
-String Record}) have arbitrary byte length and can therefore cause all
-data coming after them in the file to be misaligned.
-
-Integer data in system files may be big-endian or little-endian.  A
-reader may detect the endianness of a system file by examining
-@code{layout_code} in the file header record
-(@pxref{layout_code,,@code{layout_code}}).
-
-Floating-point data in system files may nominally be in IEEE 754, IBM,
-or VAX formats.  A reader may detect the floating-point format in use
-by examining @code{bias} in the file header record
-(@pxref{bias,,@code{bias}}).
-
-PSPP detects big-endian and little-endian integer formats in system
-files and translates as necessary.  PSPP also detects the
-floating-point format in use, as well as the endianness of IEEE 754
-floating-point numbers, and translates as needed.  However, only IEEE
-754 numbers with the same endianness as integer data in the same file
-has actually been observed in system files, and it is likely that
-other formats are obsolete or were never used.
-
-The PSPP system-missing value is represented by the largest possible
-negative number in the floating point format (@code{-DBL_MAX}).  Two
-other values are important for use as missing values: @code{HIGHEST},
-represented by the largest possible positive number (@code{DBL_MAX}),
-and @code{LOWEST}, represented by the second-largest negative number
-(in IEEE 754 format, @code{0xffeffffffffffffe}).
-
-System files are divided into records, each of which begins with a
-4-byte record type, usually regarded as an @code{int32}.
-
-The records must appear in the following order:
-
-@itemize @bullet
-@item
-File header record.
-
-@item
-Variable records.
-
-@item
-All pairs of value labels records and value label variables records,
-if present.
-
-@item
-Document record, if present.
-
-@item
-Any of the following records, if present, in any order:
-
-@itemize @minus
-@item
-Machine integer info record.
-
-@item
-Machine floating-point info record.
-
-@item
-Variable display parameter record.
-
-@item
-Long variable names record.
-
-@item
-Miscellaneous informational records.
-@end itemize
-
-@item
-Dictionary termination record.
-
-@item
-Data record.
-@end itemize
-
-Each type of record is described separately below.
-
-@menu
-* File Header Record::
-* Variable Record::
-* Value Labels Records::
-* Document Record::
-* Machine Integer Info Record::
-* Machine Floating-Point Info Record::
-* Variable Display Parameter Record::
-* Long Variable Names Record::
-* Very Long String Record::
-* Miscellaneous Informational Records::
-* Dictionary Termination Record::
-* Data Record::
-@end menu
-
-@node File Header Record
-@section File Header Record
-
-The file header is always the first record in the file.  It has the
-following format:
-
-@example
-char                rec_type[4];
-char                prod_name[60];
-int32               layout_code;
-int32               nominal_case_size;
-int32               compressed;
-int32               weight_index;
-int32               ncases;
-flt64               bias;
-char                creation_date[9];
-char                creation_time[8];
-char                file_label[64];
-char                padding[3];
-@end example
-
-@table @code
-@item char rec_type[4];
-Record type code, set to @samp{$FL2}.
-
-@item char prod_name[60];
-Product identification string.  This always begins with the characters
-@samp{@@(#) SPSS DATA FILE}.  PSPP uses the remaining characters to
-give its version and the operating system name; for example, @samp{GNU
-pspp 0.1.4 - sparc-sun-solaris2.5.2}.  The string is truncated if it
-would be longer than 60 characters; otherwise it is padded on the right
-with spaces.
-
-@anchor{layout_code}
-@item int32 layout_code;
-Normally set to 2, although a few system files have been spotted in
-the wild with a value of 3 here.  PSPP use this value to determine the
-file's integer endianness (@pxref{System File Format}).
-
-@item int32 nominal_case_size;
-Number of data elements per case.  This is the number of variables,
-except that long string variables add extra data elements (one for every
-8 characters after the first 8).  However, string variables do not
-contribute to this value beyond the first 255 bytes.   Further, system
-files written by some systems set this value to -1.  In general, it is
-unsafe for systems reading system files to rely upon this value.
-
-@item int32 compressed;
-Set to 1 if the data in the file is compressed, 0 otherwise.
-
-@item int32 weight_index;
-If one of the variables in the data set is used as a weighting
-variable, set to the dictionary index of that variable, plus 1
-(@pxref{Dictionary Index}).  Otherwise, set to 0.
-
-@item int32 ncases;
-Set to the number of cases in the file if it is known, or -1 otherwise.
-
-In the general case it is not possible to determine the number of cases
-that will be output to a system file at the time that the header is
-written.  The way that this is dealt with is by writing the entire
-system file, including the header, then seeking back to the beginning of
-the file and writing just the @code{ncases} field.  For `files' in which
-this is not valid, the seek operation fails.  In this case,
-@code{ncases} remains -1.
-
-@anchor{bias}
-@item flt64 bias;
-Compression bias, ordinarily set to 100.  Only integers between
-@code{1 - bias} and @code{251 - bias} can be compressed.
-
-By assuming that its value is 100, PSPP uses @code{bias} to determine
-the file's floating-point format and endianness (@pxref{System File
-Format}).  If the compression bias is not 100, PSPP cannot auto-detect
-the floating-point format and assumes that it is IEEE 754 format with
-the same endianness as the system file's integers, which is correct
-for all known system files.
-
-@item char creation_date[9];
-Date of creation of the system file, in @samp{dd mmm yy}
-format, with the month as standard English abbreviations, using an
-initial capital letter and following with lowercase.  If the date is not
-available then this field is arbitrarily set to @samp{01 Jan 70}.
-
-@item char creation_time[8];
-Time of creation of the system file, in @samp{hh:mm:ss}
-format and using 24-hour time.  If the time is not available then this
-field is arbitrarily set to @samp{00:00:00}.
-
-@item char file_label[64];
-File label declared by the user, if any (@pxref{FILE LABEL}).
-Padded on the right with spaces.
-
-@item char padding[3];
-Ignored padding bytes to make the structure a multiple of 32 bits in
-length.  Set to zeros.
-@end table
-
-@node Variable Record
-@section Variable Record
-
-There must be one variable record for each numeric variable and each
-string variable with width 8 bytes or less.  String variables wider
-than 8 bytes have one variable record for each 8 bytes, rounding up.
-The first variable record for a long string specifies the variable's
-correct dictionary information.  Subsequent variable records for a
-long string are filled with dummy information: a type of -1, no
-variable label or missing values, print and write formats that are
-ignored, and an empty string as name.  A few system files have been
-encountered that include a variable label on dummy variable records,
-so readers should take care to parse dummy variable records in the
-same way as other variable records.
-
-@anchor{Dictionary Index}
-The @dfn{dictionary index} of a variable is its offset in the set of
-variable records, including dummy variable records for long string
-variables.  The first variable record has a dictionary index of 0, the
-second has a dictionary index of 1, and so on.
-
-The system file format does not directly support string variables
-wider than 255 bytes.  Such very long string variables are represented
-by a number of narrower string variables.  @xref{Very Long String
-Record}, for details.
-
-@example
-int32               rec_type;
-int32               type;
-int32               has_var_label;
-int32               n_missing_values;
-int32               print;
-int32               write;
-char                name[8];
-
-/* @r{Present only if @code{has_var_label} is 1.} */
-int32               label_len;
-char                label[];
-
-/* @r{Present only if @code{n_missing_values} is nonzero}. */
-flt64               missing_values[];
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type code.  Always set to 2.
-
-@item int32 type;
-Variable type code.  Set to 0 for a numeric variable.  For a short
-string variable or the first part of a long string variable, this is set
-to the width of the string.  For the second and subsequent parts of a
-long string variable, set to -1, and the remaining fields in the
-structure are ignored.
-
-@item int32 has_var_label;
-If this variable has a variable label, set to 1; otherwise, set to 0.
-
-@item int32 n_missing_values;
-If the variable has no missing values, set to 0.  If the variable has
-one, two, or three discrete missing values, set to 1, 2, or 3,
-respectively.  If the variable has a range for missing variables, set to
--2; if the variable has a range for missing variables plus a single
-discrete value, set to -3.
-
-@item int32 print;
-Print format for this variable.  See below.
-
-@item int32 write;
-Write format for this variable.  See below.
-
-@item char name[8];
-Variable name.  The variable name must begin with a capital letter or
-the at-sign (@samp{@@}).  Subsequent characters may also be digits, octothorpes
-(@samp{#}), dollar signs (@samp{$}), underscores (@samp{_}), or full
-stops (@samp{.}).  The variable name is padded on the right with spaces.
-
-@item int32 label_len;
-This field is present only if @code{has_var_label} is set to 1.  It is
-set to the length, in characters, of the variable label, which must be a
-number between 0 and 120.
-
-@item char label[];
-This field is present only if @code{has_var_label} is set to 1.  It has
-length @code{label_len}, rounded up to the nearest multiple of 32 bits.
-The first @code{label_len} characters are the variable's variable label.
-
-@item flt64 missing_values[];
-This field is present only if @code{n_missing_values} is not 0.  It has
-the same number of elements as the absolute value of
-@code{n_missing_values}.  For discrete missing values, each element
-represents one missing value.  When a range is present, the first
-element denotes the minimum value in the range, and the second element
-denotes the maximum value in the range.  When a range plus a value are
-present, the third element denotes the additional discrete missing
-value.  HIGHEST and LOWEST are indicated as described in the chapter
-introduction.
-@end table
-
-The @code{print} and @code{write} members of sysfile_variable are output
-formats coded into @code{int32} types.  The least-significant byte
-of the @code{int32} represents the number of decimal places, and the
-next two bytes in order of increasing significance represent field width
-and format type, respectively.  The most-significant byte is not
-used and should be set to zero.
-
-Format types are defined as follows:
-
-@quotation
-@multitable {Value} {@code{DATETIME}}
-@headitem Value
-@tab Meaning
-@item 0
-@tab Not used.
-@item 1
-@tab @code{A}
-@item 2
-@tab @code{AHEX}
-@item 3
-@tab @code{COMMA}
-@item 4
-@tab @code{DOLLAR}
-@item 5
-@tab @code{F}
-@item 6
-@tab @code{IB}
-@item 7
-@tab @code{PIBHEX}
-@item 8
-@tab @code{P}
-@item 9
-@tab @code{PIB}
-@item 10
-@tab @code{PK}
-@item 11
-@tab @code{RB}
-@item 12
-@tab @code{RBHEX}
-@item 13
-@tab Not used.
-@item 14
-@tab Not used.
-@item 15
-@tab @code{Z}
-@item 16
-@tab @code{N}
-@item 17
-@tab @code{E}
-@item 18
-@tab Not used.
-@item 19
-@tab Not used.
-@item 20
-@tab @code{DATE}
-@item 21
-@tab @code{TIME}
-@item 22
-@tab @code{DATETIME}
-@item 23
-@tab @code{ADATE}
-@item 24
-@tab @code{JDATE}
-@item 25
-@tab @code{DTIME}
-@item 26
-@tab @code{WKDAY}
-@item 27
-@tab @code{MONTH}
-@item 28
-@tab @code{MOYR}
-@item 29
-@tab @code{QYR}
-@item 30
-@tab @code{WKYR}
-@item 31
-@tab @code{PCT}
-@item 32
-@tab @code{DOT}
-@item 33
-@tab @code{CCA}
-@item 34
-@tab @code{CCB}
-@item 35
-@tab @code{CCC}
-@item 36
-@tab @code{CCD}
-@item 37
-@tab @code{CCE}
-@item 38
-@tab @code{EDATE}
-@item 39
-@tab @code{SDATE}
-@end multitable
-@end quotation
-
-@node Value Labels Records
-@section Value Labels Records
-
-The value label record has the following format:
-
-@example
-int32               rec_type;
-int32               label_count;
-
-/* @r{Repeated @code{label_cnt} times}. */
-char                value[8];
-char                label_len;
-char                label[];
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 3.
-
-@item int32 label_count;
-Number of value labels present in this record.
-@end table
-
-The remaining fields are repeated @code{count} times.  Each
-repetition specifies one value label.
-
-@table @code
-@item char value[8];
-A numeric value or a short string value padded as necessary to 8 bytes
-in length.  Its type and width cannot be determined until the
-following value label variables record (see below) is read.
-
-@item char label_len;
-The label's length, in bytes.
-
-@item char label[];
-@code{label_len} bytes of the actual label, followed by up to 7 bytes
-of padding to bring @code{label} and @code{label_len} together to a
-multiple of 8 bytes in length.
-@end table
-
-The value label record is always immediately followed by a value label
-variables record with the following format:
-
-@example
-int32               rec_type;
-int32               var_count;
-int32               vars[];
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 4.
-
-@item int32 var_count;
-Number of variables that the associated value labels from the value
-label record are to be applied.
-
-@item int32 vars[];
-A list of dictionary indexes of variables to which to apply the value
-labels (@pxref{Dictionary Index}).  There are @code{var_count}
-elements.
-
-String variables wider than 8 bytes may not have value labels.
-@end table
-
-@node Document Record
-@section Document Record
-
-The document record, if present, has the following format:
-
-@example
-int32               rec_type;
-int32               n_lines;
-char                lines[][80];
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 6.
-
-@item int32 n_lines;
-Number of lines of documents present.
-
-@item char lines[][80];
-Document lines.  The number of elements is defined by @code{n_lines}.
-Lines shorter than 80 characters are padded on the right with spaces.
-@end table
-
-@node Machine Integer Info Record
-@section Machine Integer Info Record
-
-The integer info record, if present, has the following format:
-
-@example
-/* @r{Header.} */
-int32               rec_type;
-int32               subtype;
-int32               size;
-int32               count;
-
-/* @r{Data.} */
-int32               version_major;
-int32               version_minor;
-int32               version_revision;
-int32               machine_code;
-int32               floating_point_rep;
-int32               compression_code;
-int32               endianness;
-int32               character_code;
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 7.
-
-@item int32 subtype;
-Record subtype.  Always set to 3.
-
-@item int32 size;
-Size of each piece of data in the data part, in bytes.  Always set to 4.
-
-@item int32 count;
-Number of pieces of data in the data part.  Always set to 8.
-
-@item int32 version_major;
-PSPP major version number.  In version @var{x}.@var{y}.@var{z}, this
-is @var{x}.
-
-@item int32 version_minor;
-PSPP minor version number.  In version @var{x}.@var{y}.@var{z}, this
-is @var{y}.
-
-@item int32 version_revision;
-PSPP version revision number.  In version @var{x}.@var{y}.@var{z},
-this is @var{z}.
-
-@item int32 machine_code;
-Machine code.  PSPP always set this field to value to -1, but other
-values may appear.
-
-@item int32 floating_point_rep;
-Floating point representation code.  For IEEE 754 systems this is 1.
-IBM 370 sets this to 2, and DEC VAX E to 3.
-
-@item int32 compression_code;
-Compression code.  Always set to 1.
-
-@item int32 endianness;
-Machine endianness.  1 indicates big-endian, 2 indicates little-endian.
-
-@item int32 character_code;
-Character code.  1 indicates EBCDIC, 2 indicates 7-bit ASCII, 3
-indicates 8-bit ASCII, 4 indicates DEC Kanji.
-Windows code page numbers are also valid.
-@end table
-
-@node Machine Floating-Point Info Record
-@section Machine Floating-Point Info Record
-
-The floating-point info record, if present, has the following format:
-
-@example
-/* @r{Header.} */
-int32               rec_type;
-int32               subtype;
-int32               size;
-int32               count;
-
-/* @r{Data.} */
-flt64               sysmis;
-flt64               highest;
-flt64               lowest;
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 7.
-
-@item int32 subtype;
-Record subtype.  Always set to 4.
-
-@item int32 size;
-Size of each piece of data in the data part, in bytes.  Always set to 8.
-
-@item int32 count;
-Number of pieces of data in the data part.  Always set to 3.
-
-@item flt64 sysmis;
-The system missing value.
-
-@item flt64 highest;
-The value used for HIGHEST in missing values.
-
-@item flt64 lowest;
-The value used for LOWEST in missing values.
-@end table
-
-@node Variable Display Parameter Record
-@section Variable Display Parameter Record
-
-The variable display parameter record, if present, has the following
-format:
-
-@example
-/* @r{Header.} */
-int32               rec_type;
-int32               subtype;
-int32               size;
-int32               count;
-
-/* @r{Repeated @code{count} times}. */
-int32               measure;
-int32               width;
-int32               alignment;
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 7.
-
-@item int32 subtype;
-Record subtype.  Always set to 11.
-
-@item int32 size;
-The size of @code{int32}.  Always set to 4.
-
-@item int32 count;
-The number of sets of variable display parameters (ordinarily the
-number of variables in the dictionary), times 3.
-@end table
-
-The remaining members are repeated @code{count} times, in the same
-order as the variable records.  No element corresponds to variable
-records that continue long string variables.  The meanings of these
-members are as follows:
-
-@table @code
-@item int32 measure;
-The measurement type of the variable:
-@table @asis
-@item 1
-Nominal Scale
-@item 2
-Ordinal Scale
-@item 3
-Continuous Scale
-@end table
-
-SPSS 14 sometimes writes a @code{measure} of 0.  PSPP interprets this
-as nominal scale.
-
-@item int32 width;
-The width of the display column for the variable in characters.
-
-@item int32 alignment;
-The alignment of the variable for display purposes:
-
-@table @asis
-@item 0
-Left aligned
-@item 1
-Right aligned
-@item 2
-Centre aligned
-@end table
-@end table
-
-@node Long Variable Names Record
-@section Long Variable Names Record
-
-If present, the long variable names record has the following format:
-
-@example
-/* @r{Header.} */
-int32               rec_type;
-int32               subtype;
-int32               size;
-int32               count;
-
-/* @r{Exactly @code{count} bytes of data.} */
-char                var_name_pairs[];
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 7.
-
-@item int32 subtype;
-Record subtype.  Always set to 13.
-
-@item int32 size;
-The size of each element in the @code{var_name_pairs} member. Always set to 1.
-
-@item int32 count;
-The total number of bytes in @code{var_name_pairs}.
-
-@item char var_name_pairs[];
-A list of @var{key}--@var{value} tuples, where @var{key} is the name
-of a variable, and @var{value} is its long variable name.
-The @var{key} field is at most 8 bytes long and must match the
-name of a variable which appears in the variable record (@pxref{Variable
-Record}).
-The @var{value} field is at most 64 bytes long.
-The @var{key} and @var{value} fields are separated by a @samp{=} byte.
-Each tuple is separated by a byte whose value is 09.  There is no
-trailing separator following the last tuple.
-The total length is @code{count} bytes.
-@end table
-
-@node Very Long String Record
-@section Very Long String Record
-
-Old versions of SPSS limited string variables to a width of 255 bytes.
-For backward compatibility with these older versions, the system file
-format represents a string longer than 255 bytes, called a @dfn{very
-long string}, as a collection of strings no longer than 255 bytes
-each.  The strings concatenated to make a very long string are called
-its @dfn{segments}; for consistency, variables other than very long
-strings are considered to have a single segment.
-
-A very long string with a width of @var{w} has @var{n} =
-(@var{w} + 251) / 252 segments, that is, one segment for every
-252 bytes of width, rounding up.  It would be logical, then, for each
-of the segments except the last to have a width of 252 and the last
-segment to have the remainder, but this is not the case.  In fact,
-each segment except the last has a width of 255 bytes.  The last
-segment has width @var{w} - (@var{n} - 1) * 252; some versions
-of SPSS make it slightly wider, but not wide enough to make the last
-segment require another 8 bytes of data.
-
-Data is packed tightly into segments of a very long string, 255 bytes
-per segment.  Because 255 bytes of segment data are allocated for
-every 252 bytes of the very long string's width (approximately), some
-unused space is left over at the end of the allocated segments.  Data
-in unused space is ignored.
-
-Example: Consider a very long string of width 20,000.  Such a very
-long string has 20,000 / 252 = 80 (rounding up) segments.  The first
-79 segments have width 255; the last segment has width 20,000 - 79 *
-252 = 92 or slightly wider (up to 96 bytes, the next multiple of 8).
-The very long string's data is actually stored in the 19,890 bytes in
-the first 78 segments, plus the first 110 bytes of the 79th segment
-(19,890 + 110 = 20,000).  The remaining 145 bytes of the 79th segment
-and all 92 bytes of the 80th segment are unused.
-
-The very long string record explains how to stitch together segments
-to obtain very long string data.  For each of the very long string
-variables in the dictionary, it specifies the name of its first
-segment's variable and the very long string variable's actual width.
-The remaining segments immediately follow the named variable in the
-system file's dictionary.
-
-The very long string record, which is present only if the system file
-contains very long string variables, has the following format:
-
-@example
-/* @r{Header.} */
-int32               rec_type;
-int32               subtype;
-int32               size;
-int32               count;
-
-/* @r{Exactly @code{count} bytes of data.} */
-char                string_lengths[];
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 7.
-
-@item int32 subtype;
-Record subtype.  Always set to 14.
-
-@item int32 size;
-The size of each element in the @code{string_lengths} member. Always set to 1.
-
-@item int32 count;
-The total number of bytes in @code{string_lengths}.
-
-@item char string_lengths[];
-A list of @var{key}--@var{value} tuples, where @var{key} is the name
-of a variable, and @var{value} is its length.
-The @var{key} field is at most 8 bytes long and must match the
-name of a variable which appears in the variable record (@pxref{Variable
-Record}).
-The @var{value} field is exactly 5 bytes long. It is a zero-padded,
-ASCII-encoded string that is the length of the variable.
-The @var{key} and @var{value} fields are separated by a @samp{=} byte.
-Tuples are delimited by a two-byte sequence @{00, 09@}.
-After the last tuple, there may be a single byte 00, or @{00, 09@}.
-The total length is @code{count} bytes.
-@end table
-
-@node Miscellaneous Informational Records
-@section Miscellaneous Informational Records
-
-Some specific types of miscellaneous informational records are
-documented here, but others are known to exist.  PSPP ignores unknown
-miscellaneous informational records when reading system files.
-
-@example
-/* @r{Header.} */
-int32               rec_type;
-int32               subtype;
-int32               size;
-int32               count;
-
-/* @r{Exactly @code{size * count} bytes of data.} */
-char                data[];
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 7.
-
-@item int32 subtype;
-Record subtype.  May take any value.  According to Aapi
-H@"am@"al@"ainen, value 5 indicates a set of grouped variables and 6
-indicates date info (probably related to USE).
-
-@item int32 size;
-Size of each piece of data in the data part.  Should have the value 1,
-4, or 8, for @code{char}, @code{int32}, and @code{flt64} format data,
-respectively.
-
-@item int32 count;
-Number of pieces of data in the data part.
-
-@item char data[];
-Arbitrary data.  There must be @code{size} times @code{count} bytes of
-data.
-@end table
-
-@node Dictionary Termination Record
-@section Dictionary Termination Record
-
-The dictionary termination record separates all other records from the
-data records.
-
-@example
-int32               rec_type;
-int32               filler;
-@end example
-
-@table @code
-@item int32 rec_type;
-Record type.  Always set to 999.
-
-@item int32 filler;
-Ignored padding.  Should be set to 0.
-@end table
-
-@node Data Record
-@section Data Record
-
-Data records must follow all other records in the system file.  There must
-be at least one data record in every system file.
-
-The format of data records varies depending on whether the data is
-compressed.  Regardless, the data is arranged in a series of 8-byte
-elements.
-
-When data is not compressed,
-each element corresponds to
-the variable declared in the respective variable record (@pxref{Variable
-Record}).  Numeric values are given in @code{flt64} format; string
-values are literal characters string, padded on the right when
-necessary to fill out 8-byte units.
-
-Compressed data is arranged in the following manner: the first 8 bytes
-in the data section is divided into a series of 1-byte command
-codes.  These codes have meanings as described below:
-
-@table @asis
-@item 0
-Ignored.  If the program writing the system file accumulates compressed
-data in blocks of fixed length, 0 bytes can be used to pad out extra
-bytes remaining at the end of a fixed-size block.
-
-@item 1 through 251
-A number with
-value @var{code} - @var{bias}, where
-@var{code} is the value of the compression code and @var{bias} is the
-variable @code{bias} from the file header.  For example,
-code 105 with bias 100.0 (the normal value) indicates a numeric variable
-of value 5.
-
-@item 252
-End of file.  This code may or may not appear at the end of the data
-stream.  PSPP always outputs this code but its use is not required.
-
-@item 253
-A numeric or string value that is not
-compressible.  The value is stored in the 8 bytes following the
-current block of command bytes.  If this value appears twice in a block
-of command bytes, then it indicates the second group of 8 bytes following the
-command bytes, and so on.
-
-@item 254
-An 8-byte string value that is all spaces.
-
-@item 255
-The system-missing value.
-@end table
-
-When the end of the an 8-byte group of command bytes is reached, any
-blocks of non-compressible values indicated by code 253 are skipped,
-and the next element of command bytes is read and interpreted, until
-the end of the file or a code with value 252 is reached.
-@setfilename ignored
diff --git a/doc/dev/concepts.texi b/doc/dev/concepts.texi
new file mode 100644 (file)
index 0000000..b1d8583
--- /dev/null
@@ -0,0 +1,2451 @@
+@node Basic Concepts
+@chapter Basic Concepts
+
+This chapter introduces basic data structures and other concepts
+needed for developing in PSPP.
+
+@menu
+* Values::
+* Input and Output Formats::
+* User-Missing Values::
+* Value Labels::
+* Variables::
+* Dictionaries::
+* Coding Conventions::
+* Cases::
+* Data Sets::
+* Pools::
+@end menu
+
+@node Values
+@section Values
+
+@cindex value
+The unit of data in PSPP is a @dfn{value}.
+
+@cindex width
+@cindex string value
+@cindex numeric value
+@cindex MAX_STRING
+Values are classified by @dfn{type} and @dfn{width}.  The
+type of a value is either @dfn{numeric} or @dfn{string} (sometimes
+called alphanumeric).  The width of a string value ranges from 1 to
+@code{MAX_STRING} bytes.  The width of a numeric value is artificially
+defined to be 0; thus, the type of a value can be inferred from its
+width.
+
+Some support is provided for working with value types and widths, in
+@file{data/val-type.h}:
+
+@deftypefn Macro int MAX_STRING
+Maximum width of a string value, in bytes, currently 32,767.
+@end deftypefn
+
+@deftypefun bool val_type_is_valid (enum val_type @var{val_type})
+Returns true if @var{val_type} is a valid value type, that is,
+either @code{VAL_NUMERIC} or @code{VAL_STRING}.  Useful for
+assertions.
+@end deftypefun
+
+@deftypefun {enum val_type} val_type_from_width (int @var{width})
+Returns @code{VAL_NUMERIC} if @var{width} is 0 and thus represents the
+width of a numeric value, otherwise @code{VAL_STRING} to indicate that
+@var{width} is the width of a string value.
+@end deftypefun
+
+The following subsections describe how values of each type are
+represented.
+
+@menu
+* Numeric Values::
+* String Values::
+* Runtime Typed Values::
+@end menu
+
+@node Numeric Values
+@subsection Numeric Values
+
+A value known to be numeric at compile time is represented as a
+@code{double}.  PSPP provides three values of @code{double} for
+special purposes, defined in @file{data/val-type.h}:
+
+@deftypefn Macro double SYSMIS
+The @dfn{system-missing value}, used to represent a datum whose true
+value is unknown, such as a survey question that was not answered by
+the respondent, or undefined, such as the result of division by zero.
+PSPP propagates the system-missing value through calculations and
+compensates for missing values in statistical analyses.  @xref{Missing
+Observations,,,pspp, PSPP Users Guide}, for a PSPP user's view of
+missing values.
+
+PSPP currently defines @code{SYSMIS} as @code{-DBL_MAX}, that is, the
+greatest finite negative value of @code{double}.  It is best not to
+depend on this definition, because PSPP may transition to using an
+IEEE NaN (not a number) instead at some point in the future.
+@end deftypefn
+
+@deftypefn Macro double LOWEST
+@deftypefnx Macro double HIGHEST
+The greatest finite negative (except for @code{SYSMIS}) and positive
+values of @code{double}, respectively.  These values do not ordinarily
+appear in user data files.  Instead, they are used to implement
+endpoints of open-ended ranges that are occasionally permitted in PSPP
+syntax, e.g.@: @code{5 THRU HI} as a range of missing values
+(@pxref{MISSING VALUES,,,pspp, PSPP Users Guide}).
+@end deftypefn
+
+@node String Values
+@subsection String Values
+
+A value known at compile time to have string type is represented as an
+array of @code{char}.  String values do not necessarily represent
+readable text strings and may contain arbitrary 8-bit data, including
+null bytes, control codes, and bytes with the high bit set.  Thus,
+string values are not null-terminated strings, but rather opaque
+arrays of bytes.
+
+@code{SYSMIS}, @code{LOWEST}, and @code{HIGHEST} have no equivalents
+as string values.  Usually, PSPP fills an unknown or undefined string
+values with spaces, but PSPP does not treat such a string as a special
+case when it processes it later.
+
+@cindex MAX_STRING
+@code{MAX_STRING}, the maximum length of a string value, is defined in
+@file{data/val-type.h}.
+
+@node Runtime Typed Values
+@subsection Runtime Typed Values
+
+When a value's type is only known at runtime, it is often represented
+as a @union{value}, defined in @file{data/value.h}.  @union{value} has
+two members: a @code{double} named @samp{f} to store a numeric value
+and an array of @code{char} named @samp{s} to a store a string value.
+A @union{value} does not identify the type or width of the data it
+contains.  Code that works with @union{values}s must therefore have
+external knowledge of its content, often through the type and width of
+a @struct{variable} (@pxref{Variables}).
+
+@cindex MAX_SHORT_STRING
+@cindex short string
+@cindex long string
+@cindex string value
+The array of @code{char} in @union{value} has only a small, fixed
+capacity of @code{MAX_SHORT_STRING} bytes.  A value that
+fits within this capacity is called a @dfn{short string}.  Any wider
+string value, which must be represented by more than one
+@union{value}, is called a @dfn{long string}.
+
+@deftypefn Macro int MAX_SHORT_STRING
+Maximum width of a short string value, never less than 8 bytes.  It is
+wider than 8 bytes on systems where @code{double} is either larger
+than 8 bytes or has stricter alignment than 8 bytes.
+@end deftypefn
+
+@deftypefn Macro int MIN_LONG_STRING
+Minimum width of a long string value, that is, @code{MAX_SHORT_STRING
++ 1}.
+@end deftypefn
+
+Long string variables are slightly harder to work with than short
+string values, because they cannot be conveniently and efficiently
+allocated as block scope variables or structure members.  The PSPP
+language exposes this inconvenience to the user: there are many
+circumstances in PSPP syntax where short strings are allowed but not
+long strings.  Short string variables, for example, may have
+user-missing values, but long string variables may not (@pxref{Missing
+Observations,,,pspp, PSPP Users Guide}).
+
+PSPP provides a few functions for working with @union{value}s.  The
+most useful are described below.  To use these functions, recall that
+a numeric value has a width of 0.
+
+@deftypefun size_t value_cnt_from_width (int @var{width})
+Returns the number of consecutive @union{value}s that must be
+allocated to store a value of the given @var{width}.  For a numeric or
+short string value, the return value is 1; for long string
+variables, it is greater than 1.
+@end deftypefun
+
+@deftypefun void value_copy (union value *@var{dst}, @
+                             const union value *@var{src}, @
+                             int @var{width})
+Copies a value of the given @var{width} from the @union{value} array
+starting at @var{src} to the one starting at @var{dst}.  The two
+arrays must not overlap.
+@end deftypefun
+
+@deftypefun void value_set_missing (union value *@var{value}, int @var{width})
+Sets @var{value} to @code{SYSMIS} if it is numeric or to all spaces if
+it is alphanumeric, according to @var{width}.  @var{value} must point
+to the start of a @union{value} array of the given @var{width}.
+@end deftypefun
+
+@anchor{value_is_resizable}
+@deftypefun bool value_is_resizable (const union value *@var{value}, int @var{old_width}, int @var{new_width})
+Determines whether @var{value} may be resized from @var{old_width} to
+@var{new_width}.  Resizing is possible if the following criteria are
+met.  First, @var{old_width} and @var{new_width} must be both numeric
+or both string widths.  Second, if @var{new_width} is a short string
+width and less than @var{old_width}, resizing is allowed only if bytes
+@var{new_width} through @var{old_width} in @var{value} contain only
+spaces.
+
+These rules are part of those used by @func{mv_is_resizable} and
+@func{val_labs_can_set_width}.
+@end deftypefun
+
+@deftypefun void value_resize (union value *@var{value}, int @var{old_width}, int @var{new_width})
+Resizes @var{value} from @var{old_width} to @var{new_width}, which
+must be allowed by the rules stated above.  This has an effect only if
+@var{new_width} is greater than @var{old_width}, in which case the
+bytes newly added to @var{value} are cleared to spaces.
+@end deftypefun
+
+@node Input and Output Formats
+@section Input and Output Formats
+
+Input and output formats specify how to convert data fields to and
+from data values (@pxref{Input and Output Formats,,,pspp, PSPP Users
+Guide}).  PSPP uses @struct{fmt_spec} to represent input and output
+formats.
+
+Function prototypes and other declarations related to formats are in
+the @file{<data/format.h>} header.
+
+@deftp {Structure} {struct fmt_spec}
+An input or output format, with the following members:
+
+@table @code
+@item enum fmt_type type
+The format type (see below).
+
+@item int w
+Field width, in bytes.  The width of numeric fields is always between
+1 and 40 bytes, and the width of string fields is always between 1 and
+65534 bytes.  However, many individual types of formats place stricter
+limits on field width (see @ref{fmt_max_input_width},
+@ref{fmt_max_output_width}).
+
+@item int d
+Number of decimal places, in character positions.  For format types
+that do not allow decimal places to be specified, this value must be
+0.  Format types that do allow decimal places have type-specific and
+often width-specific restrictions on @code{d} (see
+@ref{fmt_max_input_decimals}, @ref{fmt_max_output_decimals}).
+@end table
+@end deftp
+
+@deftp {Enumeration} {enum fmt_type}
+An enumerated type representing an input or output format type.  Each
+PSPP input and output format has a corresponding enumeration constant
+prefixed by @samp{FMT}: @code{FMT_F}, @code{FMT_COMMA},
+@code{FMT_DOT}, and so on.
+@end deftp
+
+The following sections describe functions for manipulating formats and
+the data in fields represented by formats.
+
+@menu
+* Constructing and Verifying Formats::
+* Format Utility Functions::
+* Obtaining Properties of Format Types::
+* Numeric Formatting Styles::
+* Formatted Data Input and Output::
+@end menu
+
+@node Constructing and Verifying Formats
+@subsection Constructing and Verifying Formats
+
+These functions construct @struct{fmt_spec}s and verify that they are
+valid.
+
+@deftypefun {struct fmt_spec} fmt_for_input (enum fmt_type @var{type}, int @var{w}, int @var{d})
+@deftypefunx {struct fmt_spec} fmt_for_output (enum fmt_type @var{type}, int @var{w}, int @var{d})
+Constructs a @struct{fmt_spec} with the given @var{type}, @var{w}, and
+@var{d}, asserts that the result is a valid input (or output) format,
+and returns it.
+@end deftypefun
+
+@anchor{fmt_for_output_from_input}
+@deftypefun {struct fmt_spec} fmt_for_output_from_input (const struct fmt_spec *@var{input})
+Given @var{input}, which must be a valid input format, returns the
+equivalent output format.  @xref{Input and Output Formats,,,pspp, PSPP
+Users Guide}, for the rules for converting input formats into output
+formats.
+@end deftypefun
+
+@deftypefun {struct fmt_spec} fmt_default_for_width (int @var{width})
+Returns the default output format for a variable of the given
+@var{width}.  For a numeric variable, this is F8.2 format; for a
+string variable, it is the A format of the given @var{width}.
+@end deftypefun
+
+The following functions check whether a @struct{fmt_spec} is valid for
+various uses and return true if so, false otherwise.  When any of them
+returns false, it also outputs an explanatory error message using
+@func{msg}.  To suppress error output, enclose a call to one of these
+functions by a @func{msg_disable}/@func{msg_enable} pair.
+
+@deftypefun bool fmt_check (const struct fmt_spec *@var{format}, bool @var{for_input})
+@deftypefunx bool fmt_check_input (const struct fmt_spec *@var{format})
+@deftypefunx bool fmt_check_output (const struct fmt_spec *@var{format})
+Checks whether @var{format} is a valid input format (for
+@func{fmt_check_input}, or @func{fmt_check} if @var{for_input}) or
+output format (for @func{fmt_check_output}, or @func{fmt_check} if not
+@var{for_input}).
+@end deftypefun
+
+@deftypefun bool fmt_check_type_compat (const struct fmt_spec *@var{format}, enum val_type @var{type})
+Checks whether @var{format} matches the value type @var{type}, that
+is, if @var{type} is @code{VAL_NUMERIC} and @var{format} is a numeric
+format or @var{type} is @code{VAL_STRING} and @var{format} is a string
+format.
+@end deftypefun
+
+@deftypefun bool fmt_check_width_compat (const struct fmt_spec *@var{format}, int @var{width})
+Checks whether @var{format} may be used as an output format for a
+value of the given @var{width}.
+
+@func{fmt_var_width}, described in
+the following section, can be also be used to determine the value
+width needed by a format.
+@end deftypefun
+
+@node Format Utility Functions
+@subsection Format Utility Functions
+
+These functions work with @struct{fmt_spec}s.
+
+@deftypefun int fmt_var_width (const struct fmt_spec *@var{format})
+Returns the width for values associated with @var{format}.  If
+@var{format} is a numeric format, the width is 0; if @var{format} is
+an A format, then the width @code{@var{format}->w}; otherwise,
+@var{format} is an AHEX format and its width is @code{@var{format}->w
+/ 2}.
+@end deftypefun
+
+@deftypefun char *fmt_to_string (const struct fmt_spec *@var{format}, char @var{s}[FMT_STRING_LEN_MAX + 1])
+Converts @var{format} to a human-readable format specifier in @var{s}
+and returns @var{s}.  @var{format} need not be a valid input or output
+format specifier, e.g.@: it is allowed to have an excess width or
+decimal places.  In particular, if @var{format} has decimals, they are
+included in the output string, even if @var{format}'s type does not
+allow decimals, to allow accurately presenting incorrect formats to
+the user.
+@end deftypefun
+
+@deftypefun bool fmt_equal (const struct fmt_spec *@var{a}, const struct fmt_spec *@var{b})
+Compares @var{a} and @var{b} memberwise and returns true if they are
+identical, false otherwise.  @var{format} need not be a valid input or
+output format specifier.
+@end deftypefun
+
+@node Obtaining Properties of Format Types
+@subsection Obtaining Properties of Format Types
+
+These functions work with @enum{fmt_type}s instead of the higher-level
+@struct{fmt_spec}s.  Their primary purpose is to report properties of
+each possible format type, which in turn allows clients to abstract
+away many of the details of the very heterogeneous requirements of
+each format type.
+
+The first group of functions works with format type names.
+
+@deftypefun const char *fmt_name (enum fmt_type @var{type})
+Returns the name for the given @var{type}, e.g.@: @code{"COMMA"} for
+@code{FMT_COMMA}.
+@end deftypefun
+
+@deftypefun bool fmt_from_name (const char *@var{name}, enum fmt_type *@var{type})
+Tries to find the @enum{fmt_type} associated with @var{name}.  If
+successful, sets @code{*@var{type}} to the type and returns true;
+otherwise, returns false without modifying @code{*@var{type}}.
+@end deftypefun
+
+The functions below query basic limits on width and decimal places for
+each kind of format.
+
+@deftypefun bool fmt_takes_decimals (enum fmt_type @var{type})
+Returns true if a format of the given @var{type} is allowed to have a
+nonzero number of decimal places (the @code{d} member of
+@struct{fmt_spec}), false if not.
+@end deftypefun
+
+@anchor{fmt_min_input_width}
+@anchor{fmt_max_input_width}
+@anchor{fmt_min_output_width}
+@anchor{fmt_max_output_width}
+@deftypefun int fmt_min_input_width (enum fmt_type @var{type})
+@deftypefunx int fmt_max_input_width (enum fmt_type @var{type})
+@deftypefunx int fmt_min_output_width (enum fmt_type @var{type})
+@deftypefunx int fmt_max_output_width (enum fmt_type @var{type})
+Returns the minimum or maximum width (the @code{w} member of
+@struct{fmt_spec}) allowed for an input or output format of the
+specified @var{type}.
+@end deftypefun
+
+@anchor{fmt_max_input_decimals}
+@anchor{fmt_max_output_decimals}
+@deftypefun int fmt_max_input_decimals (enum fmt_type @var{type}, int @var{width})
+@deftypefunx int fmt_max_output_decimals (enum fmt_type @var{type}, int @var{width})
+Returns the maximum number of decimal places allowed for an input or
+output format, respectively, of the given @var{type} and @var{width}.
+Returns 0 if the specified @var{type} does not allow any decimal
+places or if @var{width} is too narrow to allow decimal places.
+@end deftypefun
+
+@deftypefun int fmt_step_width (enum fmt_type @var{type})
+Returns the ``width step'' for a @struct{fmt_spec} of the given
+@var{type}.  A @struct{fmt_spec}'s width must be a multiple of its
+type's width step.  Most format types have a width step of 1, so that
+their formats' widths may be any integer within the valid range, but
+hexadecimal numeric formats and AHEX string formats have a width step
+of 2.
+@end deftypefun
+
+These functions allow clients to broadly determine how each kind of
+input or output format behaves.
+
+@deftypefun bool fmt_is_string (enum fmt_type @var{type})
+@deftypefunx bool fmt_is_numeric (enum fmt_type @var{type})
+Returns true if @var{type} is a format for numeric or string values,
+respectively, false otherwise.
+@end deftypefun
+
+@deftypefun enum fmt_category fmt_get_category (enum fmt_type @var{type})
+Returns the category within which @var{type} falls.
+
+@deftp {Enumeration} {enum fmt_category}
+A group of format types.  Format type categories correspond to the
+input and output categories described in the PSPP user documentation
+(@pxref{Input and Output Formats,,,pspp, PSPP Users Guide}).
+
+Each format is in exactly one category.  The categories have bitwise
+disjoint values to make it easy to test whether a format type is in
+one of multiple categories, e.g.@:
+
+@example
+if (fmt_get_category (type) & (FMT_CAT_DATE | FMT_CAT_TIME))
+  @{
+    /* @dots{}@r{@code{type} is a date or time format}@dots{} */
+  @}
+@end example
+
+The format categories are:
+@table @code
+@item FMT_CAT_BASIC
+Basic numeric formats.
+
+@item FMT_CAT_CUSTOM
+Custom currency formats.
+
+@item FMT_CAT_LEGACY
+Legacy numeric formats.
+
+@item FMT_CAT_BINARY
+Binary formats.
+
+@item FMT_CAT_HEXADECIMAL
+Hexadecimal formats.
+
+@item FMT_CAT_DATE
+Date formats.
+
+@item FMT_CAT_TIME
+Time formats.
+
+@item FMT_CAT_DATE_COMPONENT
+Date component formats.
+
+@item FMT_CAT_STRING
+String formats.
+@end table
+@end deftp
+@end deftypefun
+
+The PSPP input and output routines use the following pair of functions
+to convert @enum{fmt_type}s to and from the separate set of codes used
+in system and portable files:
+
+@deftypefun int fmt_to_io (enum fmt_type @var{type})
+Returns the format code used in system and portable files that
+corresponds to @var{type}.
+@end deftypefun
+
+@deftypefun bool fmt_from_io (int @var{io}, enum fmt_type *@var{type})
+Converts @var{io}, a format code used in system and portable files,
+into a @enum{fmt_type} in @code{*@var{type}}.  Returns true if
+successful, false if @var{io} is not valid.
+@end deftypefun
+
+These functions reflect the relationship between input and output
+formats.
+
+@deftypefun enum fmt_type fmt_input_to_output (enum fmt_type @var{type})
+Returns the output format type that is used by default by DATA LIST
+and other input procedures when @var{type} is specified as an input
+format.  The conversion from input format to output format is more
+complicated than simply changing the format.
+@xref{fmt_for_output_from_input}, for a function that performs the
+entire conversion.
+@end deftypefun
+
+@deftypefun bool fmt_usable_for_input (enum fmt_type @var{type})
+Returns true if @var{type} may be used as an input format type, false
+otherwise.  The custom currency formats, in particular, may be used
+for output but not for input.
+
+All format types are valid for output.
+@end deftypefun
+
+The final group of format type property functions obtain
+human-readable templates that illustrate the formats graphically.
+
+@deftypefun const char *fmt_date_template (enum fmt_type @var{type})
+Returns a formatting template for @var{type}, which must be a date or
+time format type.  These formats are used by @func{data_in} and
+@func{data_out} to guide parsing and formatting date and time data.
+@end deftypefun
+
+@deftypefun char *fmt_dollar_template (const struct fmt_spec *@var{format})
+Returns a string of the form @code{$#,###.##} according to
+@var{format}, which must be of type @code{FMT_DOLLAR}.  The caller
+must free the string with @code{free}.
+@end deftypefun
+
+@node Numeric Formatting Styles
+@subsection Numeric Formatting Styles
+
+Each of the basic numeric formats (F, E, COMMA, DOT, DOLLAR, PCT) and
+custom currency formats (CCA, CCB, CCC, CCD, CCE) has an associated
+numeric formatting style, represented by @struct{fmt_number_style}.
+Input and output conversion of formats that have numeric styles is
+determined mainly by the style, although the formatting rules have
+special cases that are not represented within the style.
+
+@deftp {Structure} {struct fmt_number_style}
+A structure type with the following members:
+
+@table @code
+@item struct substring neg_prefix
+@itemx struct substring prefix
+@itemx struct substring suffix
+@itemx struct substring neg_suffix
+A set of strings used a prefix to negative numbers, a prefix to every
+number, a suffix to every number, and a suffix to negative numbers,
+respectively.  Each of these strings is no more than
+@code{FMT_STYLE_AFFIX_MAX} bytes (currently 16) bytes in length.
+These strings must be freed with @func{ss_dealloc} when no longer
+needed.
+
+@item decimal
+The character used as a decimal point.  It must be either @samp{.} or
+@samp{,}.
+
+@item grouping
+The character used for grouping digits to the left of the decimal
+point.  It may be @samp{.} or @samp{,}, in which case it must not be
+equal to @code{decimal}, or it may be set to 0 to disable grouping.
+@end table
+@end deftp
+
+The following functions are provided for working with numeric
+formatting styles.
+
+@deftypefun {struct fmt_number_style *} fmt_number_style_create (void)
+Creates and returns a new @struct{fmt_number_style} with all of the
+prefixes and suffixes set to the empty string, @samp{.} as the decimal
+point character, and grouping disables.
+@end deftypefun
+
+@deftypefun void fmt_number_style_destroy (struct fmt_number_style *@var{style})
+Destroys @var{style}, freeing its storage.
+@end deftypefun
+
+@deftypefun int fmt_affix_width (const struct fmt_number_style *@var{style})
+Returns the total length of @var{style}'s @code{prefix} and @code{suffix}.
+@end deftypefun
+
+@deftypefun int fmt_neg_affix_width (const struct fmt_number_style *@var{style})
+Returns the total length of @var{style}'s @code{neg_prefix} and
+@code{neg_suffix}.
+@end deftypefun
+
+PSPP maintains a global set of number styles for each of the basic
+numeric formats and custom currency formats.  The following functions
+work with these global styles:
+
+@deftypefun {const struct fmt_number_style *} fmt_get_style (enum fmt_type @var{type})
+Returns the numeric style for the given format @var{type}.
+@end deftypefun
+
+@deftypefun void fmt_set_style (enum fmt_type @var{type}, struct fmt_number_style *@var{style})
+Replaces the current numeric style for format @var{type} by the given
+@var{style}, which becomes owned by the callee.  @var{type} must be a
+custom currency format and @var{style} must follow all the rules for
+numeric styles explained above.
+@end deftypefun
+
+@deftypefun int fmt_decimal_char (enum fmt_type @var{type})
+Returns the decimal point character for the given format @var{type}.
+Equivalent to @code{fmt_get_style (@var{type})->decimal}.
+@end deftypefun
+
+@deftypefun int fmt_grouping_char (enum fmt_type @var{type})
+Returns the grouping character for the given format @var{type}, or 0
+if @var{type} output should not be grouped.  Equivalent to
+@code{fmt_get_style (@var{type})->grouping}.
+@end deftypefun
+
+@deftypefun void fmt_set_decimal (char @var{decimal})
+Changes the decimal point character for the basic numeric formats to
+@var{decimal}, which must be @samp{.} or @samp{,}.  The F, E, COMMA,
+DOLLAR, and PCT will use the specified decimal point character, and the
+opposite character for grouping where appropriate.  The DOT format
+uses the reverse choices.
+@end deftypefun
+
+@node Formatted Data Input and Output
+@subsection Formatted Data Input and Output
+
+These functions provide the ability to convert data fields into
+@union{value}s and vice versa.
+
+@deftypefun bool data_in (struct substring @var{input}, enum legacy_encoding @var{legacy_encoding}, enum fmt_type @var{type}, int @var{implied_decimals}, int @var{first_column}, union value *@var{output}, int @var{width})
+Parses @var{input} as a field containing data in the given format
+@var{type}.  The resulting value is stored in @var{output}, which has
+the given @var{width}.  For consistency, @var{width} must be 0 if
+@var{type} is a numeric format type and greater than 0 if @var{type}
+is a string format type.
+
+Ordinarily @var{legacy_encoding} should be @code{LEGACY_NATIVE},
+indicating that @var{input} is encoded in the character set
+conventionally used on the host machine.  It may be set to
+@code{LEGACY_EBCDIC} to cause @var{input} to be re-encoded from EBCDIC
+during data parsing.
+
+If @var{input} is the empty string (with length 0), @var{output} is
+set to the value set on SET BLANKS (@pxref{SET BLANKS,,,pspp, PSPP
+Users Guide}) for a numeric value, or to all spaces for a string
+value.  This applies regardless of the usual parsing requirements for
+@var{type}.
+
+If @var{implied_decimals} is greater than zero, then the numeric
+result is shifted right by @var{implied_decimals} decimal places if
+@var{input} does not contain a decimal point character or an exponent.
+Only certain numeric format types support implied decimal places; for
+string formats and other numeric formats, @var{implied_decimals} has
+no effect.  DATA LIST FIXED is the primary user of this feature
+(@pxref{DATA LIST FIXED,,,pspp, PSPP Users Guide}).  Other callers
+should generally specify 0 for @var{implied_decimals}, to disable this
+feature.
+
+When @var{input} contains invalid input data, @func{data_in} outputs a
+message using @func{msg}.
+@c (@pxref{msg}).
+If @var{first_column} is
+nonzero, it is included in any such error message as the 1-based
+column number of the start of the field.  The last column in the field
+is calculated as @math{@var{first_column} + @var{input} - 1}.  To
+suppress error output, enclose the call to @func{data_in} by calls to
+@func{msg_disable} and @func{msg_enable}.
+
+This function returns true on success, false if a message was output
+(even if suppressed).  Overflow and underflow provoke warnings but are
+not propagated to the caller as errors.
+
+This function is declared in @file{data/data-in.h}.
+@end deftypefun
+
+@deftypefun void data_out (const union value *@var{input}, const struct fmt_spec *@var{format}, char *@var{output})
+@deftypefunx void data_out_legacy (const union value *@var{input}, enum legacy_encoding @var{legacy_encoding}, const struct fmt_spec *@var{format}, char *@var{output})
+Converts the data pointed to by @var{input} into a data field in
+@var{output} according to output format specifier @var{format}, which
+must be a valid output format.  Exactly @code{@var{format}->w} bytes
+are written to @var{output}.  The width of @var{input} is also
+inferred from @var{format} using an algorithm equivalent to
+@func{fmt_var_width}.
+
+If @func{data_out} is called, or @func{data_out_legacy} is called with
+@var{legacy_encoding} set to @code{LEGACY_NATIVE}, @var{output} will
+be encoded in the character set conventionally used on the host
+machine.  If @var{legacy_encoding} is set to @code{LEGACY_EBCDIC},
+@var{output} will be re-encoded from EBCDIC during data output.
+
+When @var{input} contains data that cannot be represented in the given
+@var{format}, @func{data_out} may output a message using @func{msg},
+@c (@pxref{msg}),
+although the current implementation does not
+consistently do so.  To suppress error output, enclose the call to
+@func{data_out} by calls to @func{msg_disable} and @func{msg_enable}.
+
+This function is declared in @file{data/data-out.h}.
+@end deftypefun
+
+@node User-Missing Values
+@section User-Missing Values
+
+In addition to the system-missing value for numeric values, each
+variable has a set of user-missing values (@pxref{MISSING
+VALUES,,,pspp, PSPP Users Guide}).  A set of user-missing values is
+represented by @struct{missing_values}.
+
+It is rarely necessary to interact directly with a
+@struct{missing_values} object.  Instead, the most common operation,
+querying whether a particular value is a missing value for a given
+variable, is most conveniently executed through functions on
+@struct{variable}.  @xref{Variable Missing Values}, for details.
+
+A @struct{missing_values} is essentially a set of @union{value}s that
+have a common value width (@pxref{Values}).  For a set of
+missing values associated with a variable (the common case), the set's
+width is the same as the variable's width.  The contents of a set of
+missing values is subject to some restrictions.  Regardless of width,
+a set of missing values is allowed to be empty.  Otherwise, its
+possible contents depend on its width:
+
+@table @asis
+@item 0 (numeric values)
+Up to three discrete numeric values, or a range of numeric values
+(which includes both ends of the range), or a range plus one discrete
+numeric value.
+
+@item 1@dots{}@t{MAX_SHORT_STRING} - 1 (short string values)
+Up to three discrete string values (with the same width as the set).
+
+@item @t{MAX_SHORT_STRING}@dots{}@t{MAX_STRING} (long string values)
+Always empty.
+@end table
+
+These somewhat arbitrary restrictions are the same as those imposed by
+SPSS.  In PSPP we could easily eliminate these restrictions, but doing
+so would also require us to extend the system file format in an
+incompatible way, which we consider a bad tradeoff.
+
+Function prototypes and other declarations related to missing values
+are declared in @file{data/missing-values.h}.
+
+@deftp {Structure} {struct missing_values}
+Opaque type that represents a set of missing values.
+@end deftp
+
+The most often useful functions for missing values are those for
+testing whether a given value is missing, described in the following
+section.  Several other functions for creating, inspecting, and
+modifying @struct{missing_values} objects are described afterward, but
+these functions are much more rarely useful.  No function for
+destroying a @struct{missing_values} is provided, because
+@struct{missing_values} does not contain any pointers or other
+references to resources that need deallocation.
+
+@menu
+* Testing for Missing Values::
+* Initializing User-Missing Value Sets::
+* Changing User-Missing Value Set Width::
+* Inspecting User-Missing Value Sets::
+* Modifying User-Missing Value Sets::
+@end menu
+
+@node Testing for Missing Values
+@subsection Testing for Missing Values
+
+The most often useful functions for missing values are those for
+testing whether a given value is missing, described here.  However,
+using one of the corresponding missing value testing functions for
+variables can be even easier (@pxref{Variable Missing Values}).
+
+@deftypefun bool mv_is_value_missing (const struct missing_values *@var{mv}, const union value *@var{value}, enum mv_class @var{class})
+@deftypefunx bool mv_is_num_missing (const struct missing_values *@var{mv}, double @var{value}, enum mv_class @var{class})
+@deftypefunx bool mv_is_str_missing (const struct missing_values *@var{mv}, const char @var{value}[], enum mv_class @var{class})
+Tests whether @var{value} is in one of the categories of missing
+values given by @var{class}.  Returns true if so, false otherwise.
+
+@var{mv} determines the width of @var{value} and provides the set of
+user-missing values to test.
+
+The only difference among these functions in the form in which
+@var{value} is provided, so you may use whichever function is most
+convenient.
+
+The @var{class} argument determines the exact kinds of missing values
+that the functions test for:
+
+@deftp Enumeration {enum mv_class}
+@table @t
+@item MV_USER
+Returns true if @var{value} is in the set of user-missing values given
+by @var{mv}.
+
+@item MV_SYSTEM
+Returns true if @var{value} is system-missing.  (If @var{mv}
+represents a set of string values, then @var{value} is never
+system-missing.)
+
+@item MV_ANY
+@itemx MV_USER | MV_SYSTEM
+Returns true if @var{value} is user-missing or system-missing.
+
+@item MV_NONE
+Always returns false, that is, @var{value} is never considered
+missing.
+@end table
+@end deftp
+@end deftypefun
+
+@node Initializing User-Missing Value Sets
+@subsection Initializing User-Missing Value Sets
+
+@deftypefun void mv_init (struct missing_values *@var{mv}, int @var{width})
+Initializes @var{mv} as a set of user-missing values.  The set is
+initially empty.  Any values added to it must have the specified
+@var{width}.
+@end deftypefun
+
+@deftypefun void mv_copy (struct missing_values *@var{mv}, const struct missing_values *@var{old})
+Initializes @var{mv} as a copy of the existing set of user-missing
+values @var{old}.
+@end deftypefun
+
+@deftypefun void mv_clear (struct missing_values *@var{mv})
+Empties the user-missing value set @var{mv}, retaining its existing
+width.
+@end deftypefun
+
+@node Changing User-Missing Value Set Width
+@subsection Changing User-Missing Value Set Width
+
+A few PSPP language constructs copy sets of user-missing values from
+one variable to another.  When the source and target variables have
+the same width, this is simple.  But when the target variable's width
+might be different from the source variable's, it takes a little more
+work.  The functions described here can help.
+
+In fact, it is usually unnecessary to call these functions directly.
+Most of the time @func{var_set_missing_values}, which uses
+@func{mv_resize} internally to resize the new set of missing values to
+the required width, may be used instead.
+@xref{var_set_missing_values}, for more information.
+
+@deftypefun bool mv_is_resizable (const struct missing_values *@var{mv}, int @var{new_width})
+Tests whether @var{mv}'s width may be changed to @var{new_width} using
+@func{mv_resize}.  Returns true if it is allowed, false otherwise.
+
+If @var{new_width} is a long string width, @var{mv} may be resized
+only if it is empty.  Otherwise, if @var{mv} contains any missing
+values, then it may be resized only if each missing value may be
+resized, as determined by @func{value_is_resizable}
+(@pxref{value_is_resizable}).
+@end deftypefun
+
+@anchor{mv_resize}
+@deftypefun void mv_resize (struct missing_values *@var{mv}, int @var{width})
+Changes @var{mv}'s width to @var{width}.  @var{mv} and @var{width}
+must satisfy the constraints explained above.
+
+When a string missing value set's width is increased, each
+user-missing value is padded on the right with spaces to the new
+width.
+@end deftypefun
+
+@node Inspecting User-Missing Value Sets
+@subsection Inspecting User-Missing Value Sets
+
+These functions inspect the properties and contents of
+@struct{missing_values} objects.
+
+The first set of functions inspects the discrete values that numeric
+and short string sets of user-missing values may contain:
+
+@deftypefun bool mv_is_empty (const struct missing_values *@var{mv})
+Returns true if @var{mv} contains no user-missing values, false if it
+contains at least one user-missing value (either a discrete value or a
+numeric range).
+@end deftypefun
+
+@deftypefun int mv_get_width (const struct missing_values *@var{mv})
+Returns the width of the user-missing values that @var{mv} represents.
+@end deftypefun
+
+@deftypefun int mv_n_values (const struct missing_values *@var{mv})
+Returns the number of discrete user-missing values included in
+@var{mv}.  The return value will be between 0 and 3.  For sets of
+numeric user-missing values that include a range, the return value
+will be 0 or 1.
+@end deftypefun
+
+@deftypefun bool mv_has_value (const struct missing_values *@var{mv})
+Returns true if @var{mv} has at least one discrete user-missing
+values, that is, if @func{mv_n_values} would return nonzero for
+@var{mv}.
+@end deftypefun
+
+@deftypefun void mv_get_value (const struct missing_values *@var{mv}, union value *@var{value}, int @var{index})
+Copies the discrete user-missing value in @var{mv} with the given
+@var{index} into @var{value}.  The index must be less than the number
+of discrete user-missing values in @var{mv}, as reported by
+@func{mv_n_values}.
+@end deftypefun
+
+The second set of functions inspects the single range of values that
+numeric sets of user-missing values may contain:
+
+@deftypefun bool mv_has_range (const struct missing_values *@var{mv})
+Returns true if @var{mv} includes a range, false otherwise.
+@end deftypefun
+
+@deftypefun void mv_get_range (const struct missing_values *@var{mv}, double *@var{low}, double *@var{high})
+Stores the low endpoint of @var{mv}'s range in @code{*@var{low}} and
+the high endpoint of the range in @code{*@var{high}}.  @var{mv} must
+include a range.
+@end deftypefun
+
+@node Modifying User-Missing Value Sets
+@subsection Modifying User-Missing Value Sets
+
+These functions modify the contents of @struct{missing_values}
+objects.
+
+The first set of functions applies to all sets of user-missing values:
+
+@deftypefun bool mv_add_value (struct missing_values *@var{mv}, const union value *@var{value})
+@deftypefunx bool mv_add_str (struct missing_values *@var{mv}, const char @var{value}[])
+@deftypefunx bool mv_add_num (struct missing_values *@var{mv}, double @var{value})
+Attempts to add the given discrete @var{value} to set of user-missing
+values @var{mv}.  @var{value} must have the same width as @var{mv}.
+Returns true if @var{value} was successfully added, false if the set
+could not accept any more discrete values.  (Always returns false if
+@var{mv} is a set of long string user-missing values.)
+
+These functions are equivalent, except for the form in which
+@var{value} is provided, so you may use whichever function is most
+convenient.
+@end deftypefun
+
+@deftypefun void mv_pop_value (struct missing_values *@var{mv}, union value *@var{value})
+Removes a discrete value from @var{mv} (which must contain at least
+one discrete value) and stores it in @var{value}.
+@end deftypefun
+
+@deftypefun void mv_replace_value (struct missing_values *@var{mv}, const union value *@var{value}, int @var{index})
+Replaces the discrete value with the given @var{index} in @var{mv}
+(which must contain at least @var{index} + 1 discrete values) with
+@var{value}.
+@end deftypefun
+
+The second set of functions applies only to numeric sets of
+user-missing values:
+
+@deftypefun bool mv_add_range (struct missing_values *@var{mv}, double @var{low}, double @var{high})
+Attempts to add a numeric range covering @var{low}@dots{}@var{high}
+(inclusive on both ends) to @var{mv}, which must be a numeric set of
+user-missing values.  Returns true if the range is successful added,
+false on failure.  Fails if @var{mv} already contains a range, or if
+@var{mv} contains more than one discrete value, or if @var{low} >
+@var{high}.
+@end deftypefun
+
+@deftypefun void mv_pop_range (struct missing_values *@var{mv}, double *@var{low}, double *@var{high})
+Given @var{mv}, which must be a numeric set of user-missing values
+that contains a range, removes that range from @var{mv} and stores its
+low endpoint in @code{*@var{low}} and its high endpoint in
+@code{*@var{high}}.
+@end deftypefun
+
+@node Value Labels
+@section Value Labels
+
+Each variable has a set of value labels (@pxref{VALUE LABELS,,,pspp,
+PSPP Users Guide}), represented as @struct{val_labs}.  A
+@struct{val_labs} is essentially a map from @union{value}s to strings.
+All of the values in a set of value labels have the same width, which
+for a set of value labels owned by a variable (the common case) is the
+same as its variable.
+
+Numeric and short string sets of value labels may contain any number
+of entries.  Long string sets of value labels may not contain any
+value labels at all, due to a corresponding restriction in SPSS.  In
+PSPP we could easily eliminate this restriction, but doing so would
+also require us to extend the system file format in an incompatible
+way, which we consider a bad tradeoff.
+
+It is rarely necessary to interact directly with a @struct{val_labs}
+object.  Instead, the most common operation, looking up the label for
+a value of a given variable, can be conveniently executed through
+functions on @struct{variable}.  @xref{Variable Value Labels}, for
+details.
+
+Function prototypes and other declarations related to missing values
+are declared in @file{data/value-labels.h}.
+
+@deftp {Structure} {struct val_labs}
+Opaque type that represents a set of value labels.
+@end deftp
+
+The most often useful function for value labels is
+@func{val_labs_find}, for looking up the label associated with a
+value.
+
+@deftypefun {char *} val_labs_find (const struct val_labs *@var{val_labs}, union value @var{value})
+Looks in @var{val_labs} for a label for the given @var{value}.
+Returns the label, if one is found, or a null pointer otherwise.
+@end deftypefun
+
+Several other functions for working with value labels are described in
+the following section, but these are more rarely useful.
+
+@menu
+* Value Labels Creation and Destruction::
+* Value Labels Properties::
+* Value Labels Adding and Removing Labels::
+* Value Labels Iteration::
+@end menu
+
+@node Value Labels Creation and Destruction
+@subsection Creation and Destruction
+
+These functions create and destroy @struct{val_labs} objects.
+
+@deftypefun {struct val_labs *} val_labs_create (int @var{width})
+Creates and returns an initially empty set of value labels with the
+given @var{width}.
+@end deftypefun
+
+@deftypefun {struct val_labs *} val_labs_clone (const struct val_labs *@var{val_labs})
+Creates and returns a set of value labels whose width and contents are
+the same as those of @var{var_labs}.
+@end deftypefun
+
+@deftypefun void val_labs_clear (struct val_labs *@var{var_labs})
+Deletes all value labels from @var{var_labs}.
+@end deftypefun
+
+@deftypefun void val_labs_destroy (struct val_labs *@var{var_labs})
+Destroys @var{var_labs}, which must not be referenced again.
+@end deftypefun
+
+@node Value Labels Properties
+@subsection Value Labels Properties
+
+These functions inspect and manipulate basic properties of
+@struct{val_labs} objects.
+
+@deftypefun size_t val_labs_count (const struct val_labs *@var{val_labs})
+Returns the number of value labels in @var{val_labs}.
+@end deftypefun
+
+@deftypefun bool val_labs_can_set_width (const struct val_labs *@var{val_labs}, int @var{new_width})
+Tests whether @var{val_labs}'s width may be changed to @var{new_width}
+using @func{val_labs_set_width}.  Returns true if it is allowed, false
+otherwise.
+
+A set of value labels may be resized to a given width only if each
+value in it may be resized to that width, as determined by
+@func{value_is_resizable} (@pxref{value_is_resizable}).
+@end deftypefun
+
+@deftypefun void val_labs_set_width (struct val_labs *@var{val_labs}, int @var{new_width})
+Changes the width of @var{val_labs}'s values to @var{new_width}, which
+must be a valid new width as determined by
+@func{val_labs_can_set_width}.
+
+If @var{new_width} is a long string width, this function deletes all
+value labels from @var{val_labs}.
+@end deftypefun
+
+@node Value Labels Adding and Removing Labels
+@subsection Adding and Removing Labels
+
+These functions add and remove value labels from a @struct{val_labs}
+object.  These functions apply only to numeric and short string sets
+of value labels.  They have no effect on long string sets of value
+labels, since these sets are always empty.
+
+@deftypefun bool val_labs_add (struct val_labs *@var{val_labs}, union value @var{value}, const char *@var{label})
+Adds @var{label} to in @var{var_labs} as a label for @var{value},
+which must have the same width as the set of value labels.  Returns
+true if successful, false if @var{value} already has a label or if
+@var{val_labs} has long string width.
+@end deftypefun
+
+@deftypefun void val_labs_replace (struct val_labs *@var{val_labs}, union value @var{value}, const char *@var{label})
+Adds @var{label} to in @var{var_labs} as a label for @var{value},
+which must have the same width as the set of value labels.  If
+@var{value} already has a label in @var{var_labs}, it is replaced.
+Has no effect if @var{var_labs} has long string width.
+@end deftypefun
+
+@deftypefun bool val_labs_remove (struct val_labs *@var{val_labs}, union value @var{value})
+Removes from @var{val_labs} any label for @var{value}, which must have
+the same width as the set of value labels.  Returns true if a label
+was removed, false otherwise.
+@end deftypefun
+
+@node Value Labels Iteration
+@subsection Iterating through Value Labels
+
+These functions allow iteration through the set of value labels
+represented by a @struct{val_labs} object.  They are usually used in
+the context of a @code{for} loop:
+
+@example
+struct val_labs val_labs;
+struct val_labs_iterator *i;
+struct val_lab *vl;
+
+@dots{}
+
+for (vl = val_labs_first (val_labs, &i); vl != NULL;
+     vl = val_labs_next (val_labs, &i))
+  @{
+    @dots{}@r{do something with @code{vl}}@dots{}
+  @}
+@end example
+
+The value labels in a @struct{val_labs} must not be modified as it is
+undergoing iteration.
+
+@deftp {Structure} {struct val_lab}
+Represents a value label for iteration purposes, with two
+client-visible members:
+
+@table @code
+@item union value value
+Value being labeled, of the same width as the @struct{val_labs} being
+iterated.
+
+@item const char *label
+The label, as a null-terminated string.
+@end table
+@end deftp
+
+@deftp {Structure} {struct val_labs_iterator}
+Opaque object that represents the current state of iteration through a
+set of value value labels.  Automatically destroyed by successful
+completion of iteration.  Must be destroyed manually in other
+circumstances, by calling @func{val_labs_done}.
+@end deftp
+
+@deftypefun {struct val_lab *} val_labs_first (const struct val_labs *@var{val_labs}, struct val_labs_iterator **@var{iterator})
+If @var{val_labs} contains at least one value label, starts an
+iteration through @var{val_labs}, initializes @code{*@var{iterator}}
+to point to a newly allocated iterator, and returns the first value
+label in @var{val_labs}.  If @var{val_labs} is empty, sets
+@code{*@var{iterator}} to null and returns a null pointer.
+
+This function creates iterators that traverse sets of value labels in
+no particular order.
+@end deftypefun
+
+@deftypefun {struct val_lab *} val_labs_first_sorted (const struct val_labs *@var{val_labs}, struct val_labs_iterator **@var{iterator})
+Same as @func{val_labs_first}, except that the created iterator
+traverses the set of value labels in ascending order of value.
+@end deftypefun
+
+@deftypefun {struct val_lab *} val_labs_next (const struct val_labs *@var{val_labs}, struct val_labs_iterator **@var{iterator})
+Advances an iterator created with @func{val_labs_first} or
+@func{val_labs_first_sorted} to the next value label, which is
+returned.  If the set of value labels is exhausted, returns a null
+pointer after freeing @code{*@var{iterator}} and setting it to a null
+pointer.
+@end deftypefun
+
+@deftypefun void val_labs_done (struct val_labs_iterator **@var{iterator})
+Frees @code{*@var{iterator}} and sets it to a null pointer.  Does
+not need to be called explicitly if @func{val_labs_next} returns a
+null pointer, indicating that all value labels have been visited.
+@end deftypefun
+
+@node Variables
+@section Variables
+
+A PSPP variable is represented by @struct{variable}, an opaque type
+declared in @file{data/variable.h} along with related declarations.
+@xref{Variables,,,pspp, PSPP Users Guide}, for a description of PSPP
+variables from a user perspective.
+
+PSPP is unusual among computer languages in that, by itself, a PSPP
+variable does not have a value.  Instead, a variable in PSPP takes on
+a value only in the context of a case, which supplies one value for
+each variable in a set of variables (@pxref{Cases}).  The set of
+variables in a case, in turn, are ordinarily part of a dictionary
+(@pxref{Dictionaries}).
+
+Every variable has several attributes, most of which correspond
+directly to one of the variable attributes visible to PSPP users
+(@pxref{Attributes,,,pspp, PSPP Users Guide}).
+
+The following sections describe variable-related functions and macros.
+
+@menu
+* Variable Name::
+* Variable Type and Width::
+* Variable Missing Values::
+* Variable Value Labels::
+* Variable Print and Write Formats::
+* Variable Labels::
+* Variable GUI Attributes::
+* Variable Leave Status::
+* Dictionary Class::
+* Variable Creation and Destruction::
+* Variable Short Names::
+* Variable Relationships::
+* Variable Auxiliary Data::
+* Variable Categorical Values::
+@end menu
+
+@node Variable Name
+@subsection Variable Name
+
+A variable name is a string between 1 and @code{VAR_NAME_LEN} bytes
+long that satisfies the rules for PSPP identifiers
+(@pxref{Tokens,,,pspp, PSPP Users Guide}).  Variable names are
+mixed-case and treated case-insensitively.
+
+@deftypefn Macro int VAR_NAME_LEN
+Maximum length of a variable name, in bytes, currently 64.
+@end deftypefn
+
+Only one commonly useful function relates to variable names:
+
+@deftypefun {const char *} var_get_name (const struct variable *@var{var})
+Returns @var{var}'s variable name as a C string.
+@end deftypefun
+
+A few other functions are much more rarely used.  Some of these
+functions are used internally by the dictionary implementation:
+
+@anchor{var_set_name}
+@deftypefun {void} var_set_name (struct variable *@var{var}, const char *@var{new_name})
+Changes the name of @var{var} to @var{new_name}, which must be a
+``plausible'' name as defined below.
+
+This function cannot be applied to a variable that is part of a
+dictionary.  Use @func{dict_rename_var} instead (@pxref{Dictionary
+Renaming Variables}).
+@end deftypefun
+
+@anchor{var_is_plausible_name}
+@deftypefun {bool} var_is_valid_name (const char *@var{name}, bool @var{issue_error})
+@deftypefunx {bool} var_is_plausible_name (const char *@var{name}, bool @var{issue_error})
+Tests @var{name} for validity or ``plausibility.''  Returns true if
+the name is acceptable, false otherwise.  If the name is not
+acceptable and @var{issue_error} is true, also issues an error message
+explaining the violation.
+
+A valid name is one that fully satisfies all of the requirements for
+variable names (@pxref{Tokens,,,pspp, PSPP Users Guide}).  A
+``plausible'' name is simply a string whose length is in the valid
+range and that is not a reserved word.  PSPP accepts plausible but
+invalid names as variable names in some contexts where the character
+encoding scheme is ambiguous, as when reading variable names from
+system files.
+@end deftypefun
+
+@deftypefun {enum dict_class} var_get_dict_class (const struct variable *@var{var})
+Returns the dictionary class of @var{var}'s name (@pxref{Dictionary
+Class}).
+@end deftypefun
+
+@node Variable Type and Width
+@subsection Variable Type and Width
+
+A variable's type and width are the type and width of its values
+(@pxref{Values}).
+
+@deftypefun {enum val_type} var_get_type (const struct variable *@var{var})
+Returns the type of variable @var{var}.
+@end deftypefun
+
+@deftypefun int var_get_width (const struct variable *@var{var})
+Returns the width of variable @var{var}.
+@end deftypefun
+
+@deftypefun void var_set_width (struct variable *@var{var}, int @var{width})
+Sets the width of variable @var{var} to @var{width}.  The width of a
+variable should not normally be changed after the variable is created,
+so this function is rarely used.  This function cannot be applied to a
+variable that is part of a dictionary.
+@end deftypefun
+
+@deftypefun bool var_is_numeric (const struct variable *@var{var})
+Returns true if @var{var} is a numeric variable, false otherwise.
+@end deftypefun
+
+@deftypefun bool var_is_alpha (const struct variable *@var{var})
+Returns true if @var{var} is an alphanumeric (string) variable, false
+otherwise.
+@end deftypefun
+
+@deftypefun bool var_is_short_string (const struct variable *@var{var})
+Returns true if @var{var} is a string variable of width
+@code{MAX_SHORT_STRING} or less, false otherwise.
+@end deftypefun
+
+@deftypefun bool var_is_long_string (const struct variable *var{var})
+Returns true if @var{var} is a string variable of width greater than
+@code{MAX_SHORT_STRING}, false otherwise.
+@end deftypefun
+
+@deftypefun size_t var_get_value_cnt (const struct variable *@var{var})
+Returns the number of @union{value}s needed to hold an instance of
+variable @var{var}.  @code{var_get_value_cnt (var)} is equivalent to
+@code{value_cnt_from_width (var_get_width (var))}.
+@end deftypefun
+
+@node Variable Missing Values
+@subsection Variable Missing Values
+
+A numeric or short string variable may have a set of user-missing
+values (@pxref{MISSING VALUES,,,pspp, PSPP Users Guide}), represented
+as a @struct{missing_values} (@pxref{User-Missing Values}).
+
+The most frequent operation on a variable's missing values is to query
+whether a value is user- or system-missing:
+
+@deftypefun bool var_is_value_missing (const struct variable *@var{var}, const union value *@var{value}, enum mv_class @var{class})
+@deftypefunx bool var_is_num_missing (const struct variable *@var{var}, double @var{value}, enum mv_class @var{class})
+@deftypefunx bool var_is_str_missing (const struct variable *@var{var}, const char @var{value}[], enum mv_class @var{class})
+Tests whether @var{value} is a missing value of the given @var{class}
+for variable @var{var} and returns true if so, false otherwise.
+@func{var_is_num_missing} may only be applied to numeric variables;
+@func{var_is_str_missing} may only be applied to string variables.
+For string variables, @var{value} must contain exactly as many
+characters as @var{var}'s width.
+
+@code{var_is_@var{type}_missing (@var{var}, @var{value}, @var{class})}
+is equivalent to @code{mv_is_@var{type}_missing
+(var_get_missing_values (@var{var}), @var{value}, @var{class})}.
+@end deftypefun
+
+In addition, a few functions are provided to work more directly with a
+variable's @struct{missing_values}:
+
+@deftypefun {const struct missing_values *} var_get_missing_values (const struct variable *@var{var})
+Returns the @struct{missing_values} associated with @var{var}.  The
+caller must not modify the returned structure.  The return value is
+always non-null.
+@end deftypefun
+
+@anchor{var_set_missing_values}
+@deftypefun {void} var_set_missing_values (struct variable *@var{var}, const struct missing_values *@var{miss})
+Changes @var{var}'s missing values to a copy of @var{miss}, or if
+@var{miss} is a null pointer, clears @var{var}'s missing values.  If
+@var{miss} is non-null, it must have the same width as @var{var} or be
+resizable to @var{var}'s width (@pxref{mv_resize}).  The caller
+retains ownership of @var{miss}.
+@end deftypefun
+
+b@deftypefun void var_clear_missing_values (struct variable *@var{var})
+Clears @var{var}'s missing values.  Equivalent to
+@code{var_set_missing_values (@var{var}, NULL)}.
+@end deftypefun
+
+@deftypefun bool var_has_missing_values (const struct variable *@var{var})
+Returns true if @var{var} has any missing values, false if it has
+none.  Equivalent to @code{mv_is_empty (var_get_missing_values (@var{var}))}.
+@end deftypefun
+
+@node Variable Value Labels
+@subsection Variable Value Labels
+
+A numeric or short string variable may have a set of value labels
+(@pxref{VALUE LABELS,,,pspp, PSPP Users Guide}), represented as a
+@struct{val_labs} (@pxref{Value Labels}).  The most commonly useful
+functions for value labels return the value label associated with a
+value:
+
+@deftypefun {const char *} var_lookup_value_label (const struct variable *@var{var}, const union value *@var{value})
+Looks for a label for @var{value} in @var{var}'s set of value labels.
+Returns the label if one exists, otherwise a null pointer.
+@end deftypefun
+
+@deftypefun {const char *} var_get_value_name (const struct variable *@var{var}, const union value *@var{value})
+Looks for a label for @var{value} in @var{var}'s set of value labels.
+Returns the label if one exists.  If none exists, formats @var{label}
+using @var{var}'s print format (@pxref{Input and Output Formats}) in a
+static buffer and returns the buffer.
+
+@quotation Important
+This function's use of a static buffer means that it must be used with
+care.
+@end quotation
+@end deftypefun
+
+The underlying @struct{val_labs} structure may also be accessed
+directly using the functions described below.
+
+@deftypefun bool var_has_value_labels (const struct variable *@var{var})
+Returns true if @var{var} has at least one value label, false
+otherwise.
+@end deftypefun
+
+@deftypefun {const struct val_labs *} var_get_value_labels (const struct variable *@var{var})
+Returns the @struct{val_labs} associated with @var{var}.  If @var{var}
+has no value labels, then the return value may or may not be a null
+pointer.
+
+The variable retains ownership of the returned @struct{val_labs},
+which the caller must not attempt to modify.
+@end deftypefun
+
+@deftypefun void var_set_value_labels (struct variable *@var{var}, const struct val_labs *@var{val_labs})
+Replaces @var{var}'s value labels by a copy of @var{val_labs}.  The
+caller retains ownership of @var{val_labs}.  If @var{val_labs} is a
+null pointer, then @var{var}'s value labels, if any, are deleted.
+@end deftypefun
+
+@deftypefun void var_clear_value_labels (struct variable *@var{var})
+Deletes @var{var}'s value labels.  Equivalent to
+@code{var_set_value_labels (@var{var}, NULL)}.
+@end deftypefun
+
+A final group of functions offers shorthands for operations that would
+otherwise require getting the value labels from a variable, copying
+them, modifying them, and then setting the modified value labels into
+the variable (making a second copy):
+
+@deftypefun bool var_add_value_label (struct variable *@var{var}, const union value *@var{value}, const char *@var{label})
+Attempts to add a copy of @var{label} as a label for @var{value} for
+the given @var{var}.  If @var{value} already has a label, then the old
+label is retained.  Returns true if a label is added, false if there
+was an existing label for @var{value} or if @var{var} is a long string
+variable.  Either way, the caller retains ownership of @var{value} and
+@var{label}.
+@end deftypefun
+
+@deftypefun void var_replace_value_label (struct variable *@var{var}, const union value *@var{value}, const char *@var{label})
+Attempts to add a copy of @var{label} as a label for @var{value} for
+the given @var{var}.  If @var{value} already has a label, then
+@var{label} replaces the old label.  Either way, the caller retains
+ownership of @var{value} and @var{label}.
+
+If @var{var} is a long string variable, this function has no effect.
+@end deftypefun
+
+@node Variable Print and Write Formats
+@subsection Variable Print and Write Formats
+
+Each variable has an associated pair of output formats, called its
+@dfn{print format} and @dfn{write format}.  @xref{Input and Output
+Formats,,,pspp, PSPP Users Guide}, for an introduction to formats.
+@xref{Input and Output Formats}, for a developer's description of
+format representation.
+
+The print format is used to convert a variable's data values to
+strings for human-readable output.  The write format is used similarly
+for machine-readable output, primarily by the WRITE transformation
+(@pxref{WRITE,,,pspp, PSPP Users Guide}).  Most often a variable's
+print and write formats are the same.
+
+A newly created variable by default has format F8.2 if it is numeric
+or an A format with the same width as the variable if it is string.
+Many creators of variables override these defaults.
+
+Both the print format and write format are output formats.  Input
+formats are not part of @struct{variable}.  Instead, input programs
+and transformations keep track of variable input formats themselves.
+
+The following functions work with variable print and write formats.
+
+@deftypefun {const struct fmt_spec *} var_get_print_format (const struct variable *@var{var})
+@deftypefunx {const struct fmt_spec *} var_get_write_format (const struct variable *@var{var})
+Returns @var{var}'s print or write format, respectively.
+@end deftypefun
+
+@deftypefun void var_set_print_format (struct variable *@var{var}, const struct fmt_spec *@var{format})
+@deftypefunx void var_set_write_format (struct variable *@var{var}, const struct fmt_spec *@var{format})
+@deftypefunx void var_set_both_formats (struct variable *@var{var}, const struct fmt_spec *@var{format})
+Sets @var{var}'s print format, write format, or both formats,
+respectively, to a copy of @var{format}.
+@end deftypefun
+
+@node Variable Labels
+@subsection Variable Labels
+
+A variable label is a string that describes a variable.  Variable
+labels may contain spaces and punctuation not allowed in variable
+names.  @xref{VARIABLE LABELS,,,pspp, PSPP Users Guide}, for a
+user-level description of variable labels.
+
+The most commonly useful functions for variable labels are those to
+retrieve a variable's label:
+
+@deftypefun {const char *} var_to_string (const struct variable *@var{var})
+Returns @var{var}'s variable label, if it has one, otherwise
+@var{var}'s name.  In either case the caller must not attempt to
+modify or free the returned string.
+
+This function is useful for user output.
+@end deftypefun
+
+@deftypefun {const char *} var_get_label (const struct variable *@var{var})
+Returns @var{var}'s variable label, if it has one, or a null pointer
+otherwise.
+@end deftypefun
+
+A few other variable label functions are also provided:
+
+@deftypefun void var_set_label (struct variable *@var{var}, const char *@var{label})
+Sets @var{var}'s variable label to a copy of @var{label}, or removes
+any label from @var{var} if @var{label} is a null pointer or contains
+only spaces.  Leading and trailing spaces are removed from the
+variable label and its remaining content is truncated at 255 bytes.
+@end deftypefun
+
+@deftypefun void var_clear_label (struct variable *@var{var})
+Removes any variable label from @var{var}.
+@end deftypefun
+
+@deftypefun bool var_has_label (const struct variable *@var{var})
+Returns true if @var{var} has a variable label, false otherwise.
+@end deftypefun
+
+@node Variable GUI Attributes
+@subsection GUI Attributes
+
+These functions and types access and set attributes that are mainly
+used by graphical user interfaces.  Their values are also stored in
+and retrieved from system files (but not portable files).
+
+The first group of functions relate to the measurement level of
+numeric data.  New variables are assigned a nominal level of
+measurement by default.
+
+@deftp {Enumeration} {enum measure}
+Measurement level.  Available values are:
+
+@table @code
+@item MEASURE_NOMINAL
+Numeric data values are arbitrary.  Arithmetic operations and
+numerical comparisons of such data are not meaningful.
+
+@item MEASURE_ORDINAL
+Numeric data values indicate progression along a rank order.
+Arbitrary arithmetic operations such as addition are not meaningful on
+such data, but inequality comparisons (less, greater, etc.) have
+straightforward interpretations.
+
+@item MEASURE_SCALE
+Ratios, sums, etc. of numeric data values have meaningful
+interpretations.
+@end table
+
+PSPP does not have a separate category for interval data, which would
+naturally fall between the ordinal and scale measurement levels.
+@end deftp
+
+@deftypefun bool measure_is_valid (enum measure @var{measure})
+Returns true if @var{measure} is a valid level of measurement, that
+is, if it is one of the @code{enum measure} constants listed above,
+and false otherwise.
+@end deftypefun
+
+@deftypefun enum measure var_get_measure (const struct variable *@var{var})
+@deftypefunx void var_set_measure (struct variable *@var{var}, enum measure @var{measure})
+Gets or sets @var{var}'s measurement level.
+@end deftypefun
+
+The following set of functions relates to the width of on-screen
+columns used for displaying variable data in a graphical user
+interface environment.  The unit of measurement is the width of a
+character.  For proportionally spaced fonts, this is based on the
+average width of a character.
+
+@deftypefun int var_get_display_width (const struct variable *@var{var})
+@deftypefunx void var_set_display_width (struct variable *@var{var}, int @var{display_width})
+Gets or sets @var{var}'s display width.
+@end deftypefun
+
+@anchor{var_default_display_width}
+@deftypefun int var_default_display_width (int @var{width})
+Returns the default display width for a variable with the given
+@var{width}.  The default width of a numeric variable is 8.  The
+default width of a string variable is @var{width} or 32, whichever is
+less.
+@end deftypefun
+
+The final group of functions work with the justification of data when
+it is displayed in on-screen columns.  New variables are by default
+right-justified.
+
+@deftp {Enumeration} {enum alignment}
+Text justification.  Possible values are @code{ALIGN_LEFT},
+@code{ALIGN_RIGHT}, and @code{ALIGN_CENTRE}.
+@end deftp
+
+@deftypefun bool alignment_is_valid (enum alignment @var{alignment})
+Returns true if @var{alignment} is a valid alignment, that is, if it
+is one of the @code{enum alignment} constants listed above, and false
+otherwise.
+@end deftypefun
+
+@deftypefun enum alignment var_get_alignment (const struct variable *@var{var})
+@deftypefunx void var_set_alignment (struct variable *@var{var}, enum alignment @var{alignment})
+Gets or sets @var{var}'s alignment.
+@end deftypefun
+
+@node Variable Leave Status
+@subsection Variable Leave Status
+
+Commonly, most or all data in a case come from an input file, read
+with a command such as DATA LIST or GET, but data can also be
+generated with transformations such as COMPUTE.  In the latter case
+the question of a datum's ``initial value'' can arise.  For example,
+the value of a piece of generated data can recursively depend on its
+own value:
+@example
+COMPUTE X = X + 1.
+@end example
+Another situation where the initial value of a variable arises is when
+its value is not set at all for some cases, e.g.@: below, @code{Y} is
+set only for the first 10 cases:
+@example
+DO IF #CASENUM <= 10.
++ COMPUTE Y = 1.
+END IF.
+@end example
+
+By default, the initial value of a datum in either of these situations
+is the system-missing value for numeric values and spaces for string
+values.  This means that, above, X would be system-missing and that Y
+would be 1 for the first 10 cases and system-missing for the
+remainder.
+
+PSPP also supports retaining the value of a variable from one case to
+another, using the LEAVE command (@pxref{LEAVE,,,pspp, PSPP Users
+Guide}).  The initial value of such a variable is 0 if it is numeric
+and spaces if it is a string.  If the command @samp{LEAVE X Y} is
+appended to the above example, then X would have value 1 in the first
+case and increase by 1 in every succeeding case, and Y would have
+value 1 for the first 10 cases and 0 for later cases.
+
+The LEAVE command has no effect on data that comes from an input file
+or whose values do not depend on a variable's initial value.
+
+The value of scratch variables (@pxref{Scratch Variables,,,pspp, PSPP
+Users Guide}) are always left from one case to another.
+
+The following functions work with a variable's leave status.
+
+@deftypefun bool var_get_leave (const struct variable *@var{var})
+Returns true if @var{var}'s value is to be retained from case to case,
+false if it is reinitialized to system-missing or spaces.
+@end deftypefun
+
+@deftypefun void var_set_leave (struct variable *@var{var}, bool @var{leave})
+If @var{leave} is true, marks @var{var} to be left from case to case;
+if @var{leave} is false, marks @var{var} to be reinitialized for each
+case.
+
+If @var{var} is a scratch variable, @var{leave} must be true.
+@end deftypefun
+
+@deftypefun bool var_must_leave (const struct variable *@var{var})
+Returns true if @var{var} must be left from case to case, that is, if
+@var{var} is a scratch variable.
+@end deftypefun
+
+@node Dictionary Class
+@subsection Dictionary Class
+
+Occasionally it is useful to classify variables into @dfn{dictionary
+classes} based on their names.  Dictionary classes are represented by
+@enum{dict_class}.  This type and other declarations for dictionary
+classes are in the @file{<data/dict-class.h>} header.
+
+@deftp {Enumeration} {enum dict_class}
+The dictionary classes are:
+
+@table @code
+@item DC_ORDINARY
+An ordinary variable, one whose name does not begin with @samp{$} or
+@samp{#}.
+
+@item DC_SYSTEM
+A system variable, one whose name begins with @samp{$}.  @xref{System
+Variables,,,pspp, PSPP Users Guide}.
+
+@item DC_SCRATCH
+A scratch variable, one whose name begins with @samp{#}.
+@xref{Scratch Variables,,,pspp, PSPP Users Guide}.
+@end table
+
+The values for dictionary classes are bitwise disjoint, which allows
+them to be used in bit-masks.  An extra enumeration constant
+@code{DC_ALL}, whose value is the bitwise-@i{or} of all of the above
+constants, is provided to aid in this purpose.
+@end deftp
+
+One example use of dictionary classes arises in connection with PSPP
+syntax that uses @code{@var{a} TO @var{b}} to name the variables in a
+dictionary from @var{a} to @var{b} (@pxref{Sets of Variables,,,pspp,
+PSPP Users Guide}).  This syntax requires @var{a} and @var{b} to be in
+the same dictionary class.  It limits the variables that it includes
+to those in that dictionary class.
+
+The following functions relate to dictionary classes.
+
+@deftypefun {enum dict_class} dict_class_from_id (const char *@var{name})
+Returns the ``dictionary class'' for the given variable @var{name}, by
+looking at its first letter.
+@end deftypefun
+
+@deftypefun {const char *} dict_class_to_name (enum dict_class @var{dict_class})
+Returns a name for the given @var{dict_class} as an adjective, e.g.@:
+@code{"scratch"}.
+
+This function should probably not be used in new code as it can lead
+to difficulties for internationalization.
+@end deftypefun
+
+@node Variable Creation and Destruction
+@subsection Variable Creation and Destruction
+
+Only rarely should PSPP code create or destroy variables directly.
+Ordinarily, variables are created within a dictionary and destroying
+by individual deletion from the dictionary or by destroying the entire
+dictionary at once.  The functions here enable the exceptional case,
+of creation and destruction of variables that are not associated with
+any dictionary.  These functions are used internally in the dictionary
+implementation.
+
+@anchor{var_create}
+@deftypefun {struct variable *} var_create (const char *@var{name}, int @var{width})
+Creates and returns a new variable with the given @var{name} and
+@var{width}.  The new variable is not part of any dictionary.  Use
+@func{dict_create_var}, instead, to create a variable in a dictionary
+(@pxref{Dictionary Creating Variables}).
+
+@var{name} should be a valid variable name and must be a ``plausible''
+variable name (@pxref{Variable Name}).  @var{width} must be between 0
+and @code{MAX_STRING}, inclusive (@pxref{Values}).
+
+The new variable has no user-missing values, value labels, or variable
+label.  Numeric variables initially have F8.2 print and write formats,
+right-justified display alignment, and scale level of measurement.
+String variables are created with A print and write formats,
+left-justified display alignment, and nominal level of measurement.
+The initial display width is determined by
+@func{var_default_display_width} (@pxref{var_default_display_width}).
+
+The new variable initially has no short name (@pxref{Variable Short
+Names}) and no auxiliary data (@pxref{Variable Auxiliary Data}).
+@end deftypefun
+
+@anchor{var_clone}
+@deftypefun {struct variable *} var_clone (const struct variable *@var{old_var})
+Creates and returns a new variable with the same attributes as
+@var{old_var}, with a few exceptions.  First, the new variable is not
+part of any dictionary, regardless of whether @var{old_var} was in a
+dictionary.  Use @func{dict_clone_var}, instead, to add a clone of a
+variable to a dictionary.
+
+Second, the new variable is not given any short name, even if
+@var{old_var} had a short name.  This is because the new variable is
+likely to be immediately renamed, in which case the short name would
+be incorrect (@pxref{Variable Short Names}).
+
+Finally, @var{old_var}'s auxiliary data, if any, is not copied to the
+new variable (@pxref{Variable Auxiliary Data}).
+@end deftypefun
+
+@deftypefun {void} var_destroy (struct variable *@var{var})
+Destroys @var{var} and frees all associated storage, including its
+auxiliary data, if any.  @var{var} must not be part of a dictionary.
+To delete a variable from a dictionary and destroy it, use
+@func{dict_delete_var} (@pxref{Dictionary Deleting Variables}).
+@end deftypefun
+
+@node Variable Short Names
+@subsection Variable Short Names
+
+PSPP variable names may be up to 64 (@code{VAR_NAME_LEN}) bytes long.
+The system and portable file formats, however, were designed when
+variable names were limited to 8 bytes in length.  Since then, the
+system file format has been augmented with an extension record that
+explains how the 8-byte short names map to full-length names
+(@pxref{Long Variable Names Record}), but the short names are still
+present.  Thus, the continued presence of the short names is more or
+less invisible to PSPP users, but every variable in a system file
+still has a short name that must be unique.
+
+PSPP can generate unique short names for variables based on their full
+names at the time it creates the data file.  If all variables' full
+names are unique in their first 8 bytes, then the short names are
+simply prefixes of the full names; otherwise, PSPP changes them so
+that they are unique.
+
+By itself this algorithm interoperates well with other software that
+can read system files, as long as that software understands the
+extension record that maps short names to long names.  When the other
+software does not understand the extension record, it can produce
+surprising results.  Consider a situation where PSPP reads a system
+file that contains two variables named RANKINGSCORE, then the user
+adds a new variable named RANKINGSTATUS, then saves the modified data
+as a new system file.  A program that does not understand long names
+would then see one of these variables under the name RANKINGS---either
+one, depending on the algorithm's details---and the other under a
+different name.  The effect could be very confusing: by adding a new
+and apparently unrelated variable in PSPP, the user effectively
+renamed the existing variable.
+
+To counteract this potential problem, every @struct{variable} may have
+a short name.  A variable created by the system or portable file
+reader receives the short name from that data file.  When a variable
+with a short name is written to a system or portable file, that
+variable receives priority over other long names whose names begin
+with the same 8 bytes but which were not read from a data file under
+that short name.
+
+Variables not created by the system or portable file reader have no
+short name by default.
+
+A variable with a full name of 8 bytes or less in length has absolute
+priority for that name when the variable is written to a system file,
+even over a second variable with that assigned short name.
+
+PSPP does not enforce uniqueness of short names, although the short
+names read from any given data file will always be unique.  If two
+variables with the same short name are written to a single data file,
+neither one receives priority.
+
+The following macros and functions relate to short names.
+
+@defmac SHORT_NAME_LEN
+Maximum length of a short name, in bytes.  Its value is 8.
+@end defmac
+
+@deftypefun {const char *} var_get_short_name (const struct variable *@var{var})
+Returns @var{var}'s short name, or a null pointer if @var{var} has not
+been assigned a short name.
+@end deftypefun
+
+@deftypefun void var_set_short_name (struct variable *@var{var}, const char *@var{short_name})
+Sets @var{var}'s short name to @var{short_name}, or removes
+@var{var}'s short name if @var{short_name} is a null pointer.  If it
+is non-null, then @var{short_name} must be a plausible name for a
+variable (@pxref{var_is_plausible_name}).  The name will be truncated
+to 8 bytes in length and converted to all-uppercase.
+@end deftypefun
+
+@deftypefun void var_clear_short_name (struct variable *@var{var})
+Removes @var{var}'s short name.
+@end deftypefun
+
+@node Variable Relationships
+@subsection Variable Relationships
+
+Variables have close relationships with dictionaries
+(@pxref{Dictionaries}) and cases (@pxref{Cases}).  A variable is
+usually a member of some dictionary, and a case is often used to store
+data for the set of variables in a dictionary.
+
+These functions report on these relationships.  They may be applied
+only to variables that are in a dictionary.
+
+@deftypefun size_t var_get_dict_index (const struct variable *@var{var})
+Returns @var{var}'s index within its dictionary.  The first variable
+in a dictionary has index 0, the next variable index 1, and so on.
+
+The dictionary index can be influenced using dictionary functions such
+as dict_reorder_var (@pxref{dict_reorder_var}).
+@end deftypefun
+
+@deftypefun size_t var_get_case_index (const struct variable *@var{var})
+Returns @var{var}'s index within a case.  The case index is an index
+into an array of @union{value} large enough to contain all the data in
+the dictionary.
+
+The returned case index can be used to access the value of @var{var}
+within a case for its dictionary, as in e.g.@: @code{case_data_idx
+(case, var_get_case_index (@var{var}))}, but ordinarily it is more
+convenient to use the data access functions that do variable-to-index
+translation internally, as in e.g.@: @code{case_data (case,
+@var{var})}.
+@end deftypefun
+
+@node Variable Auxiliary Data
+@subsection Variable Auxiliary Data
+
+Each @struct{variable} can have a single pointer to auxiliary data of
+type @code{void *}.  These functions manipulate a variable's auxiliary
+data.
+
+Use of auxiliary data is discouraged because of its lack of
+flexibility.  Only one client can make use of auxiliary data on a
+given variable at any time, even though many clients could usefully
+associate data with a variable.
+
+To prevent multiple clients from attempting to use a variable's single
+auxiliary data field at the same time, we adopt the convention that
+use of auxiliary data in the active file dictionary is restricted to
+the currently executing command.  In particular, transformations must
+not attach auxiliary data to a variable in the active file in the
+expectation that it can be used later when the active file is read and
+the transformation is executed.  To help enforce this restriction,
+auxiliary data is deleted from all variables in the active file
+dictionary after the execution of each PSPP command.
+
+This convention for safe use of auxiliary data applies only to the
+active file dictionary.  Rules for other dictionaries may be
+established separately.
+
+Auxiliary data should be replaced by a more flexible mechanism at some
+point, but no replacement mechanism has been designed or implemented
+so far.
+
+The following functions work with variable auxiliary data.
+
+@deftypefun {void *} var_get_aux (const struct variable *@var{var})
+Returns @var{var}'s auxiliary data, or a null pointer if none has been
+assigned.
+@end deftypefun
+
+@deftypefun {void *} var_attach_aux (const struct variable *@var{var}, void *@var{aux}, void (*@var{aux_dtor}) (struct variable *))
+Sets @var{var}'s auxiliary data to @var{aux}, which must not be null.
+@var{var} must not already have auxiliary data.
+
+Before @var{var}'s auxiliary data is cleared by @code{var_clear_aux},
+@var{aux_dtor}, if non-null, will be called with @var{var} as its
+argument.  It should free any storage associated with @var{aux}, if
+necessary.  @code{var_dtor_free} may be appropriate for use as
+@var{aux_dtor}:
+
+@deffn {Function} void var_dtor_free (struct variable *@var{var})
+Frees @var{var}'s auxiliary data by calling @code{free}.
+@end deffn
+@end deftypefun
+
+@deftypefun void var_clear_aux (struct variable *@var{var})
+Removes auxiliary data, if any, from @var{var}, first calling the
+destructor passed to @code{var_attach_aux}, if one was provided.
+
+Use @code{dict_clear_aux} to remove auxiliary data from every variable
+in a dictionary. @c (@pxref{dict_clear_aux}).
+@end deftypefun
+
+@deftypefun {void *} var_detach_aux (struct variable *@var{var})
+Removes auxiliary data, if any, from @var{var}, and returns it.
+Returns a null pointer if @var{var} had no auxiliary data.
+
+Any destructor passed to @code{var_attach_aux} is not called, so the
+caller is responsible for freeing storage associated with the returned
+auxiliary data.
+@end deftypefun
+
+@node Variable Categorical Values
+@subsection Variable Categorical Values
+
+Some statistical procedures require a list of all the values that a
+categorical variable takes on.  Arranging such a list requires making
+a pass through the data, so PSPP caches categorical values in
+@struct{variable}.
+
+When variable auxiliary data is revamped to support multiple clients
+as described in the previous section, categorical values are an
+obvious candidate.  The form in which they are currently supported is
+inelegant.
+
+Categorical values are not robust against changes in the data.  That
+is, there is currently no way to detect that a transformation has
+changed data values, meaning that categorical values lists for the
+changed variables must be recomputed.  PSPP is in fact in need of a
+general-purpose caching and cache-invalidation mechanism, but none
+has yet been designed and built.
+
+The following functions work with cached categorical values.
+
+@deftypefun {struct cat_vals *} var_get_obs_vals (const struct variable *@var{var})
+Returns @var{var}'s set of categorical values.  Yields undefined
+behavior if @var{var} does not have any categorical values.
+@end deftypefun
+
+@deftypefun void var_set_obs_vals (const struct variable *@var{var}, struct cat_vals *@var{cat_vals})
+Destroys @var{var}'s categorical values, if any, and replaces them by
+@var{cat_vals}, ownership of which is transferred to @var{var}.  If
+@var{cat_vals} is a null pointer, then @var{var}'s categorical values
+are cleared.
+@end deftypefun
+
+@deftypefun bool var_has_obs_vals (const struct variable *@var{var})
+Returns true if @var{var} has a set of categorical values, false
+otherwise.
+@end deftypefun
+
+@node Dictionaries
+@section Dictionaries
+
+Each data file in memory or on disk has an associated dictionary,
+whose primary purpose is to describe the data in the file.
+@xref{Variables,,,pspp, PSPP Users Guide}, for a PSPP user's view of a
+dictionary.
+
+A data file stored in a PSPP format, either as a system or portable
+file, has a representation of its dictionary embedded in it.  Other
+kinds of data files are usually not self-describing enough to
+construct a dictionary unassisted, so the dictionaries for these files
+must be specified explicitly with PSPP commands such as @cmd{DATA
+LIST}.
+
+The most important content of a dictionary is an array of variables,
+which must have unique names.  A dictionary also conceptually contains
+a mapping from each of its variables to a location within a case
+(@pxref{Cases}), although in fact these mappings are stored within
+individual variables.
+
+System variables are not members of any dictionary (@pxref{System
+Variables,,,pspp, PSPP Users Guide}).
+
+Dictionaries are represented by @struct{dictionary}.  Declarations
+related to dictionaries are in the @file{<data/dictionary.h>} header.
+
+The following sections describe functions for use with dictionaries.
+
+@menu
+* Dictionary Variable Access::
+* Dictionary Creating Variables::
+* Dictionary Deleting Variables::
+* Dictionary Reordering Variables::
+* Dictionary Renaming Variables::
+* Dictionary Weight Variable::
+* Dictionary Filter Variable::
+* Dictionary Case Limit::
+* Dictionary Split Variables::
+* Dictionary File Label::
+* Dictionary Documents::
+@end menu
+
+@node Dictionary Variable Access
+@subsection Accessing Variables
+
+The most common operations on a dictionary simply retrieve a
+@code{struct variable *} of an individual variable based on its name
+or position.
+
+@deftypefun {struct variable *} dict_lookup_var (const struct dictionary *@var{dict}, const char *@var{name})
+@deftypefunx {struct variable *} dict_lookup_var_assert (const struct dictionary *@var{dict}, const char *@var{name})
+Looks up and returns the variable with the given @var{name} within
+@var{dict}.  Name lookup is not case-sensitive.
+
+@code{dict_lookup_var} returns a null pointer if @var{dict} does not
+contain a variable named @var{name}.  @code{dict_lookup_var_assert}
+asserts that such a variable exists.
+@end deftypefun
+
+@deftypefun {struct variable *} dict_get_var (const struct dictionary *@var{dict}, size_t @var{position})
+Returns the variable at the given @var{position} in @var{dict}.
+@var{position} must be less than the number of variables in @var{dict}
+(see below).
+@end deftypefun
+
+@deftypefun size_t dict_get_var_cnt (const struct dictionary *@var{dict})
+Returns the number of variables in @var{dict}.
+@end deftypefun
+
+Another pair of functions allows retrieving a number of variables at
+once.  These functions are more rarely useful.
+
+@deftypefun void dict_get_vars (const struct dictionary *@var{dict}, const struct variable ***@var{vars}, size_t *@var{cnt}, enum dict_class @var{exclude})
+@deftypefunx void dict_get_vars_mutable (const struct dictionary *@var{dict}, struct variable ***@var{vars}, size_t *@var{cnt}, enum dict_class @var{exclude})
+Retrieves all of the variables in @var{dict}, in their original order,
+except that any variables in the dictionary classes specified
+@var{exclude}, if any, are excluded (@pxref{Dictionary Class}).
+Pointers to the variables are stored in an array allocated with
+@code{malloc}, and a pointer to the first element of this array is
+stored in @code{*@var{vars}}.  The caller is responsible for freeing
+this memory when it is no longer needed.  The number of variables
+retrieved is stored in @code{*@var{cnt}}.
+
+The presence or absence of @code{DC_SYSTEM} in @var{exclude} has no
+effect, because dictionaries never include system variables.
+@end deftypefun
+
+One additional function is available.  This function is most often
+used in assertions, but it is not restricted to such use.
+
+@deftypefun bool dict_contains_var (const struct dictionary *@var{dict}, const struct variable *@var{var})
+Tests whether @var{var} is one of the variables in @var{dict}.
+Returns true if so, false otherwise.
+@end deftypefun
+
+@node Dictionary Creating Variables
+@subsection Creating Variables
+
+These functions create a new variable and insert it into a dictionary
+in a single step.
+
+There is no provision for inserting an already created variable into a
+dictionary.  There is no reason that such a function could not be
+written, but so far there has been no need for one.
+
+The names provided to one of these functions should be valid variable
+names and must be plausible variable names. @c (@pxref{Variable Names}).
+
+If a variable with the same name already exists in the dictionary, the
+non-@code{assert} variants of these functions return a null pointer,
+without modifying the dictionary.  The @code{assert} variants, on the
+other hand, assert that no duplicate name exists.
+
+A variable may be in only one dictionary at any given time.
+
+@deftypefun {struct variable *} dict_create_var (struct dictionary *@var{dict}, const char *@var{name}, int @var{width})
+@deftypefunx {struct variable *} dict_create_var_assert (struct dictionary *@var{dict}, const char *@var{name}, int @var{width})
+Creates a new variable with the given @var{name} and @var{width}, as
+if through a call to @code{var_create} with those arguments
+(@pxref{var_create}), appends the new variable to @var{dict}'s array
+of variables, and returns the new variable.
+@end deftypefun
+
+@deftypefun {struct variable *} dict_clone_var (struct dictionary *@var{dict}, const struct variable *@var{old_var}, const char *@var{name})
+@deftypefunx {struct variable *} dict_clone_var_assert (struct dictionary *@var{dict}, const struct variable *@var{old_var}, const char *@var{name})
+Creates a new variable as a clone of @var{var}, inserts the new
+variable into @var{dict}, and returns the new variable.  The new
+variable is named @var{name}.  Other properties of the new variable
+are copied from @var{old_var}, except for those not copied by
+@code{var_clone} (@pxref{var_clone}).
+
+@var{var} does not need to be a member of any dictionary.
+@end deftypefun
+
+@node Dictionary Deleting Variables
+@subsection Deleting Variables
+
+These functions remove variables from a dictionary's array of
+variables.  They also destroy the removed variables and free their
+associated storage.
+
+Deleting a variable to which there might be external pointers is a bad
+idea.  In particular, deleting variables from the active file
+dictionary is a risky proposition, because transformations can retain
+references to arbitrary variables.  Therefore, no variable should be
+deleted from the active file dictionary when any transformations are
+active, because those transformations might reference the variable to
+be deleted.  The safest time to delete a variable is just after a
+procedure has been executed, as done by @cmd{DELETE VARIABLES}.
+
+Deleting a variable automatically removes references to that variable
+from elsewhere in the dictionary as a weighting variable, filter
+variable, @cmd{SPLIT FILE} variable, or member of a vector.
+
+No functions are provided for removing a variable from a dictionary
+without destroying that variable.  As with insertion of an existing
+variable, there is no reason that this could not be implemented, but
+so far there has been no need.
+
+@deftypefun void dict_delete_var (struct dictionary *@var{dict}, struct variable *@var{var})
+Deletes @var{var} from @var{dict}, of which it must be a member.
+@end deftypefun
+
+@deftypefun void dict_delete_vars (struct dictionary *@var{dict}, struct variable *const *@var{vars}, size_t @var{count})
+Deletes the @var{count} variables in array @var{vars} from @var{dict}.
+All of the variables in @var{vars} must be members of @var{dict}.  No
+variable may be included in @var{vars} more than once.
+@end deftypefun
+
+@deftypefun void dict_delete_consecutive_vars (struct dictionary *@var{dict}, size_t @var{idx}, size_t @var{count})
+Deletes the variables in sequential positions
+@var{idx}@dots{}@var{idx} + @var{count} (exclusive) from @var{dict},
+which must contain at least @var{idx} + @var{count} variables.
+@end deftypefun
+
+@deftypefun void dict_delete_scratch_vars (struct dictionary *@var{dict})
+Deletes all scratch variables from @var{dict}.
+@end deftypefun
+
+@node Dictionary Reordering Variables
+@subsection Changing Variable Order
+
+The variables in a dictionary are stored in an array.  These functions
+change the order of a dictionary's array of variables without changing
+which variables are in the dictionary.
+
+@anchor{dict_reorder_var}
+@deftypefun void dict_reorder_var (struct dictionary *@var{dict}, struct variable *@var{var}, size_t @var{new_index})
+Moves @var{var}, which must be in @var{dict}, so that it is at
+position @var{new_index} in @var{dict}'s array of variables.  Other
+variables in @var{dict}, if any, retain their relative positions.
+@var{new_index} must be less than the number of variables in
+@var{dict}.
+@end deftypefun
+
+@deftypefun void dict_reorder_vars (struct dictionary *@var{dict}, struct variable *const *@var{new_order}, size_t @var{count})
+Moves the @var{count} variables in @var{new_order} to the beginning of
+@var{dict}'s array of variables in the specified order.  Other
+variables in @var{dict}, if any, retain their relative positions.
+
+All of the variables in @var{new_order} must be in @var{dict}.  No
+duplicates are allowed within @var{new_order}, which means that
+@var{count} must be no greater than the number of variables in
+@var{dict}.
+@end deftypefun
+
+@node Dictionary Renaming Variables
+@subsection Renaming Variables
+
+These functions change the names of variables within a dictionary.
+The @func{var_set_name} function (@pxref{var_set_name}) cannot be
+applied directly to a variable that is in a dictionary, because
+@struct{dictionary} contains an index by name that @func{var_set_name}
+would not update.  The following functions take care to update the
+index as well.  They also ensure that variable renaming does not cause
+a dictionary to contain a duplicate variable name.
+
+@deftypefun void dict_rename_var (struct dictionary *@var{dict}, struct variable *@var{var}, const char *@var{new_name})
+Changes the name of @var{var}, which must be in @var{dict}, to
+@var{new_name}.  A variable named @var{new_name} must not already be
+in @var{dict}, unless @var{new_name} is the same as @var{var}'s
+current name.
+@end deftypefun
+
+@deftypefun bool dict_rename_vars (struct dictionary *@var{dicT}, struct variable **@var{vars}, char **@var{new_names}, size_t @var{count}, char **@var{err_name})
+Renames each of the @var{count} variables in @var{vars} to the name in
+the corresponding position of @var{new_names}.  If the renaming would
+result in a duplicate variable name, returns false and stores one of
+the names that would be be duplicated into @code{*@var{err_name}}, if
+@var{err_name} is non-null.  Otherwise, the renaming is successful,
+and true is returned.
+@end deftypefun
+
+@node Dictionary Weight Variable
+@subsection Weight Variable
+
+A data set's cases may optionally be weighted by the value of a
+numeric variable.  @xref{WEIGHT,,,pspp, PSPP Users Guide}, for a user
+view of weight variables.
+
+The weight variable is written to and read from system and portable
+files.
+
+The most commonly useful function related to weighting is a
+convenience function to retrieve a weighting value from a case.
+
+@deftypefun double dict_get_case_weight (const struct dictionary *@var{dict}, const struct ccase *@var{case}, bool *@var{warn_on_invalid})
+Retrieves and returns the value of the weighting variable specified by
+@var{dict} from @var{case}.  Returns 1.0 if @var{dict} has no
+weighting variable.
+
+Returns 0.0 if @var{c}'s weight value is user- or system-missing,
+zero, or negative.  In such a case, if @var{warn_on_invalid} is
+non-null and @code{*@var{warn_on_invalid}} is true,
+@func{dict_get_case_weight} also issues an error message and sets
+@code{*@var{warn_on_invalid}} to false.  To disable error reporting,
+pass a null pointer or a pointer to false as @var{warn_on_invalid} or
+use a @func{msg_disable}/@func{msg_enable} pair.
+@end deftypefun
+
+The dictionary also has a pair of functions for getting and setting
+the weight variable.
+
+@deftypefun {struct variable *} dict_get_weight (const struct dictionary *@var{dict})
+Returns @var{dict}'s current weighting variable, or a null pointer if
+the dictionary does not have a weighting variable.
+@end deftypefun
+
+@deftypefun void dict_set_weight (struct dictionary *@var{dict}, struct variable *@var{var})
+Sets @var{dict}'s weighting variable to @var{var}.  If @var{var} is
+non-null, it must be a numeric variable in @var{dict}.  If @var{var}
+is null, then @var{dict}'s weighting variable, if any, is cleared.
+@end deftypefun
+
+@node Dictionary Filter Variable
+@subsection Filter Variable
+
+When the active file is read by a procedure, cases can be excluded
+from analysis based on the values of a @dfn{filter variable}.
+@xref{FILTER,,,pspp, PSPP Users Guide}, for a user view of filtering.
+
+These functions store and retrieve the filter variable.  They are
+rarely useful, because the data analysis framework automatically
+excludes from analysis the cases that should be filtered.
+
+@deftypefun {struct variable *} dict_get_filter (const struct dictionary *@var{dict})
+Returns @var{dict}'s current filter variable, or a null pointer if the
+dictionary does not have a filter variable.
+@end deftypefun
+
+@deftypefun void dict_set_filter (struct dictionary *@var{dict}, struct variable *@var{var})
+Sets @var{dict}'s filter variable to @var{var}.  If @var{var} is
+non-null, it must be a numeric variable in @var{dict}.  If @var{var}
+is null, then @var{dict}'s filter variable, if any, is cleared.
+@end deftypefun
+
+@node Dictionary Case Limit
+@subsection Case Limit
+
+The limit on cases analyzed by a procedure, set by the @cmd{N OF
+CASES} command (@pxref{N OF CASES,,,pspp, PSPP Users Guide}), is
+stored as part of the dictionary.  The dictionary does not, on the
+other hand, play any role in enforcing the case limit (a job done by
+data analysis framework code).
+
+A case limit of 0 means that the number of cases is not limited.
+
+These functions are rarely useful, because the data analysis framework
+automatically excludes from analysis any cases beyond the limit.
+
+@deftypefun casenumber dict_get_case_limit (const struct dictionary *@var{dict})
+Returns the current case limit for @var{dict}.
+@end deftypefun
+
+@deftypefun void dict_set_case_limit (struct dictionary *@var{dict}, casenumber @var{limit})
+Sets @var{dict}'s case limit to @var{limit}.
+@end deftypefun
+
+@node Dictionary Split Variables
+@subsection Split Variables
+
+The user may use the @cmd{SPLIT FILE} command (@pxref{SPLIT
+FILE,,,pspp, PSPP Users Guide}) to select a set of variables on which
+to split the active file into groups of cases to be analyzed
+independently in each statistical procedure.  The set of split
+variables is stored as part of the dictionary, although the effect on
+data analysis is implemented by each individual statistical procedure.
+
+Split variables may be numeric or short or long string variables.
+
+The most useful functions for split variables are those to retrieve
+them.  Even these functions are rarely useful directly: for the
+purpose of breaking cases into groups based on the values of the split
+variables, it is usually easier to use
+@func{casegrouper_create_splits}.
+
+@deftypefun {const struct variable *const *} dict_get_split_vars (const struct dictionary *@var{dict})
+Returns a pointer to an array of pointers to split variables.  If and
+only if there are no split variables, returns a null pointer.  The
+caller must not modify or free the returned array.
+@end deftypefun
+
+@deftypefun size_t dict_get_split_cnt (const struct dictionary *@var{dict})
+Returns the number of split variables.
+@end deftypefun
+
+The following functions are also available for working with split
+variables.
+
+@deftypefun void dict_set_split_vars (struct dictionary *@var{dict}, struct variable *const *@var{vars}, size_t @var{cnt})
+Sets @var{dict}'s split variables to the @var{cnt} variables in
+@var{vars}.  If @var{cnt} is 0, then @var{dict} will not have any
+split variables.  The caller retains ownership of @var{vars}.
+@end deftypefun
+
+@deftypefun void dict_unset_split_var (struct dictionary *@var{dict}, struct variable *@var{var})
+Removes @var{var}, which must be a variable in @var{dict}, from
+@var{dict}'s split of split variables.
+@end deftypefun
+
+@node Dictionary File Label
+@subsection File Label
+
+A dictionary may optionally have an associated string that describes
+its contents, called its file label.  The user may set the file label
+with the @cmd{FILE LABEL} command (@pxref{FILE LABEL,,,pspp, PSPP
+Users Guide}).
+
+These functions set and retrieve the file label.
+
+@deftypefun {const char *} dict_get_label (const struct dictionary *@var{dict})
+Returns @var{dict}'s file label.  If @var{dict} does not have a label,
+returns a null pointer.
+@end deftypefun
+
+@deftypefun void dict_set_label (struct dictionary *@var{dict}, const char *@var{label})
+Sets @var{dict}'s label to @var{label}.  If @var{label} is non-null,
+then its content, truncated to at most 60 bytes, becomes the new file
+label.  If @var{label} is null, then @var{dict}'s label is removed.
+
+The caller retains ownership of @var{label}.
+@end deftypefun
+
+@node Dictionary Documents
+@subsection Documents
+
+A dictionary may include an arbitrary number of lines of explanatory
+text, called the dictionary's documents.  For compatibility, document
+lines have a fixed width, and lines that are not exactly this width
+are truncated or padded with spaces as necessary to bring them to the
+correct width.
+
+PSPP users can use the @cmd{DOCUMENT} (@pxref{DOCUMENT,,,pspp, PSPP
+Users Guide}), @cmd{ADD DOCUMENT} (@pxref{ADD DOCUMENT,,,pspp, PSPP
+Users Guide}), and @cmd{DROP DOCUMENTS} (@pxref{DROP DOCUMENTS,,,pspp,
+PSPP Users Guide}) commands to manipulate documents.
+
+@deftypefn Macro int DOC_LINE_LENGTH
+The fixed length of a document line, in bytes, defined to 80.
+@end deftypefn
+
+The following functions work with whole sets of documents.  They
+accept or return sets of documents formatted as null-terminated
+strings that are an exact multiple of @code{DOC_LINE_LENGTH}
+bytes in length.
+
+@deftypefun {const char *} dict_get_documents (const struct dictionary *@var{dict})
+Returns the documents in @var{dict}, or a null pointer if @var{dict}
+has no documents.
+@end deftypefun
+
+@deftypefun void dict_set_documents (struct dictionary *@var{dict}, const char *@var{new_documents})
+Sets @var{dict}'s documents to @var{new_documents}.  If
+@var{new_documents} is a null pointer or an empty string, then
+@var{dict}'s documents are cleared.  The caller retains ownership of
+@var{new_documents}.
+@end deftypefun
+
+@deftypefun void dict_clear_documents (struct dictionary *@var{dict})
+Clears the documents from @var{dict}.
+@end deftypefun
+
+The following functions work with individual lines in a dictionary's
+set of documents.
+
+@deftypefun void dict_add_document_line (struct dictionary *@var{dict}, const char *@var{content})
+Appends @var{content} to the documents in @var{dict}.  The text in
+@var{content} will be truncated or padded with spaces as necessary to
+make it exactly @code{DOC_LINE_LENGTH} bytes long.  The caller retains
+ownership of @var{content}.
+
+If @var{content} is over @code{DOC_LINE_LENGTH}, this function also
+issues a warning using @func{msg}.  To suppress the warning, enclose a
+call to one of this function in a @func{msg_disable}/@func{msg_enable}
+pair.
+@end deftypefun
+
+@deftypefun size_t dict_get_document_line_cnt (const struct dictionary *@var{dict})
+Returns the number of line of documents in @var{dict}.  If the
+dictionary contains no documents, returns 0.
+@end deftypefun
+
+@deftypefun void dict_get_document_line (const struct dictionary *@var{dict}, size_t @var{idx}, struct string *@var{content})
+Replaces the text in @var{content} (which must already have been
+initialized by the caller) by the document line in @var{dict} numbered
+@var{idx}, which must be less than the number of lines of documents in
+@var{dict}.  Any trailing white space in the document line is trimmed,
+so that @var{content} will have a length between 0 and
+@code{DOC_LINE_LENGTH}.
+@end deftypefun
+
+@node Coding Conventions
+@section Coding Conventions
+
+Every @file{.c} file should have @samp{#include <config.h>} as its
+first non-comment line.  No @file{.h} file should include
+@file{config.h}.
+
+This section needs to be finished.
+
+@node Cases
+@section Cases
+
+This section needs to be written.
+
+@node Data Sets
+@section Data Sets
+
+This section needs to be written.
+
+@node Pools
+@section Pools
+
+This section needs to be written.
+
+@c  LocalWords:  bool
diff --git a/doc/dev/data.texi b/doc/dev/data.texi
new file mode 100644 (file)
index 0000000..356b5e0
--- /dev/null
@@ -0,0 +1,47 @@
+@node Processing Data
+@chapter Processing Data
+
+Developer's Guide
+
+Proposed outline:
+
+@example
+* Introduction
+* Basic concepts
+** Data sets
+** Variables
+** Dictionaries
+** Coding conventions
+** Pools
+* Syntax parsing
+* Data processing
+** Reading data
+*** Casereaders generalities
+*** Casereaders from data files
+*** Casereaders from the active file
+*** Other casereaders
+** Writing data
+*** Casewriters generally
+*** Casewriters to data files
+*** Modifying the active file
+**** Modifying cases obtained from active file casereaders has no real effect
+**** Transformations; procedures that transform
+** Transforming data
+*** Sorting and merging
+*** Filtering
+*** Grouping
+**** Ordering and interaction of filtering and grouping
+*** Multiple passes over data
+*** Counting cases and case weights
+** Best practices
+*** Multiple passes with filters versus single pass with loops
+*** Sequential versus random access
+*** Managing memory
+*** Passing cases around
+*** Renaming casereaders
+*** Avoiding excessive buffering
+*** Propagating errors
+*** Avoid static/global data
+*** Don't worry about null filters, groups, etc.
+*** Be aware of reference counting semantics for cases
+@end example
diff --git a/doc/dev/intro.texi b/doc/dev/intro.texi
new file mode 100644 (file)
index 0000000..1558745
--- /dev/null
@@ -0,0 +1,22 @@
+@node Introduction
+@chapter Introduction
+
+This manual is a guide to PSPP internals.  Its intended audience is
+developers who wish to modify or extend PSPP's capabilities.  The use
+of PSPP is documented in a separate manual.  @xref{Top, ,
+Introduction, pspp, PSPP Users Guide}.
+
+This manual is both a tutorial and a reference manual for PSPP
+developers.  It is ultimately intended to cover everything that
+developers who wish to implement new PSPP statistical procedures and
+other commands should know.  It is currently incomplete, partly
+because existing developers have not yet spent enough time on writing,
+and partly because the interfaces not yet documented are not yet
+mature enough to making documenting them worthwhile.
+
+PSPP developers should have some familiarity with the basics of PSPP
+from a user's perspective.  This manual attempts to refer to the PSPP
+user manual's descriptions of concepts that PSPP users should find
+familiar at the time of their first reference.  However, it is
+probably a good idea to at least skim the PSPP manual before reading
+this one, if you are not already familiar with PSPP.
diff --git a/doc/dev/output.texi b/doc/dev/output.texi
new file mode 100644 (file)
index 0000000..6fb8b60
--- /dev/null
@@ -0,0 +1,2 @@
+@node Presenting Output
+@chapter Presenting Output
diff --git a/doc/dev/portable-file-format.texi b/doc/dev/portable-file-format.texi
new file mode 100644 (file)
index 0000000..31c1ac3
--- /dev/null
@@ -0,0 +1,479 @@
+@node Portable File Format
+@appendix Portable File Format
+
+These days, most computers use the same internal data formats for
+integer and floating-point data, if one ignores little differences like
+big- versus little-endian byte ordering.  However, occasionally it is
+necessary to exchange data between systems with incompatible data
+formats.  This is what portable files are designed to do.
+
+@strong{Please note:} This information is gleaned from examination of
+ASCII-formatted portable files only, so some of it may be incorrect
+for portable files formatted in EBCDIC or other character sets.
+
+@menu
+* Portable File Characters::
+* Portable File Structure::
+* Portable File Header::
+* Version and Date Info Record::
+* Identification Records::
+* Variable Count Record::
+* Case Weight Variable Record::
+* Variable Records::
+* Value Label Records::
+* Portable File Document Record::
+* Portable File Data::
+@end menu
+
+@node Portable File Characters
+@section Portable File Characters
+
+Portable files are arranged as a series of lines of 80
+characters each.  Each line is terminated by a carriage-return,
+line-feed sequence (``new-lines'').  New-lines are only used to avoid
+line length limits imposed by some OSes; they are not meaningful.
+
+Most lines in portable files are exactly 80 characters long.  The only
+exception is a line that ends in one or more spaces, in which the
+spaces may optionally be omitted.  Thus, a portable file reader must
+act as though a line shorter than 80 characters is padded to that
+length with spaces.
+
+The file must be terminated with a @samp{Z} character.  In addition, if
+the final line in the file does not have exactly 80 characters, then it
+is padded on the right with @samp{Z} characters.  (The file contents may
+be in any character set; the file contains a description of its own
+character set, as explained in the next section.  Therefore, the
+@samp{Z} character is not necessarily an ASCII @samp{Z}.)
+
+For the rest of the description of the portable file format, new-lines
+and the trailing @samp{Z}s will be ignored, as if they did not exist,
+because they are not an important part of understanding the file
+contents.
+
+@node Portable File Structure
+@section Portable File Structure
+
+Every portable file consists of the following records, in sequence:
+
+@itemize @bullet
+
+@item
+File header.
+
+@item
+Version and date info.
+
+@item
+Product identification.
+
+@item
+Author identification (optional).
+
+@item
+Subproduct identification (optional).
+
+@item
+Variable count.
+
+@item
+Case weight variable (optional).
+
+@item
+Variables.  Each variable record may optionally be followed by a
+missing value record and a variable label record.
+
+@item
+Value labels (optional).
+
+@item
+Documents (optional).
+
+@item
+Data.
+@end itemize
+
+Most records are identified by a single-character tag code.  The file
+header and version info record do not have a tag.
+
+Other than these single-character codes, there are three types of fields
+in a portable file: floating-point, integer, and string.  Floating-point
+fields have the following format:
+
+@itemize @bullet
+
+@item
+Zero or more leading spaces.
+
+@item
+Optional asterisk (@samp{*}), which indicates a missing value.  The
+asterisk must be followed by a single character, generally a period
+(@samp{.}), but it appears that other characters may also be possible.
+This completes the specification of a missing value.
+
+@item
+Optional minus sign (@samp{-}) to indicate a negative number.
+
+@item
+A whole number, consisting of one or more base-30 digits: @samp{0}
+through @samp{9} plus capital letters @samp{A} through @samp{T}.
+
+@item
+Optional fraction, consisting of a radix point (@samp{.}) followed by
+one or more base-30 digits.
+
+@item
+Optional exponent, consisting of a plus or minus sign (@samp{+} or
+@samp{-}) followed by one or more base-30 digits.
+
+@item
+A forward slash (@samp{/}).
+@end itemize
+
+Integer fields take a form identical to floating-point fields, but they
+may not contain a fraction.
+
+String fields take the form of a integer field having value @var{n},
+followed by exactly @var{n} characters, which are the string content.
+
+@node Portable File Header
+@section Portable File Header
+
+Every portable file begins with a 464-byte header, consisting of a
+200-byte collection of vanity splash strings, followed by a 256-byte
+character set translation table, followed by an 8-byte tag string.
+
+The 200-byte segment is divided into five 40-byte sections, each of
+which represents the string @code{@var{charset} SPSS PORT FILE} in a
+different character set encoding, where @var{charset} is the name of
+the character set used in the file, e.g.@: @code{ASCII} or
+@code{EBCDIC}.  Each string is padded on the right with spaces in its
+respective character set.
+
+It appears that these strings exist only to inform those who might view
+the file on a screen, and that they are not parsed by SPSS products.
+Thus, they can be safely ignored.  For those interested, the strings are
+supposed to be in the following character sets, in the specified order:
+EBCDIC, 7-bit ASCII, CDC 6-bit ASCII, 6-bit ASCII, Honeywell 6-bit
+ASCII.
+
+The 256-byte segment describes a mapping from the character set used in
+the portable file to an arbitrary character set having characters at the
+following positions:
+
+@table @asis
+@item 0--60
+
+Control characters.  Not important enough to describe in full here.
+
+@item 61--63
+
+Reserved.
+
+@item 64--73
+
+Digits @samp{0} through @samp{9}.
+
+@item 74--99
+
+Capital letters @samp{A} through @samp{Z}.
+
+@item 100--125
+
+Lowercase letters @samp{a} through @samp{z}.
+
+@item 126
+
+Space.
+
+@item 127--130
+
+Symbols @code{.<(+}
+
+@item 131
+
+Solid vertical pipe.
+
+@item 132--142
+
+Symbols @code{&[]!$*);^-/}
+
+@item 143
+
+Broken vertical pipe.
+
+@item 144--150
+
+Symbols @code{,%_>}?@code{`:}   @c @code{?} is an inverted question mark
+
+@item 151
+
+British pound symbol.
+
+@item 152--155
+
+Symbols @code{@@'="}.
+
+@item 156
+
+Less than or equal symbol.
+
+@item 157
+
+Empty box.
+
+@item 158
+
+Plus or minus.
+
+@item 159
+
+Filled box.
+
+@item 160
+
+Degree symbol.
+
+@item 161
+
+Dagger.
+
+@item 162
+
+Symbol @samp{~}.
+
+@item 163
+
+En dash.
+
+@item 164
+
+Lower left corner box draw.
+
+@item 165
+
+Upper left corner box draw.
+
+@item 166
+
+Greater than or equal symbol.
+
+@item 167--176
+
+Superscript @samp{0} through @samp{9}.
+
+@item 177
+
+Lower right corner box draw.
+
+@item 178
+
+Upper right corner box draw.
+
+@item 179
+
+Not equal symbol.
+
+@item 180
+
+Em dash.
+
+@item 181
+
+Superscript @samp{(}.
+
+@item 182
+
+Superscript @samp{)}.
+
+@item 183
+
+Horizontal dagger (?).
+
+@item 184--186
+
+Symbols @samp{@{@}\}.
+@item 187
+
+Cents symbol.
+
+@item 188
+
+Centered dot, or bullet.
+
+@item 189--255
+
+Reserved.
+@end table
+
+Symbols that are not defined in a particular character set are set to
+the same value as symbol 64; i.e., to @samp{0}.
+
+The 8-byte tag string consists of the exact characters @code{SPSSPORT}
+in the portable file's character set, which can be used to verify that
+the file is indeed a portable file.
+
+@node Version and Date Info Record
+@section Version and Date Info Record
+
+This record does not have a tag code.  It has the following structure:
+
+@itemize @bullet
+@item
+A single character identifying the file format version.  The letter A
+represents version 0, and so on.
+
+@item
+An 8-character string field giving the file creation date in the format
+YYYYMMDD.
+
+@item
+A 6-character string field giving the file creation time in the format
+HHMMSS.
+@end itemize
+
+@node Identification Records
+@section Identification Records
+
+The product identification record has tag code @samp{1}.  It consists of
+a single string field giving the name of the product that wrote the
+portable file.
+
+The author identification record has tag code @samp{2}.  It is
+optional.  If present, it consists of a single string field giving the
+name of the person who caused the portable file to be written.
+
+The subproduct identification record has tag code @samp{3}.  It is
+optional.  If present, it consists of a single string field giving
+additional information on the product that wrote the portable file.
+
+@node Variable Count Record
+@section Variable Count Record
+
+The variable count record has tag code @samp{4}.  It consists of two
+integer fields.  The first contains the number of variables in the file
+dictionary.  The purpose of the second is unknown; it contains the value
+161 in all portable files examined so far.
+
+@node Case Weight Variable Record
+@section Case Weight Variable Record
+
+The case weight variable record is optional.  If it is present, it
+indicates the variable used for weighting cases; if it is absent,
+cases are unweighted.  It has tag code @samp{6}.  It consists of a
+single string field that names the weighting variable.
+
+@node Variable Records
+@section Variable Records
+
+Each variable record represents a single variable.  Variable records
+have tag code @samp{7}.  They have the following structure:
+
+@itemize @bullet
+
+@item
+Width (integer).  This is 0 for a numeric variable, and a number between 1
+and 255 for a string variable.
+
+@item
+Name (string).  1--8 characters long.  Must be in all capitals.
+
+A few portable files that contain duplicate variable names have been
+spotted in the wild.  PSPP handles these by renaming the duplicates
+with numeric extensions: @code{@var{var}_1}, @code{@var{var}_2}, and
+so on.
+
+@item
+Print format.  This is a set of three integer fields:
+
+@itemize @minus
+
+@item
+Format type (@pxref{Variable Record}).
+
+@item
+Format width.  1--40.
+
+@item
+Number of decimal places.  1--40.
+@end itemize
+
+A few portable files with invalid format types or formats that are not
+of the appropriate width for their variables have been spotted in the
+wild.  PSPP assigns a default F or A format to a variable with an
+invalid format.
+
+@item
+Write format.  Same structure as the print format described above.
+@end itemize
+
+Each variable record can optionally be followed by a missing value
+record, which has tag code @samp{8}.  A missing value record has one
+field, the missing value itself (a floating-point or string, as
+appropriate).  Up to three of these missing value records can be used.
+
+There is also a record for missing value ranges, which has tag code
+@samp{B}.  It is followed by two fields representing the range, which
+are floating-point or string as appropriate.  If a missing value range
+is present, it may be followed by a single missing value record.
+
+Tag codes @samp{9} and @samp{A} represent @code{LO THRU @var{x}} and
+@code{@var{x} THRU HI} ranges, respectively.  Each is followed by a
+single field representing @var{x}.  If one of the ranges is present, it
+may be followed by a single missing value record.
+
+In addition, each variable record can optionally be followed by a
+variable label record, which has tag code @samp{C}.  A variable label
+record has one field, the variable label itself (string).
+
+@node Value Label Records
+@section Value Label Records
+
+Value label records have tag code @samp{D}.  They have the following
+format:
+
+@itemize @bullet
+@item
+Variable count (integer).
+
+@item
+List of variables (strings).  The variable count specifies the number in
+the list.  Variables are specified by their names.  All variables must
+be of the same type (numeric or string), but string variables do not
+necessarily have the same width.
+
+@item
+Label count (integer).
+
+@item
+List of (value, label) tuples.  The label count specifies the number of
+tuples.  Each tuple consists of a value, which is numeric or string as
+appropriate to the variables, followed by a label (string).
+@end itemize
+
+A few portable files that specify duplicate value labels, that is, two
+different labels for a single value of a single variable, have been
+spotted in the wild.  PSPP uses the last value label specified in
+these cases.
+
+@node Portable File Document Record
+@section Document Record
+
+One document record may optionally follow the value label record.  The
+document record consists of tag code @samp{E}, following by the number
+of document lines as an integer, followed by that number of strings,
+each of which represents one document line.  Document lines must be 80
+bytes long or shorter.
+
+@node Portable File Data
+@section Portable File Data
+
+The data record has tag code @samp{F}.  There is only one tag for all
+the data; thus, all the data must follow the dictionary.  The data is
+terminated by the end-of-file marker @samp{Z}, which is not valid as the
+beginning of a data element.
+
+Data elements are output in the same order as the variable records
+describing them.  String variables are output as string fields, and
+numeric variables are output as floating-point fields.
+@setfilename ignored
diff --git a/doc/dev/q2c.texi b/doc/dev/q2c.texi
new file mode 100644 (file)
index 0000000..af6b1da
--- /dev/null
@@ -0,0 +1,300 @@
+@node q2c Input Format
+@appendix @code{q2c} Input Format
+
+PSPP statistical procedures have a bizarre and somewhat irregular
+syntax.  Despite this, a parser generator has been written that
+adequately addresses many of the possibilities and tries to provide
+hooks for the exceptional cases.  This parser generator is named
+@code{q2c}.
+
+@menu
+* Invoking q2c::                q2c command-line syntax.
+* q2c Input Structure::         High-level layout of the input file.
+* Grammar Rules::               Syntax of the grammar rules.
+@end menu
+
+@node Invoking q2c
+@section Invoking q2c
+
+@example
+q2c @var{input.q} @var{output.c}
+@end example
+
+@code{q2c} translates a @samp{.q} file into a @samp{.c} file.  It takes
+exactly two command-line arguments, which are the input file name and
+output file name, respectively.  @code{q2c} does not accept any
+command-line options.
+
+@node q2c Input Structure
+@section @code{q2c} Input Structure
+
+@code{q2c} input files are divided into two sections: the grammar rules
+and the supporting code.  The @dfn{grammar rules}, which make up the
+first part of the input, are used to define the syntax of the
+statistical procedure to be parsed.  The @dfn{supporting code},
+following the grammar rules, are copied largely unchanged to the output
+file, except for certain escapes.
+
+The most important lines in the grammar rules are used for defining
+procedure syntax.  These lines can be prefixed with a dollar sign
+(@samp{$}), which prevents Emacs' CC-mode from munging them.  Besides
+this, a bang (@samp{!}) at the beginning of a line causes the line,
+minus the bang, to be written verbatim to the output file (useful for
+comments).  As a third special case, any line that begins with the exact
+characters @code{/* *INDENT} is ignored and not written to the output.
+This allows @code{.q} files to be processed through @code{indent}
+without being munged.
+
+The syntax of the grammar rules themselves is given in the following
+sections.
+
+The supporting code is passed into the output file largely unchanged.
+However, the following escapes are supported.  Each escape must appear
+on a line by itself.
+
+@table @code
+@item /* (header) */
+
+Expands to a series of C @code{#include} directives which include the
+headers that are required for the parser generated by @code{q2c}.
+
+@item /* (decls @var{scope}) */
+
+Expands to C variable and data type declarations for the variables and
+@code{enum}s input and output by the @code{q2c} parser.  @var{scope}
+must be either @code{local} or @code{global}.  @code{local} causes the
+declarations to be output as function locals.  @code{global} causes them
+to be declared as @code{static} module variables; thus, @code{global} is
+a bit of a misnomer.
+
+@item /* (parser) */
+
+Expands to the entire parser.  Must be enclosed within a C function.
+
+@item /* (free) */
+
+Expands to a set of calls to the @code{free} function for variables
+declared by the parser.  Only needs to be invoked if subcommands of type
+@code{string} are used in the grammar rules.
+@end table
+
+@node Grammar Rules
+@section Grammar Rules
+
+The grammar rules describe the format of the syntax that the parser
+generated by @code{q2c} will understand.  The way that the grammar rules
+are included in @code{q2c} input file are described above.
+
+The grammar rules are divided into tokens of the following types:
+
+@table @asis
+@item Identifier (@code{ID})
+
+An identifier token is a sequence of letters, digits, and underscores
+(@samp{_}).  Identifiers are @emph{not} case-sensitive.
+
+@item String (@code{STRING})
+
+String tokens are initiated by a double-quote character (@samp{"}) and
+consist of all the characters between that double quote and the next
+double quote, which must be on the same line as the first.  Within a
+string, a backslash can be used as a ``literal escape''.  The only
+reasons to use a literal escape are to include a double quote or a
+backslash within a string.
+
+@item Special character
+
+Other characters, other than white space, constitute tokens in
+themselves.
+
+@end table
+
+The syntax of the grammar rules is as follows:
+
+@example
+grammar-rules ::= command-name opt-prefix : subcommands .
+command-name ::= ID
+             ::= STRING
+opt-prefix ::=
+           ::= ( ID )
+subcommands ::= subcommand
+            ::= subcommands ; subcommand
+@end example
+
+The syntax begins with an ID token that gives the name of the
+procedure to be parsed.  For command names that contain multiple
+words, a STRING token may be used instead, e.g.@: @samp{"FILE
+HANDLE"}.  Optionally, an ID in parentheses specifies a prefix used
+for all file-scope identifiers declared by the emitted code.
+
+The rest of the syntax consists of subcommands separated by semicolons
+(@samp{;}) and terminated with a full stop (@samp{.}).
+
+@example
+subcommand ::= default-opt arity-opt ID sbc-defn
+default-opt ::=
+            ::= *
+arity-opt ::=
+          ::= +
+          ::= ^
+sbc-defn ::= opt-prefix = specifiers
+         ::= [ ID ] = array-sbc
+         ::= opt-prefix = sbc-special-form
+@end example
+
+A subcommand that begins with an asterisk (@samp{*}) is the default
+subcommand.  The keyword used for the default subcommand can be omitted
+in the PSPP syntax file.
+
+A plus sign (@samp{+}) indicates that a subcommand can appear more than
+once.  A caret (@samp{^}) indicate that a subcommand must appear exactly
+once.  A subcommand marked with neither character may appear once or not
+at all, but not more than once.
+
+The subcommand name appears after the leading option characters.
+
+There are three forms of subcommands.  The first and most common form
+simply gives an equals sign (@samp{=}) and a list of specifiers, which
+can each be set to a single setting.  The second form declares an array,
+which is a set of flags that can be individually turned on by the user.
+There are also several special forms that do not take a list of
+specifiers.
+
+Arrays require an additional @code{ID} argument.  This is used as a
+prefix, prepended to the variable names constructed from the
+specifiers.  The other forms also allow an optional prefix to be
+specified.
+
+@example
+array-sbc ::= alternatives
+          ::= array-sbc , alternatives
+alternatives ::= ID
+             ::= alternatives | ID
+@end example
+
+An array subcommand is a set of Boolean values that can independently be
+turned on by the user, listed separated by commas (@samp{,}).  If an value has more
+than one name then these names are separated by pipes (@samp{|}).
+
+@example
+specifiers ::= specifier
+           ::= specifiers , specifier
+specifier ::= opt-id : settings
+opt-id ::=
+       ::= ID
+@end example
+
+Ordinary subcommands (other than arrays and special forms) require a
+list of specifiers.  Each specifier has an optional name and a list of
+settings.  If the name is given then a correspondingly named variable
+will be used to store the user's choice of setting.  If no name is given
+then there is no way to tell which setting the user picked; in this case
+the settings should probably have values attached.
+
+@example
+settings ::= setting
+         ::= settings / setting
+setting ::= setting-options ID setting-value
+setting-options ::=
+                ::= *
+                ::= !
+                ::= * !
+@end example
+
+Individual settings are separated by forward slashes (@samp{/}).  Each
+setting can be as little as an @code{ID} token, but options and values
+can optionally be included.  The @samp{*} option means that, for this
+setting, the @code{ID} can be omitted.  The @samp{!} option means that
+this option is the default for its specifier.
+
+@example
+setting-value ::=
+              ::= ( setting-value-2 )
+              ::= setting-value-2
+setting-value-2 ::= setting-value-options setting-value-type : ID
+                    setting-value-restriction
+setting-value-options ::=
+                      ::= *
+setting-value-type ::= N
+                   ::= D
+                   ::= S
+setting-value-restriction ::=
+                          ::= , STRING
+@end example
+
+Settings may have values.  If the value must be enclosed in parentheses,
+then enclose the value declaration in parentheses.  Declare the setting
+type as @samp{n}, @samp{d}, or @samp{s} for integer, floating-point,
+or string type, respectively.  The given @code{ID} is used to
+construct a variable name.
+If option @samp{*} is given, then the value is optional; otherwise it
+must be specified whenever the corresponding setting is specified.  A
+``restriction'' can also be specified which is a string giving a C
+expression limiting the valid range of the value.  The special escape
+@code{%s} should be used within the restriction to refer to the
+setting's value variable.
+
+@example
+sbc-special-form ::= VAR
+                 ::= VARLIST varlist-options
+                 ::= INTEGER opt-list
+                 ::= DOUBLE opt-list
+                 ::= PINT
+                 ::= STRING @r{(the literal word STRING)} string-options
+                 ::= CUSTOM
+varlist-options ::=
+                ::= ( STRING )
+opt-list ::=
+         ::= LIST
+string-options ::=
+               ::= ( STRING STRING )
+@end example
+
+The special forms are of the following types:
+
+@table @code
+@item VAR
+
+A single variable name.
+
+@item VARLIST
+
+A list of variables.  If given, the string can be used to provide
+@code{PV_@var{*}} options to the call to @code{parse_variables}.
+
+@item INTEGER
+
+A single integer value.
+
+@item INTEGER LIST
+
+A list of integers separated by spaces or commas.
+
+@item DOUBLE
+
+A single floating-point value.
+
+@item DOUBLE LIST
+
+A list of floating-point values.
+
+@item PINT
+
+A single positive integer value.
+
+@item STRING
+
+A string value.  If the options are given then the first string is an
+expression giving a restriction on the value of the string; the second
+string is an error message to display when the restriction is violated.
+
+@item CUSTOM
+
+A custom function is used to parse this subcommand.  The function must
+have prototype @code{int custom_@var{name} (void)}.  It should return 0
+on failure (when it has already issued an appropriate diagnostic), 1 on
+success, or 2 if it fails and the calling function should issue a syntax
+error on behalf of the custom handler.
+
+@end table
+@setfilename ignored
diff --git a/doc/dev/syntax.texi b/doc/dev/syntax.texi
new file mode 100644 (file)
index 0000000..81d34c0
--- /dev/null
@@ -0,0 +1,2 @@
+@node Parsing Command Syntax
+@chapter Parsing Command Syntax
diff --git a/doc/dev/system-file-format.texi b/doc/dev/system-file-format.texi
new file mode 100644 (file)
index 0000000..193c660
--- /dev/null
@@ -0,0 +1,906 @@
+@node System File Format
+@appendix System File Format
+
+A system file encapsulates a set of cases and dictionary information
+that describes how they may be interpreted.  This chapter describes
+the format of a system file.
+
+System files use three data types: 8-bit characters, 32-bit integers,
+and 64-bit floating points, called here @code{char}, @code{int32}, and
+@code{flt64}, respectively.  Data is not necessarily aligned on a word
+or double-word boundary: the long variable name record (@pxref{Long
+Variable Names Record}) and very long string records (@pxref{Very Long
+String Record}) have arbitrary byte length and can therefore cause all
+data coming after them in the file to be misaligned.
+
+Integer data in system files may be big-endian or little-endian.  A
+reader may detect the endianness of a system file by examining
+@code{layout_code} in the file header record
+(@pxref{layout_code,,@code{layout_code}}).
+
+Floating-point data in system files may nominally be in IEEE 754, IBM,
+or VAX formats.  A reader may detect the floating-point format in use
+by examining @code{bias} in the file header record
+(@pxref{bias,,@code{bias}}).
+
+PSPP detects big-endian and little-endian integer formats in system
+files and translates as necessary.  PSPP also detects the
+floating-point format in use, as well as the endianness of IEEE 754
+floating-point numbers, and translates as needed.  However, only IEEE
+754 numbers with the same endianness as integer data in the same file
+has actually been observed in system files, and it is likely that
+other formats are obsolete or were never used.
+
+The PSPP system-missing value is represented by the largest possible
+negative number in the floating point format (@code{-DBL_MAX}).  Two
+other values are important for use as missing values: @code{HIGHEST},
+represented by the largest possible positive number (@code{DBL_MAX}),
+and @code{LOWEST}, represented by the second-largest negative number
+(in IEEE 754 format, @code{0xffeffffffffffffe}).
+
+System files are divided into records, each of which begins with a
+4-byte record type, usually regarded as an @code{int32}.
+
+The records must appear in the following order:
+
+@itemize @bullet
+@item
+File header record.
+
+@item
+Variable records.
+
+@item
+All pairs of value labels records and value label variables records,
+if present.
+
+@item
+Document record, if present.
+
+@item
+Any of the following records, if present, in any order:
+
+@itemize @minus
+@item
+Machine integer info record.
+
+@item
+Machine floating-point info record.
+
+@item
+Variable display parameter record.
+
+@item
+Long variable names record.
+
+@item
+Miscellaneous informational records.
+@end itemize
+
+@item
+Dictionary termination record.
+
+@item
+Data record.
+@end itemize
+
+Each type of record is described separately below.
+
+@menu
+* File Header Record::
+* Variable Record::
+* Value Labels Records::
+* Document Record::
+* Machine Integer Info Record::
+* Machine Floating-Point Info Record::
+* Variable Display Parameter Record::
+* Long Variable Names Record::
+* Very Long String Record::
+* Miscellaneous Informational Records::
+* Dictionary Termination Record::
+* Data Record::
+@end menu
+
+@node File Header Record
+@section File Header Record
+
+The file header is always the first record in the file.  It has the
+following format:
+
+@example
+char                rec_type[4];
+char                prod_name[60];
+int32               layout_code;
+int32               nominal_case_size;
+int32               compressed;
+int32               weight_index;
+int32               ncases;
+flt64               bias;
+char                creation_date[9];
+char                creation_time[8];
+char                file_label[64];
+char                padding[3];
+@end example
+
+@table @code
+@item char rec_type[4];
+Record type code, set to @samp{$FL2}.
+
+@item char prod_name[60];
+Product identification string.  This always begins with the characters
+@samp{@@(#) SPSS DATA FILE}.  PSPP uses the remaining characters to
+give its version and the operating system name; for example, @samp{GNU
+pspp 0.1.4 - sparc-sun-solaris2.5.2}.  The string is truncated if it
+would be longer than 60 characters; otherwise it is padded on the right
+with spaces.
+
+@anchor{layout_code}
+@item int32 layout_code;
+Normally set to 2, although a few system files have been spotted in
+the wild with a value of 3 here.  PSPP use this value to determine the
+file's integer endianness (@pxref{System File Format}).
+
+@item int32 nominal_case_size;
+Number of data elements per case.  This is the number of variables,
+except that long string variables add extra data elements (one for every
+8 characters after the first 8).  However, string variables do not
+contribute to this value beyond the first 255 bytes.   Further, system
+files written by some systems set this value to -1.  In general, it is
+unsafe for systems reading system files to rely upon this value.
+
+@item int32 compressed;
+Set to 1 if the data in the file is compressed, 0 otherwise.
+
+@item int32 weight_index;
+If one of the variables in the data set is used as a weighting
+variable, set to the dictionary index of that variable, plus 1
+(@pxref{Dictionary Index}).  Otherwise, set to 0.
+
+@item int32 ncases;
+Set to the number of cases in the file if it is known, or -1 otherwise.
+
+In the general case it is not possible to determine the number of cases
+that will be output to a system file at the time that the header is
+written.  The way that this is dealt with is by writing the entire
+system file, including the header, then seeking back to the beginning of
+the file and writing just the @code{ncases} field.  For `files' in which
+this is not valid, the seek operation fails.  In this case,
+@code{ncases} remains -1.
+
+@anchor{bias}
+@item flt64 bias;
+Compression bias, ordinarily set to 100.  Only integers between
+@code{1 - bias} and @code{251 - bias} can be compressed.
+
+By assuming that its value is 100, PSPP uses @code{bias} to determine
+the file's floating-point format and endianness (@pxref{System File
+Format}).  If the compression bias is not 100, PSPP cannot auto-detect
+the floating-point format and assumes that it is IEEE 754 format with
+the same endianness as the system file's integers, which is correct
+for all known system files.
+
+@item char creation_date[9];
+Date of creation of the system file, in @samp{dd mmm yy}
+format, with the month as standard English abbreviations, using an
+initial capital letter and following with lowercase.  If the date is not
+available then this field is arbitrarily set to @samp{01 Jan 70}.
+
+@item char creation_time[8];
+Time of creation of the system file, in @samp{hh:mm:ss}
+format and using 24-hour time.  If the time is not available then this
+field is arbitrarily set to @samp{00:00:00}.
+
+@item char file_label[64];
+File label declared by the user, if any (@pxref{FILE LABEL,,,pspp,
+PSPP Users Guide}).  Padded on the right with spaces.
+
+@item char padding[3];
+Ignored padding bytes to make the structure a multiple of 32 bits in
+length.  Set to zeros.
+@end table
+
+@node Variable Record
+@section Variable Record
+
+There must be one variable record for each numeric variable and each
+string variable with width 8 bytes or less.  String variables wider
+than 8 bytes have one variable record for each 8 bytes, rounding up.
+The first variable record for a long string specifies the variable's
+correct dictionary information.  Subsequent variable records for a
+long string are filled with dummy information: a type of -1, no
+variable label or missing values, print and write formats that are
+ignored, and an empty string as name.  A few system files have been
+encountered that include a variable label on dummy variable records,
+so readers should take care to parse dummy variable records in the
+same way as other variable records.
+
+@anchor{Dictionary Index}
+The @dfn{dictionary index} of a variable is its offset in the set of
+variable records, including dummy variable records for long string
+variables.  The first variable record has a dictionary index of 0, the
+second has a dictionary index of 1, and so on.
+
+The system file format does not directly support string variables
+wider than 255 bytes.  Such very long string variables are represented
+by a number of narrower string variables.  @xref{Very Long String
+Record}, for details.
+
+@example
+int32               rec_type;
+int32               type;
+int32               has_var_label;
+int32               n_missing_values;
+int32               print;
+int32               write;
+char                name[8];
+
+/* @r{Present only if @code{has_var_label} is 1.} */
+int32               label_len;
+char                label[];
+
+/* @r{Present only if @code{n_missing_values} is nonzero}. */
+flt64               missing_values[];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type code.  Always set to 2.
+
+@item int32 type;
+Variable type code.  Set to 0 for a numeric variable.  For a short
+string variable or the first part of a long string variable, this is set
+to the width of the string.  For the second and subsequent parts of a
+long string variable, set to -1, and the remaining fields in the
+structure are ignored.
+
+@item int32 has_var_label;
+If this variable has a variable label, set to 1; otherwise, set to 0.
+
+@item int32 n_missing_values;
+If the variable has no missing values, set to 0.  If the variable has
+one, two, or three discrete missing values, set to 1, 2, or 3,
+respectively.  If the variable has a range for missing variables, set to
+-2; if the variable has a range for missing variables plus a single
+discrete value, set to -3.
+
+@item int32 print;
+Print format for this variable.  See below.
+
+@item int32 write;
+Write format for this variable.  See below.
+
+@item char name[8];
+Variable name.  The variable name must begin with a capital letter or
+the at-sign (@samp{@@}).  Subsequent characters may also be digits, octothorpes
+(@samp{#}), dollar signs (@samp{$}), underscores (@samp{_}), or full
+stops (@samp{.}).  The variable name is padded on the right with spaces.
+
+@item int32 label_len;
+This field is present only if @code{has_var_label} is set to 1.  It is
+set to the length, in characters, of the variable label, which must be a
+number between 0 and 120.
+
+@item char label[];
+This field is present only if @code{has_var_label} is set to 1.  It has
+length @code{label_len}, rounded up to the nearest multiple of 32 bits.
+The first @code{label_len} characters are the variable's variable label.
+
+@item flt64 missing_values[];
+This field is present only if @code{n_missing_values} is not 0.  It has
+the same number of elements as the absolute value of
+@code{n_missing_values}.  For discrete missing values, each element
+represents one missing value.  When a range is present, the first
+element denotes the minimum value in the range, and the second element
+denotes the maximum value in the range.  When a range plus a value are
+present, the third element denotes the additional discrete missing
+value.  HIGHEST and LOWEST are indicated as described in the chapter
+introduction.
+@end table
+
+The @code{print} and @code{write} members of sysfile_variable are output
+formats coded into @code{int32} types.  The least-significant byte
+of the @code{int32} represents the number of decimal places, and the
+next two bytes in order of increasing significance represent field width
+and format type, respectively.  The most-significant byte is not
+used and should be set to zero.
+
+Format types are defined as follows:
+
+@quotation
+@multitable {Value} {@code{DATETIME}}
+@headitem Value
+@tab Meaning
+@item 0
+@tab Not used.
+@item 1
+@tab @code{A}
+@item 2
+@tab @code{AHEX}
+@item 3
+@tab @code{COMMA}
+@item 4
+@tab @code{DOLLAR}
+@item 5
+@tab @code{F}
+@item 6
+@tab @code{IB}
+@item 7
+@tab @code{PIBHEX}
+@item 8
+@tab @code{P}
+@item 9
+@tab @code{PIB}
+@item 10
+@tab @code{PK}
+@item 11
+@tab @code{RB}
+@item 12
+@tab @code{RBHEX}
+@item 13
+@tab Not used.
+@item 14
+@tab Not used.
+@item 15
+@tab @code{Z}
+@item 16
+@tab @code{N}
+@item 17
+@tab @code{E}
+@item 18
+@tab Not used.
+@item 19
+@tab Not used.
+@item 20
+@tab @code{DATE}
+@item 21
+@tab @code{TIME}
+@item 22
+@tab @code{DATETIME}
+@item 23
+@tab @code{ADATE}
+@item 24
+@tab @code{JDATE}
+@item 25
+@tab @code{DTIME}
+@item 26
+@tab @code{WKDAY}
+@item 27
+@tab @code{MONTH}
+@item 28
+@tab @code{MOYR}
+@item 29
+@tab @code{QYR}
+@item 30
+@tab @code{WKYR}
+@item 31
+@tab @code{PCT}
+@item 32
+@tab @code{DOT}
+@item 33
+@tab @code{CCA}
+@item 34
+@tab @code{CCB}
+@item 35
+@tab @code{CCC}
+@item 36
+@tab @code{CCD}
+@item 37
+@tab @code{CCE}
+@item 38
+@tab @code{EDATE}
+@item 39
+@tab @code{SDATE}
+@end multitable
+@end quotation
+
+@node Value Labels Records
+@section Value Labels Records
+
+The value label record has the following format:
+
+@example
+int32               rec_type;
+int32               label_count;
+
+/* @r{Repeated @code{label_cnt} times}. */
+char                value[8];
+char                label_len;
+char                label[];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 3.
+
+@item int32 label_count;
+Number of value labels present in this record.
+@end table
+
+The remaining fields are repeated @code{count} times.  Each
+repetition specifies one value label.
+
+@table @code
+@item char value[8];
+A numeric value or a short string value padded as necessary to 8 bytes
+in length.  Its type and width cannot be determined until the
+following value label variables record (see below) is read.
+
+@item char label_len;
+The label's length, in bytes.
+
+@item char label[];
+@code{label_len} bytes of the actual label, followed by up to 7 bytes
+of padding to bring @code{label} and @code{label_len} together to a
+multiple of 8 bytes in length.
+@end table
+
+The value label record is always immediately followed by a value label
+variables record with the following format:
+
+@example
+int32               rec_type;
+int32               var_count;
+int32               vars[];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 4.
+
+@item int32 var_count;
+Number of variables that the associated value labels from the value
+label record are to be applied.
+
+@item int32 vars[];
+A list of dictionary indexes of variables to which to apply the value
+labels (@pxref{Dictionary Index}).  There are @code{var_count}
+elements.
+
+String variables wider than 8 bytes may not have value labels.
+@end table
+
+@node Document Record
+@section Document Record
+
+The document record, if present, has the following format:
+
+@example
+int32               rec_type;
+int32               n_lines;
+char                lines[][80];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 6.
+
+@item int32 n_lines;
+Number of lines of documents present.
+
+@item char lines[][80];
+Document lines.  The number of elements is defined by @code{n_lines}.
+Lines shorter than 80 characters are padded on the right with spaces.
+@end table
+
+@node Machine Integer Info Record
+@section Machine Integer Info Record
+
+The integer info record, if present, has the following format:
+
+@example
+/* @r{Header.} */
+int32               rec_type;
+int32               subtype;
+int32               size;
+int32               count;
+
+/* @r{Data.} */
+int32               version_major;
+int32               version_minor;
+int32               version_revision;
+int32               machine_code;
+int32               floating_point_rep;
+int32               compression_code;
+int32               endianness;
+int32               character_code;
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 7.
+
+@item int32 subtype;
+Record subtype.  Always set to 3.
+
+@item int32 size;
+Size of each piece of data in the data part, in bytes.  Always set to 4.
+
+@item int32 count;
+Number of pieces of data in the data part.  Always set to 8.
+
+@item int32 version_major;
+PSPP major version number.  In version @var{x}.@var{y}.@var{z}, this
+is @var{x}.
+
+@item int32 version_minor;
+PSPP minor version number.  In version @var{x}.@var{y}.@var{z}, this
+is @var{y}.
+
+@item int32 version_revision;
+PSPP version revision number.  In version @var{x}.@var{y}.@var{z},
+this is @var{z}.
+
+@item int32 machine_code;
+Machine code.  PSPP always set this field to value to -1, but other
+values may appear.
+
+@item int32 floating_point_rep;
+Floating point representation code.  For IEEE 754 systems this is 1.
+IBM 370 sets this to 2, and DEC VAX E to 3.
+
+@item int32 compression_code;
+Compression code.  Always set to 1.
+
+@item int32 endianness;
+Machine endianness.  1 indicates big-endian, 2 indicates little-endian.
+
+@item int32 character_code;
+Character code.  1 indicates EBCDIC, 2 indicates 7-bit ASCII, 3
+indicates 8-bit ASCII, 4 indicates DEC Kanji.
+Windows code page numbers are also valid.
+@end table
+
+@node Machine Floating-Point Info Record
+@section Machine Floating-Point Info Record
+
+The floating-point info record, if present, has the following format:
+
+@example
+/* @r{Header.} */
+int32               rec_type;
+int32               subtype;
+int32               size;
+int32               count;
+
+/* @r{Data.} */
+flt64               sysmis;
+flt64               highest;
+flt64               lowest;
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 7.
+
+@item int32 subtype;
+Record subtype.  Always set to 4.
+
+@item int32 size;
+Size of each piece of data in the data part, in bytes.  Always set to 8.
+
+@item int32 count;
+Number of pieces of data in the data part.  Always set to 3.
+
+@item flt64 sysmis;
+The system missing value.
+
+@item flt64 highest;
+The value used for HIGHEST in missing values.
+
+@item flt64 lowest;
+The value used for LOWEST in missing values.
+@end table
+
+@node Variable Display Parameter Record
+@section Variable Display Parameter Record
+
+The variable display parameter record, if present, has the following
+format:
+
+@example
+/* @r{Header.} */
+int32               rec_type;
+int32               subtype;
+int32               size;
+int32               count;
+
+/* @r{Repeated @code{count} times}. */
+int32               measure;
+int32               width;
+int32               alignment;
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 7.
+
+@item int32 subtype;
+Record subtype.  Always set to 11.
+
+@item int32 size;
+The size of @code{int32}.  Always set to 4.
+
+@item int32 count;
+The number of sets of variable display parameters (ordinarily the
+number of variables in the dictionary), times 3.
+@end table
+
+The remaining members are repeated @code{count} times, in the same
+order as the variable records.  No element corresponds to variable
+records that continue long string variables.  The meanings of these
+members are as follows:
+
+@table @code
+@item int32 measure;
+The measurement type of the variable:
+@table @asis
+@item 1
+Nominal Scale
+@item 2
+Ordinal Scale
+@item 3
+Continuous Scale
+@end table
+
+SPSS 14 sometimes writes a @code{measure} of 0.  PSPP interprets this
+as nominal scale.
+
+@item int32 width;
+The width of the display column for the variable in characters.
+
+@item int32 alignment;
+The alignment of the variable for display purposes:
+
+@table @asis
+@item 0
+Left aligned
+@item 1
+Right aligned
+@item 2
+Centre aligned
+@end table
+@end table
+
+@node Long Variable Names Record
+@section Long Variable Names Record
+
+If present, the long variable names record has the following format:
+
+@example
+/* @r{Header.} */
+int32               rec_type;
+int32               subtype;
+int32               size;
+int32               count;
+
+/* @r{Exactly @code{count} bytes of data.} */
+char                var_name_pairs[];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 7.
+
+@item int32 subtype;
+Record subtype.  Always set to 13.
+
+@item int32 size;
+The size of each element in the @code{var_name_pairs} member. Always set to 1.
+
+@item int32 count;
+The total number of bytes in @code{var_name_pairs}.
+
+@item char var_name_pairs[];
+A list of @var{key}--@var{value} tuples, where @var{key} is the name
+of a variable, and @var{value} is its long variable name.
+The @var{key} field is at most 8 bytes long and must match the
+name of a variable which appears in the variable record (@pxref{Variable
+Record}).
+The @var{value} field is at most 64 bytes long.
+The @var{key} and @var{value} fields are separated by a @samp{=} byte.
+Each tuple is separated by a byte whose value is 09.  There is no
+trailing separator following the last tuple.
+The total length is @code{count} bytes.
+@end table
+
+@node Very Long String Record
+@section Very Long String Record
+
+Old versions of SPSS limited string variables to a width of 255 bytes.
+For backward compatibility with these older versions, the system file
+format represents a string longer than 255 bytes, called a @dfn{very
+long string}, as a collection of strings no longer than 255 bytes
+each.  The strings concatenated to make a very long string are called
+its @dfn{segments}; for consistency, variables other than very long
+strings are considered to have a single segment.
+
+A very long string with a width of @var{w} has @var{n} =
+(@var{w} + 251) / 252 segments, that is, one segment for every
+252 bytes of width, rounding up.  It would be logical, then, for each
+of the segments except the last to have a width of 252 and the last
+segment to have the remainder, but this is not the case.  In fact,
+each segment except the last has a width of 255 bytes.  The last
+segment has width @var{w} - (@var{n} - 1) * 252; some versions
+of SPSS make it slightly wider, but not wide enough to make the last
+segment require another 8 bytes of data.
+
+Data is packed tightly into segments of a very long string, 255 bytes
+per segment.  Because 255 bytes of segment data are allocated for
+every 252 bytes of the very long string's width (approximately), some
+unused space is left over at the end of the allocated segments.  Data
+in unused space is ignored.
+
+Example: Consider a very long string of width 20,000.  Such a very
+long string has 20,000 / 252 = 80 (rounding up) segments.  The first
+79 segments have width 255; the last segment has width 20,000 - 79 *
+252 = 92 or slightly wider (up to 96 bytes, the next multiple of 8).
+The very long string's data is actually stored in the 19,890 bytes in
+the first 78 segments, plus the first 110 bytes of the 79th segment
+(19,890 + 110 = 20,000).  The remaining 145 bytes of the 79th segment
+and all 92 bytes of the 80th segment are unused.
+
+The very long string record explains how to stitch together segments
+to obtain very long string data.  For each of the very long string
+variables in the dictionary, it specifies the name of its first
+segment's variable and the very long string variable's actual width.
+The remaining segments immediately follow the named variable in the
+system file's dictionary.
+
+The very long string record, which is present only if the system file
+contains very long string variables, has the following format:
+
+@example
+/* @r{Header.} */
+int32               rec_type;
+int32               subtype;
+int32               size;
+int32               count;
+
+/* @r{Exactly @code{count} bytes of data.} */
+char                string_lengths[];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 7.
+
+@item int32 subtype;
+Record subtype.  Always set to 14.
+
+@item int32 size;
+The size of each element in the @code{string_lengths} member. Always set to 1.
+
+@item int32 count;
+The total number of bytes in @code{string_lengths}.
+
+@item char string_lengths[];
+A list of @var{key}--@var{value} tuples, where @var{key} is the name
+of a variable, and @var{value} is its length.
+The @var{key} field is at most 8 bytes long and must match the
+name of a variable which appears in the variable record (@pxref{Variable
+Record}).
+The @var{value} field is exactly 5 bytes long. It is a zero-padded,
+ASCII-encoded string that is the length of the variable.
+The @var{key} and @var{value} fields are separated by a @samp{=} byte.
+Tuples are delimited by a two-byte sequence @{00, 09@}.
+After the last tuple, there may be a single byte 00, or @{00, 09@}.
+The total length is @code{count} bytes.
+@end table
+
+@node Miscellaneous Informational Records
+@section Miscellaneous Informational Records
+
+Some specific types of miscellaneous informational records are
+documented here, but others are known to exist.  PSPP ignores unknown
+miscellaneous informational records when reading system files.
+
+@example
+/* @r{Header.} */
+int32               rec_type;
+int32               subtype;
+int32               size;
+int32               count;
+
+/* @r{Exactly @code{size * count} bytes of data.} */
+char                data[];
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 7.
+
+@item int32 subtype;
+Record subtype.  May take any value.  According to Aapi
+H@"am@"al@"ainen, value 5 indicates a set of grouped variables and 6
+indicates date info (probably related to USE).
+
+@item int32 size;
+Size of each piece of data in the data part.  Should have the value 1,
+4, or 8, for @code{char}, @code{int32}, and @code{flt64} format data,
+respectively.
+
+@item int32 count;
+Number of pieces of data in the data part.
+
+@item char data[];
+Arbitrary data.  There must be @code{size} times @code{count} bytes of
+data.
+@end table
+
+@node Dictionary Termination Record
+@section Dictionary Termination Record
+
+The dictionary termination record separates all other records from the
+data records.
+
+@example
+int32               rec_type;
+int32               filler;
+@end example
+
+@table @code
+@item int32 rec_type;
+Record type.  Always set to 999.
+
+@item int32 filler;
+Ignored padding.  Should be set to 0.
+@end table
+
+@node Data Record
+@section Data Record
+
+Data records must follow all other records in the system file.  There must
+be at least one data record in every system file.
+
+The format of data records varies depending on whether the data is
+compressed.  Regardless, the data is arranged in a series of 8-byte
+elements.
+
+When data is not compressed,
+each element corresponds to
+the variable declared in the respective variable record (@pxref{Variable
+Record}).  Numeric values are given in @code{flt64} format; string
+values are literal characters string, padded on the right when
+necessary to fill out 8-byte units.
+
+Compressed data is arranged in the following manner: the first 8 bytes
+in the data section is divided into a series of 1-byte command
+codes.  These codes have meanings as described below:
+
+@table @asis
+@item 0
+Ignored.  If the program writing the system file accumulates compressed
+data in blocks of fixed length, 0 bytes can be used to pad out extra
+bytes remaining at the end of a fixed-size block.
+
+@item 1 through 251
+A number with
+value @var{code} - @var{bias}, where
+@var{code} is the value of the compression code and @var{bias} is the
+variable @code{bias} from the file header.  For example,
+code 105 with bias 100.0 (the normal value) indicates a numeric variable
+of value 5.
+
+@item 252
+End of file.  This code may or may not appear at the end of the data
+stream.  PSPP always outputs this code but its use is not required.
+
+@item 253
+A numeric or string value that is not
+compressible.  The value is stored in the 8 bytes following the
+current block of command bytes.  If this value appears twice in a block
+of command bytes, then it indicates the second group of 8 bytes following the
+command bytes, and so on.
+
+@item 254
+An 8-byte string value that is all spaces.
+
+@item 255
+The system-missing value.
+@end table
+
+When the end of the an 8-byte group of command bytes is reached, any
+blocks of non-compressible values indicated by code 253 are skipped,
+and the next element of command bytes is read and interpreted, until
+the end of the file or a code with value 252 is reached.
+@setfilename ignored
index 5706068764f485b3645e78b24cb4a3ddcb4dcd2f..0dd77d499803e456e82093145d825dfe804e0ad0 100644 (file)
@@ -7,6 +7,6 @@ implemented.
 @cindex unimplemented commands
 @cindex commands, unimplemented
 
 @cindex unimplemented commands
 @cindex commands, unimplemented
 
-@include ni.texi
+@include doc/ni.texi
 
 @setfilename ignored
 
 @setfilename ignored
diff --git a/doc/portable-file-format.texi b/doc/portable-file-format.texi
deleted file mode 100644 (file)
index d58a987..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-@node Portable File Format
-@appendix Portable File Format
-
-These days, most computers use the same internal data formats for
-integer and floating-point data, if one ignores little differences like
-big- versus little-endian byte ordering.  However, occasionally it is
-necessary to exchange data between systems with incompatible data
-formats.  This is what portable files are designed to do.
-
-@strong{Please note:} Although all of the following information is
-correct, as far as the author has been able to ascertain, it is gleaned
-from examination of ASCII-formatted portable files only, so some of it
-may be incorrect in the general case.
-
-@menu
-* Portable File Characters::    
-* Portable File Structure::     
-* Portable File Header::        
-* Version and Date Info Record::  
-* Identification Records::      
-* Variable Count Record::       
-* Case Weight Variable Record::  
-* Variable Records::            
-* Value Label Records::         
-* Portable File Document Record::
-* Portable File Data::          
-@end menu
-
-@node Portable File Characters
-@section Portable File Characters
-
-Portable files are arranged as a series of lines of 80
-characters each.  Each line is terminated by a carriage-return,
-line-feed sequence (``new-lines'').  New-lines are only used to avoid
-line length limits imposed by some OSes; they are not meaningful.
-
-Most lines in portable files are exactly 80 characters long.  The only
-exception is a line that ends in one or more spaces, in which the
-spaces may optionally be omitted.  Thus, a portable file reader must
-act as though a line shorter than 80 characters is padded to that
-length with spaces.
-
-The file must be terminated with a @samp{Z} character.  In addition, if
-the final line in the file does not have exactly 80 characters, then it
-is padded on the right with @samp{Z} characters.  (The file contents may
-be in any character set; the file contains a description of its own
-character set, as explained in the next section.  Therefore, the
-@samp{Z} character is not necessarily an ASCII @samp{Z}.)
-
-For the rest of the description of the portable file format, new-lines
-and the trailing @samp{Z}s will be ignored, as if they did not exist,
-because they are not an important part of understanding the file
-contents.
-
-@node Portable File Structure
-@section Portable File Structure
-
-Every portable file consists of the following records, in sequence:
-
-@itemize @bullet
-
-@item
-File header.
-
-@item
-Version and date info.
-
-@item
-Product identification.
-
-@item
-Author identification (optional).
-
-@item
-Subproduct identification (optional).
-
-@item
-Variable count.
-
-@item
-Case weight variable (optional).
-
-@item
-Variables.  Each variable record may optionally be followed by a
-missing value record and a variable label record.
-
-@item
-Value labels (optional).
-
-@item
-Documents (optional).
-
-@item
-Data.
-@end itemize
-
-Most records are identified by a single-character tag code.  The file
-header and version info record do not have a tag.
-
-Other than these single-character codes, there are three types of fields
-in a portable file: floating-point, integer, and string.  Floating-point
-fields have the following format:
-
-@itemize @bullet
-
-@item
-Zero or more leading spaces.
-
-@item
-Optional asterisk (@samp{*}), which indicates a missing value.  The
-asterisk must be followed by a single character, generally a period
-(@samp{.}), but it appears that other characters may also be possible.
-This completes the specification of a missing value.
-
-@item
-Optional minus sign (@samp{-}) to indicate a negative number.
-
-@item
-A whole number, consisting of one or more base-30 digits: @samp{0}
-through @samp{9} plus capital letters @samp{A} through @samp{T}.
-
-@item
-Optional fraction, consisting of a radix point (@samp{.}) followed by
-one or more base-30 digits.
-
-@item
-Optional exponent, consisting of a plus or minus sign (@samp{+} or
-@samp{-}) followed by one or more base-30 digits.
-
-@item
-A forward slash (@samp{/}).
-@end itemize
-
-Integer fields take a form identical to floating-point fields, but they
-may not contain a fraction.
-
-String fields take the form of a integer field having value @var{n},
-followed by exactly @var{n} characters, which are the string content.
-
-@node Portable File Header
-@section Portable File Header
-
-Every portable file begins with a 464-byte header, consisting of a
-200-byte collection of vanity splash strings, followed by a 256-byte
-character set translation table, followed by an 8-byte tag string.
-
-The 200-byte segment is divided into five 40-byte sections, each of
-which represents the string @code{@var{charset} SPSS PORT FILE} in a
-different character set encoding, where @var{charset} is the name of
-the character set used in the file, e.g.@: @code{ASCII} or
-@code{EBCDIC}.  Each string is padded on the right with spaces in its
-respective character set.
-
-It appears that these strings exist only to inform those who might view
-the file on a screen, and that they are not parsed by SPSS products.
-Thus, they can be safely ignored.  For those interested, the strings are
-supposed to be in the following character sets, in the specified order:
-EBCDIC, 7-bit ASCII, CDC 6-bit ASCII, 6-bit ASCII, Honeywell 6-bit
-ASCII.
-
-The 256-byte segment describes a mapping from the character set used in
-the portable file to an arbitrary character set having characters at the
-following positions:
-
-@table @asis
-@item 0--60
-
-Control characters.  Not important enough to describe in full here.
-
-@item 61--63
-
-Reserved.
-
-@item 64--73
-
-Digits @samp{0} through @samp{9}.
-
-@item 74--99
-
-Capital letters @samp{A} through @samp{Z}. 
-
-@item 100--125
-
-Lowercase letters @samp{a} through @samp{z}.
-
-@item 126
-
-Space.
-
-@item 127--130
-
-Symbols @code{.<(+}
-
-@item 131
-
-Solid vertical pipe.
-
-@item 132--142
-
-Symbols @code{&[]!$*);^-/}
-
-@item 143
-
-Broken vertical pipe.
-
-@item 144--150
-
-Symbols @code{,%_>}?@code{`:}   @c @code{?} is an inverted question mark
-
-@item 151
-
-British pound symbol.
-
-@item 152--155
-
-Symbols @code{@@'="}.
-
-@item 156
-
-Less than or equal symbol.
-
-@item 157
-
-Empty box.
-
-@item 158
-
-Plus or minus.
-
-@item 159
-
-Filled box.
-
-@item 160
-
-Degree symbol.
-
-@item 161
-
-Dagger.
-
-@item 162
-
-Symbol @samp{~}.
-
-@item 163
-
-En dash.
-
-@item 164
-
-Lower left corner box draw.
-
-@item 165
-
-Upper left corner box draw.
-
-@item 166
-
-Greater than or equal symbol.
-
-@item 167--176
-
-Superscript @samp{0} through @samp{9}.
-
-@item 177
-
-Lower right corner box draw.
-
-@item 178
-
-Upper right corner box draw.
-
-@item 179
-
-Not equal symbol.
-
-@item 180
-
-Em dash.
-
-@item 181
-
-Superscript @samp{(}.
-
-@item 182
-
-Superscript @samp{)}.
-
-@item 183
-
-Horizontal dagger (?).
-
-@item 184--186
-
-Symbols @samp{@{@}\}.
-@item 187
-
-Cents symbol.
-
-@item 188
-
-Centered dot, or bullet.
-
-@item 189--255
-
-Reserved.
-@end table
-
-Symbols that are not defined in a particular character set are set to
-the same value as symbol 64; i.e., to @samp{0}.
-
-The 8-byte tag string consists of the exact characters @code{SPSSPORT}
-in the portable file's character set, which can be used to verify that
-the file is indeed a portable file.
-
-@node Version and Date Info Record
-@section Version and Date Info Record
-
-This record does not have a tag code.  It has the following structure:
-
-@itemize @bullet
-@item
-A single character identifying the file format version.  The letter A
-represents version 0, and so on.
-
-@item
-An 8-character string field giving the file creation date in the format
-YYYYMMDD.
-
-@item
-A 6-character string field giving the file creation time in the format
-HHMMSS.
-@end itemize
-
-@node Identification Records
-@section Identification Records
-
-The product identification record has tag code @samp{1}.  It consists of
-a single string field giving the name of the product that wrote the
-portable file.
-
-The author identification record has tag code @samp{2}.  It is
-optional.  If present, it consists of a single string field giving the
-name of the person who caused the portable file to be written.
-
-The subproduct identification record has tag code @samp{3}.  It is
-optional.  If present, it consists of a single string field giving
-additional information on the product that wrote the portable file.
-
-@node Variable Count Record
-@section Variable Count Record
-
-The variable count record has tag code @samp{4}.  It consists of two
-integer fields.  The first contains the number of variables in the file
-dictionary.  The purpose of the second is unknown; it contains the value
-161 in all portable files examined so far.
-
-@node Case Weight Variable Record
-@section Case Weight Variable Record
-
-The case weight variable record is optional.  If it is present, it
-indicates the variable used for weighting cases; if it is absent,
-cases are unweighted.  It has tag code @samp{6}.  It consists of a
-single string field that names the weighting variable.
-
-@node Variable Records
-@section Variable Records
-
-Each variable record represents a single variable.  Variable records
-have tag code @samp{7}.  They have the following structure:
-
-@itemize @bullet
-
-@item
-Width (integer).  This is 0 for a numeric variable, and a number between 1
-and 255 for a string variable.
-
-@item
-Name (string).  1--8 characters long.  Must be in all capitals.
-
-A few portable files that contain duplicate variable names have been
-spotted in the wild.  PSPP handles these by renaming the duplicates
-with numeric extensions: @code{@var{var}_1}, @code{@var{var}_2}, and
-so on.
-
-@item
-Print format.  This is a set of three integer fields:
-
-@itemize @minus
-
-@item
-Format type (@pxref{Variable Record}).
-
-@item
-Format width.  1--40.
-
-@item
-Number of decimal places.  1--40.
-@end itemize
-
-A few portable files with invalid format types or formats that are not
-of the appropriate width for their variables have been spotted in the
-wild.  PSPP assigns a default F or A format to a variable with an
-invalid format.
-
-@item
-Write format.  Same structure as the print format described above.
-@end itemize
-
-Each variable record can optionally be followed by a missing value
-record, which has tag code @samp{8}.  A missing value record has one
-field, the missing value itself (a floating-point or string, as
-appropriate).  Up to three of these missing value records can be used.
-
-There is also a record for missing value ranges, which has tag code
-@samp{B}.  It is followed by two fields representing the range, which
-are floating-point or string as appropriate.  If a missing value range
-is present, it may be followed by a single missing value record.
-
-Tag codes @samp{9} and @samp{A} represent @code{LO THRU @var{x}} and
-@code{@var{x} THRU HI} ranges, respectively.  Each is followed by a
-single field representing @var{x}.  If one of the ranges is present, it
-may be followed by a single missing value record.
-
-In addition, each variable record can optionally be followed by a
-variable label record, which has tag code @samp{C}.  A variable label
-record has one field, the variable label itself (string).
-
-@node Value Label Records
-@section Value Label Records
-
-Value label records have tag code @samp{D}.  They have the following
-format:
-
-@itemize @bullet
-@item
-Variable count (integer).
-
-@item
-List of variables (strings).  The variable count specifies the number in
-the list.  Variables are specified by their names.  All variables must
-be of the same type (numeric or string), but string variables do not
-necessarily have the same width.
-
-@item
-Label count (integer).
-
-@item
-List of (value, label) tuples.  The label count specifies the number of
-tuples.  Each tuple consists of a value, which is numeric or string as
-appropriate to the variables, followed by a label (string).
-@end itemize
-
-A few portable files that specify duplicate value labels, that is, two
-different labels for a single value of a single variable, have been
-spotted in the wild.  PSPP uses the last value label specified in
-these cases.
-
-@node Portable File Document Record
-@section Document Record
-
-One document record may optionally follow the value label record.  The
-document record consists of tag code @samp{E}, following by the number
-of document lines as an integer, followed by that number of strings,
-each of which represents one document line.  Document lines must be 80
-bytes long or shorter.
-
-@node Portable File Data
-@section Portable File Data
-
-The data record has tag code @samp{F}.  There is only one tag for all
-the data; thus, all the data must follow the dictionary.  The data is
-terminated by the end-of-file marker @samp{Z}, which is not valid as the
-beginning of a data element.
-
-Data elements are output in the same order as the variable records
-describing them.  String variables are output as string fields, and
-numeric variables are output as floating-point fields.
-@setfilename ignored
diff --git a/doc/pspp-dev.texinfo b/doc/pspp-dev.texinfo
new file mode 100644 (file)
index 0000000..991b04b
--- /dev/null
@@ -0,0 +1,113 @@
+\input texinfo @c -*- texinfo -*-
+@c %**start of header
+@setfilename pspp-dev.info
+@settitle PSPP
+@c For double-sided printing, uncomment:
+@c @setchapternewpage odd
+@c %**end of header
+
+@include version-dev.texi
+
+@macro cmd{CMDNAME}
+\CMDNAME\
+@end macro
+@macro struct{TAG}
+@code{struct \TAG\}
+@end macro
+@macro union{TAG}
+@code{union \TAG\}
+@end macro
+@macro enum{TAG}
+@code{enum \TAG\}
+@end macro
+@macro func{NAME}
+@code{\NAME\}
+@end macro
+
+@iftex
+@finalout
+@end iftex
+
+@dircategory Math
+@direntry
+* PSPP Developers Guide: (pspp-dev). Tutorial and reference for PSPP developers.
+@end direntry
+
+@copying
+This manual is for GNU PSPP version @value{VERSION},
+software for statistical analysis.
+
+Copyright @copyright{} 1997, 1998, 2004, 2005, 2007 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
+and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License.''
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+@end quotation
+@end copying
+
+@titlepage
+@title PSPP Developers Guide
+@subtitle GNU PSPP Statistical Analysis Software
+@subtitle Release @value{VERSION}
+@author
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@contents
+
+
+@ifnottex
+@node Top
+@top GNU PSPP Developers Guide
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Introduction::                Introduction to PSPP development.
+* Basic Concepts::              Data structures and concepts.
+* Parsing Command Syntax::      How to parse command syntax.
+* Processing Data::             Data input, output, and processing.
+* Presenting Output::           Producing machine- and human-readable output.
+
+* Function Index::              Index of PSPP functions.
+* Concept Index::               Index of concepts.
+
+* Portable File Format::        Format of PSPP portable files.
+* System File Format::          Format of PSPP system files.
+* q2c Input Format::            Format of syntax accepted by q2c.
+
+* GNU Free Documentation License:: License for copying this manual.
+@end menu
+
+@include dev/intro.texi
+@include dev/concepts.texi
+@include dev/syntax.texi
+@include dev/data.texi
+@include dev/output.texi
+
+@include function-index.texi
+@include concept-index.texi
+
+@include dev/portable-file-format.texi
+@include dev/system-file-format.texi
+@include dev/q2c.texi
+
+@include fdl.texi
+
+@bye
+
+@c Local Variables:
+@c compile-command: "makeinfo pspp-dev.texinfo"
+@c End:
index 9698cc588bc7b342fee2868ed0f5203251a3d306..b0759dd4c1ef095f43395c3145eb7976b20baa56 100644 (file)
@@ -43,9 +43,10 @@ Software Foundation raise funds for GNU development.''
 @end copying
 
 @titlepage
 @end copying
 
 @titlepage
-@title GNU PSPP
-@subtitle A System for Statistical Analysis
-@subtitle Edition @value{EDITION}, for PSPP version @value{VERSION}
+@title PSPP Users Guide
+@subtitle GNU PSPP Statistical Analysis Software
+@subtitle Release @value{VERSION}
+@author
 @page
 @vskip 0pt plus 1filll
 @insertcopying
 @page
 @vskip 0pt plus 1filll
 @insertcopying
@@ -87,10 +88,6 @@ Software Foundation raise funds for GNU development.''
 
 * Configuration::               Configuring PSPP.
 
 
 * Configuration::               Configuring PSPP.
 
-* Portable File Format::        Format of PSPP portable files.
-* System File Format::          Format of PSPP system files.
-* q2c Input Format::            Format of syntax accepted by q2c.
-
 * GNU Free Documentation License:: License for copying this manual.
 @end menu
 
 * GNU Free Documentation License:: License for copying this manual.
 @end menu
 
@@ -117,10 +114,6 @@ Software Foundation raise funds for GNU development.''
 
 @include configuring.texi
 
 
 @include configuring.texi
 
-@include portable-file-format.texi
-@include data-file-format.texi
-@include q2c.texi
-
 @include fdl.texi
 
 @bye
 @include fdl.texi
 
 @bye
diff --git a/doc/q2c.texi b/doc/q2c.texi
deleted file mode 100644 (file)
index fb61173..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-@node q2c Input Format
-@appendix @code{q2c} Input Format
-
-PSPP statistical procedures have a bizarre and somewhat irregular
-syntax.  Despite this, a parser generator has been written that
-adequately addresses many of the possibilities and tries to provide
-hooks for the exceptional cases.  This parser generator is named
-@code{q2c}.
-
-@menu
-* Invoking q2c::                q2c command-line syntax.
-* q2c Input Structure::         High-level layout of the input file.
-* Grammar Rules::               Syntax of the grammar rules.
-@end menu
-
-@node Invoking q2c
-@section Invoking q2c
-
-@example
-q2c @var{input.q} @var{output.c}
-@end example
-
-@code{q2c} translates a @samp{.q} file into a @samp{.c} file.  It takes
-exactly two command-line arguments, which are the input file name and
-output file name, respectively.  @code{q2c} does not accept any
-command-line options.
-
-@node q2c Input Structure
-@section @code{q2c} Input Structure
-
-@code{q2c} input files are divided into two sections: the grammar rules
-and the supporting code.  The @dfn{grammar rules}, which make up the
-first part of the input, are used to define the syntax of the
-statistical procedure to be parsed.  The @dfn{supporting code},
-following the grammar rules, are copied largely unchanged to the output
-file, except for certain escapes.
-
-The most important lines in the grammar rules are used for defining
-procedure syntax.  These lines can be prefixed with a dollar sign
-(@samp{$}), which prevents Emacs' CC-mode from munging them.  Besides
-this, a bang (@samp{!}) at the beginning of a line causes the line,
-minus the bang, to be written verbatim to the output file (useful for
-comments).  As a third special case, any line that begins with the exact
-characters @code{/* *INDENT} is ignored and not written to the output.
-This allows @code{.q} files to be processed through @code{indent}
-without being munged.
-
-The syntax of the grammar rules themselves is given in the following
-sections.
-
-The supporting code is passed into the output file largely unchanged.
-However, the following escapes are supported.  Each escape must appear
-on a line by itself.
-
-@table @code
-@item /* (header) */
-
-Expands to a series of C @code{#include} directives which include the
-headers that are required for the parser generated by @code{q2c}.
-
-@item /* (decls @var{scope}) */
-
-Expands to C variable and data type declarations for the variables and
-@code{enum}s input and output by the @code{q2c} parser.  @var{scope}
-must be either @code{local} or @code{global}.  @code{local} causes the
-declarations to be output as function locals.  @code{global} causes them
-to be declared as @code{static} module variables; thus, @code{global} is
-a bit of a misnomer.
-
-@item /* (parser) */
-
-Expands to the entire parser.  Must be enclosed within a C function.
-
-@item /* (free) */
-
-Expands to a set of calls to the @code{free} function for variables
-declared by the parser.  Only needs to be invoked if subcommands of type
-@code{string} are used in the grammar rules.
-@end table
-
-@node Grammar Rules
-@section Grammar Rules
-
-The grammar rules describe the format of the syntax that the parser
-generated by @code{q2c} will understand.  The way that the grammar rules
-are included in @code{q2c} input file are described above.
-
-The grammar rules are divided into tokens of the following types:
-
-@table @asis
-@item Identifier (@code{ID})
-
-An identifier token is a sequence of letters, digits, and underscores
-(@samp{_}).  Identifiers are @emph{not} case-sensitive.
-
-@item String (@code{STRING})
-
-String tokens are initiated by a double-quote character (@samp{"}) and
-consist of all the characters between that double quote and the next
-double quote, which must be on the same line as the first.  Within a
-string, a backslash can be used as a ``literal escape''.  The only
-reasons to use a literal escape are to include a double quote or a
-backslash within a string.
-
-@item Special character
-
-Other characters, other than white space, constitute tokens in
-themselves.
-
-@end table
-
-The syntax of the grammar rules is as follows:
-
-@example
-grammar-rules ::= command-name opt-prefix : subcommands .
-command-name ::= ID
-             ::= STRING
-opt-prefix ::=
-           ::= ( ID )
-subcommands ::= subcommand
-            ::= subcommands ; subcommand
-@end example
-
-The syntax begins with an ID token that gives the name of the
-procedure to be parsed.  For command names that contain multiple
-words, a STRING token may be used instead, e.g.@: @samp{"FILE
-HANDLE"}.  Optionally, an ID in parentheses specifies a prefix used
-for all file-scope identifiers declared by the emitted code.
-
-The rest of the syntax consists of subcommands separated by semicolons
-(@samp{;}) and terminated with a full stop (@samp{.}).
-
-@example
-subcommand ::= default-opt arity-opt ID sbc-defn
-default-opt ::=
-            ::= *
-arity-opt ::=
-          ::= +
-          ::= ^
-sbc-defn ::= opt-prefix = specifiers
-         ::= [ ID ] = array-sbc
-         ::= opt-prefix = sbc-special-form
-@end example
-
-A subcommand that begins with an asterisk (@samp{*}) is the default
-subcommand.  The keyword used for the default subcommand can be omitted
-in the PSPP syntax file.
-
-A plus sign (@samp{+}) indicates that a subcommand can appear more than
-once.  A caret (@samp{^}) indicate that a subcommand must appear exactly
-once.  A subcommand marked with neither character may appear once or not
-at all, but not more than once.
-
-The subcommand name appears after the leading option characters.
-
-There are three forms of subcommands.  The first and most common form
-simply gives an equals sign (@samp{=}) and a list of specifiers, which
-can each be set to a single setting.  The second form declares an array,
-which is a set of flags that can be individually turned on by the user.
-There are also several special forms that do not take a list of
-specifiers.
-
-Arrays require an additional @code{ID} argument.  This is used as a
-prefix, prepended to the variable names constructed from the
-specifiers.  The other forms also allow an optional prefix to be
-specified.
-
-@example
-array-sbc ::= alternatives
-          ::= array-sbc , alternatives
-alternatives ::= ID
-             ::= alternatives | ID
-@end example
-
-An array subcommand is a set of Boolean values that can independently be
-turned on by the user, listed separated by commas (@samp{,}).  If an value has more
-than one name then these names are separated by pipes (@samp{|}).
-
-@example
-specifiers ::= specifier
-           ::= specifiers , specifier
-specifier ::= opt-id : settings
-opt-id ::=
-       ::= ID
-@end example
-
-Ordinary subcommands (other than arrays and special forms) require a
-list of specifiers.  Each specifier has an optional name and a list of
-settings.  If the name is given then a correspondingly named variable
-will be used to store the user's choice of setting.  If no name is given
-then there is no way to tell which setting the user picked; in this case
-the settings should probably have values attached.
-
-@example
-settings ::= setting
-         ::= settings / setting
-setting ::= setting-options ID setting-value
-setting-options ::=
-                ::= *
-                ::= !
-                ::= * !
-@end example
-
-Individual settings are separated by forward slashes (@samp{/}).  Each
-setting can be as little as an @code{ID} token, but options and values
-can optionally be included.  The @samp{*} option means that, for this
-setting, the @code{ID} can be omitted.  The @samp{!} option means that
-this option is the default for its specifier.
-
-@example
-setting-value ::=
-              ::= ( setting-value-2 )
-              ::= setting-value-2
-setting-value-2 ::= setting-value-options setting-value-type : ID 
-                    setting-value-restriction
-setting-value-options ::=
-                      ::= *
-setting-value-type ::= N
-                   ::= D
-                   ::= S
-setting-value-restriction ::= 
-                          ::= , STRING
-@end example
-
-Settings may have values.  If the value must be enclosed in parentheses,
-then enclose the value declaration in parentheses.  Declare the setting
-type as @samp{n}, @samp{d}, or @samp{s} for integer, floating-point,
-or string type, respectively.  The given @code{ID} is used to
-construct a variable name.
-If option @samp{*} is given, then the value is optional; otherwise it
-must be specified whenever the corresponding setting is specified.  A
-``restriction'' can also be specified which is a string giving a C
-expression limiting the valid range of the value.  The special escape
-@code{%s} should be used within the restriction to refer to the
-setting's value variable.
-
-@example
-sbc-special-form ::= VAR
-                 ::= VARLIST varlist-options
-                 ::= INTEGER opt-list
-                 ::= DOUBLE opt-list
-                 ::= PINT
-                 ::= STRING @r{(the literal word STRING)} string-options
-                 ::= CUSTOM
-varlist-options ::= 
-                ::= ( STRING )
-opt-list ::=
-         ::= LIST
-string-options ::= 
-               ::= ( STRING STRING )
-@end example
-
-The special forms are of the following types:
-
-@table @code
-@item VAR
-
-A single variable name.
-
-@item VARLIST
-
-A list of variables.  If given, the string can be used to provide
-@code{PV_@var{*}} options to the call to @code{parse_variables}. 
-
-@item INTEGER
-
-A single integer value.
-
-@item INTEGER LIST
-
-A list of integers separated by spaces or commas.
-
-@item DOUBLE
-
-A single floating-point value.
-
-@item DOUBLE LIST
-
-A list of floating-point values.
-
-@item PINT
-
-A single positive integer value.
-
-@item STRING
-
-A string value.  If the options are given then the first string is an
-expression giving a restriction on the value of the string; the second
-string is an error message to display when the restriction is violated.
-
-@item CUSTOM
-
-A custom function is used to parse this subcommand.  The function must
-have prototype @code{int custom_@var{name} (void)}.  It should return 0
-on failure (when it has already issued an appropriate diagnostic), 1 on
-success, or 2 if it fails and the calling function should issue a syntax
-error on behalf of the custom handler.
-
-@end table
-@setfilename ignored
index 94fa50744d6a4c70d48befce93b2b57438c1d658..314c435e37d1a1985202f4738ea5bf007815ad24 100644 (file)
@@ -406,6 +406,7 @@ files.  The data input subcommands are
 
 @table @asis
 @item BLANKS
 
 @table @asis
 @item BLANKS
+@anchor{SET BLANKS}
 This is the value assigned to an item data item that is empty or
 contains only white space.  An argument of SYSMIS or '.' will cause the
 system-missing value to be assigned to null items.  This is the
 This is the value assigned to an item data item that is empty or
 contains only white space.  An argument of SYSMIS or '.' will cause the
 system-missing value to be assigned to null items.  This is the
index 46c6df8f6cac9037fdfe42aef55b0c2f83501bdb..a66e423292054adf60892eb059449e8db7dff2a1 100644 (file)
@@ -378,7 +378,7 @@ statistical procedures.
 To assign a variable label to a group of variables, specify a 
 list of variable names and the variable label as a string.
 To assign different labels to different variables in the same command, 
 To assign a variable label to a group of variables, specify a 
 list of variable names and the variable label as a string.
 To assign different labels to different variables in the same command, 
-preceed the subsequent variable list with a slash (@samp{/}).
+precede the subsequent variable list with a slash (@samp{/}).
 
 
 @node VARIABLE ALIGNMENT
 
 
 @node VARIABLE ALIGNMENT
index 0e91bb1a81a845e6f76d014b063548e1ff80fa87..3c374e700ffdd2de9b09b46fcad9b6fdbf8e331c 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PSPP 0.4.3\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
 msgstr ""
 "Project-Id-Version: PSPP 0.4.3\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2007-11-08 09:15+0900\n"
+"POT-Creation-Date: 2007-11-10 20:49-0800\n"
 "PO-Revision-Date: 2006-07-28 19:32+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: German <pspp-dev@gnu.org>\n"
 "PO-Revision-Date: 2006-07-28 19:32+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: German <pspp-dev@gnu.org>\n"
@@ -47,12 +47,6 @@ msgstr "Tag %d muß zwischen 0 bit 31 sein."
 msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15."
 msgstr ""
 
 msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15."
 msgstr ""
 
-#: src/data/casereader-filter.c:221
-msgid ""
-"At least one case in the data read had a weight value that was user-missing, "
-"system-missing, zero, or negative.  These case(s) were ignored."
-msgstr ""
-
 #: src/data/case-tmpfile.c:57
 msgid "failed to create temporary file"
 msgstr ""
 #: src/data/case-tmpfile.c:57
 msgid "failed to create temporary file"
 msgstr ""
@@ -73,157 +67,163 @@ msgstr "plotzlich ist der Datei beendet"
 msgid "writing to temporary file"
 msgstr ""
 
 msgid "writing to temporary file"
 msgstr ""
 
-#: src/data/data-in.c:267 src/data/data-in.c:457
+#: src/data/casereader-filter.c:221
+msgid ""
+"At least one case in the data read had a weight value that was user-missing, "
+"system-missing, zero, or negative.  These case(s) were ignored."
+msgstr ""
+
+#: src/data/data-in.c:287 src/data/data-in.c:477
 msgid "Field contents are not numeric."
 msgstr ""
 
 msgid "Field contents are not numeric."
 msgstr ""
 
-#: src/data/data-in.c:269 src/data/data-in.c:459
+#: src/data/data-in.c:289 src/data/data-in.c:479
 msgid "Number followed by garbage."
 msgstr ""
 
 msgid "Number followed by garbage."
 msgstr ""
 
-#: src/data/data-in.c:280
+#: src/data/data-in.c:300
 msgid "Invalid numeric syntax."
 msgstr ""
 
 msgid "Invalid numeric syntax."
 msgstr ""
 
-#: src/data/data-in.c:289 src/data/data-in.c:472
+#: src/data/data-in.c:309 src/data/data-in.c:492
 msgid "Too-large number set to system-missing."
 msgstr ""
 
 msgid "Too-large number set to system-missing."
 msgstr ""
 
-#: src/data/data-in.c:294 src/data/data-in.c:477
+#: src/data/data-in.c:314 src/data/data-in.c:497
 msgid "Too-small number set to zero."
 msgstr ""
 
 msgid "Too-small number set to zero."
 msgstr ""
 
-#: src/data/data-in.c:320
+#: src/data/data-in.c:340
 msgid "All characters in field must be digits."
 msgstr ""
 
 msgid "All characters in field must be digits."
 msgstr ""
 
-#: src/data/data-in.c:343
+#: src/data/data-in.c:363
 msgid "Unrecognized character in field."
 msgstr ""
 
 msgid "Unrecognized character in field."
 msgstr ""
 
-#: src/data/data-in.c:367 src/data/data-in.c:631
+#: src/data/data-in.c:387 src/data/data-in.c:660
 msgid "Field must have even length."
 msgstr ""
 
 msgid "Field must have even length."
 msgstr ""
 
-#: src/data/data-in.c:372 src/data/data-in.c:637
+#: src/data/data-in.c:392 src/data/data-in.c:671
 msgid "Field must contain only hex digits."
 msgstr ""
 
 msgid "Field must contain only hex digits."
 msgstr ""
 
-#: src/data/data-in.c:676 src/data/data-in.c:723
+#: src/data/data-in.c:710 src/data/data-in.c:757
 msgid "Syntax error in date field."
 msgstr ""
 
 msgid "Syntax error in date field."
 msgstr ""
 
-#: src/data/data-in.c:692
+#: src/data/data-in.c:726
 #, c-format
 msgid "Day (%ld) must be between 1 and 31."
 msgstr ""
 
 #, c-format
 msgid "Day (%ld) must be between 1 and 31."
 msgstr ""
 
-#: src/data/data-in.c:739
+#: src/data/data-in.c:773
 msgid "Delimiter expected between fields in date."
 msgstr ""
 
 msgid "Delimiter expected between fields in date."
 msgstr ""
 
-#: src/data/data-in.c:813
+#: src/data/data-in.c:847
 msgid ""
 "Unrecognized month format.  Months may be specified as Arabic or Roman "
 "numerals or as at least 3 letters of their English names."
 msgstr ""
 
 msgid ""
 "Unrecognized month format.  Months may be specified as Arabic or Roman "
 "numerals or as at least 3 letters of their English names."
 msgstr ""
 
-#: src/data/data-in.c:840
+#: src/data/data-in.c:874
 #, c-format
 msgid "Year (%ld) must be between 1582 and 19999."
 msgstr ""
 
 #, c-format
 msgid "Year (%ld) must be between 1582 and 19999."
 msgstr ""
 
-#: src/data/data-in.c:852
+#: src/data/data-in.c:886
 #, c-format
 msgid "Trailing garbage \"%.*s\" following date."
 msgstr ""
 
 #, c-format
 msgid "Trailing garbage \"%.*s\" following date."
 msgstr ""
 
-#: src/data/data-in.c:868
+#: src/data/data-in.c:902
 msgid "Julian day must have exactly three digits."
 msgstr ""
 
 msgid "Julian day must have exactly three digits."
 msgstr ""
 
-#: src/data/data-in.c:873
+#: src/data/data-in.c:907
 #, c-format
 msgid "Julian day (%ld) must be between 1 and 366."
 msgstr ""
 
 #, c-format
 msgid "Julian day (%ld) must be between 1 and 366."
 msgstr ""
 
-#: src/data/data-in.c:897
+#: src/data/data-in.c:931
 #, c-format
 msgid "Quarter (%ld) must be between 1 and 4."
 msgstr ""
 
 #, c-format
 msgid "Quarter (%ld) must be between 1 and 4."
 msgstr ""
 
-#: src/data/data-in.c:917
+#: src/data/data-in.c:951
 #, c-format
 msgid "Week (%ld) must be between 1 and 53."
 msgstr ""
 
 #, c-format
 msgid "Week (%ld) must be between 1 and 53."
 msgstr ""
 
-#: src/data/data-in.c:930
+#: src/data/data-in.c:964
 msgid "Delimiter expected between fields in time."
 msgstr ""
 
 msgid "Delimiter expected between fields in time."
 msgstr ""
 
-#: src/data/data-in.c:950
+#: src/data/data-in.c:984
 #, c-format
 msgid "Minute (%ld) must be between 0 and 59."
 msgstr ""
 
 #, c-format
 msgid "Minute (%ld) must be between 0 and 59."
 msgstr ""
 
-#: src/data/data-in.c:990
+#: src/data/data-in.c:1024
 msgid ""
 "Unrecognized weekday name.  At least the first two letters of an English "
 "weekday name must be specified."
 msgstr ""
 
 msgid ""
 "Unrecognized weekday name.  At least the first two letters of an English "
 "weekday name must be specified."
 msgstr ""
 
-#: src/data/data-in.c:1128
+#: src/data/data-in.c:1162
 #, c-format
 msgid "`%c' expected in date field."
 msgstr ""
 
 #, c-format
 msgid "`%c' expected in date field."
 msgstr ""
 
-#: src/data/data-in.c:1169
+#: src/data/data-in.c:1203
 #, c-format
 msgid "column %d"
 msgstr "Spalten %d"
 
 #, c-format
 msgid "column %d"
 msgstr "Spalten %d"
 
-#: src/data/data-in.c:1171
+#: src/data/data-in.c:1205
 #, fuzzy, c-format
 msgid "columns %d-%d"
 msgstr "Spalten"
 
 #, fuzzy, c-format
 msgid "columns %d-%d"
 msgstr "Spalten"
 
-#: src/data/data-in.c:1175
+#: src/data/data-in.c:1209
 #, c-format
 msgid "%s field) "
 msgstr ""
 
 #, c-format
 msgid "%s field) "
 msgstr ""
 
-#: src/data/data-out.c:465
+#: src/data/data-out.c:476
 #, c-format
 msgid "Weekday number %f is not between 1 and 7."
 msgstr ""
 
 #, c-format
 msgid "Weekday number %f is not between 1 and 7."
 msgstr ""
 
-#: src/data/data-out.c:486
+#: src/data/data-out.c:497
 #, c-format
 msgid "Month number %f is not between 1 and 12."
 msgstr ""
 
 #, c-format
 msgid "Month number %f is not between 1 and 12."
 msgstr ""
 
-#: src/data/dictionary.c:758
+#: src/data/dictionary.c:762
 msgid ""
 "At least one case in the data file had a weight value that was user-missing, "
 "system-missing, zero, or negative.  These case(s) were ignored."
 msgstr ""
 
 msgid ""
 "At least one case in the data file had a weight value that was user-missing, "
 "system-missing, zero, or negative.  These case(s) were ignored."
 msgstr ""
 
-#: src/data/dictionary.c:1059
+#: src/data/dictionary.c:1060
 #, c-format
 msgid "Truncating document line to %d bytes."
 msgstr ""
 
 #, c-format
 msgid "Truncating document line to %d bytes."
 msgstr ""
 
-#: src/data/file-handle-def.c:452
+#: src/data/file-handle-def.c:462
 #, c-format
 msgid "Can't read from %s as a %s because it is already being read as a %s."
 msgstr ""
 
 #, c-format
 msgid "Can't read from %s as a %s because it is already being read as a %s."
 msgstr ""
 
-#: src/data/file-handle-def.c:456
+#: src/data/file-handle-def.c:466
 #, c-format
 msgid "Can't write to %s as a %s because it is already being written as a %s."
 msgstr ""
 
 #, c-format
 msgid "Can't write to %s as a %s because it is already being written as a %s."
 msgstr ""
 
-#: src/data/file-handle-def.c:463
+#: src/data/file-handle-def.c:473
 #, c-format
 msgid "Can't re-open %s as a %s."
 msgstr ""
 #, c-format
 msgid "Can't re-open %s as a %s."
 msgstr ""
@@ -305,33 +305,33 @@ msgstr[1] ""
 msgid "%s variables are not compatible with %s format %s."
 msgstr ""
 
 msgid "%s variables are not compatible with %s format %s."
 msgstr ""
 
-#: src/data/format.c:318 src/data/sys-file-reader.c:638
-#: src/ui/gui/data-editor.glade:1285 src/ui/gui/psppire.glade:2176
-#: src/ui/gui/psppire-var-store.c:493
+#: src/data/format.c:318 src/data/sys-file-reader.c:639
+#: src/ui/gui/data-editor.glade:1285 src/ui/gui/psppire-var-store.c:493
+#: src/ui/gui/psppire.glade:2176
 msgid "String"
 msgstr "Zeichenkette"
 
 msgid "String"
 msgstr "Zeichenkette"
 
-#: src/data/format.c:318 src/data/sys-file-reader.c:638
-#: src/ui/gui/data-editor.glade:1174 src/ui/gui/psppire.glade:2131
-#: src/ui/gui/psppire-var-store.c:486
+#: src/data/format.c:318 src/data/sys-file-reader.c:639
+#: src/ui/gui/data-editor.glade:1174 src/ui/gui/psppire-var-store.c:486
+#: src/ui/gui/psppire.glade:2131
 msgid "Numeric"
 msgstr "Nummer"
 
 msgid "Numeric"
 msgstr "Nummer"
 
-#: src/data/format.c:319 src/data/sys-file-reader.c:1113
-#: src/data/sys-file-reader.c:1115
+#: src/data/format.c:319 src/data/sys-file-reader.c:1114
+#: src/data/sys-file-reader.c:1116
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
-#: src/language/xforms/recode.c:471 src/language/xforms/recode.c:472
-#: src/language/xforms/recode.c:484 src/language/xforms/recode.c:485
+#: src/language/xforms/recode.c:472 src/language/xforms/recode.c:473
+#: src/language/xforms/recode.c:485 src/language/xforms/recode.c:486
 msgid "numeric"
 msgstr "numerisch"
 
 msgid "numeric"
 msgstr "numerisch"
 
-#: src/data/format.c:319 src/data/sys-file-reader.c:1113
-#: src/data/sys-file-reader.c:1115
+#: src/data/format.c:319 src/data/sys-file-reader.c:1114
+#: src/data/sys-file-reader.c:1116
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
-#: src/language/xforms/recode.c:471 src/language/xforms/recode.c:472
-#: src/language/xforms/recode.c:484 src/language/xforms/recode.c:485
+#: src/language/xforms/recode.c:472 src/language/xforms/recode.c:473
+#: src/language/xforms/recode.c:485 src/language/xforms/recode.c:486
 msgid "string"
 msgstr "kette"
 
 msgid "string"
 msgstr "kette"
 
@@ -405,150 +405,150 @@ msgstr ""
 msgid "Removing %s: %s."
 msgstr ""
 
 msgid "Removing %s: %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:98
+#: src/data/por-file-reader.c:99
 #, c-format
 msgid "portable file %s corrupt at offset 0x%lx: "
 msgstr ""
 
 #, c-format
 msgid "portable file %s corrupt at offset 0x%lx: "
 msgstr ""
 
-#: src/data/por-file-reader.c:127
+#: src/data/por-file-reader.c:128
 #, c-format
 msgid "reading portable file %s at offset 0x%lx: "
 msgstr ""
 
 #, c-format
 msgid "reading portable file %s at offset 0x%lx: "
 msgstr ""
 
-#: src/data/por-file-reader.c:155
+#: src/data/por-file-reader.c:156
 #, c-format
 msgid "Error closing portable file \"%s\": %s."
 msgstr ""
 
 #, c-format
 msgid "Error closing portable file \"%s\": %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:207
+#: src/data/por-file-reader.c:208
 msgid "unexpected end of file"
 msgstr "plotzlich ist der Datei beendet"
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 msgid "unexpected end of file"
 msgstr "plotzlich ist der Datei beendet"
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/por-file-reader.c:267 src/data/por-file-writer.c:148
+#: src/data/por-file-reader.c:268 src/data/por-file-writer.c:148
 #, fuzzy
 msgid "portable file"
 msgstr "Tragbardatein (*.por)"
 
 #, fuzzy
 msgid "portable file"
 msgstr "Tragbardatein (*.por)"
 
-#: src/data/por-file-reader.c:275
+#: src/data/por-file-reader.c:276
 #, c-format
 msgid ""
 "An error occurred while opening \"%s\" for reading as a portable file: %s."
 msgstr ""
 
 #, c-format
 msgid ""
 "An error occurred while opening \"%s\" for reading as a portable file: %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:296
+#: src/data/por-file-reader.c:297
 msgid "Data record expected."
 msgstr ""
 
 msgid "Data record expected."
 msgstr ""
 
-#: src/data/por-file-reader.c:378
+#: src/data/por-file-reader.c:379
 msgid "Number expected."
 msgstr ""
 
 msgid "Number expected."
 msgstr ""
 
-#: src/data/por-file-reader.c:406
+#: src/data/por-file-reader.c:407
 msgid "Missing numeric terminator."
 msgstr ""
 
 msgid "Missing numeric terminator."
 msgstr ""
 
-#: src/data/por-file-reader.c:429
+#: src/data/por-file-reader.c:430
 msgid "Invalid integer."
 msgstr ""
 
 msgid "Invalid integer."
 msgstr ""
 
-#: src/data/por-file-reader.c:440
+#: src/data/por-file-reader.c:441
 #, c-format
 msgid "Bad string length %d."
 msgstr ""
 
 #, c-format
 msgid "Bad string length %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:501
+#: src/data/por-file-reader.c:502
 #, c-format
 msgid "%s: Not a portable file."
 msgstr ""
 
 #, c-format
 msgid "%s: Not a portable file."
 msgstr ""
 
-#: src/data/por-file-reader.c:517
+#: src/data/por-file-reader.c:518
 #, c-format
 msgid "Unrecognized version code `%c'."
 msgstr ""
 
 #, c-format
 msgid "Unrecognized version code `%c'."
 msgstr ""
 
-#: src/data/por-file-reader.c:526
+#: src/data/por-file-reader.c:527
 #, c-format
 msgid "Bad date string length %zu."
 msgstr ""
 
 #, c-format
 msgid "Bad date string length %zu."
 msgstr ""
 
-#: src/data/por-file-reader.c:528
+#: src/data/por-file-reader.c:529
 #, c-format
 msgid "Bad time string length %zu."
 msgstr ""
 
 #, c-format
 msgid "Bad time string length %zu."
 msgstr ""
 
-#: src/data/por-file-reader.c:570
+#: src/data/por-file-reader.c:571
 #, c-format
 msgid ""
 "%s: Bad format specifier byte (%d).  Variable will be assigned a default "
 "format."
 msgstr ""
 
 #, c-format
 msgid ""
 "%s: Bad format specifier byte (%d).  Variable will be assigned a default "
 "format."
 msgstr ""
 
-#: src/data/por-file-reader.c:591
+#: src/data/por-file-reader.c:592
 #, c-format
 msgid "Numeric variable %s has invalid format specifier %s."
 msgstr ""
 
 #, c-format
 msgid "Numeric variable %s has invalid format specifier %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:595
+#: src/data/por-file-reader.c:596
 #, c-format
 msgid "String variable %s with width %d has invalid format specifier %s."
 msgstr ""
 
 #, c-format
 msgid "String variable %s with width %d has invalid format specifier %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:619
+#: src/data/por-file-reader.c:620
 msgid "Expected variable count record."
 msgstr ""
 
 msgid "Expected variable count record."
 msgstr ""
 
-#: src/data/por-file-reader.c:623
+#: src/data/por-file-reader.c:624
 #, c-format
 msgid "Invalid number of variables %d."
 msgstr ""
 
 #, c-format
 msgid "Invalid number of variables %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:633
+#: src/data/por-file-reader.c:634
 #, c-format
 msgid "Weight variable name (%s) truncated."
 msgstr ""
 
 #, c-format
 msgid "Weight variable name (%s) truncated."
 msgstr ""
 
-#: src/data/por-file-reader.c:648
+#: src/data/por-file-reader.c:649
 msgid "Expected variable record."
 msgstr ""
 
 msgid "Expected variable record."
 msgstr ""
 
-#: src/data/por-file-reader.c:652
+#: src/data/por-file-reader.c:653
 #, c-format
 msgid "Invalid variable width %d."
 msgstr ""
 
 #, c-format
 msgid "Invalid variable width %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:660
+#: src/data/por-file-reader.c:661
 #, c-format
 msgid "Invalid variable name `%s' in position %d."
 msgstr ""
 
 #, c-format
 msgid "Invalid variable name `%s' in position %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:664
+#: src/data/por-file-reader.c:665
 #, c-format
 msgid "Bad width %d for variable %s."
 msgstr ""
 
 #, c-format
 msgid "Bad width %d for variable %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:679
+#: src/data/por-file-reader.c:680
 #, c-format
 msgid "Duplicate variable name %s in position %d."
 msgstr ""
 
 #, c-format
 msgid "Duplicate variable name %s in position %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:680
+#: src/data/por-file-reader.c:681
 #, c-format
 msgid "Duplicate variable name %s in position %d renamed to %s."
 msgstr ""
 
 #, c-format
 msgid "Duplicate variable name %s in position %d renamed to %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:723
+#: src/data/por-file-reader.c:724
 #, c-format
 msgid "Weighting variable %s not present in dictionary."
 msgstr ""
 
 #, c-format
 msgid "Weighting variable %s not present in dictionary."
 msgstr ""
 
-#: src/data/por-file-reader.c:770
+#: src/data/por-file-reader.c:771
 #, c-format
 msgid "Unknown variable %s while parsing value labels."
 msgstr ""
 
 #, c-format
 msgid "Unknown variable %s while parsing value labels."
 msgstr ""
 
-#: src/data/por-file-reader.c:773
+#: src/data/por-file-reader.c:774
 #, c-format
 msgid ""
 "Cannot assign value labels to %s and %s, which have different variable types."
 #, c-format
 msgid ""
 "Cannot assign value labels to %s and %s, which have different variable types."
@@ -578,7 +578,7 @@ msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/scratch-writer.c:67 src/language/data-io/file-handle.q:151
+#: src/data/scratch-writer.c:67 src/language/data-io/file-handle.q:180
 msgid "scratch file"
 msgstr ""
 
 msgid "scratch file"
 msgstr ""
 
@@ -588,299 +588,299 @@ msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/sys-file-reader.c:197 src/data/sys-file-writer.c:190
+#: src/data/sys-file-reader.c:198 src/data/sys-file-writer.c:190
 #, fuzzy
 msgid "system file"
 msgstr "Systemedatein (*.sav)"
 
 #, fuzzy
 msgid "system file"
 msgstr "Systemedatein (*.sav)"
 
-#: src/data/sys-file-reader.c:204
+#: src/data/sys-file-reader.c:205
 #, c-format
 msgid "Error opening \"%s\" for reading as a system file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error opening \"%s\" for reading as a system file: %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:243
+#: src/data/sys-file-reader.c:244
 msgid "Misplaced type 4 record."
 msgstr ""
 
 msgid "Misplaced type 4 record."
 msgstr ""
 
-#: src/data/sys-file-reader.c:254
+#: src/data/sys-file-reader.c:255
 #, c-format
 msgid "Unrecognized record type %d."
 msgstr ""
 
 #, c-format
 msgid "Unrecognized record type %d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:293
+#: src/data/sys-file-reader.c:294
 #, c-format
 msgid "File header claims %d variable positions but %d were read from file."
 msgstr ""
 
 #, c-format
 msgid "File header claims %d variable positions but %d were read from file."
 msgstr ""
 
-#: src/data/sys-file-reader.c:333
+#: src/data/sys-file-reader.c:334
 #, c-format
 msgid "Error closing system file \"%s\": %s."
 msgstr ""
 
 #, c-format
 msgid "Error closing system file \"%s\": %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:398 src/data/sys-file-reader.c:408
+#: src/data/sys-file-reader.c:399 src/data/sys-file-reader.c:409
 #, fuzzy
 msgid "This is not an SPSS system file."
 msgstr "\"%s\" ist kein Systemdatei und kein Tragbardatei."
 
 #, fuzzy
 msgid "This is not an SPSS system file."
 msgstr "\"%s\" ist kein Systemdatei und kein Tragbardatei."
 
-#: src/data/sys-file-reader.c:427
+#: src/data/sys-file-reader.c:428
 #, c-format
 msgid ""
 "Compression bias (%g) is not the usual value of 100, or system file uses "
 "unrecognized floating-point format."
 msgstr ""
 
 #, c-format
 msgid ""
 "Compression bias (%g) is not the usual value of 100, or system file uses "
 "unrecognized floating-point format."
 msgstr ""
 
-#: src/data/sys-file-reader.c:496
+#: src/data/sys-file-reader.c:497
 #, c-format
 msgid "Invalid variable name `%s'."
 msgstr ""
 
 #, c-format
 msgid "Invalid variable name `%s'."
 msgstr ""
 
-#: src/data/sys-file-reader.c:500
+#: src/data/sys-file-reader.c:501
 #, c-format
 msgid "Bad variable width %d."
 msgstr ""
 
 #, c-format
 msgid "Bad variable width %d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:504
+#: src/data/sys-file-reader.c:505
 #, c-format
 msgid "Duplicate variable name `%s' within system file."
 msgstr ""
 
 #, c-format
 msgid "Duplicate variable name `%s' within system file."
 msgstr ""
 
-#: src/data/sys-file-reader.c:512
+#: src/data/sys-file-reader.c:513
 msgid "Variable label indicator field is not 0 or 1."
 msgstr ""
 
 msgid "Variable label indicator field is not 0 or 1."
 msgstr ""
 
-#: src/data/sys-file-reader.c:520
+#: src/data/sys-file-reader.c:521
 #, c-format
 msgid "Variable %s has label of invalid length %zu."
 msgstr ""
 
 #, c-format
 msgid "Variable %s has label of invalid length %zu."
 msgstr ""
 
-#: src/data/sys-file-reader.c:539
+#: src/data/sys-file-reader.c:540
 msgid "Numeric missing value indicator field is not -3, -2, 0, 1, 2, or 3."
 msgstr ""
 
 msgid "Numeric missing value indicator field is not -3, -2, 0, 1, 2, or 3."
 msgstr ""
 
-#: src/data/sys-file-reader.c:554
+#: src/data/sys-file-reader.c:555
 msgid "String missing value indicator field is not 0, 1, 2, or 3."
 msgstr ""
 
 msgid "String missing value indicator field is not 0, 1, 2, or 3."
 msgstr ""
 
-#: src/data/sys-file-reader.c:564
+#: src/data/sys-file-reader.c:565
 #, c-format
 msgid "Long string variable %s may not have missing values."
 msgstr ""
 
 #, c-format
 msgid "Long string variable %s may not have missing values."
 msgstr ""
 
-#: src/data/sys-file-reader.c:585
+#: src/data/sys-file-reader.c:586
 msgid "Missing string continuation record."
 msgstr ""
 
 msgid "Missing string continuation record."
 msgstr ""
 
-#: src/data/sys-file-reader.c:619
+#: src/data/sys-file-reader.c:620
 #, c-format
 msgid "Unknown variable format %<PRIu8>."
 msgstr ""
 
 #, c-format
 msgid "Unknown variable format %<PRIu8>."
 msgstr ""
 
-#: src/data/sys-file-reader.c:637
+#: src/data/sys-file-reader.c:638
 #, c-format
 msgid "%s variable %s has invalid %s format %s."
 msgstr ""
 
 #, c-format
 msgid "%s variable %s has invalid %s format %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
 msgid "print"
 msgstr "drucken"
 
 msgid "print"
 msgstr "drucken"
 
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
 msgid "write"
 msgstr "schreiben"
 
 msgid "write"
 msgstr "schreiben"
 
-#: src/data/sys-file-reader.c:644
+#: src/data/sys-file-reader.c:645
 msgid "Suppressing further invalid format warnings."
 msgstr ""
 
 msgid "Suppressing further invalid format warnings."
 msgstr ""
 
-#: src/data/sys-file-reader.c:662
+#: src/data/sys-file-reader.c:663
 msgid "Weighting variable must be numeric."
 msgstr ""
 
 msgid "Weighting variable must be numeric."
 msgstr ""
 
-#: src/data/sys-file-reader.c:676
+#: src/data/sys-file-reader.c:677
 msgid "Multiple type 6 (document) records."
 msgstr ""
 
 msgid "Multiple type 6 (document) records."
 msgstr ""
 
-#: src/data/sys-file-reader.c:680
+#: src/data/sys-file-reader.c:681
 #, c-format
 msgid "Number of document lines (%d) must be greater than 0."
 msgstr ""
 
 #, c-format
 msgid "Number of document lines (%d) must be greater than 0."
 msgstr ""
 
-#: src/data/sys-file-reader.c:688
+#: src/data/sys-file-reader.c:689
 msgid "Document line contains null byte."
 msgstr ""
 
 msgid "Document line contains null byte."
 msgstr ""
 
-#: src/data/sys-file-reader.c:755
+#: src/data/sys-file-reader.c:756
 #, c-format
 msgid "Unrecognized record type 7, subtype %d."
 msgstr ""
 
 #, c-format
 msgid "Unrecognized record type 7, subtype %d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:780
+#: src/data/sys-file-reader.c:781
 #, c-format
 msgid "Bad size (%zu) or count (%zu) field on record type 7, subtype 3."
 msgstr ""
 
 #, c-format
 msgid "Bad size (%zu) or count (%zu) field on record type 7, subtype 3."
 msgstr ""
 
-#: src/data/sys-file-reader.c:800
+#: src/data/sys-file-reader.c:801
 #, c-format
 msgid ""
 "Floating-point representation indicated by system file (%d) differs from "
 "expected (%d)."
 msgstr ""
 
 #, c-format
 msgid ""
 "Floating-point representation indicated by system file (%d) differs from "
 "expected (%d)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
 msgid "little-endian"
 msgstr ""
 
 msgid "little-endian"
 msgstr ""
 
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
 msgid "big-endian"
 msgstr ""
 
 msgid "big-endian"
 msgstr ""
 
-#: src/data/sys-file-reader.c:814
+#: src/data/sys-file-reader.c:815
 #, c-format
 msgid ""
 "Integer format indicated by system file (%s) differs from expected (%s)."
 msgstr ""
 
 #, c-format
 msgid ""
 "Integer format indicated by system file (%s) differs from expected (%s)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:830
+#: src/data/sys-file-reader.c:831
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 4."
 msgstr ""
 
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 4."
 msgstr ""
 
-#: src/data/sys-file-reader.c:834
+#: src/data/sys-file-reader.c:835
 #, c-format
 msgid "File specifies unexpected value %g as SYSMIS."
 msgstr ""
 
 #, c-format
 msgid "File specifies unexpected value %g as SYSMIS."
 msgstr ""
 
-#: src/data/sys-file-reader.c:836
+#: src/data/sys-file-reader.c:837
 #, c-format
 msgid "File specifies unexpected value %g as HIGHEST."
 msgstr ""
 
 #, c-format
 msgid "File specifies unexpected value %g as HIGHEST."
 msgstr ""
 
-#: src/data/sys-file-reader.c:838
+#: src/data/sys-file-reader.c:839
 #, c-format
 msgid "File specifies unexpected value %g as LOWEST."
 msgstr ""
 
 #, c-format
 msgid "File specifies unexpected value %g as LOWEST."
 msgstr ""
 
-#: src/data/sys-file-reader.c:852
+#: src/data/sys-file-reader.c:853
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 11."
 msgstr ""
 
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 11."
 msgstr ""
 
-#: src/data/sys-file-reader.c:875
+#: src/data/sys-file-reader.c:876
 msgid "Invalid variable display parameters.  Default parameters substituted."
 msgstr ""
 
 msgid "Invalid variable display parameters.  Default parameters substituted."
 msgstr ""
 
-#: src/data/sys-file-reader.c:914
+#: src/data/sys-file-reader.c:915
 #, c-format
 msgid "Long variable mapping from %s to invalid variable name `%s'."
 msgstr ""
 
 #, c-format
 msgid "Long variable mapping from %s to invalid variable name `%s'."
 msgstr ""
 
-#: src/data/sys-file-reader.c:924
+#: src/data/sys-file-reader.c:925
 #, c-format
 msgid "Duplicate long variable name `%s' within system file."
 msgstr ""
 
 #, c-format
 msgid "Duplicate long variable name `%s' within system file."
 msgstr ""
 
-#: src/data/sys-file-reader.c:979
+#: src/data/sys-file-reader.c:980
 #, c-format
 msgid "%s listed as string of invalid length %s in very length string record."
 msgstr ""
 
 #, c-format
 msgid "%s listed as string of invalid length %s in very length string record."
 msgstr ""
 
-#: src/data/sys-file-reader.c:989
+#: src/data/sys-file-reader.c:990
 #, c-format
 msgid ""
 "%s listed in very long string record with width %s, which requires only one "
 "segment."
 msgstr ""
 
 #, c-format
 msgid ""
 "%s listed in very long string record with width %s, which requires only one "
 "segment."
 msgstr ""
 
-#: src/data/sys-file-reader.c:995
+#: src/data/sys-file-reader.c:996
 #, c-format
 msgid "Very long string %s overflows dictionary."
 msgstr ""
 
 #, c-format
 msgid "Very long string %s overflows dictionary."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1009
+#: src/data/sys-file-reader.c:1010
 #, c-format
 msgid ""
 "Very long string with width %ld has segment %d of width %d (expected %d)"
 msgstr ""
 
 #, c-format
 msgid ""
 "Very long string with width %ld has segment %d of width %d (expected %d)"
 msgstr ""
 
-#: src/data/sys-file-reader.c:1054
+#: src/data/sys-file-reader.c:1055
 #, c-format
 msgid "Invalid number of labels: %d.  Ignoring labels."
 msgstr ""
 
 #, c-format
 msgid "Invalid number of labels: %d.  Ignoring labels."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1085
+#: src/data/sys-file-reader.c:1086
 msgid ""
 "Variable index record (type 4) does not immediately follow value label "
 "record (type 3) as it should."
 msgstr ""
 
 msgid ""
 "Variable index record (type 4) does not immediately follow value label "
 "record (type 3) as it should."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1092
+#: src/data/sys-file-reader.c:1093
 #, c-format
 msgid ""
 "Number of variables associated with a value label (%d) is not between 1 and "
 "the number of variables (%zu)."
 msgstr ""
 
 #, c-format
 msgid ""
 "Number of variables associated with a value label (%d) is not between 1 and "
 "the number of variables (%zu)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1102
+#: src/data/sys-file-reader.c:1103
 #, c-format
 msgid "Value labels are not allowed on long string variables (%s)."
 msgstr ""
 
 #, c-format
 msgid "Value labels are not allowed on long string variables (%s)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1109
+#: src/data/sys-file-reader.c:1110
 #, c-format
 msgid ""
 "Variables associated with value label are not all of identical type.  "
 "Variable %s is %s, but variable %s is %s."
 msgstr ""
 
 #, c-format
 msgid ""
 "Variables associated with value label are not all of identical type.  "
 "Variable %s is %s, but variable %s is %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1142
+#: src/data/sys-file-reader.c:1143
 #, c-format
 msgid "Duplicate value label for %g on %s."
 msgstr ""
 
 #, c-format
 msgid "Duplicate value label for %g on %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1145
+#: src/data/sys-file-reader.c:1146
 #, c-format
 msgid "Duplicate value label for \"%.*s\" on %s."
 msgstr ""
 
 #, c-format
 msgid "Duplicate value label for \"%.*s\" on %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1223
+#: src/data/sys-file-reader.c:1224
 msgid "File ends in partial case."
 msgstr ""
 
 msgid "File ends in partial case."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1231
+#: src/data/sys-file-reader.c:1232
 #, c-format
 msgid "Error reading case from file %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading case from file %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1328 src/data/sys-file-reader.c:1364
+#: src/data/sys-file-reader.c:1329 src/data/sys-file-reader.c:1365
 msgid "Compressed data is corrupt."
 msgstr ""
 
 msgid "Compressed data is corrupt."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1451
+#: src/data/sys-file-reader.c:1452
 #, c-format
 msgid "Variable index %d not in valid range 1...%d."
 msgstr ""
 
 #, c-format
 msgid "Variable index %d not in valid range 1...%d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1456
+#: src/data/sys-file-reader.c:1457
 #, c-format
 msgid "Variable index %d refers to long string continuation."
 msgstr ""
 
 #, c-format
 msgid "Variable index %d refers to long string continuation."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1542
+#: src/data/sys-file-reader.c:1543
 #, c-format
 msgid "Suppressed %d additional variable map warnings."
 msgstr ""
 
 #, c-format
 msgid "Suppressed %d additional variable map warnings."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1555
+#: src/data/sys-file-reader.c:1556
 #, c-format
 msgid "Variable map refers to unknown variable %s."
 msgstr ""
 
 #, c-format
 msgid "Variable map refers to unknown variable %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1631
+#: src/data/sys-file-reader.c:1632
 #, c-format
 msgid "System error: %s."
 msgstr ""
 
 #, c-format
 msgid "System error: %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1633
+#: src/data/sys-file-reader.c:1634
 msgid "Unexpected end of file."
 msgstr "plotzlich ist der Datei beendet"
 
 msgid "Unexpected end of file."
 msgstr "plotzlich ist der Datei beendet"
 
@@ -899,44 +899,32 @@ msgstr ""
 msgid "An I/O error occurred writing system file \"%s\"."
 msgstr ""
 
 msgid "An I/O error occurred writing system file \"%s\"."
 msgstr ""
 
-#: src/data/variable.c:231
+#: src/data/variable.c:217
 #, c-format
 msgid ""
 "Character `%c' (in %s) may not appear as the first character in a variable "
 "name."
 msgstr ""
 
 #, c-format
 msgid ""
 "Character `%c' (in %s) may not appear as the first character in a variable "
 "name."
 msgstr ""
 
-#: src/data/variable.c:243
+#: src/data/variable.c:229
 #, c-format
 msgid "Character `%c' (in %s) may not appear in a variable name."
 msgstr ""
 
 #, c-format
 msgid "Character `%c' (in %s) may not appear in a variable name."
 msgstr ""
 
-#: src/data/variable.c:271
+#: src/data/variable.c:257
 msgid "Variable name cannot be empty string."
 msgstr "Ein Variablename darf nicht eines leeres Kette sein."
 
 msgid "Variable name cannot be empty string."
 msgstr "Ein Variablename darf nicht eines leeres Kette sein."
 
-#: src/data/variable.c:277
+#: src/data/variable.c:263
 #, c-format
 msgid "Variable name %s exceeds %d-character limit."
 msgstr "Der Variabelname %s ist große als %d Buchstaben."
 
 #, c-format
 msgid "Variable name %s exceeds %d-character limit."
 msgstr "Der Variabelname %s ist große als %d Buchstaben."
 
-#: src/data/variable.c:285
+#: src/data/variable.c:271
 #, c-format
 msgid "`%s' may not be used as a variable name because it is a reserved word."
 msgstr ""
 
 #, c-format
 msgid "`%s' may not be used as a variable name because it is a reserved word."
 msgstr ""
 
-#: src/data/variable.c:1003
-msgid "ordinary"
-msgstr ""
-
-#: src/data/variable.c:1005
-msgid "system"
-msgstr ""
-
-#: src/data/variable.c:1007
-msgid "scratch"
-msgstr ""
-
 #: src/language/command.c:208
 #, c-format
 msgid "%s is unimplemented."
 #: src/language/command.c:208
 #, c-format
 msgid "%s is unimplemented."
@@ -1175,7 +1163,7 @@ msgid ""
 msgstr ""
 
 #: src/language/data-io/data-list.c:434 src/language/data-io/data-list.c:543
 msgstr ""
 
 #: src/language/data-io/data-list.c:434 src/language/data-io/data-list.c:543
-#: src/language/data-io/print.c:397 src/language/dictionary/split-file.c:84
+#: src/language/data-io/print.c:401 src/language/dictionary/split-file.c:84
 #: src/language/dictionary/sys-file-info.c:161
 #: src/language/dictionary/sys-file-info.c:390
 #: src/language/dictionary/sys-file-info.c:634
 #: src/language/dictionary/sys-file-info.c:161
 #: src/language/dictionary/sys-file-info.c:390
 #: src/language/dictionary/sys-file-info.c:634
@@ -1183,17 +1171,17 @@ msgstr ""
 msgid "Variable"
 msgstr ""
 
 msgid "Variable"
 msgstr ""
 
-#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:398
+#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:402
 msgid "Record"
 msgstr ""
 
 msgid "Record"
 msgstr ""
 
-#: src/language/data-io/data-list.c:436 src/language/data-io/print.c:399
+#: src/language/data-io/data-list.c:436 src/language/data-io/print.c:403
 #: src/ui/gui/var-sheet.c:72
 msgid "Columns"
 msgstr "Spalten"
 
 #: src/language/data-io/data-list.c:437 src/language/data-io/data-list.c:544
 #: src/ui/gui/var-sheet.c:72
 msgid "Columns"
 msgstr "Spalten"
 
 #: src/language/data-io/data-list.c:437 src/language/data-io/data-list.c:544
-#: src/language/data-io/print.c:400
+#: src/language/data-io/print.c:404
 msgid "Format"
 msgstr ""
 
 msgid "Format"
 msgstr ""
 
@@ -1213,17 +1201,17 @@ msgstr ""
 msgid "Quoted string extends beyond end of line."
 msgstr ""
 
 msgid "Quoted string extends beyond end of line."
 msgstr ""
 
-#: src/language/data-io/data-list.c:689
+#: src/language/data-io/data-list.c:690
 #, c-format
 msgid "Partial case of %d of %d records discarded."
 msgstr ""
 
 #, c-format
 msgid "Partial case of %d of %d records discarded."
 msgstr ""
 
-#: src/language/data-io/data-list.c:733
+#: src/language/data-io/data-list.c:736
 #, c-format
 msgid "Partial case discarded.  The first variable missing was %s."
 msgstr ""
 
 #, c-format
 msgid "Partial case discarded.  The first variable missing was %s."
 msgstr ""
 
-#: src/language/data-io/data-list.c:764
+#: src/language/data-io/data-list.c:768
 #, c-format
 msgid ""
 "Missing value(s) for all variables from %s onward.  These will be filled "
 #, c-format
 msgid ""
 "Missing value(s) for all variables from %s onward.  These will be filled "
@@ -1232,98 +1220,128 @@ msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/language/data-io/data-reader.c:116
-#: src/language/data-io/data-writer.c:56
+#: src/language/data-io/data-reader.c:120
+#: src/language/data-io/data-writer.c:58
 #, fuzzy
 msgid "data file"
 msgstr "Speichern unter"
 
 #, fuzzy
 msgid "data file"
 msgstr "Speichern unter"
 
-#: src/language/data-io/data-reader.c:140
+#: src/language/data-io/data-reader.c:146
 #, c-format
 msgid "Could not open \"%s\" for reading as a data file: %s."
 msgstr ""
 
 #, c-format
 msgid "Could not open \"%s\" for reading as a data file: %s."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:178
+#: src/language/data-io/data-reader.c:184
 msgid ""
 "Unexpected end-of-file while reading data in BEGIN DATA.  This probably "
 "indicates a missing or misformatted END DATA command.  END DATA must appear "
 "by itself on a single line with exactly one space between words."
 msgstr ""
 
 msgid ""
 "Unexpected end-of-file while reading data in BEGIN DATA.  This probably "
 "indicates a missing or misformatted END DATA command.  END DATA must appear "
 "by itself on a single line with exactly one space between words."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:210
-#: src/language/data-io/data-reader.c:223
+#: src/language/data-io/data-reader.c:209
 #, c-format
 msgid "Error reading file %s: %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading file %s: %s."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:226
+#: src/language/data-io/data-reader.c:212
+#, fuzzy, c-format
+msgid "Unexpected end of file reading %s."
+msgstr "plotzlich ist der Datei beendet"
+
+#: src/language/data-io/data-reader.c:221
+#, fuzzy, c-format
+msgid "Unexpected end of file in partial record reading %s."
+msgstr "plotzlich ist der Datei beendet"
+
+#: src/language/data-io/data-reader.c:281
+#, c-format
+msgid "Corrupt block descriptor word at offset 0x%lx in %s."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:282
 #, c-format
 #, c-format
-msgid "%s: Partial record at end of file."
+msgid "Corrupt record descriptor word at offset 0x%lx in %s."
 msgstr ""
 
 msgstr ""
 
-#: src/language/data-io/data-reader.c:277
+#: src/language/data-io/data-reader.c:295
+#, c-format
+msgid "Corrupt record size at offset 0x%lx in %s."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:437
+msgid "Record exceeds remaining block length."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:511
 #, c-format
 msgid "Attempt to read beyond end-of-file on file %s."
 msgstr ""
 
 #, c-format
 msgid "Attempt to read beyond end-of-file on file %s."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:280
+#: src/language/data-io/data-reader.c:514
 msgid "Attempt to read beyond END DATA."
 msgstr ""
 
 msgid "Attempt to read beyond END DATA."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:438
+#: src/language/data-io/data-reader.c:679
 msgid ""
 "This command is not valid here since the current input program does not "
 "access the inline file."
 msgstr ""
 
 msgid ""
 "This command is not valid here since the current input program does not "
 "access the inline file."
 msgstr ""
 
-#: src/language/data-io/data-writer.c:72
+#: src/language/data-io/data-writer.c:74
 #, c-format
 msgid "An error occurred while opening \"%s\" for writing as a data file: %s."
 msgstr ""
 
 #, c-format
 msgid "An error occurred while opening \"%s\" for writing as a data file: %s."
 msgstr ""
 
-#: src/language/data-io/data-writer.c:150
+#: src/language/data-io/data-writer.c:191
 #, c-format
 msgid "I/O error occurred writing data file \"%s\"."
 msgstr ""
 
 #, c-format
 msgid "I/O error occurred writing data file \"%s\"."
 msgstr ""
 
-#: src/language/data-io/file-handle.q:65
+#: src/language/data-io/file-handle.q:64
 #, c-format
 msgid ""
 "File handle %s is already defined.  Use CLOSE FILE HANDLE before redefining "
 "a file handle."
 msgstr ""
 
 #, c-format
 msgid ""
 "File handle %s is already defined.  Use CLOSE FILE HANDLE before redefining "
 "a file handle."
 msgstr ""
 
-#: src/language/data-io/file-handle.q:97
+#: src/language/data-io/file-handle.q:119
+msgid "RECFORM must be specified with MODE=360."
+msgstr ""
+
+#: src/language/data-io/file-handle.q:130
 #, c-format
 #, c-format
-msgid ""
-"Fixed-length records were specified on /RECFORM, but record length was not "
-"specified on /LRECL.  Assuming %zu-character records."
+msgid "The specified file mode requires LRECL.  Assuming %d-character records."
 msgstr ""
 
 msgstr ""
 
-#: src/language/data-io/file-handle.q:102
+#: src/language/data-io/file-handle.q:134
 #, c-format
 msgid ""
 #, c-format
 msgid ""
-"Record length (%ld) must be at least one byte.  Assuming %zu-character "
+"Record length (%ld) must be between 1 and %lu bytes.  Assuming %d-character "
 "records."
 msgstr ""
 
 "records."
 msgstr ""
 
-#: src/language/data-io/file-handle.q:147
+#: src/language/data-io/file-handle.q:176
 msgid "file"
 msgstr ""
 
 msgid "file"
 msgstr ""
 
-#: src/language/data-io/file-handle.q:149
+#: src/language/data-io/file-handle.q:178
 msgid "inline file"
 msgstr ""
 
 msgid "inline file"
 msgstr ""
 
-#: src/language/data-io/file-handle.q:175
+#: src/language/data-io/file-handle.q:204
 msgid "expecting a file name or handle name"
 msgstr ""
 
 msgid "expecting a file name or handle name"
 msgstr ""
 
-#: src/language/data-io/file-handle.q:195
+#: src/language/data-io/file-handle.q:224
 #, c-format
 msgid "Handle for %s not allowed here."
 msgstr ""
 
 #, c-format
 msgid "Handle for %s not allowed here."
 msgstr ""
 
+#: src/language/data-io/get-data.c:48
+#, c-format
+msgid "Unsupported TYPE %s"
+msgstr ""
+
 #: src/language/data-io/get.c:106
 msgid "expecting COMM or TAPE"
 msgstr ""
 #: src/language/data-io/get.c:106
 msgid "expecting COMM or TAPE"
 msgstr ""
@@ -1334,7 +1352,7 @@ msgstr ""
 msgid "expecting %s or %s"
 msgstr ""
 
 msgid "expecting %s or %s"
 msgstr ""
 
-#: src/language/data-io/get.c:513 src/language/data-io/print.c:176
+#: src/language/data-io/get.c:513 src/language/data-io/print.c:177
 msgid "expecting a valid subcommand"
 msgstr ""
 
 msgid "expecting a valid subcommand"
 msgstr ""
 
@@ -1413,11 +1431,6 @@ msgid ""
 "variable in earlier file (%s)."
 msgstr ""
 
 "variable in earlier file (%s)."
 msgstr ""
 
-#: src/language/data-io/get-data.c:48
-#, c-format
-msgid "Unsupported TYPE %s"
-msgstr ""
-
 #: src/language/data-io/inpt-pgm.c:129
 msgid "Unexpected end-of-file within INPUT PROGRAM."
 msgstr ""
 #: src/language/data-io/inpt-pgm.c:129
 msgid "Unexpected end-of-file within INPUT PROGRAM."
 msgstr ""
@@ -1435,39 +1448,39 @@ msgid ""
 "REREAD: Column numbers must be positive finite numbers.  Column set to 1."
 msgstr ""
 
 "REREAD: Column numbers must be positive finite numbers.  Column set to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:156 src/language/stats/descriptives.c:362
+#: src/language/data-io/list.q:157 src/language/stats/descriptives.c:362
 msgid "No variables specified."
 msgstr ""
 
 msgid "No variables specified."
 msgstr ""
 
-#: src/language/data-io/list.q:164
+#: src/language/data-io/list.q:165
 #, c-format
 msgid ""
 "The first case (%ld) specified precedes the last case (%ld) specified.  The "
 "values will be swapped."
 msgstr ""
 
 #, c-format
 msgid ""
 "The first case (%ld) specified precedes the last case (%ld) specified.  The "
 "values will be swapped."
 msgstr ""
 
-#: src/language/data-io/list.q:172
+#: src/language/data-io/list.q:173
 #, c-format
 msgid ""
 "The first case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
 #, c-format
 msgid ""
 "The first case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:178
+#: src/language/data-io/list.q:179
 #, c-format
 msgid ""
 "The last case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
 #, c-format
 msgid ""
 "The last case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:184
+#: src/language/data-io/list.q:185
 #, c-format
 msgid "The step value %ld is less than 1.  The value is being reset to 1."
 msgstr ""
 
 #, c-format
 msgid "The step value %ld is less than 1.  The value is being reset to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:210
+#: src/language/data-io/list.q:211
 msgid "`/FORMAT WEIGHT' specified, but weighting is not on."
 msgstr ""
 
 msgid "`/FORMAT WEIGHT' specified, but weighting is not on."
 msgstr ""
 
-#: src/language/data-io/list.q:466
+#: src/language/data-io/list.q:467
 msgid "Line"
 msgstr ""
 
 msgid "Line"
 msgstr ""
 
@@ -1511,39 +1524,39 @@ msgid ""
 "Data fields must be listed in order of increasing record number."
 msgstr ""
 
 "Data fields must be listed in order of increasing record number."
 msgstr ""
 
-#: src/language/data-io/print.c:261
+#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:476
+#: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:60
+msgid "expecting end of command"
+msgstr ""
+
+#: src/language/data-io/print-space.c:116
+msgid "The expression on PRINT SPACE evaluated to the system-missing value."
+msgstr ""
+
+#: src/language/data-io/print-space.c:119
+#, c-format
+msgid "The expression on PRINT SPACE evaluated to %g."
+msgstr ""
+
+#: src/language/data-io/print.c:265
 #, c-format
 msgid "Output calls for %d records but %zu specified on RECORDS subcommand."
 msgstr ""
 
 #, c-format
 msgid "Output calls for %d records but %zu specified on RECORDS subcommand."
 msgstr ""
 
-#: src/language/data-io/print.c:430
+#: src/language/data-io/print.c:434
 #, c-format
 msgid "Writing %d record to %s."
 msgid_plural "Writing %d records to %s."
 msgstr[0] ""
 msgstr[1] ""
 
 #, c-format
 msgid "Writing %d record to %s."
 msgid_plural "Writing %d records to %s."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/language/data-io/print.c:434
+#: src/language/data-io/print.c:438
 #, c-format
 msgid "Writing %d record."
 msgid_plural "Writing %d records."
 msgstr[0] ""
 msgstr[1] ""
 
 #, c-format
 msgid "Writing %d record."
 msgid_plural "Writing %d records."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:476
-#: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:60
-msgid "expecting end of command"
-msgstr ""
-
-#: src/language/data-io/print-space.c:116
-msgid "The expression on PRINT SPACE evaluated to the system-missing value."
-msgstr ""
-
-#: src/language/data-io/print-space.c:119
-#, c-format
-msgid "The expression on PRINT SPACE evaluated to %g."
-msgstr ""
-
 #: src/language/dictionary/apply-dictionary.c:75
 #, c-format
 msgid "Variable %s is %s in target file, but %s in source file."
 #: src/language/dictionary/apply-dictionary.c:75
 #, c-format
 msgid "Variable %s is %s in target file, but %s in source file."
@@ -2302,11 +2315,11 @@ msgstr ""
 msgid "LO or LOWEST must be part of a range."
 msgstr ""
 
 msgid "LO or LOWEST must be part of a range."
 msgstr ""
 
-#: src/language/lexer/range-parser.c:106
+#: src/language/lexer/range-parser.c:107
 msgid "System-missing value is not valid here."
 msgstr ""
 
 msgid "System-missing value is not valid here."
 msgstr ""
 
-#: src/language/lexer/range-parser.c:114
+#: src/language/lexer/range-parser.c:115
 msgid "expecting number or data string"
 msgstr ""
 
 msgid "expecting number or data string"
 msgstr ""
 
@@ -3045,73 +3058,73 @@ msgstr ""
 msgid "Tukey's Hinges"
 msgstr ""
 
 msgid "Tukey's Hinges"
 msgstr ""
 
-#: src/language/stats/flip.c:95
+#: src/language/stats/flip.c:96
 msgid ""
 "FLIP ignores TEMPORARY.  Temporary transformations will be made permanent."
 msgstr ""
 
 msgid ""
 "FLIP ignores TEMPORARY.  Temporary transformations will be made permanent."
 msgstr ""
 
-#: src/language/stats/flip.c:150
+#: src/language/stats/flip.c:151
 msgid "Could not create temporary file for FLIP."
 msgstr ""
 
 msgid "Could not create temporary file for FLIP."
 msgstr ""
 
-#: src/language/stats/flip.c:161
+#: src/language/stats/flip.c:162
 #, c-format
 msgid "Error writing FLIP file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error writing FLIP file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:261
+#: src/language/stats/flip.c:262
 #, c-format
 msgid "Could not create acceptable variant for variable %s."
 msgstr ""
 
 #, c-format
 msgid "Could not create acceptable variant for variable %s."
 msgstr ""
 
-#: src/language/stats/flip.c:277
+#: src/language/stats/flip.c:278
 msgid "Cannot create more than 99999 variable names."
 msgstr ""
 
 msgid "Cannot create more than 99999 variable names."
 msgstr ""
 
-#: src/language/stats/flip.c:393
+#: src/language/stats/flip.c:394
 #, c-format
 msgid "Error rewinding FLIP file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error rewinding FLIP file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:400
+#: src/language/stats/flip.c:401
 msgid "Error creating FLIP source file."
 msgstr ""
 
 msgid "Error creating FLIP source file."
 msgstr ""
 
-#: src/language/stats/flip.c:413
+#: src/language/stats/flip.c:414
 #, c-format
 msgid "Error reading FLIP file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading FLIP file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:415
+#: src/language/stats/flip.c:416
 msgid "Unexpected end of file reading FLIP file."
 msgstr "plotzlich ist der Datei beendet"
 
 msgid "Unexpected end of file reading FLIP file."
 msgstr "plotzlich ist der Datei beendet"
 
-#: src/language/stats/flip.c:431
+#: src/language/stats/flip.c:432
 #, c-format
 msgid "Error seeking FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error seeking FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:439
+#: src/language/stats/flip.c:440
 #, c-format
 msgid "Error writing FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error writing FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:450
+#: src/language/stats/flip.c:451
 #, c-format
 msgid "Error closing FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error closing FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:458
+#: src/language/stats/flip.c:459
 #, c-format
 msgid "Error rewinding FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error rewinding FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:487
+#: src/language/stats/flip.c:488
 #, c-format
 msgid "Error reading FLIP temporary file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading FLIP temporary file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:490
+#: src/language/stats/flip.c:491
 msgid "Unexpected end of file reading FLIP temporary file."
 msgstr ""
 
 msgid "Unexpected end of file reading FLIP temporary file."
 msgstr ""
 
@@ -3198,11 +3211,11 @@ msgstr ""
 msgid "Multivariate GLM not yet supported"
 msgstr ""
 
 msgid "Multivariate GLM not yet supported"
 msgstr ""
 
-#: src/language/stats/glm.q:271 src/language/stats/regression.q:1165
+#: src/language/stats/glm.q:271 src/language/stats/regression.q:1164
 msgid "Dependent variable must be numeric."
 msgstr ""
 
 msgid "Dependent variable must be numeric."
 msgstr ""
 
-#: src/language/stats/glm.q:346 src/language/stats/regression.q:1262
+#: src/language/stats/glm.q:346 src/language/stats/regression.q:1261
 msgid "No valid data found. This command was skipped."
 msgstr ""
 
 msgid "No valid data found. This command was skipped."
 msgstr ""
 
@@ -3214,6 +3227,22 @@ msgstr ""
 msgid "TABLES subcommand may not appear more than once."
 msgstr ""
 
 msgid "TABLES subcommand may not appear more than once."
 msgstr ""
 
+#: src/language/stats/npar-summary.c:108
+msgid "Descriptive Statistics"
+msgstr ""
+
+#: src/language/stats/npar-summary.c:145
+msgid "25th"
+msgstr ""
+
+#: src/language/stats/npar-summary.c:148
+msgid "50th (Median)"
+msgstr ""
+
+#: src/language/stats/npar-summary.c:151
+msgid "75th"
+msgstr ""
+
 #: src/language/stats/npar.q:98
 msgid "NPAR subcommand not currently implemented."
 msgstr ""
 #: src/language/stats/npar.q:98
 msgid "NPAR subcommand not currently implemented."
 msgstr ""
@@ -3238,22 +3267,6 @@ msgid ""
 "not match the number following (%zu)."
 msgstr ""
 
 "not match the number following (%zu)."
 msgstr ""
 
-#: src/language/stats/npar-summary.c:108
-msgid "Descriptive Statistics"
-msgstr ""
-
-#: src/language/stats/npar-summary.c:145
-msgid "25th"
-msgstr ""
-
-#: src/language/stats/npar-summary.c:148
-msgid "50th (Median)"
-msgstr ""
-
-#: src/language/stats/npar-summary.c:151
-msgid "75th"
-msgstr ""
-
 #: src/language/stats/oneway.q:169
 msgid "Number of contrast coefficients must equal the number of groups"
 msgstr ""
 #: src/language/stats/oneway.q:169
 msgid "Number of contrast coefficients must equal the number of groups"
 msgstr ""
@@ -3349,56 +3362,56 @@ msgstr ""
 msgid "Does not assume equal"
 msgstr ""
 
 msgid "Does not assume equal"
 msgstr ""
 
-#: src/language/stats/rank.q:220
+#: src/language/stats/rank.q:221
 #, c-format
 msgid "%s of %s by %s"
 msgstr ""
 
 #, c-format
 msgid "%s of %s by %s"
 msgstr ""
 
-#: src/language/stats/rank.q:225
+#: src/language/stats/rank.q:226
 #, c-format
 msgid "%s of %s"
 msgstr ""
 
 #, c-format
 msgid "%s of %s"
 msgstr ""
 
-#: src/language/stats/rank.q:601
+#: src/language/stats/rank.q:602
 msgid "Cannot create new rank variable.  All candidates in use."
 msgstr ""
 
 msgid "Cannot create new rank variable.  All candidates in use."
 msgstr ""
 
-#: src/language/stats/rank.q:694
+#: src/language/stats/rank.q:695
 msgid "Variables Created By RANK"
 msgstr ""
 
 msgid "Variables Created By RANK"
 msgstr ""
 
-#: src/language/stats/rank.q:718
+#: src/language/stats/rank.q:719
 #, c-format
 msgid "%s into %s(%s of %s using %s BY %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s using %s BY %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:729
+#: src/language/stats/rank.q:730
 #, c-format
 msgid "%s into %s(%s of %s BY %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s BY %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:743
+#: src/language/stats/rank.q:744
 #, c-format
 msgid "%s into %s(%s of %s using %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s using %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:753
+#: src/language/stats/rank.q:754
 #, c-format
 msgid "%s into %s(%s of %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:766
+#: src/language/stats/rank.q:767
 msgid ""
 "FRACTION has been specified, but NORMAL and PROPORTION rank functions have "
 "not been requested.  The FRACTION subcommand will be ignored."
 msgstr ""
 
 msgid ""
 "FRACTION has been specified, but NORMAL and PROPORTION rank functions have "
 "not been requested.  The FRACTION subcommand will be ignored."
 msgstr ""
 
-#: src/language/stats/rank.q:859
+#: src/language/stats/rank.q:860
 #, c-format
 msgid "Variable %s already exists."
 msgstr ""
 
 #, c-format
 msgid "Variable %s already exists."
 msgstr ""
 
-#: src/language/stats/rank.q:864
+#: src/language/stats/rank.q:865
 msgid "Too many variables in INTO clause."
 msgstr ""
 
 msgid "Too many variables in INTO clause."
 msgstr ""
 
@@ -3880,44 +3893,44 @@ msgstr ""
 msgid "Destination cannot be a string variable."
 msgstr ""
 
 msgid "Destination cannot be a string variable."
 msgstr ""
 
-#: src/language/xforms/recode.c:245
+#: src/language/xforms/recode.c:246
 msgid ""
 "Inconsistent target variable types.  Target variables must be all numeric or "
 "all string."
 msgstr ""
 
 msgid ""
 "Inconsistent target variable types.  Target variables must be all numeric or "
 "all string."
 msgstr ""
 
-#: src/language/xforms/recode.c:266
+#: src/language/xforms/recode.c:267
 msgid "CONVERT requires string input values and numeric output values."
 msgstr ""
 
 msgid "CONVERT requires string input values and numeric output values."
 msgstr ""
 
-#: src/language/xforms/recode.c:316
+#: src/language/xforms/recode.c:317
 msgid "THRU is not allowed with string variables."
 msgstr ""
 
 msgid "THRU is not allowed with string variables."
 msgstr ""
 
-#: src/language/xforms/recode.c:390
+#: src/language/xforms/recode.c:391
 msgid "expecting output value"
 msgstr ""
 
 msgid "expecting output value"
 msgstr ""
 
-#: src/language/xforms/recode.c:439
+#: src/language/xforms/recode.c:440
 #, c-format
 msgid ""
 "%zu variable(s) cannot be recoded into %zu variable(s).  Specify the same "
 "number of variables as source and target variables."
 msgstr ""
 
 #, c-format
 msgid ""
 "%zu variable(s) cannot be recoded into %zu variable(s).  Specify the same "
 "number of variables as source and target variables."
 msgstr ""
 
-#: src/language/xforms/recode.c:454
+#: src/language/xforms/recode.c:455
 #, c-format
 msgid ""
 "There is no variable named %s.  (All string variables specified on INTO must "
 "already exist.  Use the STRING command to create a string variable.)"
 msgstr ""
 
 #, c-format
 msgid ""
 "There is no variable named %s.  (All string variables specified on INTO must "
 "already exist.  Use the STRING command to create a string variable.)"
 msgstr ""
 
-#: src/language/xforms/recode.c:469
+#: src/language/xforms/recode.c:470
 #, c-format
 msgid "INTO is required with %s input values and %s output values."
 msgstr ""
 
 #, c-format
 msgid "INTO is required with %s input values and %s output values."
 msgstr ""
 
-#: src/language/xforms/recode.c:482
+#: src/language/xforms/recode.c:483
 #, c-format
 msgid "Type mismatch.  Cannot store %s data in %s variable %s."
 msgstr ""
 #, c-format
 msgid "Type mismatch.  Cannot store %s data in %s variable %s."
 msgstr ""
@@ -3948,23 +3961,23 @@ msgstr ""
 msgid "hash table:"
 msgstr ""
 
 msgid "hash table:"
 msgstr ""
 
-#: src/math/percentiles.c:40
+#: src/math/percentiles.c:41
 msgid "HAverage"
 msgstr ""
 
 msgid "HAverage"
 msgstr ""
 
-#: src/math/percentiles.c:41
+#: src/math/percentiles.c:42
 msgid "Weighted Average"
 msgstr ""
 
 msgid "Weighted Average"
 msgstr ""
 
-#: src/math/percentiles.c:42
+#: src/math/percentiles.c:43
 msgid "Rounded"
 msgstr ""
 
 msgid "Rounded"
 msgstr ""
 
-#: src/math/percentiles.c:43
+#: src/math/percentiles.c:44
 msgid "Empirical"
 msgstr ""
 
 msgid "Empirical"
 msgstr ""
 
-#: src/math/percentiles.c:44
+#: src/math/percentiles.c:45
 msgid "Empirical with averaging"
 msgstr ""
 
 msgid "Empirical with averaging"
 msgstr ""
 
@@ -5014,7 +5027,7 @@ msgstr ""
 msgid "Options:"
 msgstr ""
 
 msgid "Options:"
 msgstr ""
 
-#: src/ui/gui/find-dialog.c:657
+#: src/ui/gui/find-dialog.c:658
 #, c-format
 msgid "Bad regular expression: %s"
 msgstr ""
 #, c-format
 msgid "Bad regular expression: %s"
 msgstr ""
@@ -5189,10 +5202,6 @@ msgstr "xyzzy"
 msgid "Paste"
 msgstr "Datum"
 
 msgid "Paste"
 msgstr "Datum"
 
-#: src/ui/gui/psppire.c:197
-msgid "_Reset"
-msgstr "_Zurücksetzen"
-
 #: src/ui/gui/psppire-data-store.c:816
 msgid "var"
 msgstr ""
 #: src/ui/gui/psppire-data-store.c:816
 msgid "var"
 msgstr ""
@@ -5202,6 +5211,28 @@ msgstr ""
 msgid "%ld"
 msgstr ""
 
 msgid "%ld"
 msgstr ""
 
+#: src/ui/gui/psppire-var-store.c:479 src/ui/gui/var-display.c:14
+msgid "None"
+msgstr "Keine"
+
+#: src/ui/gui/psppire-var-store.c:489
+msgid "Scientific"
+msgstr "Wissenschäflich"
+
+#: src/ui/gui/psppire-var-store.c:492
+msgid "Custom"
+msgstr "Spezial"
+
+#: src/ui/gui/psppire-var-store.c:563 src/ui/gui/psppire-var-store.c:573
+#: src/ui/gui/psppire-var-store.c:583
+#, c-format
+msgid "%d"
+msgstr ""
+
+#: src/ui/gui/psppire.c:198
+msgid "_Reset"
+msgstr "_Zurücksetzen"
+
 #: src/ui/gui/psppire.glade:11
 #, fuzzy
 msgid "This is pre-alpha software.  Use at your own risk."
 #: src/ui/gui/psppire.glade:11
 #, fuzzy
 msgid "This is pre-alpha software.  Use at your own risk."
@@ -5445,24 +5476,6 @@ msgstr ""
 msgid "Search backward"
 msgstr ""
 
 msgid "Search backward"
 msgstr ""
 
-#: src/ui/gui/psppire-var-store.c:479 src/ui/gui/var-display.c:14
-msgid "None"
-msgstr "Keine"
-
-#: src/ui/gui/psppire-var-store.c:489
-msgid "Scientific"
-msgstr "Wissenschäflich"
-
-#: src/ui/gui/psppire-var-store.c:492
-msgid "Custom"
-msgstr "Spezial"
-
-#: src/ui/gui/psppire-var-store.c:563 src/ui/gui/psppire-var-store.c:573
-#: src/ui/gui/psppire-var-store.c:583
-#, c-format
-msgid "%d"
-msgstr ""
-
 #: src/ui/gui/rank.glade:111
 msgid "By:"
 msgstr ""
 #: src/ui/gui/rank.glade:111
 msgid "By:"
 msgstr ""
@@ -5627,6 +5640,11 @@ msgstr ""
 msgid "To End"
 msgstr ""
 
 msgid "To End"
 msgstr ""
 
+#: src/ui/gui/t-test-independent-samples-dialog.c:175
+#, c-format
+msgid "Confidence Interval: %2d %%"
+msgstr ""
+
 #: src/ui/gui/t-test.glade:56
 msgid "Define Groups"
 msgstr ""
 #: src/ui/gui/t-test.glade:56
 msgid "Define Groups"
 msgstr ""
@@ -5661,10 +5679,25 @@ msgstr ""
 msgid "Exclude cases _listwise"
 msgstr ""
 
 msgid "Exclude cases _listwise"
 msgstr ""
 
-#: src/ui/gui/t-test-independent-samples-dialog.c:175
-#, c-format
-msgid "Confidence Interval: %2d %%"
-msgstr ""
+#: src/ui/gui/var-sheet.c:65
+msgid "Name"
+msgstr "Name"
+
+#: src/ui/gui/var-sheet.c:68
+msgid "Decimals"
+msgstr "Dezimalstellen"
+
+#: src/ui/gui/var-sheet.c:70
+msgid "Values"
+msgstr "Werten"
+
+#: src/ui/gui/var-sheet.c:73
+msgid "Align"
+msgstr "Einstellung"
+
+#: src/ui/gui/var-sheet.c:74
+msgid "Measure"
+msgstr "Messe"
 
 #: src/ui/gui/variable-info-dialog.c:88
 #, fuzzy, c-format
 
 #: src/ui/gui/variable-info-dialog.c:88
 #, fuzzy, c-format
@@ -5696,26 +5729,6 @@ msgstr "Werten"
 msgid "%s %s\n"
 msgstr ""
 
 msgid "%s %s\n"
 msgstr ""
 
-#: src/ui/gui/var-sheet.c:65
-msgid "Name"
-msgstr "Name"
-
-#: src/ui/gui/var-sheet.c:68
-msgid "Decimals"
-msgstr "Dezimalstellen"
-
-#: src/ui/gui/var-sheet.c:70
-msgid "Values"
-msgstr "Werten"
-
-#: src/ui/gui/var-sheet.c:73
-msgid "Align"
-msgstr "Einstellung"
-
-#: src/ui/gui/var-sheet.c:74
-msgid "Measure"
-msgstr "Messe"
-
 #: src/ui/gui/weight-cases-dialog.c:88
 #, c-format
 msgid "Weight cases by %s"
 #: src/ui/gui/weight-cases-dialog.c:88
 #, c-format
 msgid "Weight cases by %s"
index 758a4e8ffb69a6a3380449f2a8cd1dee0833ad4d..fbafcf76d15733976696867b47e763da19a8cb34 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PSPP 0.4.3\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
 msgstr ""
 "Project-Id-Version: PSPP 0.4.3\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2007-11-08 09:15+0900\n"
+"POT-Creation-Date: 2007-11-10 20:49-0800\n"
 "PO-Revision-Date: 2007-09-15 08:29+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: John Darrington <john@darrington.wattle.id.au>\n"
 "PO-Revision-Date: 2007-09-15 08:29+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: John Darrington <john@darrington.wattle.id.au>\n"
@@ -44,12 +44,6 @@ msgstr ""
 msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15."
 msgstr ""
 
 msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15."
 msgstr ""
 
-#: src/data/casereader-filter.c:221
-msgid ""
-"At least one case in the data read had a weight value that was user-missing, "
-"system-missing, zero, or negative.  These case(s) were ignored."
-msgstr ""
-
 #: src/data/case-tmpfile.c:57
 msgid "failed to create temporary file"
 msgstr ""
 #: src/data/case-tmpfile.c:57
 msgid "failed to create temporary file"
 msgstr ""
@@ -70,157 +64,163 @@ msgstr ""
 msgid "writing to temporary file"
 msgstr ""
 
 msgid "writing to temporary file"
 msgstr ""
 
-#: src/data/data-in.c:267 src/data/data-in.c:457
+#: src/data/casereader-filter.c:221
+msgid ""
+"At least one case in the data read had a weight value that was user-missing, "
+"system-missing, zero, or negative.  These case(s) were ignored."
+msgstr ""
+
+#: src/data/data-in.c:287 src/data/data-in.c:477
 msgid "Field contents are not numeric."
 msgstr ""
 
 msgid "Field contents are not numeric."
 msgstr ""
 
-#: src/data/data-in.c:269 src/data/data-in.c:459
+#: src/data/data-in.c:289 src/data/data-in.c:479
 msgid "Number followed by garbage."
 msgstr ""
 
 msgid "Number followed by garbage."
 msgstr ""
 
-#: src/data/data-in.c:280
+#: src/data/data-in.c:300
 msgid "Invalid numeric syntax."
 msgstr ""
 
 msgid "Invalid numeric syntax."
 msgstr ""
 
-#: src/data/data-in.c:289 src/data/data-in.c:472
+#: src/data/data-in.c:309 src/data/data-in.c:492
 msgid "Too-large number set to system-missing."
 msgstr ""
 
 msgid "Too-large number set to system-missing."
 msgstr ""
 
-#: src/data/data-in.c:294 src/data/data-in.c:477
+#: src/data/data-in.c:314 src/data/data-in.c:497
 msgid "Too-small number set to zero."
 msgstr ""
 
 msgid "Too-small number set to zero."
 msgstr ""
 
-#: src/data/data-in.c:320
+#: src/data/data-in.c:340
 msgid "All characters in field must be digits."
 msgstr ""
 
 msgid "All characters in field must be digits."
 msgstr ""
 
-#: src/data/data-in.c:343
+#: src/data/data-in.c:363
 msgid "Unrecognized character in field."
 msgstr ""
 
 msgid "Unrecognized character in field."
 msgstr ""
 
-#: src/data/data-in.c:367 src/data/data-in.c:631
+#: src/data/data-in.c:387 src/data/data-in.c:660
 msgid "Field must have even length."
 msgstr ""
 
 msgid "Field must have even length."
 msgstr ""
 
-#: src/data/data-in.c:372 src/data/data-in.c:637
+#: src/data/data-in.c:392 src/data/data-in.c:671
 msgid "Field must contain only hex digits."
 msgstr ""
 
 msgid "Field must contain only hex digits."
 msgstr ""
 
-#: src/data/data-in.c:676 src/data/data-in.c:723
+#: src/data/data-in.c:710 src/data/data-in.c:757
 msgid "Syntax error in date field."
 msgstr ""
 
 msgid "Syntax error in date field."
 msgstr ""
 
-#: src/data/data-in.c:692
+#: src/data/data-in.c:726
 #, c-format
 msgid "Day (%ld) must be between 1 and 31."
 msgstr ""
 
 #, c-format
 msgid "Day (%ld) must be between 1 and 31."
 msgstr ""
 
-#: src/data/data-in.c:739
+#: src/data/data-in.c:773
 msgid "Delimiter expected between fields in date."
 msgstr ""
 
 msgid "Delimiter expected between fields in date."
 msgstr ""
 
-#: src/data/data-in.c:813
+#: src/data/data-in.c:847
 msgid ""
 "Unrecognized month format.  Months may be specified as Arabic or Roman "
 "numerals or as at least 3 letters of their English names."
 msgstr ""
 
 msgid ""
 "Unrecognized month format.  Months may be specified as Arabic or Roman "
 "numerals or as at least 3 letters of their English names."
 msgstr ""
 
-#: src/data/data-in.c:840
+#: src/data/data-in.c:874
 #, c-format
 msgid "Year (%ld) must be between 1582 and 19999."
 msgstr ""
 
 #, c-format
 msgid "Year (%ld) must be between 1582 and 19999."
 msgstr ""
 
-#: src/data/data-in.c:852
+#: src/data/data-in.c:886
 #, c-format
 msgid "Trailing garbage \"%.*s\" following date."
 msgstr ""
 
 #, c-format
 msgid "Trailing garbage \"%.*s\" following date."
 msgstr ""
 
-#: src/data/data-in.c:868
+#: src/data/data-in.c:902
 msgid "Julian day must have exactly three digits."
 msgstr ""
 
 msgid "Julian day must have exactly three digits."
 msgstr ""
 
-#: src/data/data-in.c:873
+#: src/data/data-in.c:907
 #, c-format
 msgid "Julian day (%ld) must be between 1 and 366."
 msgstr ""
 
 #, c-format
 msgid "Julian day (%ld) must be between 1 and 366."
 msgstr ""
 
-#: src/data/data-in.c:897
+#: src/data/data-in.c:931
 #, c-format
 msgid "Quarter (%ld) must be between 1 and 4."
 msgstr ""
 
 #, c-format
 msgid "Quarter (%ld) must be between 1 and 4."
 msgstr ""
 
-#: src/data/data-in.c:917
+#: src/data/data-in.c:951
 #, c-format
 msgid "Week (%ld) must be between 1 and 53."
 msgstr ""
 
 #, c-format
 msgid "Week (%ld) must be between 1 and 53."
 msgstr ""
 
-#: src/data/data-in.c:930
+#: src/data/data-in.c:964
 msgid "Delimiter expected between fields in time."
 msgstr ""
 
 msgid "Delimiter expected between fields in time."
 msgstr ""
 
-#: src/data/data-in.c:950
+#: src/data/data-in.c:984
 #, c-format
 msgid "Minute (%ld) must be between 0 and 59."
 msgstr ""
 
 #, c-format
 msgid "Minute (%ld) must be between 0 and 59."
 msgstr ""
 
-#: src/data/data-in.c:990
+#: src/data/data-in.c:1024
 msgid ""
 "Unrecognized weekday name.  At least the first two letters of an English "
 "weekday name must be specified."
 msgstr ""
 
 msgid ""
 "Unrecognized weekday name.  At least the first two letters of an English "
 "weekday name must be specified."
 msgstr ""
 
-#: src/data/data-in.c:1128
+#: src/data/data-in.c:1162
 #, c-format
 msgid "`%c' expected in date field."
 msgstr ""
 
 #, c-format
 msgid "`%c' expected in date field."
 msgstr ""
 
-#: src/data/data-in.c:1169
+#: src/data/data-in.c:1203
 #, c-format
 msgid "column %d"
 msgstr ""
 
 #, c-format
 msgid "column %d"
 msgstr ""
 
-#: src/data/data-in.c:1171
+#: src/data/data-in.c:1205
 #, c-format
 msgid "columns %d-%d"
 msgstr ""
 
 #, c-format
 msgid "columns %d-%d"
 msgstr ""
 
-#: src/data/data-in.c:1175
+#: src/data/data-in.c:1209
 #, c-format
 msgid "%s field) "
 msgstr ""
 
 #, c-format
 msgid "%s field) "
 msgstr ""
 
-#: src/data/data-out.c:465
+#: src/data/data-out.c:476
 #, c-format
 msgid "Weekday number %f is not between 1 and 7."
 msgstr ""
 
 #, c-format
 msgid "Weekday number %f is not between 1 and 7."
 msgstr ""
 
-#: src/data/data-out.c:486
+#: src/data/data-out.c:497
 #, c-format
 msgid "Month number %f is not between 1 and 12."
 msgstr ""
 
 #, c-format
 msgid "Month number %f is not between 1 and 12."
 msgstr ""
 
-#: src/data/dictionary.c:758
+#: src/data/dictionary.c:762
 msgid ""
 "At least one case in the data file had a weight value that was user-missing, "
 "system-missing, zero, or negative.  These case(s) were ignored."
 msgstr ""
 
 msgid ""
 "At least one case in the data file had a weight value that was user-missing, "
 "system-missing, zero, or negative.  These case(s) were ignored."
 msgstr ""
 
-#: src/data/dictionary.c:1059
+#: src/data/dictionary.c:1060
 #, c-format
 msgid "Truncating document line to %d bytes."
 msgstr ""
 
 #, c-format
 msgid "Truncating document line to %d bytes."
 msgstr ""
 
-#: src/data/file-handle-def.c:452
+#: src/data/file-handle-def.c:462
 #, c-format
 msgid "Can't read from %s as a %s because it is already being read as a %s."
 msgstr ""
 
 #, c-format
 msgid "Can't read from %s as a %s because it is already being read as a %s."
 msgstr ""
 
-#: src/data/file-handle-def.c:456
+#: src/data/file-handle-def.c:466
 #, c-format
 msgid "Can't write to %s as a %s because it is already being written as a %s."
 msgstr ""
 
 #, c-format
 msgid "Can't write to %s as a %s because it is already being written as a %s."
 msgstr ""
 
-#: src/data/file-handle-def.c:463
+#: src/data/file-handle-def.c:473
 #, c-format
 msgid "Can't re-open %s as a %s."
 msgstr ""
 #, c-format
 msgid "Can't re-open %s as a %s."
 msgstr ""
@@ -302,33 +302,33 @@ msgstr[1] ""
 msgid "%s variables are not compatible with %s format %s."
 msgstr ""
 
 msgid "%s variables are not compatible with %s format %s."
 msgstr ""
 
-#: src/data/format.c:318 src/data/sys-file-reader.c:638
-#: src/ui/gui/data-editor.glade:1285 src/ui/gui/psppire.glade:2176
-#: src/ui/gui/psppire-var-store.c:493
+#: src/data/format.c:318 src/data/sys-file-reader.c:639
+#: src/ui/gui/data-editor.glade:1285 src/ui/gui/psppire-var-store.c:493
+#: src/ui/gui/psppire.glade:2176
 msgid "String"
 msgstr ""
 
 msgid "String"
 msgstr ""
 
-#: src/data/format.c:318 src/data/sys-file-reader.c:638
-#: src/ui/gui/data-editor.glade:1174 src/ui/gui/psppire.glade:2131
-#: src/ui/gui/psppire-var-store.c:486
+#: src/data/format.c:318 src/data/sys-file-reader.c:639
+#: src/ui/gui/data-editor.glade:1174 src/ui/gui/psppire-var-store.c:486
+#: src/ui/gui/psppire.glade:2131
 msgid "Numeric"
 msgstr ""
 
 msgid "Numeric"
 msgstr ""
 
-#: src/data/format.c:319 src/data/sys-file-reader.c:1113
-#: src/data/sys-file-reader.c:1115
+#: src/data/format.c:319 src/data/sys-file-reader.c:1114
+#: src/data/sys-file-reader.c:1116
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
-#: src/language/xforms/recode.c:471 src/language/xforms/recode.c:472
-#: src/language/xforms/recode.c:484 src/language/xforms/recode.c:485
+#: src/language/xforms/recode.c:472 src/language/xforms/recode.c:473
+#: src/language/xforms/recode.c:485 src/language/xforms/recode.c:486
 msgid "numeric"
 msgstr ""
 
 msgid "numeric"
 msgstr ""
 
-#: src/data/format.c:319 src/data/sys-file-reader.c:1113
-#: src/data/sys-file-reader.c:1115
+#: src/data/format.c:319 src/data/sys-file-reader.c:1114
+#: src/data/sys-file-reader.c:1116
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
 #: src/language/dictionary/apply-dictionary.c:78
 #: src/language/dictionary/apply-dictionary.c:79
-#: src/language/xforms/recode.c:471 src/language/xforms/recode.c:472
-#: src/language/xforms/recode.c:484 src/language/xforms/recode.c:485
+#: src/language/xforms/recode.c:472 src/language/xforms/recode.c:473
+#: src/language/xforms/recode.c:485 src/language/xforms/recode.c:486
 msgid "string"
 msgstr ""
 
 msgid "string"
 msgstr ""
 
@@ -402,149 +402,149 @@ msgstr ""
 msgid "Removing %s: %s."
 msgstr ""
 
 msgid "Removing %s: %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:98
+#: src/data/por-file-reader.c:99
 #, c-format
 msgid "portable file %s corrupt at offset 0x%lx: "
 msgstr ""
 
 #, c-format
 msgid "portable file %s corrupt at offset 0x%lx: "
 msgstr ""
 
-#: src/data/por-file-reader.c:127
+#: src/data/por-file-reader.c:128
 #, c-format
 msgid "reading portable file %s at offset 0x%lx: "
 msgstr ""
 
 #, c-format
 msgid "reading portable file %s at offset 0x%lx: "
 msgstr ""
 
-#: src/data/por-file-reader.c:155
+#: src/data/por-file-reader.c:156
 #, c-format
 msgid "Error closing portable file \"%s\": %s."
 msgstr ""
 
 #, c-format
 msgid "Error closing portable file \"%s\": %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:207
+#: src/data/por-file-reader.c:208
 msgid "unexpected end of file"
 msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 msgid "unexpected end of file"
 msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/por-file-reader.c:267 src/data/por-file-writer.c:148
+#: src/data/por-file-reader.c:268 src/data/por-file-writer.c:148
 msgid "portable file"
 msgstr ""
 
 msgid "portable file"
 msgstr ""
 
-#: src/data/por-file-reader.c:275
+#: src/data/por-file-reader.c:276
 #, c-format
 msgid ""
 "An error occurred while opening \"%s\" for reading as a portable file: %s."
 msgstr ""
 
 #, c-format
 msgid ""
 "An error occurred while opening \"%s\" for reading as a portable file: %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:296
+#: src/data/por-file-reader.c:297
 msgid "Data record expected."
 msgstr ""
 
 msgid "Data record expected."
 msgstr ""
 
-#: src/data/por-file-reader.c:378
+#: src/data/por-file-reader.c:379
 msgid "Number expected."
 msgstr ""
 
 msgid "Number expected."
 msgstr ""
 
-#: src/data/por-file-reader.c:406
+#: src/data/por-file-reader.c:407
 msgid "Missing numeric terminator."
 msgstr ""
 
 msgid "Missing numeric terminator."
 msgstr ""
 
-#: src/data/por-file-reader.c:429
+#: src/data/por-file-reader.c:430
 msgid "Invalid integer."
 msgstr ""
 
 msgid "Invalid integer."
 msgstr ""
 
-#: src/data/por-file-reader.c:440
+#: src/data/por-file-reader.c:441
 #, c-format
 msgid "Bad string length %d."
 msgstr ""
 
 #, c-format
 msgid "Bad string length %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:501
+#: src/data/por-file-reader.c:502
 #, c-format
 msgid "%s: Not a portable file."
 msgstr ""
 
 #, c-format
 msgid "%s: Not a portable file."
 msgstr ""
 
-#: src/data/por-file-reader.c:517
+#: src/data/por-file-reader.c:518
 #, c-format
 msgid "Unrecognized version code `%c'."
 msgstr ""
 
 #, c-format
 msgid "Unrecognized version code `%c'."
 msgstr ""
 
-#: src/data/por-file-reader.c:526
+#: src/data/por-file-reader.c:527
 #, c-format
 msgid "Bad date string length %zu."
 msgstr ""
 
 #, c-format
 msgid "Bad date string length %zu."
 msgstr ""
 
-#: src/data/por-file-reader.c:528
+#: src/data/por-file-reader.c:529
 #, c-format
 msgid "Bad time string length %zu."
 msgstr ""
 
 #, c-format
 msgid "Bad time string length %zu."
 msgstr ""
 
-#: src/data/por-file-reader.c:570
+#: src/data/por-file-reader.c:571
 #, c-format
 msgid ""
 "%s: Bad format specifier byte (%d).  Variable will be assigned a default "
 "format."
 msgstr ""
 
 #, c-format
 msgid ""
 "%s: Bad format specifier byte (%d).  Variable will be assigned a default "
 "format."
 msgstr ""
 
-#: src/data/por-file-reader.c:591
+#: src/data/por-file-reader.c:592
 #, c-format
 msgid "Numeric variable %s has invalid format specifier %s."
 msgstr ""
 
 #, c-format
 msgid "Numeric variable %s has invalid format specifier %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:595
+#: src/data/por-file-reader.c:596
 #, c-format
 msgid "String variable %s with width %d has invalid format specifier %s."
 msgstr ""
 
 #, c-format
 msgid "String variable %s with width %d has invalid format specifier %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:619
+#: src/data/por-file-reader.c:620
 msgid "Expected variable count record."
 msgstr ""
 
 msgid "Expected variable count record."
 msgstr ""
 
-#: src/data/por-file-reader.c:623
+#: src/data/por-file-reader.c:624
 #, c-format
 msgid "Invalid number of variables %d."
 msgstr ""
 
 #, c-format
 msgid "Invalid number of variables %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:633
+#: src/data/por-file-reader.c:634
 #, c-format
 msgid "Weight variable name (%s) truncated."
 msgstr ""
 
 #, c-format
 msgid "Weight variable name (%s) truncated."
 msgstr ""
 
-#: src/data/por-file-reader.c:648
+#: src/data/por-file-reader.c:649
 msgid "Expected variable record."
 msgstr ""
 
 msgid "Expected variable record."
 msgstr ""
 
-#: src/data/por-file-reader.c:652
+#: src/data/por-file-reader.c:653
 #, c-format
 msgid "Invalid variable width %d."
 msgstr ""
 
 #, c-format
 msgid "Invalid variable width %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:660
+#: src/data/por-file-reader.c:661
 #, c-format
 msgid "Invalid variable name `%s' in position %d."
 msgstr ""
 
 #, c-format
 msgid "Invalid variable name `%s' in position %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:664
+#: src/data/por-file-reader.c:665
 #, c-format
 msgid "Bad width %d for variable %s."
 msgstr ""
 
 #, c-format
 msgid "Bad width %d for variable %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:679
+#: src/data/por-file-reader.c:680
 #, c-format
 msgid "Duplicate variable name %s in position %d."
 msgstr ""
 
 #, c-format
 msgid "Duplicate variable name %s in position %d."
 msgstr ""
 
-#: src/data/por-file-reader.c:680
+#: src/data/por-file-reader.c:681
 #, c-format
 msgid "Duplicate variable name %s in position %d renamed to %s."
 msgstr ""
 
 #, c-format
 msgid "Duplicate variable name %s in position %d renamed to %s."
 msgstr ""
 
-#: src/data/por-file-reader.c:723
+#: src/data/por-file-reader.c:724
 #, c-format
 msgid "Weighting variable %s not present in dictionary."
 msgstr ""
 
 #, c-format
 msgid "Weighting variable %s not present in dictionary."
 msgstr ""
 
-#: src/data/por-file-reader.c:770
+#: src/data/por-file-reader.c:771
 #, c-format
 msgid "Unknown variable %s while parsing value labels."
 msgstr ""
 
 #, c-format
 msgid "Unknown variable %s while parsing value labels."
 msgstr ""
 
-#: src/data/por-file-reader.c:773
+#: src/data/por-file-reader.c:774
 #, c-format
 msgid ""
 "Cannot assign value labels to %s and %s, which have different variable types."
 #, c-format
 msgid ""
 "Cannot assign value labels to %s and %s, which have different variable types."
@@ -574,7 +574,7 @@ msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/scratch-writer.c:67 src/language/data-io/file-handle.q:151
+#: src/data/scratch-writer.c:67 src/language/data-io/file-handle.q:180
 msgid "scratch file"
 msgstr ""
 
 msgid "scratch file"
 msgstr ""
 
@@ -584,297 +584,297 @@ msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/data/sys-file-reader.c:197 src/data/sys-file-writer.c:190
+#: src/data/sys-file-reader.c:198 src/data/sys-file-writer.c:190
 msgid "system file"
 msgstr ""
 
 msgid "system file"
 msgstr ""
 
-#: src/data/sys-file-reader.c:204
+#: src/data/sys-file-reader.c:205
 #, c-format
 msgid "Error opening \"%s\" for reading as a system file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error opening \"%s\" for reading as a system file: %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:243
+#: src/data/sys-file-reader.c:244
 msgid "Misplaced type 4 record."
 msgstr ""
 
 msgid "Misplaced type 4 record."
 msgstr ""
 
-#: src/data/sys-file-reader.c:254
+#: src/data/sys-file-reader.c:255
 #, c-format
 msgid "Unrecognized record type %d."
 msgstr ""
 
 #, c-format
 msgid "Unrecognized record type %d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:293
+#: src/data/sys-file-reader.c:294
 #, c-format
 msgid "File header claims %d variable positions but %d were read from file."
 msgstr ""
 
 #, c-format
 msgid "File header claims %d variable positions but %d were read from file."
 msgstr ""
 
-#: src/data/sys-file-reader.c:333
+#: src/data/sys-file-reader.c:334
 #, c-format
 msgid "Error closing system file \"%s\": %s."
 msgstr ""
 
 #, c-format
 msgid "Error closing system file \"%s\": %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:398 src/data/sys-file-reader.c:408
+#: src/data/sys-file-reader.c:399 src/data/sys-file-reader.c:409
 msgid "This is not an SPSS system file."
 msgstr ""
 
 msgid "This is not an SPSS system file."
 msgstr ""
 
-#: src/data/sys-file-reader.c:427
+#: src/data/sys-file-reader.c:428
 #, c-format
 msgid ""
 "Compression bias (%g) is not the usual value of 100, or system file uses "
 "unrecognized floating-point format."
 msgstr ""
 
 #, c-format
 msgid ""
 "Compression bias (%g) is not the usual value of 100, or system file uses "
 "unrecognized floating-point format."
 msgstr ""
 
-#: src/data/sys-file-reader.c:496
+#: src/data/sys-file-reader.c:497
 #, c-format
 msgid "Invalid variable name `%s'."
 msgstr ""
 
 #, c-format
 msgid "Invalid variable name `%s'."
 msgstr ""
 
-#: src/data/sys-file-reader.c:500
+#: src/data/sys-file-reader.c:501
 #, c-format
 msgid "Bad variable width %d."
 msgstr ""
 
 #, c-format
 msgid "Bad variable width %d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:504
+#: src/data/sys-file-reader.c:505
 #, c-format
 msgid "Duplicate variable name `%s' within system file."
 msgstr ""
 
 #, c-format
 msgid "Duplicate variable name `%s' within system file."
 msgstr ""
 
-#: src/data/sys-file-reader.c:512
+#: src/data/sys-file-reader.c:513
 msgid "Variable label indicator field is not 0 or 1."
 msgstr ""
 
 msgid "Variable label indicator field is not 0 or 1."
 msgstr ""
 
-#: src/data/sys-file-reader.c:520
+#: src/data/sys-file-reader.c:521
 #, c-format
 msgid "Variable %s has label of invalid length %zu."
 msgstr ""
 
 #, c-format
 msgid "Variable %s has label of invalid length %zu."
 msgstr ""
 
-#: src/data/sys-file-reader.c:539
+#: src/data/sys-file-reader.c:540
 msgid "Numeric missing value indicator field is not -3, -2, 0, 1, 2, or 3."
 msgstr ""
 
 msgid "Numeric missing value indicator field is not -3, -2, 0, 1, 2, or 3."
 msgstr ""
 
-#: src/data/sys-file-reader.c:554
+#: src/data/sys-file-reader.c:555
 msgid "String missing value indicator field is not 0, 1, 2, or 3."
 msgstr ""
 
 msgid "String missing value indicator field is not 0, 1, 2, or 3."
 msgstr ""
 
-#: src/data/sys-file-reader.c:564
+#: src/data/sys-file-reader.c:565
 #, c-format
 msgid "Long string variable %s may not have missing values."
 msgstr ""
 
 #, c-format
 msgid "Long string variable %s may not have missing values."
 msgstr ""
 
-#: src/data/sys-file-reader.c:585
+#: src/data/sys-file-reader.c:586
 msgid "Missing string continuation record."
 msgstr ""
 
 msgid "Missing string continuation record."
 msgstr ""
 
-#: src/data/sys-file-reader.c:619
+#: src/data/sys-file-reader.c:620
 #, c-format
 msgid "Unknown variable format %<PRIu8>."
 msgstr ""
 
 #, c-format
 msgid "Unknown variable format %<PRIu8>."
 msgstr ""
 
-#: src/data/sys-file-reader.c:637
+#: src/data/sys-file-reader.c:638
 #, c-format
 msgid "%s variable %s has invalid %s format %s."
 msgstr ""
 
 #, c-format
 msgid "%s variable %s has invalid %s format %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
 msgid "print"
 msgstr ""
 
 msgid "print"
 msgstr ""
 
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
 msgid "write"
 msgstr ""
 
 msgid "write"
 msgstr ""
 
-#: src/data/sys-file-reader.c:644
+#: src/data/sys-file-reader.c:645
 msgid "Suppressing further invalid format warnings."
 msgstr ""
 
 msgid "Suppressing further invalid format warnings."
 msgstr ""
 
-#: src/data/sys-file-reader.c:662
+#: src/data/sys-file-reader.c:663
 msgid "Weighting variable must be numeric."
 msgstr ""
 
 msgid "Weighting variable must be numeric."
 msgstr ""
 
-#: src/data/sys-file-reader.c:676
+#: src/data/sys-file-reader.c:677
 msgid "Multiple type 6 (document) records."
 msgstr ""
 
 msgid "Multiple type 6 (document) records."
 msgstr ""
 
-#: src/data/sys-file-reader.c:680
+#: src/data/sys-file-reader.c:681
 #, c-format
 msgid "Number of document lines (%d) must be greater than 0."
 msgstr ""
 
 #, c-format
 msgid "Number of document lines (%d) must be greater than 0."
 msgstr ""
 
-#: src/data/sys-file-reader.c:688
+#: src/data/sys-file-reader.c:689
 msgid "Document line contains null byte."
 msgstr ""
 
 msgid "Document line contains null byte."
 msgstr ""
 
-#: src/data/sys-file-reader.c:755
+#: src/data/sys-file-reader.c:756
 #, c-format
 msgid "Unrecognized record type 7, subtype %d."
 msgstr ""
 
 #, c-format
 msgid "Unrecognized record type 7, subtype %d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:780
+#: src/data/sys-file-reader.c:781
 #, c-format
 msgid "Bad size (%zu) or count (%zu) field on record type 7, subtype 3."
 msgstr ""
 
 #, c-format
 msgid "Bad size (%zu) or count (%zu) field on record type 7, subtype 3."
 msgstr ""
 
-#: src/data/sys-file-reader.c:800
+#: src/data/sys-file-reader.c:801
 #, c-format
 msgid ""
 "Floating-point representation indicated by system file (%d) differs from "
 "expected (%d)."
 msgstr ""
 
 #, c-format
 msgid ""
 "Floating-point representation indicated by system file (%d) differs from "
 "expected (%d)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
 msgid "little-endian"
 msgstr ""
 
 msgid "little-endian"
 msgstr ""
 
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
 msgid "big-endian"
 msgstr ""
 
 msgid "big-endian"
 msgstr ""
 
-#: src/data/sys-file-reader.c:814
+#: src/data/sys-file-reader.c:815
 #, c-format
 msgid ""
 "Integer format indicated by system file (%s) differs from expected (%s)."
 msgstr ""
 
 #, c-format
 msgid ""
 "Integer format indicated by system file (%s) differs from expected (%s)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:830
+#: src/data/sys-file-reader.c:831
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 4."
 msgstr ""
 
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 4."
 msgstr ""
 
-#: src/data/sys-file-reader.c:834
+#: src/data/sys-file-reader.c:835
 #, c-format
 msgid "File specifies unexpected value %g as SYSMIS."
 msgstr ""
 
 #, c-format
 msgid "File specifies unexpected value %g as SYSMIS."
 msgstr ""
 
-#: src/data/sys-file-reader.c:836
+#: src/data/sys-file-reader.c:837
 #, c-format
 msgid "File specifies unexpected value %g as HIGHEST."
 msgstr ""
 
 #, c-format
 msgid "File specifies unexpected value %g as HIGHEST."
 msgstr ""
 
-#: src/data/sys-file-reader.c:838
+#: src/data/sys-file-reader.c:839
 #, c-format
 msgid "File specifies unexpected value %g as LOWEST."
 msgstr ""
 
 #, c-format
 msgid "File specifies unexpected value %g as LOWEST."
 msgstr ""
 
-#: src/data/sys-file-reader.c:852
+#: src/data/sys-file-reader.c:853
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 11."
 msgstr ""
 
 #, c-format
 msgid "Bad size (%zu) or count (%zu) on extension 11."
 msgstr ""
 
-#: src/data/sys-file-reader.c:875
+#: src/data/sys-file-reader.c:876
 msgid "Invalid variable display parameters.  Default parameters substituted."
 msgstr ""
 
 msgid "Invalid variable display parameters.  Default parameters substituted."
 msgstr ""
 
-#: src/data/sys-file-reader.c:914
+#: src/data/sys-file-reader.c:915
 #, c-format
 msgid "Long variable mapping from %s to invalid variable name `%s'."
 msgstr ""
 
 #, c-format
 msgid "Long variable mapping from %s to invalid variable name `%s'."
 msgstr ""
 
-#: src/data/sys-file-reader.c:924
+#: src/data/sys-file-reader.c:925
 #, c-format
 msgid "Duplicate long variable name `%s' within system file."
 msgstr ""
 
 #, c-format
 msgid "Duplicate long variable name `%s' within system file."
 msgstr ""
 
-#: src/data/sys-file-reader.c:979
+#: src/data/sys-file-reader.c:980
 #, c-format
 msgid "%s listed as string of invalid length %s in very length string record."
 msgstr ""
 
 #, c-format
 msgid "%s listed as string of invalid length %s in very length string record."
 msgstr ""
 
-#: src/data/sys-file-reader.c:989
+#: src/data/sys-file-reader.c:990
 #, c-format
 msgid ""
 "%s listed in very long string record with width %s, which requires only one "
 "segment."
 msgstr ""
 
 #, c-format
 msgid ""
 "%s listed in very long string record with width %s, which requires only one "
 "segment."
 msgstr ""
 
-#: src/data/sys-file-reader.c:995
+#: src/data/sys-file-reader.c:996
 #, c-format
 msgid "Very long string %s overflows dictionary."
 msgstr ""
 
 #, c-format
 msgid "Very long string %s overflows dictionary."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1009
+#: src/data/sys-file-reader.c:1010
 #, c-format
 msgid ""
 "Very long string with width %ld has segment %d of width %d (expected %d)"
 msgstr ""
 
 #, c-format
 msgid ""
 "Very long string with width %ld has segment %d of width %d (expected %d)"
 msgstr ""
 
-#: src/data/sys-file-reader.c:1054
+#: src/data/sys-file-reader.c:1055
 #, c-format
 msgid "Invalid number of labels: %d.  Ignoring labels."
 msgstr ""
 
 #, c-format
 msgid "Invalid number of labels: %d.  Ignoring labels."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1085
+#: src/data/sys-file-reader.c:1086
 msgid ""
 "Variable index record (type 4) does not immediately follow value label "
 "record (type 3) as it should."
 msgstr ""
 
 msgid ""
 "Variable index record (type 4) does not immediately follow value label "
 "record (type 3) as it should."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1092
+#: src/data/sys-file-reader.c:1093
 #, c-format
 msgid ""
 "Number of variables associated with a value label (%d) is not between 1 and "
 "the number of variables (%zu)."
 msgstr ""
 
 #, c-format
 msgid ""
 "Number of variables associated with a value label (%d) is not between 1 and "
 "the number of variables (%zu)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1102
+#: src/data/sys-file-reader.c:1103
 #, c-format
 msgid "Value labels are not allowed on long string variables (%s)."
 msgstr ""
 
 #, c-format
 msgid "Value labels are not allowed on long string variables (%s)."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1109
+#: src/data/sys-file-reader.c:1110
 #, c-format
 msgid ""
 "Variables associated with value label are not all of identical type.  "
 "Variable %s is %s, but variable %s is %s."
 msgstr ""
 
 #, c-format
 msgid ""
 "Variables associated with value label are not all of identical type.  "
 "Variable %s is %s, but variable %s is %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1142
+#: src/data/sys-file-reader.c:1143
 #, c-format
 msgid "Duplicate value label for %g on %s."
 msgstr ""
 
 #, c-format
 msgid "Duplicate value label for %g on %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1145
+#: src/data/sys-file-reader.c:1146
 #, c-format
 msgid "Duplicate value label for \"%.*s\" on %s."
 msgstr ""
 
 #, c-format
 msgid "Duplicate value label for \"%.*s\" on %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1223
+#: src/data/sys-file-reader.c:1224
 msgid "File ends in partial case."
 msgstr ""
 
 msgid "File ends in partial case."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1231
+#: src/data/sys-file-reader.c:1232
 #, c-format
 msgid "Error reading case from file %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading case from file %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1328 src/data/sys-file-reader.c:1364
+#: src/data/sys-file-reader.c:1329 src/data/sys-file-reader.c:1365
 msgid "Compressed data is corrupt."
 msgstr ""
 
 msgid "Compressed data is corrupt."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1451
+#: src/data/sys-file-reader.c:1452
 #, c-format
 msgid "Variable index %d not in valid range 1...%d."
 msgstr ""
 
 #, c-format
 msgid "Variable index %d not in valid range 1...%d."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1456
+#: src/data/sys-file-reader.c:1457
 #, c-format
 msgid "Variable index %d refers to long string continuation."
 msgstr ""
 
 #, c-format
 msgid "Variable index %d refers to long string continuation."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1542
+#: src/data/sys-file-reader.c:1543
 #, c-format
 msgid "Suppressed %d additional variable map warnings."
 msgstr ""
 
 #, c-format
 msgid "Suppressed %d additional variable map warnings."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1555
+#: src/data/sys-file-reader.c:1556
 #, c-format
 msgid "Variable map refers to unknown variable %s."
 msgstr ""
 
 #, c-format
 msgid "Variable map refers to unknown variable %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1631
+#: src/data/sys-file-reader.c:1632
 #, c-format
 msgid "System error: %s."
 msgstr ""
 
 #, c-format
 msgid "System error: %s."
 msgstr ""
 
-#: src/data/sys-file-reader.c:1633
+#: src/data/sys-file-reader.c:1634
 msgid "Unexpected end of file."
 msgstr ""
 
 msgid "Unexpected end of file."
 msgstr ""
 
@@ -893,44 +893,32 @@ msgstr ""
 msgid "An I/O error occurred writing system file \"%s\"."
 msgstr ""
 
 msgid "An I/O error occurred writing system file \"%s\"."
 msgstr ""
 
-#: src/data/variable.c:231
+#: src/data/variable.c:217
 #, c-format
 msgid ""
 "Character `%c' (in %s) may not appear as the first character in a variable "
 "name."
 msgstr ""
 
 #, c-format
 msgid ""
 "Character `%c' (in %s) may not appear as the first character in a variable "
 "name."
 msgstr ""
 
-#: src/data/variable.c:243
+#: src/data/variable.c:229
 #, c-format
 msgid "Character `%c' (in %s) may not appear in a variable name."
 msgstr ""
 
 #, c-format
 msgid "Character `%c' (in %s) may not appear in a variable name."
 msgstr ""
 
-#: src/data/variable.c:271
+#: src/data/variable.c:257
 msgid "Variable name cannot be empty string."
 msgstr ""
 
 msgid "Variable name cannot be empty string."
 msgstr ""
 
-#: src/data/variable.c:277
+#: src/data/variable.c:263
 #, c-format
 msgid "Variable name %s exceeds %d-character limit."
 msgstr ""
 
 #, c-format
 msgid "Variable name %s exceeds %d-character limit."
 msgstr ""
 
-#: src/data/variable.c:285
+#: src/data/variable.c:271
 #, c-format
 msgid "`%s' may not be used as a variable name because it is a reserved word."
 msgstr ""
 
 #, c-format
 msgid "`%s' may not be used as a variable name because it is a reserved word."
 msgstr ""
 
-#: src/data/variable.c:1003
-msgid "ordinary"
-msgstr ""
-
-#: src/data/variable.c:1005
-msgid "system"
-msgstr ""
-
-#: src/data/variable.c:1007
-msgid "scratch"
-msgstr ""
-
 #: src/language/command.c:208
 #, c-format
 msgid "%s is unimplemented."
 #: src/language/command.c:208
 #, c-format
 msgid "%s is unimplemented."
@@ -1169,7 +1157,7 @@ msgid ""
 msgstr ""
 
 #: src/language/data-io/data-list.c:434 src/language/data-io/data-list.c:543
 msgstr ""
 
 #: src/language/data-io/data-list.c:434 src/language/data-io/data-list.c:543
-#: src/language/data-io/print.c:397 src/language/dictionary/split-file.c:84
+#: src/language/data-io/print.c:401 src/language/dictionary/split-file.c:84
 #: src/language/dictionary/sys-file-info.c:161
 #: src/language/dictionary/sys-file-info.c:390
 #: src/language/dictionary/sys-file-info.c:634
 #: src/language/dictionary/sys-file-info.c:161
 #: src/language/dictionary/sys-file-info.c:390
 #: src/language/dictionary/sys-file-info.c:634
@@ -1177,17 +1165,17 @@ msgstr ""
 msgid "Variable"
 msgstr ""
 
 msgid "Variable"
 msgstr ""
 
-#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:398
+#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:402
 msgid "Record"
 msgstr ""
 
 msgid "Record"
 msgstr ""
 
-#: src/language/data-io/data-list.c:436 src/language/data-io/print.c:399
+#: src/language/data-io/data-list.c:436 src/language/data-io/print.c:403
 #: src/ui/gui/var-sheet.c:72
 msgid "Columns"
 msgstr ""
 
 #: src/language/data-io/data-list.c:437 src/language/data-io/data-list.c:544
 #: src/ui/gui/var-sheet.c:72
 msgid "Columns"
 msgstr ""
 
 #: src/language/data-io/data-list.c:437 src/language/data-io/data-list.c:544
-#: src/language/data-io/print.c:400
+#: src/language/data-io/print.c:404
 msgid "Format"
 msgstr ""
 
 msgid "Format"
 msgstr ""
 
@@ -1207,17 +1195,17 @@ msgstr ""
 msgid "Quoted string extends beyond end of line."
 msgstr ""
 
 msgid "Quoted string extends beyond end of line."
 msgstr ""
 
-#: src/language/data-io/data-list.c:689
+#: src/language/data-io/data-list.c:690
 #, c-format
 msgid "Partial case of %d of %d records discarded."
 msgstr ""
 
 #, c-format
 msgid "Partial case of %d of %d records discarded."
 msgstr ""
 
-#: src/language/data-io/data-list.c:733
+#: src/language/data-io/data-list.c:736
 #, c-format
 msgid "Partial case discarded.  The first variable missing was %s."
 msgstr ""
 
 #, c-format
 msgid "Partial case discarded.  The first variable missing was %s."
 msgstr ""
 
-#: src/language/data-io/data-list.c:764
+#: src/language/data-io/data-list.c:768
 #, c-format
 msgid ""
 "Missing value(s) for all variables from %s onward.  These will be filled "
 #, c-format
 msgid ""
 "Missing value(s) for all variables from %s onward.  These will be filled "
@@ -1226,97 +1214,127 @@ msgstr ""
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
 
 #. TRANSLATORS: this fragment will be interpolated into
 #. messages in fh_lock() that identify types of files.
-#: src/language/data-io/data-reader.c:116
-#: src/language/data-io/data-writer.c:56
+#: src/language/data-io/data-reader.c:120
+#: src/language/data-io/data-writer.c:58
 msgid "data file"
 msgstr ""
 
 msgid "data file"
 msgstr ""
 
-#: src/language/data-io/data-reader.c:140
+#: src/language/data-io/data-reader.c:146
 #, c-format
 msgid "Could not open \"%s\" for reading as a data file: %s."
 msgstr ""
 
 #, c-format
 msgid "Could not open \"%s\" for reading as a data file: %s."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:178
+#: src/language/data-io/data-reader.c:184
 msgid ""
 "Unexpected end-of-file while reading data in BEGIN DATA.  This probably "
 "indicates a missing or misformatted END DATA command.  END DATA must appear "
 "by itself on a single line with exactly one space between words."
 msgstr ""
 
 msgid ""
 "Unexpected end-of-file while reading data in BEGIN DATA.  This probably "
 "indicates a missing or misformatted END DATA command.  END DATA must appear "
 "by itself on a single line with exactly one space between words."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:210
-#: src/language/data-io/data-reader.c:223
+#: src/language/data-io/data-reader.c:209
 #, c-format
 msgid "Error reading file %s: %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading file %s: %s."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:226
+#: src/language/data-io/data-reader.c:212
 #, c-format
 #, c-format
-msgid "%s: Partial record at end of file."
+msgid "Unexpected end of file reading %s."
 msgstr ""
 
 msgstr ""
 
-#: src/language/data-io/data-reader.c:277
+#: src/language/data-io/data-reader.c:221
+#, c-format
+msgid "Unexpected end of file in partial record reading %s."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:281
+#, c-format
+msgid "Corrupt block descriptor word at offset 0x%lx in %s."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:282
+#, c-format
+msgid "Corrupt record descriptor word at offset 0x%lx in %s."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:295
+#, c-format
+msgid "Corrupt record size at offset 0x%lx in %s."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:437
+msgid "Record exceeds remaining block length."
+msgstr ""
+
+#: src/language/data-io/data-reader.c:511
 #, c-format
 msgid "Attempt to read beyond end-of-file on file %s."
 msgstr ""
 
 #, c-format
 msgid "Attempt to read beyond end-of-file on file %s."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:280
+#: src/language/data-io/data-reader.c:514
 msgid "Attempt to read beyond END DATA."
 msgstr ""
 
 msgid "Attempt to read beyond END DATA."
 msgstr ""
 
-#: src/language/data-io/data-reader.c:438
+#: src/language/data-io/data-reader.c:679
 msgid ""
 "This command is not valid here since the current input program does not "
 "access the inline file."
 msgstr ""
 
 msgid ""
 "This command is not valid here since the current input program does not "
 "access the inline file."
 msgstr ""
 
-#: src/language/data-io/data-writer.c:72
+#: src/language/data-io/data-writer.c:74
 #, c-format
 msgid "An error occurred while opening \"%s\" for writing as a data file: %s."
 msgstr ""
 
 #, c-format
 msgid "An error occurred while opening \"%s\" for writing as a data file: %s."
 msgstr ""
 
-#: src/language/data-io/data-writer.c:150
+#: src/language/data-io/data-writer.c:191
 #, c-format
 msgid "I/O error occurred writing data file \"%s\"."
 msgstr ""
 
 #, c-format
 msgid "I/O error occurred writing data file \"%s\"."
 msgstr ""
 
-#: src/language/data-io/file-handle.q:65
+#: src/language/data-io/file-handle.q:64
 #, c-format
 msgid ""
 "File handle %s is already defined.  Use CLOSE FILE HANDLE before redefining "
 "a file handle."
 msgstr ""
 
 #, c-format
 msgid ""
 "File handle %s is already defined.  Use CLOSE FILE HANDLE before redefining "
 "a file handle."
 msgstr ""
 
-#: src/language/data-io/file-handle.q:97
+#: src/language/data-io/file-handle.q:119
+msgid "RECFORM must be specified with MODE=360."
+msgstr ""
+
+#: src/language/data-io/file-handle.q:130
 #, c-format
 #, c-format
-msgid ""
-"Fixed-length records were specified on /RECFORM, but record length was not "
-"specified on /LRECL.  Assuming %zu-character records."
+msgid "The specified file mode requires LRECL.  Assuming %d-character records."
 msgstr ""
 
 msgstr ""
 
-#: src/language/data-io/file-handle.q:102
+#: src/language/data-io/file-handle.q:134
 #, c-format
 msgid ""
 #, c-format
 msgid ""
-"Record length (%ld) must be at least one byte.  Assuming %zu-character "
+"Record length (%ld) must be between 1 and %lu bytes.  Assuming %d-character "
 "records."
 msgstr ""
 
 "records."
 msgstr ""
 
-#: src/language/data-io/file-handle.q:147
+#: src/language/data-io/file-handle.q:176
 msgid "file"
 msgstr ""
 
 msgid "file"
 msgstr ""
 
-#: src/language/data-io/file-handle.q:149
+#: src/language/data-io/file-handle.q:178
 msgid "inline file"
 msgstr ""
 
 msgid "inline file"
 msgstr ""
 
-#: src/language/data-io/file-handle.q:175
+#: src/language/data-io/file-handle.q:204
 msgid "expecting a file name or handle name"
 msgstr ""
 
 msgid "expecting a file name or handle name"
 msgstr ""
 
-#: src/language/data-io/file-handle.q:195
+#: src/language/data-io/file-handle.q:224
 #, c-format
 msgid "Handle for %s not allowed here."
 msgstr ""
 
 #, c-format
 msgid "Handle for %s not allowed here."
 msgstr ""
 
+#: src/language/data-io/get-data.c:48
+#, c-format
+msgid "Unsupported TYPE %s"
+msgstr ""
+
 #: src/language/data-io/get.c:106
 msgid "expecting COMM or TAPE"
 msgstr ""
 #: src/language/data-io/get.c:106
 msgid "expecting COMM or TAPE"
 msgstr ""
@@ -1327,7 +1345,7 @@ msgstr ""
 msgid "expecting %s or %s"
 msgstr ""
 
 msgid "expecting %s or %s"
 msgstr ""
 
-#: src/language/data-io/get.c:513 src/language/data-io/print.c:176
+#: src/language/data-io/get.c:513 src/language/data-io/print.c:177
 msgid "expecting a valid subcommand"
 msgstr ""
 
 msgid "expecting a valid subcommand"
 msgstr ""
 
@@ -1406,11 +1424,6 @@ msgid ""
 "variable in earlier file (%s)."
 msgstr ""
 
 "variable in earlier file (%s)."
 msgstr ""
 
-#: src/language/data-io/get-data.c:48
-#, c-format
-msgid "Unsupported TYPE %s"
-msgstr ""
-
 #: src/language/data-io/inpt-pgm.c:129
 msgid "Unexpected end-of-file within INPUT PROGRAM."
 msgstr ""
 #: src/language/data-io/inpt-pgm.c:129
 msgid "Unexpected end-of-file within INPUT PROGRAM."
 msgstr ""
@@ -1428,39 +1441,39 @@ msgid ""
 "REREAD: Column numbers must be positive finite numbers.  Column set to 1."
 msgstr ""
 
 "REREAD: Column numbers must be positive finite numbers.  Column set to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:156 src/language/stats/descriptives.c:362
+#: src/language/data-io/list.q:157 src/language/stats/descriptives.c:362
 msgid "No variables specified."
 msgstr ""
 
 msgid "No variables specified."
 msgstr ""
 
-#: src/language/data-io/list.q:164
+#: src/language/data-io/list.q:165
 #, c-format
 msgid ""
 "The first case (%ld) specified precedes the last case (%ld) specified.  The "
 "values will be swapped."
 msgstr ""
 
 #, c-format
 msgid ""
 "The first case (%ld) specified precedes the last case (%ld) specified.  The "
 "values will be swapped."
 msgstr ""
 
-#: src/language/data-io/list.q:172
+#: src/language/data-io/list.q:173
 #, c-format
 msgid ""
 "The first case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
 #, c-format
 msgid ""
 "The first case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:178
+#: src/language/data-io/list.q:179
 #, c-format
 msgid ""
 "The last case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
 #, c-format
 msgid ""
 "The last case (%ld) to list is less than 1.  The value is being reset to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:184
+#: src/language/data-io/list.q:185
 #, c-format
 msgid "The step value %ld is less than 1.  The value is being reset to 1."
 msgstr ""
 
 #, c-format
 msgid "The step value %ld is less than 1.  The value is being reset to 1."
 msgstr ""
 
-#: src/language/data-io/list.q:210
+#: src/language/data-io/list.q:211
 msgid "`/FORMAT WEIGHT' specified, but weighting is not on."
 msgstr ""
 
 msgid "`/FORMAT WEIGHT' specified, but weighting is not on."
 msgstr ""
 
-#: src/language/data-io/list.q:466
+#: src/language/data-io/list.q:467
 msgid "Line"
 msgstr ""
 
 msgid "Line"
 msgstr ""
 
@@ -1504,39 +1517,39 @@ msgid ""
 "Data fields must be listed in order of increasing record number."
 msgstr ""
 
 "Data fields must be listed in order of increasing record number."
 msgstr ""
 
-#: src/language/data-io/print.c:261
+#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:476
+#: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:60
+msgid "expecting end of command"
+msgstr ""
+
+#: src/language/data-io/print-space.c:116
+msgid "The expression on PRINT SPACE evaluated to the system-missing value."
+msgstr ""
+
+#: src/language/data-io/print-space.c:119
+#, c-format
+msgid "The expression on PRINT SPACE evaluated to %g."
+msgstr ""
+
+#: src/language/data-io/print.c:265
 #, c-format
 msgid "Output calls for %d records but %zu specified on RECORDS subcommand."
 msgstr ""
 
 #, c-format
 msgid "Output calls for %d records but %zu specified on RECORDS subcommand."
 msgstr ""
 
-#: src/language/data-io/print.c:430
+#: src/language/data-io/print.c:434
 #, c-format
 msgid "Writing %d record to %s."
 msgid_plural "Writing %d records to %s."
 msgstr[0] ""
 msgstr[1] ""
 
 #, c-format
 msgid "Writing %d record to %s."
 msgid_plural "Writing %d records to %s."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/language/data-io/print.c:434
+#: src/language/data-io/print.c:438
 #, c-format
 msgid "Writing %d record."
 msgid_plural "Writing %d records."
 msgstr[0] ""
 msgstr[1] ""
 
 #, c-format
 msgid "Writing %d record."
 msgid_plural "Writing %d records."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/language/data-io/print-space.c:73 src/language/lexer/lexer.c:476
-#: src/language/stats/autorecode.c:154 src/language/xforms/select-if.c:60
-msgid "expecting end of command"
-msgstr ""
-
-#: src/language/data-io/print-space.c:116
-msgid "The expression on PRINT SPACE evaluated to the system-missing value."
-msgstr ""
-
-#: src/language/data-io/print-space.c:119
-#, c-format
-msgid "The expression on PRINT SPACE evaluated to %g."
-msgstr ""
-
 #: src/language/dictionary/apply-dictionary.c:75
 #, c-format
 msgid "Variable %s is %s in target file, but %s in source file."
 #: src/language/dictionary/apply-dictionary.c:75
 #, c-format
 msgid "Variable %s is %s in target file, but %s in source file."
@@ -2295,11 +2308,11 @@ msgstr ""
 msgid "LO or LOWEST must be part of a range."
 msgstr ""
 
 msgid "LO or LOWEST must be part of a range."
 msgstr ""
 
-#: src/language/lexer/range-parser.c:106
+#: src/language/lexer/range-parser.c:107
 msgid "System-missing value is not valid here."
 msgstr ""
 
 msgid "System-missing value is not valid here."
 msgstr ""
 
-#: src/language/lexer/range-parser.c:114
+#: src/language/lexer/range-parser.c:115
 msgid "expecting number or data string"
 msgstr ""
 
 msgid "expecting number or data string"
 msgstr ""
 
@@ -3038,73 +3051,73 @@ msgstr ""
 msgid "Tukey's Hinges"
 msgstr ""
 
 msgid "Tukey's Hinges"
 msgstr ""
 
-#: src/language/stats/flip.c:95
+#: src/language/stats/flip.c:96
 msgid ""
 "FLIP ignores TEMPORARY.  Temporary transformations will be made permanent."
 msgstr ""
 
 msgid ""
 "FLIP ignores TEMPORARY.  Temporary transformations will be made permanent."
 msgstr ""
 
-#: src/language/stats/flip.c:150
+#: src/language/stats/flip.c:151
 msgid "Could not create temporary file for FLIP."
 msgstr ""
 
 msgid "Could not create temporary file for FLIP."
 msgstr ""
 
-#: src/language/stats/flip.c:161
+#: src/language/stats/flip.c:162
 #, c-format
 msgid "Error writing FLIP file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error writing FLIP file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:261
+#: src/language/stats/flip.c:262
 #, c-format
 msgid "Could not create acceptable variant for variable %s."
 msgstr ""
 
 #, c-format
 msgid "Could not create acceptable variant for variable %s."
 msgstr ""
 
-#: src/language/stats/flip.c:277
+#: src/language/stats/flip.c:278
 msgid "Cannot create more than 99999 variable names."
 msgstr ""
 
 msgid "Cannot create more than 99999 variable names."
 msgstr ""
 
-#: src/language/stats/flip.c:393
+#: src/language/stats/flip.c:394
 #, c-format
 msgid "Error rewinding FLIP file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error rewinding FLIP file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:400
+#: src/language/stats/flip.c:401
 msgid "Error creating FLIP source file."
 msgstr ""
 
 msgid "Error creating FLIP source file."
 msgstr ""
 
-#: src/language/stats/flip.c:413
+#: src/language/stats/flip.c:414
 #, c-format
 msgid "Error reading FLIP file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading FLIP file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:415
+#: src/language/stats/flip.c:416
 msgid "Unexpected end of file reading FLIP file."
 msgstr ""
 
 msgid "Unexpected end of file reading FLIP file."
 msgstr ""
 
-#: src/language/stats/flip.c:431
+#: src/language/stats/flip.c:432
 #, c-format
 msgid "Error seeking FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error seeking FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:439
+#: src/language/stats/flip.c:440
 #, c-format
 msgid "Error writing FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error writing FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:450
+#: src/language/stats/flip.c:451
 #, c-format
 msgid "Error closing FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error closing FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:458
+#: src/language/stats/flip.c:459
 #, c-format
 msgid "Error rewinding FLIP source file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error rewinding FLIP source file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:487
+#: src/language/stats/flip.c:488
 #, c-format
 msgid "Error reading FLIP temporary file: %s."
 msgstr ""
 
 #, c-format
 msgid "Error reading FLIP temporary file: %s."
 msgstr ""
 
-#: src/language/stats/flip.c:490
+#: src/language/stats/flip.c:491
 msgid "Unexpected end of file reading FLIP temporary file."
 msgstr ""
 
 msgid "Unexpected end of file reading FLIP temporary file."
 msgstr ""
 
@@ -3191,11 +3204,11 @@ msgstr ""
 msgid "Multivariate GLM not yet supported"
 msgstr ""
 
 msgid "Multivariate GLM not yet supported"
 msgstr ""
 
-#: src/language/stats/glm.q:271 src/language/stats/regression.q:1165
+#: src/language/stats/glm.q:271 src/language/stats/regression.q:1164
 msgid "Dependent variable must be numeric."
 msgstr ""
 
 msgid "Dependent variable must be numeric."
 msgstr ""
 
-#: src/language/stats/glm.q:346 src/language/stats/regression.q:1262
+#: src/language/stats/glm.q:346 src/language/stats/regression.q:1261
 msgid "No valid data found. This command was skipped."
 msgstr ""
 
 msgid "No valid data found. This command was skipped."
 msgstr ""
 
@@ -3207,6 +3220,22 @@ msgstr ""
 msgid "TABLES subcommand may not appear more than once."
 msgstr ""
 
 msgid "TABLES subcommand may not appear more than once."
 msgstr ""
 
+#: src/language/stats/npar-summary.c:108
+msgid "Descriptive Statistics"
+msgstr ""
+
+#: src/language/stats/npar-summary.c:145
+msgid "25th"
+msgstr ""
+
+#: src/language/stats/npar-summary.c:148
+msgid "50th (Median)"
+msgstr ""
+
+#: src/language/stats/npar-summary.c:151
+msgid "75th"
+msgstr ""
+
 #: src/language/stats/npar.q:98
 msgid "NPAR subcommand not currently implemented."
 msgstr ""
 #: src/language/stats/npar.q:98
 msgid "NPAR subcommand not currently implemented."
 msgstr ""
@@ -3231,22 +3260,6 @@ msgid ""
 "not match the number following (%zu)."
 msgstr ""
 
 "not match the number following (%zu)."
 msgstr ""
 
-#: src/language/stats/npar-summary.c:108
-msgid "Descriptive Statistics"
-msgstr ""
-
-#: src/language/stats/npar-summary.c:145
-msgid "25th"
-msgstr ""
-
-#: src/language/stats/npar-summary.c:148
-msgid "50th (Median)"
-msgstr ""
-
-#: src/language/stats/npar-summary.c:151
-msgid "75th"
-msgstr ""
-
 #: src/language/stats/oneway.q:169
 msgid "Number of contrast coefficients must equal the number of groups"
 msgstr ""
 #: src/language/stats/oneway.q:169
 msgid "Number of contrast coefficients must equal the number of groups"
 msgstr ""
@@ -3342,56 +3355,56 @@ msgstr ""
 msgid "Does not assume equal"
 msgstr ""
 
 msgid "Does not assume equal"
 msgstr ""
 
-#: src/language/stats/rank.q:220
+#: src/language/stats/rank.q:221
 #, c-format
 msgid "%s of %s by %s"
 msgstr ""
 
 #, c-format
 msgid "%s of %s by %s"
 msgstr ""
 
-#: src/language/stats/rank.q:225
+#: src/language/stats/rank.q:226
 #, c-format
 msgid "%s of %s"
 msgstr ""
 
 #, c-format
 msgid "%s of %s"
 msgstr ""
 
-#: src/language/stats/rank.q:601
+#: src/language/stats/rank.q:602
 msgid "Cannot create new rank variable.  All candidates in use."
 msgstr ""
 
 msgid "Cannot create new rank variable.  All candidates in use."
 msgstr ""
 
-#: src/language/stats/rank.q:694
+#: src/language/stats/rank.q:695
 msgid "Variables Created By RANK"
 msgstr ""
 
 msgid "Variables Created By RANK"
 msgstr ""
 
-#: src/language/stats/rank.q:718
+#: src/language/stats/rank.q:719
 #, c-format
 msgid "%s into %s(%s of %s using %s BY %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s using %s BY %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:729
+#: src/language/stats/rank.q:730
 #, c-format
 msgid "%s into %s(%s of %s BY %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s BY %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:743
+#: src/language/stats/rank.q:744
 #, c-format
 msgid "%s into %s(%s of %s using %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s using %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:753
+#: src/language/stats/rank.q:754
 #, c-format
 msgid "%s into %s(%s of %s)"
 msgstr ""
 
 #, c-format
 msgid "%s into %s(%s of %s)"
 msgstr ""
 
-#: src/language/stats/rank.q:766
+#: src/language/stats/rank.q:767
 msgid ""
 "FRACTION has been specified, but NORMAL and PROPORTION rank functions have "
 "not been requested.  The FRACTION subcommand will be ignored."
 msgstr ""
 
 msgid ""
 "FRACTION has been specified, but NORMAL and PROPORTION rank functions have "
 "not been requested.  The FRACTION subcommand will be ignored."
 msgstr ""
 
-#: src/language/stats/rank.q:859
+#: src/language/stats/rank.q:860
 #, c-format
 msgid "Variable %s already exists."
 msgstr ""
 
 #, c-format
 msgid "Variable %s already exists."
 msgstr ""
 
-#: src/language/stats/rank.q:864
+#: src/language/stats/rank.q:865
 msgid "Too many variables in INTO clause."
 msgstr ""
 
 msgid "Too many variables in INTO clause."
 msgstr ""
 
@@ -3873,44 +3886,44 @@ msgstr ""
 msgid "Destination cannot be a string variable."
 msgstr ""
 
 msgid "Destination cannot be a string variable."
 msgstr ""
 
-#: src/language/xforms/recode.c:245
+#: src/language/xforms/recode.c:246
 msgid ""
 "Inconsistent target variable types.  Target variables must be all numeric or "
 "all string."
 msgstr ""
 
 msgid ""
 "Inconsistent target variable types.  Target variables must be all numeric or "
 "all string."
 msgstr ""
 
-#: src/language/xforms/recode.c:266
+#: src/language/xforms/recode.c:267
 msgid "CONVERT requires string input values and numeric output values."
 msgstr ""
 
 msgid "CONVERT requires string input values and numeric output values."
 msgstr ""
 
-#: src/language/xforms/recode.c:316
+#: src/language/xforms/recode.c:317
 msgid "THRU is not allowed with string variables."
 msgstr ""
 
 msgid "THRU is not allowed with string variables."
 msgstr ""
 
-#: src/language/xforms/recode.c:390
+#: src/language/xforms/recode.c:391
 msgid "expecting output value"
 msgstr ""
 
 msgid "expecting output value"
 msgstr ""
 
-#: src/language/xforms/recode.c:439
+#: src/language/xforms/recode.c:440
 #, c-format
 msgid ""
 "%zu variable(s) cannot be recoded into %zu variable(s).  Specify the same "
 "number of variables as source and target variables."
 msgstr ""
 
 #, c-format
 msgid ""
 "%zu variable(s) cannot be recoded into %zu variable(s).  Specify the same "
 "number of variables as source and target variables."
 msgstr ""
 
-#: src/language/xforms/recode.c:454
+#: src/language/xforms/recode.c:455
 #, c-format
 msgid ""
 "There is no variable named %s.  (All string variables specified on INTO must "
 "already exist.  Use the STRING command to create a string variable.)"
 msgstr ""
 
 #, c-format
 msgid ""
 "There is no variable named %s.  (All string variables specified on INTO must "
 "already exist.  Use the STRING command to create a string variable.)"
 msgstr ""
 
-#: src/language/xforms/recode.c:469
+#: src/language/xforms/recode.c:470
 #, c-format
 msgid "INTO is required with %s input values and %s output values."
 msgstr ""
 
 #, c-format
 msgid "INTO is required with %s input values and %s output values."
 msgstr ""
 
-#: src/language/xforms/recode.c:482
+#: src/language/xforms/recode.c:483
 #, c-format
 msgid "Type mismatch.  Cannot store %s data in %s variable %s."
 msgstr ""
 #, c-format
 msgid "Type mismatch.  Cannot store %s data in %s variable %s."
 msgstr ""
@@ -3941,23 +3954,23 @@ msgstr ""
 msgid "hash table:"
 msgstr ""
 
 msgid "hash table:"
 msgstr ""
 
-#: src/math/percentiles.c:40
+#: src/math/percentiles.c:41
 msgid "HAverage"
 msgstr ""
 
 msgid "HAverage"
 msgstr ""
 
-#: src/math/percentiles.c:41
+#: src/math/percentiles.c:42
 msgid "Weighted Average"
 msgstr ""
 
 msgid "Weighted Average"
 msgstr ""
 
-#: src/math/percentiles.c:42
+#: src/math/percentiles.c:43
 msgid "Rounded"
 msgstr ""
 
 msgid "Rounded"
 msgstr ""
 
-#: src/math/percentiles.c:43
+#: src/math/percentiles.c:44
 msgid "Empirical"
 msgstr ""
 
 msgid "Empirical"
 msgstr ""
 
-#: src/math/percentiles.c:44
+#: src/math/percentiles.c:45
 msgid "Empirical with averaging"
 msgstr ""
 
 msgid "Empirical with averaging"
 msgstr ""
 
@@ -4976,7 +4989,7 @@ msgstr ""
 msgid "Options:"
 msgstr ""
 
 msgid "Options:"
 msgstr ""
 
-#: src/ui/gui/find-dialog.c:657
+#: src/ui/gui/find-dialog.c:658
 #, c-format
 msgid "Bad regular expression: %s"
 msgstr ""
 #, c-format
 msgid "Bad regular expression: %s"
 msgstr ""
@@ -5142,10 +5155,6 @@ msgstr ""
 msgid "Paste"
 msgstr ""
 
 msgid "Paste"
 msgstr ""
 
-#: src/ui/gui/psppire.c:197
-msgid "_Reset"
-msgstr ""
-
 #: src/ui/gui/psppire-data-store.c:816
 msgid "var"
 msgstr ""
 #: src/ui/gui/psppire-data-store.c:816
 msgid "var"
 msgstr ""
@@ -5155,6 +5164,28 @@ msgstr ""
 msgid "%ld"
 msgstr ""
 
 msgid "%ld"
 msgstr ""
 
+#: src/ui/gui/psppire-var-store.c:479 src/ui/gui/var-display.c:14
+msgid "None"
+msgstr ""
+
+#: src/ui/gui/psppire-var-store.c:489
+msgid "Scientific"
+msgstr ""
+
+#: src/ui/gui/psppire-var-store.c:492
+msgid "Custom"
+msgstr ""
+
+#: src/ui/gui/psppire-var-store.c:563 src/ui/gui/psppire-var-store.c:573
+#: src/ui/gui/psppire-var-store.c:583
+#, c-format
+msgid "%d"
+msgstr ""
+
+#: src/ui/gui/psppire.c:198
+msgid "_Reset"
+msgstr ""
+
 #: src/ui/gui/psppire.glade:11
 msgid "This is pre-alpha software.  Use at your own risk."
 msgstr ""
 #: src/ui/gui/psppire.glade:11
 msgid "This is pre-alpha software.  Use at your own risk."
 msgstr ""
@@ -5382,24 +5413,6 @@ msgstr ""
 msgid "Search backward"
 msgstr ""
 
 msgid "Search backward"
 msgstr ""
 
-#: src/ui/gui/psppire-var-store.c:479 src/ui/gui/var-display.c:14
-msgid "None"
-msgstr ""
-
-#: src/ui/gui/psppire-var-store.c:489
-msgid "Scientific"
-msgstr ""
-
-#: src/ui/gui/psppire-var-store.c:492
-msgid "Custom"
-msgstr ""
-
-#: src/ui/gui/psppire-var-store.c:563 src/ui/gui/psppire-var-store.c:573
-#: src/ui/gui/psppire-var-store.c:583
-#, c-format
-msgid "%d"
-msgstr ""
-
 #: src/ui/gui/rank.glade:111
 msgid "By:"
 msgstr ""
 #: src/ui/gui/rank.glade:111
 msgid "By:"
 msgstr ""
@@ -5556,6 +5569,11 @@ msgstr ""
 msgid "To End"
 msgstr ""
 
 msgid "To End"
 msgstr ""
 
+#: src/ui/gui/t-test-independent-samples-dialog.c:175
+#, c-format
+msgid "Confidence Interval: %2d %%"
+msgstr ""
+
 #: src/ui/gui/t-test.glade:56
 msgid "Define Groups"
 msgstr ""
 #: src/ui/gui/t-test.glade:56
 msgid "Define Groups"
 msgstr ""
@@ -5588,9 +5606,24 @@ msgstr ""
 msgid "Exclude cases _listwise"
 msgstr ""
 
 msgid "Exclude cases _listwise"
 msgstr ""
 
-#: src/ui/gui/t-test-independent-samples-dialog.c:175
-#, c-format
-msgid "Confidence Interval: %2d %%"
+#: src/ui/gui/var-sheet.c:65
+msgid "Name"
+msgstr ""
+
+#: src/ui/gui/var-sheet.c:68
+msgid "Decimals"
+msgstr ""
+
+#: src/ui/gui/var-sheet.c:70
+msgid "Values"
+msgstr ""
+
+#: src/ui/gui/var-sheet.c:73
+msgid "Align"
+msgstr ""
+
+#: src/ui/gui/var-sheet.c:74
+msgid "Measure"
 msgstr ""
 
 #: src/ui/gui/variable-info-dialog.c:88
 msgstr ""
 
 #: src/ui/gui/variable-info-dialog.c:88
@@ -5622,26 +5655,6 @@ msgstr ""
 msgid "%s %s\n"
 msgstr ""
 
 msgid "%s %s\n"
 msgstr ""
 
-#: src/ui/gui/var-sheet.c:65
-msgid "Name"
-msgstr ""
-
-#: src/ui/gui/var-sheet.c:68
-msgid "Decimals"
-msgstr ""
-
-#: src/ui/gui/var-sheet.c:70
-msgid "Values"
-msgstr ""
-
-#: src/ui/gui/var-sheet.c:73
-msgid "Align"
-msgstr ""
-
-#: src/ui/gui/var-sheet.c:74
-msgid "Measure"
-msgstr ""
-
 #: src/ui/gui/weight-cases-dialog.c:88
 #, c-format
 msgid "Weight cases by %s"
 #: src/ui/gui/weight-cases-dialog.c:88
 #, c-format
 msgid "Weight cases by %s"
index 7ddf9fd280b87705dea1bbf3fa4d8387447aec69..05bafc37136fcb5cb1332e48ac91e3880b324523 100644 (file)
@@ -1,3 +1,80 @@
+2007-11-10  Ben Pfaff  <blp@gnu.org>
+
+       Cleanups and bug fixes devised while writing up documentation.
+       Patch #6262.
+
+       * automake.mk (src_data_libdata_a_SOURCES): Add new files.
+
+       * dict-class.c: New file.
+       (dict_class_from_id): Move here.
+       (dict_class_to_name): Move here.
+
+       * dict-class.h: New file.
+       (enum dict_class): Move here.  Change from consecutive integers to
+       consecutive bits, to make testing for any of multiple values
+       easier.  Add new DC_ALL constant.
+
+       * dictionary.c (struct dictionary): Change `case_limit' from
+       size_t to casenumber.
+       (dict_get_vars): Make final argument an enum dict_class.
+       (dict_get_vars_mutable): Ditto.
+       (dict_get_case_limit): Change return value to casenumber.
+       (dict_set_case_limit): Change final argument to a casenumber.
+       (dict_unset_split_var): Add assertion.  Rephrase slightly.
+       (dict_set_label): Use xstrndup to simplify.
+
+       * format.c (fmt_step_width): AHEX format also needs 2-byte
+       stepping.
+       (fmt_set_style): Simplify assertions.
+
+       * missing-values.c (mv_add_num_range): Rename mv_add_range.
+       Simplify implementation.
+       (mv_has_value): Simplify implementation.
+       (mv_pop_value): Remove the first value, not the last, to avoid
+       having GET followed by SAVE reverse the order of missing values.
+       (mv_peek_value): Rename mv_get_value.  Simplify assertion.
+       (mv_has_range): Simplify implementation.
+       (mv_peek_range): Rename mv_get_range.
+       (can_resize_string): Removed.
+       (mv_is_resizable): Use value_is_resizable.
+       (mv_resize): Use value_resize.
+
+       * short-names.h (SHORT_NAME_LEN): Move here.
+
+       * val-type.h: New file, for definitions related to type and width
+       of abstract values.  Before, these definitions were mixed among
+       those related to "union value" and those related to variables.
+       (macro SYSMIS): Move here.
+       (macro LOWEST): Move here.
+       (macro HIGHEST): Move here.
+       (macro MAX_STRING); Move here.
+       (enum val_type): New enum with values VAL_NUMERIC and VAL_STRING.
+       Replaces enum var_type that had values VAR_NUMERIC and VAR_STRING.
+       All references updated.
+       (val_type_is_valid): New function.  Replaces var_type_is_valid.
+       All references updated.
+       (val_type_from_width): New function.  Replaces
+       var_type_from_width.  All references updated.
+
+       * value-labels.c (val_labs_copy): Renamed val_labs_clone.  All
+       references updated.
+       (val_labs_can_set_width): Use value_is_resizable.
+       (val_labs_add): Simply return false if the value labels set is too
+       wide, instead of having undefined behavior.
+       (val_labs_replace): Ditto.
+       (val_labs_replace): Ditto.
+       (val_labs_first): Set iterator to null if iteration is complete.
+       (val_labs_first_sorted): Ditto.
+       (val_labs_done): Become a no-op if the iterator is null.
+
+       * value.c (value_is_resizable): New function.
+       (value_resize): New function.
+
+       * variable.c (var_get_dict_class): New function.
+
+       * variable.h (macro LONG_NAME_LEN): Rename VAR_NAME_LEN.  Update
+       all references.
+
 2007-11-08  Ben Pfaff  <blp@gnu.org>
 
        * data-in.c: Make formatted data parsing locale-independent.
 2007-11-08  Ben Pfaff  <blp@gnu.org>
 
        * data-in.c: Make formatted data parsing locale-independent.
index 112dc3b071d124d9db59baaf42eb6d499103f8b0..dc28a7f87112f4c521c1a39498fc4aaccaddeb6b 100644 (file)
@@ -42,6 +42,8 @@ src_data_libdata_a_SOURCES = \
        src/data/data-out.h \
        src/data/datasheet.c \
        src/data/datasheet.h \
        src/data/data-out.h \
        src/data/datasheet.c \
        src/data/datasheet.h \
+       src/data/dict-class.c \
+       src/data/dict-class.h \
        src/data/dictionary.c \
        src/data/dictionary.h \
        src/data/file-handle-def.c \
        src/data/dictionary.c \
        src/data/dictionary.h \
        src/data/file-handle-def.c \
index 7330b1a659621d850d4acf9d78ec8fd968bb97e9..ac37f86987341d7085d01990ba947ab1cd9cdecb 100644 (file)
@@ -2,8 +2,8 @@
 #include "calendar.h"
 #include <assert.h>
 #include <stdbool.h>
 #include "calendar.h"
 #include <assert.h>
 #include <stdbool.h>
-#include "settings.h"
-#include "value.h"
+#include <data/settings.h>
+#include <data/val-type.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 10963a6e7bbe8cd211843e5b00e12d4e0f22c228..aa5b9dd0d7c99397ebcb00c7ef908f6ee6a4d719 100644 (file)
@@ -14,8 +14,8 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef HEADER_CASE
-#define HEADER_CASE
+#ifndef DATA_CASE_H
+#define DATA_CASE_H 1
 
 #include <limits.h>
 #include <stddef.h>
 
 #include <limits.h>
 #include <stddef.h>
@@ -82,4 +82,4 @@ int case_compare_2dict (const struct ccase *, const struct ccase *,
 const union value *case_data_all (const struct ccase *);
 union value *case_data_all_rw (struct ccase *);
 
 const union value *case_data_all (const struct ccase *);
 union value *case_data_all_rw (struct ccase *);
 
-#endif /* case.h */
+#endif /* data/case.h */
index 198128863bebec7e502d3e308600965905d50320..d66b1c644903cd9795821c03e2ad71da453eea71 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#if !data_in_h
-#define data_in_h 1
+#ifndef DATA_DATA_IN_H
+#define DATA_DATA_IN_H 1
 
 
-#include <stddef.h>
 #include <stdbool.h>
 #include <stdbool.h>
+#include <data/format.h>
 #include <libpspp/legacy-encoding.h>
 #include <libpspp/float-format.h>
 #include <libpspp/integer-format.h>
 #include <libpspp/str.h>
 #include <libpspp/legacy-encoding.h>
 #include <libpspp/float-format.h>
 #include <libpspp/integer-format.h>
 #include <libpspp/str.h>
-#include "format.h"
 
 enum integer_format data_in_get_integer_format (void);
 void data_in_set_integer_format (enum integer_format);
 
 enum integer_format data_in_get_integer_format (void);
 void data_in_set_integer_format (enum integer_format);
@@ -31,8 +30,9 @@ void data_in_set_integer_format (enum integer_format);
 enum float_format data_in_get_float_format (void);
 void data_in_set_float_format (enum float_format);
 
 enum float_format data_in_get_float_format (void);
 void data_in_set_float_format (enum float_format);
 
+union value;
 bool data_in (struct substring input, enum legacy_encoding,
               enum fmt_type, int implied_decimals, int first_column,
               union value *output, int width);
 
 bool data_in (struct substring input, enum legacy_encoding,
               enum fmt_type, int implied_decimals, int first_column,
               union value *output, int width);
 
-#endif /* data-in.h */
+#endif /* data/data-in.h */
index 02ff06572fabcb1f282c2b9aa51319ee32ae0850..26abc7cc112a9897f1ebf4b928a429000ed67b5a 100644 (file)
 #include <stdlib.h>
 #include <time.h>
 
 #include <stdlib.h>
 #include <time.h>
 
-#include "calendar.h"
-#include "format.h"
-#include "settings.h"
-#include "value.h"
+#include <data/calendar.h>
+#include <data/format.h>
+#include <data/settings.h>
+#include <data/value.h>
 
 #include <libpspp/assertion.h>
 #include <libpspp/float-format.h>
 #include <libpspp/integer-format.h>
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
 
 #include <libpspp/assertion.h>
 #include <libpspp/float-format.h>
 #include <libpspp/integer-format.h>
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include <libpspp/misc.h>
 #include <libpspp/str.h>
 
 #include "minmax.h"
 #include <libpspp/str.h>
 
 #include "minmax.h"
diff --git a/src/data/dict-class.c b/src/data/dict-class.c
new file mode 100644 (file)
index 0000000..c79b29a
--- /dev/null
@@ -0,0 +1,60 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2007 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <data/dict-class.h>
+
+#include <libpspp/assertion.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* Returns the dictionary class corresponding to a variable named
+   NAME. */
+enum dict_class
+dict_class_from_id (const char *name)
+{
+  switch (name[0])
+    {
+    default:
+      return DC_ORDINARY;
+    case '$':
+      return DC_SYSTEM;
+    case '#':
+      return DC_SCRATCH;
+    }
+}
+
+/* Returns the name of dictionary class DICT_CLASS.
+
+   This function should probably not be used in new code as it
+   can lead to difficulties for internationalization. */
+const char *
+dict_class_to_name (enum dict_class dict_class)
+{
+  switch (dict_class)
+    {
+    case DC_ORDINARY:
+      return _("ordinary");
+    case DC_SYSTEM:
+      return _("system");
+    case DC_SCRATCH:
+      return _("scratch");
+    default:
+      NOT_REACHED ();
+    }
+}
diff --git a/src/data/dict-class.h b/src/data/dict-class.h
new file mode 100644 (file)
index 0000000..e3872e8
--- /dev/null
@@ -0,0 +1,42 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2007 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* Dictionary classes.
+
+   Occasionally it is useful to classify variables into three
+   groups: system variables (those whose names begin with $),
+   scratch variables (those whose names begin with #), and
+   ordinary variables (all others).  This header provides a
+   little bit of support for this. */
+
+#ifndef DATA_DICT_CLASS_H
+#define DATA_DICT_CLASS_H 1
+
+/* Classes of variables.
+   These values are bitwise disjoint so that they can be used in
+   masks. */
+enum dict_class
+  {
+    DC_ORDINARY = 0x0001,       /* Ordinary identifier. */
+    DC_SYSTEM = 0x0002,         /* System variable. */
+    DC_SCRATCH = 0x0004,        /* Scratch variable. */
+    DC_ALL = 0x0007             /* All of the above. */
+  };
+
+enum dict_class dict_class_from_id (const char *name);
+const char *dict_class_to_name (enum dict_class);
+
+#endif /* data/dict-class.h */
index 0f3e25e3285d0ac76fe6814c1a29436ed5ac196c..94a0292e17b54d878b69e6d37539118cff47b6e2 100644 (file)
@@ -53,7 +53,7 @@ struct dictionary
     size_t split_cnt;           /* SPLIT FILE count. */
     struct variable *weight;    /* WEIGHT variable. */
     struct variable *filter;    /* FILTER variable. */
     size_t split_cnt;           /* SPLIT FILE count. */
     struct variable *weight;    /* WEIGHT variable. */
     struct variable *filter;    /* FILTER variable. */
-    size_t case_limit;          /* Current case limit (N command). */
+    casenumber case_limit;      /* Current case limit (N command). */
     char *label;               /* File label. */
     struct string documents;    /* Documents, as a string. */
     struct vector **vector;     /* Vectors of variables. */
     char *label;               /* File label. */
     struct string documents;    /* Documents, as a string. */
     struct vector **vector;     /* Vectors of variables. */
@@ -257,21 +257,26 @@ dict_get_var (const struct dictionary *d, size_t idx)
   return d->var[idx];
 }
 
   return d->var[idx];
 }
 
-inline void
+/* Sets *VARS to an array of pointers to variables in D and *CNT
+   to the number of variables in *D.  All variables are returned
+   except for those, if any, in the classes indicated by EXCLUDE.
+   (There is no point in putting DC_SYSTEM in EXCLUDE as
+   dictionaries never include system variables.) */
+void
 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
-               size_t *cnt, unsigned exclude_classes)
+               size_t *cnt, enum dict_class exclude)
 {
 {
-  dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude_classes);
+  dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude);
 }
 
 /* Sets *VARS to an array of pointers to variables in D and *CNT
    to the number of variables in *D.  All variables are returned
 }
 
 /* Sets *VARS to an array of pointers to variables in D and *CNT
    to the number of variables in *D.  All variables are returned
-   if EXCLUDE_CLASSES is 0, or it may contain one or more of (1u
-   << DC_ORDINARY), (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to
-   exclude the corresponding type of variable. */
+   except for those, if any, in the classes indicated by EXCLUDE.
+   (There is no point in putting DC_SYSTEM in EXCLUDE as
+   dictionaries never include system variables.) */
 void
 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
 void
 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
-               size_t *cnt, unsigned exclude_classes)
+                       size_t *cnt, enum dict_class exclude)
 {
   size_t count;
   size_t i;
 {
   size_t count;
   size_t i;
@@ -279,15 +284,13 @@ dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
   assert (d != NULL);
   assert (vars != NULL);
   assert (cnt != NULL);
   assert (d != NULL);
   assert (vars != NULL);
   assert (cnt != NULL);
-  assert ((exclude_classes & ~((1u << DC_ORDINARY)
-                               | (1u << DC_SYSTEM)
-                               | (1u << DC_SCRATCH))) == 0);
+  assert (exclude == (exclude & DC_ALL));
 
   count = 0;
   for (i = 0; i < d->var_cnt; i++)
     {
 
   count = 0;
   for (i = 0; i < d->var_cnt; i++)
     {
-      enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
-      if (!(exclude_classes & (1u << class)))
+      enum dict_class class = var_get_dict_class (d->var[i]);
+      if (!(class & exclude))
         count++;
     }
 
         count++;
     }
 
@@ -295,8 +298,8 @@ dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
   *cnt = 0;
   for (i = 0; i < d->var_cnt; i++)
     {
   *cnt = 0;
   for (i = 0; i < d->var_cnt; i++)
     {
-      enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
-      if (!(exclude_classes & (1u << class)))
+      enum dict_class class = var_get_dict_class (d->var[i]);
+      if (!(class & exclude))
         (*vars)[(*cnt)++] = d->var[i];
     }
   assert (*cnt == count);
         (*vars)[(*cnt)++] = d->var[i];
     }
   assert (*cnt == count);
@@ -480,7 +483,7 @@ reindex_vars (struct dictionary *d, size_t from, size_t to)
    active on the dictionary's dataset, because those
    transformations might reference the deleted variable.  The
    safest time to delete a variable is just after a procedure has
    active on the dictionary's dataset, because those
    transformations might reference the deleted variable.  The
    safest time to delete a variable is just after a procedure has
-   been executed, as done by MODIFY VARS.
+   been executed, as done by DELETE VARIABLES.
 
    Pointers to V within D are not a problem, because
    dict_delete_var() knows to remove V from split variables,
 
    Pointers to V within D are not a problem, because
    dict_delete_var() knows to remove V from split variables,
@@ -567,7 +570,7 @@ dict_delete_scratch_vars (struct dictionary *d)
   assert (d != NULL);
 
   for (i = 0; i < d->var_cnt; )
   assert (d != NULL);
 
   for (i = 0; i < d->var_cnt; )
-    if (dict_class_from_id (var_get_name (d->var[i])) == DC_SCRATCH)
+    if (var_get_dict_class (d->var[i]) == DC_SCRATCH)
       dict_delete_var (d, d->var[i]);
     else
       i++;
       dict_delete_var (d, d->var[i]);
     else
       i++;
@@ -734,11 +737,12 @@ dict_get_weight (const struct dictionary *d)
   return d->weight;
 }
 
   return d->weight;
 }
 
-/* Returns the value of D's weighting variable in case C, except that a
-   negative weight is returned as 0.  Returns 1 if the dictionary is
-   unweighted. Will warn about missing, negative, or zero values if
-   warn_on_invalid is true. The function will set warn_on_invalid to false
-   if an invalid weight is found. */
+/* Returns the value of D's weighting variable in case C, except
+   that a negative weight is returned as 0.  Returns 1 if the
+   dictionary is unweighted.  Will warn about missing, negative,
+   or zero values if *WARN_ON_INVALID is true.  The function will
+   set *WARN_ON_INVALID to false if an invalid weight is
+   found. */
 double
 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
                      bool *warn_on_invalid)
 double
 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
                      bool *warn_on_invalid)
@@ -798,6 +802,7 @@ dict_set_filter (struct dictionary *d, struct variable *v)
 {
   assert (d != NULL);
   assert (v == NULL || dict_contains_var (d, v));
 {
   assert (d != NULL);
   assert (v == NULL || dict_contains_var (d, v));
+  assert (v == NULL || var_is_numeric (v));
 
   d->filter = v;
 
 
   d->filter = v;
 
@@ -809,7 +814,7 @@ dict_set_filter (struct dictionary *d, struct variable *v)
 
 /* Returns the case limit for dictionary D, or zero if the number
    of cases is unlimited. */
 
 /* Returns the case limit for dictionary D, or zero if the number
    of cases is unlimited. */
-size_t
+casenumber
 dict_get_case_limit (const struct dictionary *d)
 {
   assert (d != NULL);
 dict_get_case_limit (const struct dictionary *d)
 {
   assert (d != NULL);
@@ -820,7 +825,7 @@ dict_get_case_limit (const struct dictionary *d)
 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
    0 for CASE_LIMIT to indicate no limit. */
 void
 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
    0 for CASE_LIMIT to indicate no limit. */
 void
-dict_set_case_limit (struct dictionary *d, size_t case_limit)
+dict_set_case_limit (struct dictionary *d, casenumber case_limit)
 {
   assert (d != NULL);
 
 {
   assert (d != NULL);
 
@@ -913,7 +918,7 @@ dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
   cnt = 0;
   for (i = 0; i < d->var_cnt; i++)
     {
   cnt = 0;
   for (i = 0; i < d->var_cnt; i++)
     {
-      enum dict_class class = dict_class_from_id (var_get_name (d->var[i]));
+      enum dict_class class = var_get_dict_class (d->var[i]);
       if (!(exclude_classes & (1u << class)))
         cnt += var_get_value_cnt (d->var[i]);
     }
       if (!(exclude_classes & (1u << class)))
         cnt += var_get_value_cnt (d->var[i]);
     }
@@ -941,20 +946,25 @@ dict_get_split_cnt (const struct dictionary *d)
   return d->split_cnt;
 }
 
   return d->split_cnt;
 }
 
-/* Removes variable V from the set of split variables in dictionary D */
+/* Removes variable V, which must be in D, from D's set of split
+   variables. */
 void
 void
-dict_unset_split_var (struct dictionary *d,
-                     struct variable *v)
+dict_unset_split_var (struct dictionary *d, struct variable *v)
 {
 {
-  const int count = d->split_cnt;
-  d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
-                               &v, compare_var_ptrs, NULL);
+  int orig_count;
 
 
-  if ( count == d->split_cnt)
-    return;
+  assert (dict_contains_var (d, v));
 
 
-  if ( d->callbacks &&  d->callbacks->split_changed )
-    d->callbacks->split_changed (d, d->cb_data);
+  orig_count = d->split_cnt;
+  d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
+                               &v, compare_var_ptrs, NULL);
+  if (orig_count != d->split_cnt)
+    {
+      /* We changed the set of split variables so invoke the
+         callback. */
+      if (d->callbacks &&  d->callbacks->split_changed)
+        d->callbacks->split_changed (d, d->cb_data);
+    }
 }
 
 /* Sets CNT split vars SPLIT in dictionary D. */
 }
 
 /* Sets CNT split vars SPLIT in dictionary D. */
@@ -999,16 +1009,7 @@ dict_set_label (struct dictionary *d, const char *label)
   assert (d != NULL);
 
   free (d->label);
   assert (d != NULL);
 
   free (d->label);
-  if (label == NULL)
-    d->label = NULL;
-  else if (strlen (label) < 60)
-    d->label = xstrdup (label);
-  else
-    {
-      d->label = xmalloc (61);
-      memcpy (d->label, label, 60);
-      d->label[60] = '\0';
-    }
+  d->label = label != NULL ? xstrndup (label, 60) : NULL;
 }
 
 /* Returns the documents for D, or a null pointer if D has no
 }
 
 /* Returns the documents for D, or a null pointer if D has no
index 581a49d827614a56277dd65cf7564addc9a0f49b..167487fbd10a34182ed5457c62a7770262c8e794 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef DICTIONARY_H
-#define DICTIONARY_H
+#ifndef DATA_DICTIONARY_H
+#define DATA_DICTIONARY_H 1
 
 #include <stdbool.h>
 #include <stddef.h>
 
 #include <stdbool.h>
 #include <stddef.h>
+#include <data/case.h>
+#include <data/dict-class.h>
 
 
-/* Dictionary. */
-
-struct variable;
-struct dictionary;
 struct string;
 struct string;
+struct ccase;
 
 
-struct dict_callbacks
- {
-  void (*var_added) (struct dictionary *, int, void *);
-  void (*var_deleted) (struct dictionary *, int, int, int, void *);
-  void (*var_changed) (struct dictionary *, int, void *);
-  void (*var_resized) (struct dictionary *, int, int, void *);
-  void (*weight_changed) (struct dictionary *, int, void *);
-  void (*filter_changed) (struct dictionary *, int, void *);
-  void (*split_changed) (struct dictionary *, void *);
- };
-
-
+/* Creating dictionaries. */
 struct dictionary *dict_create (void);
 struct dictionary *dict_clone (const struct dictionary *);
 struct dictionary *dict_create (void);
 struct dictionary *dict_clone (const struct dictionary *);
-void dict_set_callbacks (struct dictionary *, const struct dict_callbacks *,
-                        void *);
-void dict_copy_callbacks (struct dictionary *, const struct dictionary *);
 
 
 
 
+/* Clearing and destroying dictionaries. */
 void dict_clear (struct dictionary *);
 void dict_clear_aux (struct dictionary *);
 void dict_destroy (struct dictionary *);
 
 void dict_clear (struct dictionary *);
 void dict_clear_aux (struct dictionary *);
 void dict_destroy (struct dictionary *);
 
+/* Common ways to access variables. */
+struct variable *dict_lookup_var (const struct dictionary *, const char *);
+struct variable *dict_lookup_var_assert (const struct dictionary *,
+                                         const char *);
+struct variable *dict_get_var (const struct dictionary *, size_t position);
 size_t dict_get_var_cnt (const struct dictionary *);
 size_t dict_get_var_cnt (const struct dictionary *);
-struct variable *dict_get_var (const struct dictionary *, size_t idx);
-inline void dict_get_vars (const struct dictionary *,
+
+/* Other access to variables. */
+bool dict_contains_var (const struct dictionary *, const struct variable *);
+void dict_get_vars (const struct dictionary *,
                     const struct variable ***vars, size_t *cnt,
                     const struct variable ***vars, size_t *cnt,
-                    unsigned exclude_classes);
+                    enum dict_class exclude);
 void dict_get_vars_mutable (const struct dictionary *,
 void dict_get_vars_mutable (const struct dictionary *,
-                    struct variable ***vars, size_t *cnt,
-                    unsigned exclude_classes);
+                            struct variable ***vars, size_t *cnt,
+                            enum dict_class exclude);
 
 
+/* Creating variables. */
 struct variable *dict_create_var (struct dictionary *, const char *,
                                   int width);
 struct variable *dict_create_var (struct dictionary *, const char *,
                                   int width);
-
 struct variable *dict_create_var_assert (struct dictionary *, const char *,
 struct variable *dict_create_var_assert (struct dictionary *, const char *,
-                                  int width);
+                                         int width);
 struct variable *dict_clone_var (struct dictionary *, const struct variable *,
                                  const char *);
 struct variable *dict_clone_var_assert (struct dictionary *,
                                         const struct variable *, const char *);
 
 struct variable *dict_clone_var (struct dictionary *, const struct variable *,
                                  const char *);
 struct variable *dict_clone_var_assert (struct dictionary *,
                                         const struct variable *, const char *);
 
-struct variable *dict_lookup_var (const struct dictionary *, const char *);
-struct variable *dict_lookup_var_assert (const struct dictionary *,
-                                         const char *);
-bool dict_contains_var (const struct dictionary *, const struct variable *);
+/* Deleting variables. */
 void dict_delete_var (struct dictionary *, struct variable *);
 void dict_delete_vars (struct dictionary *,
                        struct variable *const *, size_t count);
 void dict_delete_var (struct dictionary *, struct variable *);
 void dict_delete_vars (struct dictionary *,
                        struct variable *const *, size_t count);
-void dict_delete_consecutive_vars (struct dictionary *d,
+void dict_delete_consecutive_vars (struct dictionary *,
                                    size_t idx, size_t count);
 void dict_delete_scratch_vars (struct dictionary *);
                                    size_t idx, size_t count);
 void dict_delete_scratch_vars (struct dictionary *);
-void dict_reorder_var (struct dictionary *d, struct variable *v,
+
+/* Changing the order of variables. */
+void dict_reorder_var (struct dictionary *, struct variable *,
                        size_t new_index);
 void dict_reorder_vars (struct dictionary *,
                         struct variable *const *, size_t count);
                        size_t new_index);
 void dict_reorder_vars (struct dictionary *,
                         struct variable *const *, size_t count);
+
+/* Changing variable names. */
 void dict_rename_var (struct dictionary *, struct variable *, const char *);
 bool dict_rename_vars (struct dictionary *,
                        struct variable **, char **new_names,
                        size_t count, char **err_name);
 
 void dict_rename_var (struct dictionary *, struct variable *, const char *);
 bool dict_rename_vars (struct dictionary *,
                        struct variable **, char **new_names,
                        size_t count, char **err_name);
 
-struct ccase;
-struct variable *dict_get_weight (const struct dictionary *);
+/* Weight variable. */
 double dict_get_case_weight (const struct dictionary *,
                             const struct ccase *, bool *);
 double dict_get_case_weight (const struct dictionary *,
                             const struct ccase *, bool *);
+struct variable *dict_get_weight (const struct dictionary *);
 void dict_set_weight (struct dictionary *, struct variable *);
 
 void dict_set_weight (struct dictionary *, struct variable *);
 
+/* Filter variable. */
 struct variable *dict_get_filter (const struct dictionary *);
 void dict_set_filter (struct dictionary *, struct variable *);
 
 struct variable *dict_get_filter (const struct dictionary *);
 void dict_set_filter (struct dictionary *, struct variable *);
 
-size_t dict_get_case_limit (const struct dictionary *);
-void dict_set_case_limit (struct dictionary *, size_t);
+/* Case limit (N OF CASES). */
+casenumber dict_get_case_limit (const struct dictionary *);
+void dict_set_case_limit (struct dictionary *, casenumber);
 
 
+/* Size of cases for this dictionary. */
 int dict_get_next_value_idx (const struct dictionary *);
 size_t dict_get_case_size (const struct dictionary *);
 
 int dict_get_next_value_idx (const struct dictionary *);
 size_t dict_get_case_size (const struct dictionary *);
 
+/* Making this dictionary's cases smaller (if some variables were
+   deleted). */
 size_t dict_count_values (const struct dictionary *,
                           unsigned int exclude_classes);
 void dict_compact_values (struct dictionary *);
 
 size_t dict_count_values (const struct dictionary *,
                           unsigned int exclude_classes);
 void dict_compact_values (struct dictionary *);
 
+/* SPLIT FILE variables. */
 const struct variable *const *dict_get_split_vars (const struct dictionary *);
 size_t dict_get_split_cnt (const struct dictionary *);
 void dict_set_split_vars (struct dictionary *,
                           struct variable *const *, size_t cnt);
 const struct variable *const *dict_get_split_vars (const struct dictionary *);
 size_t dict_get_split_cnt (const struct dictionary *);
 void dict_set_split_vars (struct dictionary *,
                           struct variable *const *, size_t cnt);
-void dict_unset_split_var (struct dictionary *d,
-                          struct variable *v);
+void dict_unset_split_var (struct dictionary *, struct variable *);
 
 
+/* File label. */
 const char *dict_get_label (const struct dictionary *);
 void dict_set_label (struct dictionary *, const char *);
 
 const char *dict_get_label (const struct dictionary *);
 void dict_set_label (struct dictionary *, const char *);
 
-/* Fixed length of lines in dictionary documents. */
-#define DOC_LINE_LENGTH 80
+/* Documents. */
+#define DOC_LINE_LENGTH 80 /* Fixed length of document lines. */
 
 const char *dict_get_documents (const struct dictionary *);
 void dict_set_documents (struct dictionary *, const char *);
 void dict_clear_documents (struct dictionary *);
 
 const char *dict_get_documents (const struct dictionary *);
 void dict_set_documents (struct dictionary *, const char *);
 void dict_clear_documents (struct dictionary *);
+
 void dict_add_document_line (struct dictionary *, const char *);
 size_t dict_get_document_line_cnt (const struct dictionary *);
 void dict_get_document_line (const struct dictionary *,
                              size_t, struct string *);
 
 void dict_add_document_line (struct dictionary *, const char *);
 size_t dict_get_document_line_cnt (const struct dictionary *);
 void dict_get_document_line (const struct dictionary *,
                              size_t, struct string *);
 
-bool dict_create_vector (struct dictionary *,
-                         const char *name,
+/* Vectors. */
+bool dict_create_vector (struct dictionary *, const char *name,
                          struct variable **, size_t cnt);
                          struct variable **, size_t cnt);
-void dict_create_vector_assert (struct dictionary *,
-                                const char *name,
+void dict_create_vector_assert (struct dictionary *, const char *name,
                                 struct variable **, size_t cnt);
                                 struct variable **, size_t cnt);
-const struct vector *dict_get_vector (const struct dictionary *,
-                                      size_t idx);
+const struct vector *dict_get_vector (const struct dictionary *, size_t idx);
 size_t dict_get_vector_cnt (const struct dictionary *);
 const struct vector *dict_lookup_vector (const struct dictionary *,
                                          const char *name);
 void dict_clear_vectors (struct dictionary *);
 
 size_t dict_get_vector_cnt (const struct dictionary *);
 const struct vector *dict_lookup_vector (const struct dictionary *,
                                          const char *name);
 void dict_clear_vectors (struct dictionary *);
 
+/* Functions to be called upon dictionary changes. */
+struct dict_callbacks
+ {
+  void (*var_added) (struct dictionary *, int, void *);
+  void (*var_deleted) (struct dictionary *, int, int, int, void *);
+  void (*var_changed) (struct dictionary *, int, void *);
+  void (*var_resized) (struct dictionary *, int, int, void *);
+  void (*weight_changed) (struct dictionary *, int, void *);
+  void (*filter_changed) (struct dictionary *, int, void *);
+  void (*split_changed) (struct dictionary *, void *);
+ };
+
+void dict_set_callbacks (struct dictionary *, const struct dict_callbacks *,
+                        void *);
+void dict_copy_callbacks (struct dictionary *, const struct dictionary *);
+
+/* Debug use only. */
 void dict_dump (const struct dictionary *);
 
 void dict_dump (const struct dictionary *);
 
-#endif /* dictionary.h */
+#endif /* data/dictionary.h */
index 54c6281716b5025d0c23ebd47a9ed9cf1e203bfb..c90ff95b6f5fc51a486b58cd1f10c6ce2ce07220 100644 (file)
@@ -66,7 +66,7 @@ fmt_done (void)
 {
   int t;
   for (t = 0 ; t < FMT_NUMBER_OF_FORMATS ; ++t )
 {
   int t;
   for (t = 0 ; t < FMT_NUMBER_OF_FORMATS ; ++t )
-         fmt_number_style_destroy (styles[t]);
+    fmt_number_style_destroy (styles[t]);
 }
 
 /* Returns an input format specification with type TYPE, width W,
 }
 
 /* Returns an input format specification with type TYPE, width W,
@@ -305,18 +305,18 @@ fmt_check_output (const struct fmt_spec *spec)
 }
 
 /* Checks that FORMAT is appropriate for a variable of the given
 }
 
 /* Checks that FORMAT is appropriate for a variable of the given
-   TYPE and returns true if so.  Otherwise returns false and
+   VAR_TYPE and returns true if so.  Otherwise returns false and
    emits an error message. */
 bool
    emits an error message. */
 bool
-fmt_check_type_compat (const struct fmt_spec *format, enum var_type var_type)
+fmt_check_type_compat (const struct fmt_spec *format, enum val_type var_type)
 {
 {
-  assert (var_type_is_valid (var_type));
-  if ((var_type == VAR_STRING) != (fmt_is_string (format->type) != 0))
+  assert (val_type_is_valid (var_type));
+  if ((var_type == VAL_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."),
     {
       char str[FMT_STRING_LEN_MAX + 1];
       msg (SE, _("%s variables are not compatible with %s format %s."),
-           var_type == VAR_STRING ? _("String") : _("Numeric"),
-           var_type == VAR_STRING ? _("numeric") : _("string"),
+           var_type == VAL_STRING ? _("String") : _("Numeric"),
+           var_type == VAL_STRING ? _("numeric") : _("string"),
            fmt_to_string (format, str));
       return false;
     }
            fmt_to_string (format, str));
       return false;
     }
@@ -329,7 +329,7 @@ fmt_check_type_compat (const struct fmt_spec *format, enum var_type var_type)
 bool
 fmt_check_width_compat (const struct fmt_spec *format, int width)
 {
 bool
 fmt_check_width_compat (const struct fmt_spec *format, int width)
 {
-  if (!fmt_check_type_compat (format, var_type_from_width (width)))
+  if (!fmt_check_type_compat (format, val_type_from_width (width)))
     return false;
   if (fmt_var_width (format) != width)
     {
     return false;
   if (fmt_var_width (format) != width)
     {
@@ -342,14 +342,13 @@ fmt_check_width_compat (const struct fmt_spec *format, int width)
   return true;
 }
 
   return true;
 }
 
-/* Returns the width corresponding to the format specifier.  The
-   return value is the value of the `width' member of a `struct
-   variable' for such an input format. */
+/* Returns the width corresponding to FORMAT.  The return value
+   is the width of the `union value's required by FORMAT. */
 int
 int
-fmt_var_width (const struct fmt_spec *spec)
+fmt_var_width (const struct fmt_spec *format)
 {
 {
-  return (spec->type == FMT_AHEX ? spec->w / 2
-          : spec->type == FMT_A ? spec->w
+  return (format->type == FMT_AHEX ? format->w / 2
+          : format->type == FMT_A ? format->w
           : 0);
 }
 
           : 0);
 }
 
@@ -499,7 +498,8 @@ fmt_max_output_decimals (enum fmt_type type, int width)
 int
 fmt_step_width (enum fmt_type type)
 {
 int
 fmt_step_width (enum fmt_type type)
 {
-  return fmt_get_category (type) == FMT_CAT_HEXADECIMAL ? 2 : 1;
+  return (fmt_get_category (type) == FMT_CAT_HEXADECIMAL || type == FMT_AHEX
+          ? 2 : 1);
 }
 
 /* Returns true if TYPE is used for string fields,
 }
 
 /* Returns true if TYPE is used for string fields,
@@ -868,9 +868,9 @@ fmt_set_style (enum fmt_type type, struct fmt_number_style *style)
   assert (ss_length (style->suffix) <= FMT_STYLE_AFFIX_MAX);
   assert (ss_length (style->neg_suffix) <= FMT_STYLE_AFFIX_MAX);
   assert (style->decimal == '.' || style->decimal == ',');
   assert (ss_length (style->suffix) <= FMT_STYLE_AFFIX_MAX);
   assert (ss_length (style->neg_suffix) <= FMT_STYLE_AFFIX_MAX);
   assert (style->decimal == '.' || style->decimal == ',');
-  assert (style->grouping != style->decimal
-          && (style->grouping == '.' || style->grouping == ','
-              || style->grouping == 0));
+  assert (style->grouping == '.' || style->grouping == ','
+          || style->grouping == 0);
+  assert (style->grouping != style->decimal);
 
   assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
   assert (styles[type] != NULL);
 
   assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
   assert (styles[type] != NULL);
index fbaf062558aab7e5704cbc190da9fe6577c651ee..d00cb1d9eefc1ea46e3c2166afcf601475da379d 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef FORMAT_H
-#define FORMAT_H 1
+#ifndef DATA_FORMAT_H
+#define DATA_FORMAT_H 1
 
 /* Display format types. */
 
 #include <stdbool.h>
 
 /* Display format types. */
 
 #include <stdbool.h>
-#include <stddef.h>
-#include <data/variable.h>
 #include <libpspp/str.h>
 #include <libpspp/str.h>
+#include <data/val-type.h>
 
 
-/* Format type categories. */
+/* Format type categories.
+
+   Each format is in exactly one category.  We give categories
+   bitwise disjoint values only to enable bitwise comparisons
+   against a mask of FMT_CAT_* values, not to allow multiple
+   categories per format. */
 enum fmt_category
   {
     /* Numeric formats. */
 enum fmt_category
   {
     /* Numeric formats. */
@@ -41,6 +45,7 @@ enum fmt_category
     FMT_CAT_STRING         = 0x100      /* String formats. */
   };
 
     FMT_CAT_STRING         = 0x100      /* String formats. */
   };
 
+/* Format type. */
 enum fmt_type
   {
 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) FMT_##NAME,
 enum fmt_type
   {
 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) FMT_##NAME,
@@ -64,8 +69,6 @@ struct fmt_spec
     int d;                     /* Number of implied decimal places. */
   };
 
     int d;                     /* Number of implied decimal places. */
   };
 
-union value;
-
 /* Initialization. */
 void fmt_init (void);
 void fmt_done (void);
 /* Initialization. */
 void fmt_init (void);
 void fmt_done (void);
@@ -74,13 +77,13 @@ void fmt_done (void);
 struct fmt_spec fmt_for_input (enum fmt_type, int w, int d) PURE_FUNCTION;
 struct fmt_spec fmt_for_output (enum fmt_type, int w, int d) PURE_FUNCTION;
 struct fmt_spec fmt_for_output_from_input (const struct fmt_spec *);
 struct fmt_spec fmt_for_input (enum fmt_type, int w, int d) PURE_FUNCTION;
 struct fmt_spec fmt_for_output (enum fmt_type, int w, int d) PURE_FUNCTION;
 struct fmt_spec fmt_for_output_from_input (const struct fmt_spec *);
-struct fmt_spec fmt_default_for_width (int var_width);
+struct fmt_spec fmt_default_for_width (int width);
 
 /* Verifying formats. */
 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 *);
 
 /* Verifying formats. */
 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 *, enum var_type);
+bool fmt_check_type_compat (const struct fmt_spec *, enum val_type);
 bool fmt_check_width_compat (const struct fmt_spec *, int var_width);
 
 /* Working with formats. */
 bool fmt_check_width_compat (const struct fmt_spec *, int var_width);
 
 /* Working with formats. */
@@ -108,11 +111,11 @@ bool fmt_is_numeric (enum fmt_type) PURE_FUNCTION;
 enum fmt_category fmt_get_category (enum fmt_type) PURE_FUNCTION;
 
 enum fmt_type fmt_input_to_output (enum fmt_type) PURE_FUNCTION;
 enum fmt_category fmt_get_category (enum fmt_type) PURE_FUNCTION;
 
 enum fmt_type fmt_input_to_output (enum fmt_type) PURE_FUNCTION;
+bool fmt_usable_for_input (enum fmt_type) PURE_FUNCTION;
 
 int fmt_to_io (enum fmt_type) PURE_FUNCTION;
 bool fmt_from_io (int io, enum fmt_type *);
 
 
 int fmt_to_io (enum fmt_type) PURE_FUNCTION;
 bool fmt_from_io (int io, enum fmt_type *);
 
-bool fmt_usable_for_input (enum fmt_type) PURE_FUNCTION;
 const char *fmt_date_template (enum fmt_type) PURE_FUNCTION;
 char *fmt_dollar_template (const struct fmt_spec *);
 \f
 const char *fmt_date_template (enum fmt_type) PURE_FUNCTION;
 char *fmt_dollar_template (const struct fmt_spec *);
 \f
@@ -134,15 +137,15 @@ struct fmt_number_style
 struct fmt_number_style *fmt_number_style_create (void);
 void fmt_number_style_destroy (struct fmt_number_style *);
 
 struct fmt_number_style *fmt_number_style_create (void);
 void fmt_number_style_destroy (struct fmt_number_style *);
 
-const struct fmt_number_style *fmt_get_style (enum fmt_type);
-void fmt_set_style (enum fmt_type, struct fmt_number_style *);
-
 int fmt_affix_width (const struct fmt_number_style *);
 int fmt_neg_affix_width (const struct fmt_number_style *);
 
 int fmt_affix_width (const struct fmt_number_style *);
 int fmt_neg_affix_width (const struct fmt_number_style *);
 
+const struct fmt_number_style *fmt_get_style (enum fmt_type);
+void fmt_set_style (enum fmt_type, struct fmt_number_style *);
+
 int fmt_decimal_char (enum fmt_type);
 int fmt_grouping_char (enum fmt_type);
 
 void fmt_set_decimal (char);
 
 int fmt_decimal_char (enum fmt_type);
 int fmt_grouping_char (enum fmt_type);
 
 void fmt_set_decimal (char);
 
-#endif /* format.h */
+#endif /* data/format.h */
index c4d40baae13c0c25c23d9bdd3226837a6c438844..07ebb77a17312a388ced25b3f04e2ae4f4f0fea5 100644 (file)
@@ -18,6 +18,7 @@
 #include "missing-values.h"
 #include <assert.h>
 #include <stdlib.h>
 #include "missing-values.h"
 #include <assert.h>
 #include <stdlib.h>
+#include <libpspp/array.h>
 #include <libpspp/assertion.h>
 #include "variable.h"
 #include <libpspp/str.h>
 #include <libpspp/assertion.h>
 #include "variable.h"
 #include <libpspp/str.h>
@@ -129,27 +130,18 @@ mv_add_num (struct missing_values *mv, double d)
    missing values MV.  Returns true if successful, false if MV
    has no room for a range, or if LOW > HIGH. */
 bool
    missing values MV.  Returns true if successful, false if MV
    has no room for a range, or if LOW > HIGH. */
 bool
-mv_add_num_range (struct missing_values *mv, double low, double high)
+mv_add_range (struct missing_values *mv, double low, double high)
 {
   assert (mv->width == 0);
 {
   assert (mv->width == 0);
-  if (low > high)
-    return false;
-  switch (mv->type)
+  if (low <= high && (mv->type == MVT_NONE || mv->type == MVT_1))
     {
     {
-    case MVT_NONE:
-    case MVT_1:
       mv->values[1].f = low;
       mv->values[2].f = high;
       mv->type |= 4;
       return true;
       mv->values[1].f = low;
       mv->values[2].f = high;
       mv->type |= 4;
       return true;
-
-    case MVT_2:
-    case MVT_3:
-    case MVT_RANGE:
-    case MVT_RANGE_1:
-      return false;
     }
     }
-  NOT_REACHED ();
+  else
+    return false;
 }
 
 /* Returns true if MV contains an individual value,
 }
 
 /* Returns true if MV contains an individual value,
@@ -157,44 +149,36 @@ mv_add_num_range (struct missing_values *mv, double low, double high)
 bool
 mv_has_value (const struct missing_values *mv)
 {
 bool
 mv_has_value (const struct missing_values *mv)
 {
-  switch (mv->type)
-    {
-    case MVT_1:
-    case MVT_2:
-    case MVT_3:
-    case MVT_RANGE_1:
-      return true;
-
-    case MVT_NONE:
-    case MVT_RANGE:
-      return false;
-    }
-  NOT_REACHED ();
+  return mv_n_values (mv) > 0;
 }
 
 /* Removes one individual value from MV and stores it in *V.
    MV must contain an individual value (as determined by
 }
 
 /* Removes one individual value from MV and stores it in *V.
    MV must contain an individual value (as determined by
-   mv_has_value()). */
+   mv_has_value()).
+
+   We remove the first value from MV, not the last, because the
+   common use for this function is in iterating through a set of
+   missing values.  If we remove the last value then we'll output
+   the missing values in order opposite of that in which they
+   were added, so that a GET followed by a SAVE would reverse the
+   order of missing values in the system file, a weird effect. */
 void
 mv_pop_value (struct missing_values *mv, union value *v)
 {
   assert (mv_has_value (mv));
 void
 mv_pop_value (struct missing_values *mv, union value *v)
 {
   assert (mv_has_value (mv));
+
+  *v = mv->values[0];
+  remove_element (mv->values, mv->type & 3, sizeof *mv->values, 0);
   mv->type--;
   mv->type--;
-  *v = mv->values[mv->type & 3];
 }
 
 }
 
-/* Stores  a value  in *V.
-   MV must contain an individual value (as determined by
-   mv_has_value()).
-   IDX is the zero based index of the value to get
-*/
+/* Stores MV's value with index IDX in *V.
+   IDX must be less than the number of discrete values in MV, as
+   reported by mv_n_values(MV). */
 void
 void
-mv_peek_value (const struct missing_values *mv, union value *v, int idx)
+mv_get_value (const struct missing_values *mv, union value *v, int idx)
 {
 {
-  assert (idx >= 0 ) ;
-  assert (idx < 3);
-
-  assert (mv_has_value (mv));
+  assert (idx >= 0 && idx < mv_n_values (mv));
   *v = mv->values[idx];
 }
 
   *v = mv->values[idx];
 }
 
@@ -222,19 +206,7 @@ mv_n_values (const struct missing_values *mv)
 bool
 mv_has_range (const struct missing_values *mv)
 {
 bool
 mv_has_range (const struct missing_values *mv)
 {
-  switch (mv->type)
-    {
-    case MVT_RANGE:
-    case MVT_RANGE_1:
-      return true;
-
-    case MVT_NONE:
-    case MVT_1:
-    case MVT_2:
-    case MVT_3:
-      return false;
-    }
-  NOT_REACHED ();
+  return mv->type == MVT_RANGE || mv->type == MVT_RANGE_1;
 }
 
 /* Removes the numeric range from MV and stores it in *LOW and
 }
 
 /* Removes the numeric range from MV and stores it in *LOW and
@@ -249,12 +221,11 @@ mv_pop_range (struct missing_values *mv, double *low, double *high)
   mv->type &= 3;
 }
 
   mv->type &= 3;
 }
 
-
 /* Returns the numeric range from MV  into *LOW and
    *HIGH.  MV must contain a individual range (as determined by
    mv_has_range()). */
 void
 /* Returns the numeric range from MV  into *LOW and
    *HIGH.  MV must contain a individual range (as determined by
    mv_has_range()). */
 void
-mv_peek_range (const struct missing_values *mv, double *low, double *high)
+mv_get_range (const struct missing_values *mv, double *low, double *high)
 {
   assert (mv_has_range (mv));
   *low = mv->values[1].f;
 {
   assert (mv_has_range (mv));
   *low = mv->values[1].f;
@@ -288,65 +259,39 @@ using_element (unsigned type, int idx)
   NOT_REACHED ();
 }
 
   NOT_REACHED ();
 }
 
-/* Returns true if S contains only spaces between indexes
-   NEW_WIDTH (inclusive) and OLD_WIDTH (exclusive),
-   false otherwise. */
-static bool
-can_resize_string (const char *s, int old_width, int new_width)
-{
-  int i;
-
-  assert (new_width < old_width);
-  for (i = new_width; i < old_width; i++)
-    if (s[i] != ' ')
-      return false;
-  return true;
-}
-
 /* Returns true if MV can be resized to the given WIDTH with
 /* Returns true if MV can be resized to the given WIDTH with
-   mv_resize(), false otherwise.  Resizing to the same width is
-   always possible.  Resizing to a long string WIDTH is only
-   possible if MV is an empty set of missing values; otherwise,
-   resizing to a larger WIDTH is always possible.  Resizing to a
-   shorter width is possible only when each missing value
-   contains only spaces in the characters that will be
-   trimmed. */
+   mv_resize(), false otherwise.  Resizing is possible only when
+   each value in MV (if any) is resizable from MV's current width
+   to WIDTH, as determined by value_is_resizable.  In addition,
+   resizing must not produce a non-empty set of long string
+   missing values. */
 bool
 mv_is_resizable (const struct missing_values *mv, int width)
 {
 bool
 mv_is_resizable (const struct missing_values *mv, int width)
 {
-  if ( var_type_from_width (width) != var_type_from_width (mv->width) )
-    return false;
+  int i;
 
   if (width > MAX_SHORT_STRING && mv->type != MVT_NONE)
     return false;
 
 
   if (width > MAX_SHORT_STRING && mv->type != MVT_NONE)
     return false;
 
-  if (width >= mv->width)
-    return true;
-  else
-    {
-      int i;
+  for (i = 0; i < 3; i++)
+    if (using_element (mv->type, i)
+        && !value_is_resizable (&mv->values[i], mv->width, width))
+      return false;
 
 
-      for (i = 0; i < 3; i++)
-        if (using_element (mv->type, i)
-            && !can_resize_string (mv->values[i].s, mv->width, width))
-          return false;
-      return true;
-    }
+  return true;
 }
 
 /* Resizes MV to the given WIDTH.  WIDTH must fit the constraints
 }
 
 /* Resizes MV to the given WIDTH.  WIDTH must fit the constraints
-   explained for mv_is_resizable(). */
+   explained for mv_is_resizable. */
 void
 mv_resize (struct missing_values *mv, int width)
 {
 void
 mv_resize (struct missing_values *mv, int width)
 {
-  assert (mv_is_resizable (mv, width));
-  if (width > mv->width && mv->type != MVT_NONE)
-    {
-      int i;
+  int i;
 
 
-      for (i = 0; i < 3; i++)
-        memset (mv->values[i].s + mv->width, ' ', width - mv->width);
-    }
+  assert (mv_is_resizable (mv, width));
+  for (i = 0; i < 3; i++)
+    if (using_element (mv->type, i))
+      value_resize (&mv->values[i], mv->width, width);
   mv->width = width;
 }
 
   mv->width = width;
 }
 
index 4f87f54360ff3aa19616489ef1c9a0848a219620..b504f8c769a928be238ce8d161a8cf577dbee051 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#if !missing_values_h
-#define missing_values_h 1
+/* User-missing values.
+
+   struct missing_values is an opaque type that represents a set
+   of user-missing values associated with a variable.  Valid sets
+   of missing values depend on variable width:
+
+        - Numeric variables may have up to 3 discrete numeric
+          user-missing values, or a range of numeric values, or a
+          range plus one discrete value.
+
+        - Short string variables may have up to 3 discrete string
+          user-missing values.
+
+        - Long string variables may not have user-missing
+          values. */
+
+#ifndef DATA_MISSING_VALUES_H
+#define DATA_MISSING_VALUES_H 1
 
 #include <stdbool.h>
 
 #include <stdbool.h>
-#include "value.h"
+#include "data/value.h"
 
 /* Missing values.
    Opaque--use access functions defined below. */
 
 /* Missing values.
    Opaque--use access functions defined below. */
@@ -26,7 +42,7 @@ struct missing_values
   {
     int type;                   /* Types of missing values, one of MVT_*. */
     int width;                  /* 0=numeric, otherwise string width. */
   {
     int type;                   /* Types of missing values, one of MVT_*. */
     int width;                  /* 0=numeric, otherwise string width. */
-    union value values[3];      /* Missing values.  [y,z] are the range. */
+    union value values[3];      /* Missing values.  [1], [2] are the range. */
   };
 
 /* Classes of missing values. */
   };
 
 /* Classes of missing values. */
@@ -38,41 +54,44 @@ enum mv_class
     MV_ANY = MV_USER | MV_SYSTEM /* Missing if it is user or system-missing. */
   };
 
     MV_ANY = MV_USER | MV_SYSTEM /* Missing if it is user or system-missing. */
   };
 
+/* Is a value missing? */
+bool mv_is_value_missing (const struct missing_values *, const union value *,
+                          enum mv_class);
+bool mv_is_num_missing (const struct missing_values *, double, enum mv_class);
+bool mv_is_str_missing (const struct missing_values *, const char[],
+                        enum mv_class);
+
+/* Initializing missing value sets. */
 void mv_init (struct missing_values *, int width);
 void mv_init (struct missing_values *, int width);
+void mv_copy (struct missing_values *, const struct missing_values *);
 void mv_clear (struct missing_values *);
 
 void mv_clear (struct missing_values *);
 
-void mv_copy (struct missing_values *, const struct missing_values *);
+/* Changing width of a missing value set. */
+bool mv_is_resizable (const struct missing_values *, int width);
+void mv_resize (struct missing_values *, int width);
+
+/* Basic property inspection. */
 bool mv_is_empty (const struct missing_values *);
 int mv_get_width (const struct missing_values *);
 
 bool mv_is_empty (const struct missing_values *);
 int mv_get_width (const struct missing_values *);
 
+/* Inspecting discrete values. */
+int mv_n_values (const struct missing_values *);
+bool mv_has_value (const struct missing_values *);
+void mv_get_value (const struct missing_values *, union value *, int idx);
+
+/* Inspecting ranges. */
+bool mv_has_range (const struct missing_values *);
+void mv_get_range (const struct missing_values *, double *low, double *high);
+
+/* Adding and modifying discrete values. */
 bool mv_add_value (struct missing_values *, const union value *);
 bool mv_add_str (struct missing_values *, const char[]);
 bool mv_add_num (struct missing_values *, double);
 bool mv_add_value (struct missing_values *, const union value *);
 bool mv_add_str (struct missing_values *, const char[]);
 bool mv_add_num (struct missing_values *, double);
-bool mv_add_num_range (struct missing_values *, double low, double high);
-
-bool mv_has_value (const struct missing_values *);
 void mv_pop_value (struct missing_values *, union value *);
 void mv_pop_value (struct missing_values *, union value *);
-void mv_peek_value (const struct missing_values *mv, union value *v, int idx);
-void mv_replace_value (struct missing_values *mv, const union value *v, int idx);
-
-int  mv_n_values (const struct missing_values *mv);
+void mv_replace_value (struct missing_values *, const union value *, int idx);
 
 
-
-bool mv_has_range (const struct missing_values *);
+/* Adding and modifying ranges. */
+bool mv_add_range (struct missing_values *, double low, double high);
 void mv_pop_range (struct missing_values *, double *low, double *high);
 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 (const struct missing_values *, int width);
-void mv_resize (struct missing_values *, int width);
-
-typedef bool mv_is_missing_func (const struct missing_values *,
-                                 const union value *);
-
-/* Is a value missing? */
-bool mv_is_value_missing (const struct missing_values *, const union value *,
-                          enum mv_class);
-bool mv_is_num_missing (const struct missing_values *, double, enum mv_class);
-bool mv_is_str_missing (const struct missing_values *, const char[],
-                        enum mv_class);
 
 
-#endif /* missing-values.h */
+#endif /* data/missing-values.h */
index ce1f562f4f9389f323acacdeff5f606e289f68a7..b5486a4a0e3dcfa1ee795869b46a2922fe03b725 100644 (file)
@@ -33,6 +33,7 @@
 #include <data/file-name.h>
 #include <data/format.h>
 #include <data/missing-values.h>
 #include <data/file-name.h>
 #include <data/format.h>
 #include <data/missing-values.h>
+#include <data/short-names.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 #include <libpspp/compiler.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 #include <libpspp/compiler.h>
@@ -669,8 +670,8 @@ read_variables (struct pfm_reader *r, struct dictionary *dict)
           int i;
           for (i = 1; i < 100000; i++)
             {
           int i;
           for (i = 1; i < 100000; i++)
             {
-              char try_name[LONG_NAME_LEN + 1];
-              sprintf (try_name, "%.*s_%d", LONG_NAME_LEN - 6, name, i);
+              char try_name[VAR_NAME_LEN + 1];
+              sprintf (try_name, "%.*s_%d", VAR_NAME_LEN - 6, name, i);
               v = dict_create_var (dict, try_name, width);
               if (v != NULL)
                 break;
               v = dict_create_var (dict, try_name, width);
               if (v != NULL)
                 break;
@@ -692,12 +693,12 @@ read_variables (struct pfm_reader *r, struct dictionary *dict)
         {
           double x = read_float (r);
           double y = read_float (r);
         {
           double x = read_float (r);
           double y = read_float (r);
-          mv_add_num_range (&miss, x, y);
+          mv_add_range (&miss, x, y);
         }
       else if (match (r, 'A'))
         }
       else if (match (r, 'A'))
-        mv_add_num_range (&miss, read_float (r), HIGHEST);
+        mv_add_range (&miss, read_float (r), HIGHEST);
       else if (match (r, '9'))
       else if (match (r, '9'))
-        mv_add_num_range (&miss, LOWEST, read_float (r));
+        mv_add_range (&miss, LOWEST, read_float (r));
 
       /* Single missing values. */
       while (match (r, '8'))
 
       /* Single missing values. */
       while (match (r, '8'))
index e446a659b907e14680e9cf20e0f2415ea201436a..278077e7db93bf3e8786308c85adcac9fe55f78a 100644 (file)
@@ -664,10 +664,10 @@ static trns_free_func case_limit_trns_free;
 static void
 add_case_limit_trns (struct dataset *ds)
 {
 static void
 add_case_limit_trns (struct dataset *ds)
 {
-  size_t case_limit = dict_get_case_limit (ds->dict);
+  casenumber case_limit = dict_get_case_limit (ds->dict);
   if (case_limit != 0)
     {
   if (case_limit != 0)
     {
-      size_t *cases_remaining = xmalloc (sizeof *cases_remaining);
+      casenumber *cases_remaining = xmalloc (sizeof *cases_remaining);
       *cases_remaining = case_limit;
       add_transformation (ds, case_limit_trns_proc, case_limit_trns_free,
                           cases_remaining);
       *cases_remaining = case_limit;
       add_transformation (ds, case_limit_trns_proc, case_limit_trns_free,
                           cases_remaining);
index d5bbb205f517bb245c3d75ad32b148a2da7adae8..2bce53e98c246aa60792912dda462d214e7c3491 100644 (file)
@@ -33,6 +33,9 @@
 
 struct dictionary;
 
 
 struct dictionary;
 
+/* Maximum length of a short name, in bytes. */
+#define SHORT_NAME_LEN 8
+
 void short_names_assign (struct dictionary *);
 
 #endif /* data/short-names.h */
 void short_names_assign (struct dictionary *);
 
 #endif /* data/short-names.h */
index b00a7b236a891e97a6752eb9a748d50692e3965c..1d172adefd46a65d9751832ffc10a7df3cf90efc 100644 (file)
@@ -42,6 +42,7 @@
 #include <data/file-name.h>
 #include <data/format.h>
 #include <data/missing-values.h>
 #include <data/file-name.h>
 #include <data/format.h>
 #include <data/missing-values.h>
+#include <data/short-names.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 #include <data/value.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 #include <data/value.h>
@@ -263,8 +264,8 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
       for (i = 0; i < dict_get_var_cnt (*dict); i++)
        {
          struct variable *var = dict_get_var (*dict, i);
       for (i = 0; i < dict_get_var_cnt (*dict); i++)
        {
          struct variable *var = dict_get_var (*dict, i);
-         char short_name [SHORT_NAME_LEN + 1];
-         char long_name [SHORT_NAME_LEN + 1];
+         char short_name[SHORT_NAME_LEN + 1];
+         char long_name[SHORT_NAME_LEN + 1];
 
          strcpy (short_name, var_get_name (var));
 
 
          strcpy (short_name, var_get_name (var));
 
@@ -542,7 +543,7 @@ read_variable_record (struct sfm_reader *r, struct dictionary *dict,
             {
               double low = read_float (r);
               double high = read_float (r);
             {
               double low = read_float (r);
               double high = read_float (r);
-              mv_add_num_range (&mv, low, high);
+              mv_add_range (&mv, low, high);
               missing_value_code = -missing_value_code - 2;
             }
           for (i = 0; i < missing_value_code; i++)
               missing_value_code = -missing_value_code - 2;
             }
           for (i = 0; i < missing_value_code; i++)
index 3e0d3499c9cd543450929e1b5dbb628552bc6640..acf9d5c0b681d4d702a52b81b6798bc93a54358c 100644 (file)
@@ -445,14 +445,14 @@ write_variable (struct sfm_writer *w, const struct variable *v)
   if (mv_has_range (mv))
     {
       double x, y;
   if (mv_has_range (mv))
     {
       double x, y;
-      mv_peek_range (mv, &x, &y);
+      mv_get_range (mv, &x, &y);
       write_float (w, x);
       write_float (w, y);
     }
   for (i = 0; i < mv_n_values (mv); i++)
     {
       union value value;
       write_float (w, x);
       write_float (w, y);
     }
   for (i = 0; i < mv_n_values (mv); i++)
     {
       union value value;
-      mv_peek_value (mv, &value, i);
+      mv_get_value (mv, &value, i);
       write_value (w, &value, seg0_width);
     }
 
       write_value (w, &value, seg0_width);
     }
 
diff --git a/src/data/val-type.h b/src/data/val-type.h
new file mode 100644 (file)
index 0000000..27139af
--- /dev/null
@@ -0,0 +1,55 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2007 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 3 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_VAL_TYPE_H
+#define DATA_VAL_TYPE_H 1
+
+#include <float.h>
+#include <stdbool.h>
+#include <libpspp/float-format.h>
+
+/* Special numeric values. */
+#define SYSMIS (-DBL_MAX)               /* System-missing value. */
+#define LOWEST (float_get_lowest ())    /* Smallest nonmissing finite value. */
+#define HIGHEST DBL_MAX                 /* Largest finite value. */
+
+/* Maximum length of a string variable. */
+#define MAX_STRING 32767
+
+/* Value type. */
+enum val_type
+  {
+    VAL_NUMERIC,              /* A numeric value. */
+    VAL_STRING                /* A string value. */
+  };
+
+/* Returns true if VAL_TYPE is a valid value type. */
+static inline bool
+val_type_is_valid (enum val_type val_type)
+{
+  return val_type == VAL_NUMERIC || val_type == VAL_STRING;
+}
+
+/* Returns the value type for the given WIDTH. */
+static inline enum val_type
+val_type_from_width (int width)
+{
+  return width != 0 ? VAL_STRING : VAL_NUMERIC;
+}
+
+#endif /* data/val-type.h */
index b9acc2bda59ffb8a199efafc425a852afb2ec55f..6387f72fc44d4c321d4857cf7194e35bd794c3ce 100644 (file)
@@ -66,7 +66,7 @@ val_labs_create (int width)
 /* Creates and returns a new set of value labels identical to
    VLS. */
 struct val_labs *
 /* Creates and returns a new set of value labels identical to
    VLS. */
 struct val_labs *
-val_labs_copy (const struct val_labs *vls)
+val_labs_clone (const struct val_labs *vls)
 {
   struct val_labs *copy;
   struct val_labs_iterator *i;
 {
   struct val_labs *copy;
   struct val_labs_iterator *i;
@@ -82,46 +82,29 @@ val_labs_copy (const struct val_labs *vls)
   return copy;
 }
 
   return copy;
 }
 
-/* Determines whether VLS's width can be changed to NEW_WIDTH.
-   Numeric widths cannot be changed at all.
-   Strings can be widened.  They can be shortened only if the
-   characters that will be truncated are spaces. */
+/* Determines whether VLS's width can be changed to NEW_WIDTH,
+   using the rules checked by value_is_resizable. */
 bool
 val_labs_can_set_width (const struct val_labs *vls, int new_width)
 {
 bool
 val_labs_can_set_width (const struct val_labs *vls, int new_width)
 {
-  if ( var_type_from_width (new_width) != var_type_from_width (vls->width ))
-    return false;
+  struct val_labs_iterator *i;
+  struct val_lab *lab;
 
 
-  if (vls->width == 0)
-    return new_width == 0;
-  else if (new_width < vls->width)
-    {
-      struct val_labs_iterator *i;
-      struct val_lab *lab;
+  for (lab = val_labs_first (vls, &i); lab != NULL;
+       lab = val_labs_next (vls, &i))
+    if (!value_is_resizable (&lab->value, vls->width, new_width))
+      {
+        val_labs_done (&i);
+        return false;
+      }
 
 
-      for (lab = val_labs_first (vls, &i); lab != NULL;
-           lab = val_labs_next (vls, &i))
-        {
-          int j;
-
-          /* We can shorten the value labels only if all the
-             truncated characters are blanks. */
-          for (j = vls->width; j < new_width; j++)
-            if (lab->value.s[j] != ' ')
-              {
-                val_labs_done (&i);
-                return false;
-              }
-        }
-      return true;
-    }
-  else
-    return true;
+  return true;
 }
 
 }
 
-/* Changes the width of VLS to NEW_WIDTH.  If VLS is numeric,
-   NEW_WIDTH must be 0, otherwise it must be within the range
-   1...MAX_SHORT_STRING inclusive. */
+/* Changes the width of VLS to NEW_WIDTH.  The original and new
+   width must be both numeric or both string.  If the new width
+   is a long string width, then any value labels in VLS are
+   deleted. */
 void
 val_labs_set_width (struct val_labs *vls, int new_width)
 {
 void
 val_labs_set_width (struct val_labs *vls, int new_width)
 {
@@ -186,64 +169,61 @@ create_int_val_lab (struct val_labs *vls, union value value, const char *label)
   return ivl;
 }
 
   return ivl;
 }
 
-/* If VLS does not already contain a value label for VALUE, adds
-   LABEL for it and returns true.  Otherwise, returns false.
-   Behavior is undefined if VLS's width is greater than
-   MAX_SHORT_STRING. */
+/* If VLS does not already contain a value label for VALUE (and
+   VLS represents a numeric or short string set of value labels),
+   adds LABEL for it and returns true.  Otherwise, returns
+   false. */
 bool
 val_labs_add (struct val_labs *vls, union value value, const char *label)
 {
 bool
 val_labs_add (struct val_labs *vls, union value value, const char *label)
 {
-  struct int_val_lab *ivl;
-  void **vlpp;
-
-  assert (vls != NULL);
-  assert (vls->width <= MAX_SHORT_STRING);
   assert (label != NULL);
   assert (label != NULL);
+  if (vls->width < MIN_LONG_STRING)
+    {
+      struct int_val_lab *ivl;
+      void **vlpp;
 
 
-  if (vls->labels == NULL)
-    vls->labels = hsh_create (8, compare_int_val_lab, hash_int_val_lab,
-                              free_int_val_lab, vls);
+      if (vls->labels == NULL)
+        vls->labels = hsh_create (8, compare_int_val_lab, hash_int_val_lab,
+                                  free_int_val_lab, vls);
 
 
-  ivl = create_int_val_lab (vls, value, label);
-  vlpp = hsh_probe (vls->labels, ivl);
-  if (*vlpp == NULL)
-    {
-      *vlpp = ivl;
-      return true;
+      ivl = create_int_val_lab (vls, value, label);
+      vlpp = hsh_probe (vls->labels, ivl);
+      if (*vlpp == NULL)
+        {
+          *vlpp = ivl;
+          return true;
+        }
+      free_int_val_lab (ivl, vls);
     }
     }
-  free_int_val_lab (ivl, vls);
   return false;
 }
 
   return false;
 }
 
-/* Sets LABEL as the value label for VALUE in VLS.  Returns false
-   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. */
+/* Sets LABEL as the value label for VALUE in VLS, replacing any
+   existing label for VALUE.  Has no effect if VLS has a long
+   string width. */
 void
 val_labs_replace (struct val_labs *vls, union value value, const char *label)
 {
 void
 val_labs_replace (struct val_labs *vls, union value value, const char *label)
 {
-  assert (vls->width <= MAX_SHORT_STRING);
-  if (vls->labels != NULL)
+  if (vls->width < MIN_LONG_STRING)
     {
     {
-      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);
+      if (vls->labels != NULL)
+        {
+          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);
+        }
+      else
+        val_labs_add (vls, value, label);
     }
     }
-  else
-    val_labs_add (vls, value, label);
 }
 
 /* Removes any value label for VALUE within VLS.  Returns true
 }
 
 /* Removes any value label for VALUE within VLS.  Returns true
-   if a value label was removed. Behavior is undefined if VLS's
-   width is greater than MAX_SHORT_STRING. */
+   if a value label was removed. */
 bool
 val_labs_remove (struct val_labs *vls, union value value)
 {
 bool
 val_labs_remove (struct val_labs *vls, union value value)
 {
-  assert (vls != NULL);
-  assert (vls->width <= MAX_SHORT_STRING);
-
-  if (vls->labels != NULL)
+  if (vls->width < MIN_LONG_STRING && vls->labels != NULL)
     {
       struct int_val_lab *ivl = create_int_val_lab (vls, value, "");
       int deleted = hsh_delete (vls->labels, ivl);
     {
       struct int_val_lab *ivl = create_int_val_lab (vls, value, "");
       int deleted = hsh_delete (vls->labels, ivl);
@@ -298,7 +278,10 @@ val_labs_first (const struct val_labs *vls, struct val_labs_iterator **ip)
   assert (ip != NULL);
 
   if (vls->labels == NULL || vls->width > MAX_SHORT_STRING)
   assert (ip != NULL);
 
   if (vls->labels == NULL || vls->width > MAX_SHORT_STRING)
-    return NULL;
+    {
+      *ip = NULL;
+      return NULL;
+    }
 
   i = *ip = xmalloc (sizeof *i);
   i->labels = hsh_data_copy (vls->labels);
 
   i = *ip = xmalloc (sizeof *i);
   i->labels = hsh_data_copy (vls->labels);
@@ -322,7 +305,10 @@ val_labs_first_sorted (const struct val_labs *vls,
   assert (ip != NULL);
 
   if (vls->labels == NULL || vls->width > MAX_SHORT_STRING)
   assert (ip != NULL);
 
   if (vls->labels == NULL || vls->width > MAX_SHORT_STRING)
-    return NULL;
+    {
+      *ip = NULL;
+      return NULL;
+    }
 
   i = *ip = xmalloc (sizeof *i);
   i->lp = i->labels = hsh_sort_copy (vls->labels);
 
   i = *ip = xmalloc (sizeof *i);
   i->lp = i->labels = hsh_sort_copy (vls->labels);
@@ -367,15 +353,13 @@ val_labs_next (const struct val_labs *vls, struct val_labs_iterator **ip)
 void
 val_labs_done (struct val_labs_iterator **ip)
 {
 void
 val_labs_done (struct val_labs_iterator **ip)
 {
-  struct val_labs_iterator *i;
-
-  assert (ip != NULL);
-  assert (*ip != NULL);
-
-  i = *ip;
-  free (i->labels);
-  free (i);
-  *ip = NULL;
+  if (*ip != NULL)
+    {
+      struct val_labs_iterator *i = *ip;
+      free (i->labels);
+      free (i);
+      *ip = NULL;
+    }
 }
 \f
 /* Compares two value labels and returns a strcmp()-type result. */
 }
 \f
 /* Compares two value labels and returns a strcmp()-type result. */
index ce863a40db82df3aec7eb22653773e8358d12f49..fb7ec22b57564a922562fa2c46acc557532bc6d5 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef VAL_LABS_H
-#define VAL_LABS_H 1
+/* Sets of value labels.
+
+   struct val_labs represents a mapping from `union value's to
+   strings.  The `union value's in the mapping all have the same
+   width.  If this width is numeric or short string, the mapping
+   may contain any number of entries; long string mappings are
+   always empty. */
+
+#ifndef DATA_VALUE_LABELS_H
+#define DATA_VALUE_LABELS_H 1
 
 #include <stdbool.h>
 #include <stddef.h>
 
 #include <stdbool.h>
 #include <stddef.h>
-
 #include <data/value.h>
 
 #include <data/value.h>
 
-struct val_labs;
-struct variable;
-
+/* One value label. */
 struct val_lab
   {
     union value value;
     const char *label;
   };
 
 struct val_lab
   {
     union value value;
     const char *label;
   };
 
+/* Creating and destroying sets of value labels. */
 struct val_labs *val_labs_create (int width);
 struct val_labs *val_labs_create (int width);
-struct val_labs *val_labs_copy (const struct val_labs *);
-void val_labs_destroy (struct val_labs *);
+struct val_labs *val_labs_clone (const struct val_labs *);
 void val_labs_clear (struct val_labs *);
 void val_labs_clear (struct val_labs *);
-size_t val_labs_count (const struct val_labs *);
+void val_labs_destroy (struct val_labs *);
+
+/* Looking up value labels. */
+char *val_labs_find (const struct val_labs *, union value);
 
 
+/* Basic properties. */
+size_t val_labs_count (const struct val_labs *);
 bool val_labs_can_set_width (const struct val_labs *, int new_width);
 void val_labs_set_width (struct val_labs *, int new_width);
 
 bool val_labs_can_set_width (const struct val_labs *, int new_width);
 void val_labs_set_width (struct val_labs *, int new_width);
 
+/* Adding value labels. */
 bool val_labs_add (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);
 bool val_labs_add (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);
 
 
+/* Iterating through value labels. */
 struct val_labs_iterator;
 struct val_labs_iterator;
-
 struct val_lab *val_labs_first (const struct val_labs *,
                                 struct val_labs_iterator **);
 struct val_lab *val_labs_first_sorted (const struct val_labs *,
 struct val_lab *val_labs_first (const struct val_labs *,
                                 struct val_labs_iterator **);
 struct val_lab *val_labs_first_sorted (const struct val_labs *,
@@ -55,4 +65,4 @@ struct val_lab *val_labs_next (const struct val_labs *,
                                struct val_labs_iterator **);
 void val_labs_done (struct val_labs_iterator **);
 
                                struct val_labs_iterator **);
 void val_labs_done (struct val_labs_iterator **);
 
-#endif /* value-labels.h */
+#endif /* data/value-labels.h */
index cd52f147ca3a0f4fd924c40861788cfc22081623..34e3fe58bb37bf40d80943d38fc4d5ecafdc76d2 100644 (file)
@@ -15,8 +15,9 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include "value.h"
+#include <data/value.h>
 
 
+#include <data/val-type.h>
 #include <libpspp/hash.h>
 #include <libpspp/str.h>
 
 #include <libpspp/hash.h>
 #include <libpspp/str.h>
 
@@ -83,3 +84,32 @@ value_set_missing (union value *v, int width)
   else
     memset (v->s, ' ', width);
 }
   else
     memset (v->s, ' ', width);
 }
+
+/* Tests whether VALUE may be resized from OLD_WIDTH to
+   NEW_WIDTH, using the following rules that match those for
+   resizing missing values and value labels.  First, OLD_WIDTH
+   and NEW_WIDTH must be both numeric or both string.  Second, if
+   NEW_WIDTH is less than OLD_WIDTH, then the bytes that would be
+   trimmed off the right end of VALUE must be all spaces. */
+bool
+value_is_resizable (const union value *value, int old_width, int new_width)
+{
+  int i;
+
+  if (val_type_from_width (old_width) != val_type_from_width (new_width))
+    return false;
+  for (i = new_width; i < old_width; i++)
+    if (value->s[i] != ' ')
+      return false;
+  return true;
+}
+
+/* Resizes VALUE from OLD_WIDTH to NEW_WIDTH.  The arguments must
+   satisfy the rules specified above for value_is_resizable. */
+void
+value_resize (union value *value, int old_width, int new_width)
+{
+  assert (value_is_resizable (value, old_width, new_width));
+  if (new_width > old_width)
+    memset (&value->s[old_width], ' ', new_width - old_width);
+}
index b7a7ee701f8ae31f695e35629ca26b562b853842..cb66cb0836c7b00eeb7e992199650c192b15f780 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007 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
 
    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
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#if !value_h
-#define value_h 1
+#ifndef DATA_VALUE_H
+#define DATA_VALUE_H 1
 
 
-#include <float.h>
-#include <libpspp/float-format.h>
 #include <libpspp/misc.h>
 #include <libpspp/misc.h>
+#include <stdbool.h>
 #include "minmax.h"
 
 #include "minmax.h"
 
-/* Values. */
-
 /* "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)
 /* "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)
-#define MAX_STRING 32767
-
-/* Special values. */
-#define SYSMIS (-DBL_MAX)
-#define LOWEST (float_get_lowest ())
-#define HIGHEST DBL_MAX
-
-/* Number of "union value"s required for a variable of the given
-   WIDTH. */
-static inline size_t
-value_cnt_from_width (int width)
-{
-  return width == 0 ? 1 : DIV_RND_UP (width, MAX_SHORT_STRING);
-}
 
 /* A numeric or short string value.
    Multiple consecutive values represent a long string. */
 
 /* A numeric or short string value.
    Multiple consecutive values represent a long string. */
@@ -58,7 +41,18 @@ union value *value_create (int width);
 int compare_values (const union value *, const union value *, int width);
 unsigned hash_value (const union value  *, int width);
 
 int compare_values (const union value *, const union value *, int width);
 unsigned hash_value (const union value  *, int width);
 
+static inline size_t value_cnt_from_width (int width);
 void value_copy (union value *, const union value *, int width);
 void value_set_missing (union value *, int width);
 void value_copy (union value *, const union value *, int width);
 void value_set_missing (union value *, int width);
+bool value_is_resizable (const union value *, int old_width, int new_width);
+void value_resize (union value *, int old_width, int new_width);
+
+/* Number of "union value"s required for a variable of the given
+   WIDTH. */
+static inline size_t
+value_cnt_from_width (int width)
+{
+  return width == 0 ? 1 : DIV_RND_UP (width, MAX_SHORT_STRING);
+}
 
 
-#endif /* !value.h */
+#endif /* data/value.h */
index aaf8ba05e6573e9658640b4032402099d5365b87..35440a0de644af2fbeb3a407d7da837fe97aca1d 100644 (file)
@@ -31,13 +31,14 @@ struct vardict_info
     struct dictionary *dict;  /* The dictionary containing the variable */
   };
 
     struct dictionary *dict;  /* The dictionary containing the variable */
   };
 
+/* Called by dictionary code, defined in variable.c. */
 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 *);
 
 
 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 *);
 
 
-/* Called only from variable.c, but defined in dictionary.c */
+/* Called by variable.c, defined in dictionary.c. */
 void dict_var_changed (const struct variable *v);
 void dict_var_resized (const struct variable *v, int delta);
 
 void dict_var_changed (const struct variable *v);
 void dict_var_resized (const struct variable *v, int delta);
 
index 4a2e44057c70c23aeff99d17ee206cc205ad5105..4623b77b13a9f65ddcab64565898dcfc390c4cc5 100644 (file)
@@ -44,7 +44,7 @@
 struct variable
   {
     /* Dictionary information. */
 struct variable
   {
     /* Dictionary information. */
-    char name[LONG_NAME_LEN + 1]; /* Variable name.  Mixed case. */
+    char name[VAR_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. */
     int width;                 /* 0 for numeric, otherwise string width. */
     struct missing_values miss; /* Missing values. */
     struct fmt_spec print;     /* Default format for PRINT. */
@@ -77,20 +77,6 @@ struct variable
        have its values stored here. */
     struct cat_vals *obs_vals;
   };
        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 == VAR_NUMERIC || var_type == VAR_STRING;
-}
-
-/* Returns the variable type for the given width. */
-enum var_type
-var_type_from_width (int width)
-{
-  return width != 0 ? VAR_STRING : VAR_NUMERIC;
-}
 \f
 /* Creates and returns a new variable with the given NAME and
    WIDTH and other fields initialized to default values.  The
 \f
 /* Creates and returns a new variable with the given NAME and
    WIDTH and other fields initialized to default values.  The
@@ -271,11 +257,11 @@ var_is_plausible_name (const char *name, bool issue_error)
         msg (SE, _("Variable name cannot be empty string."));
       return false;
     }
         msg (SE, _("Variable name cannot be empty string."));
       return false;
     }
-  else if (length > LONG_NAME_LEN)
+  else if (length > VAR_NAME_LEN)
     {
       if (issue_error)
         msg (SE, _("Variable name %s exceeds %d-character limit."),
     {
       if (issue_error)
         msg (SE, _("Variable name %s exceeds %d-character limit."),
-             name, (int) LONG_NAME_LEN);
+             name, (int) VAR_NAME_LEN);
       return false;
     }
 
       return false;
     }
 
@@ -290,6 +276,13 @@ var_is_plausible_name (const char *name, bool issue_error)
   return true;
 }
 
   return true;
 }
 
+/* Returns VAR's dictionary class. */
+enum dict_class
+var_get_dict_class (const struct variable *var)
+{
+  return dict_class_from_id (var->name);
+}
+
 /* A hsh_compare_func that orders variables A and B by their
    names. */
 int
 /* A hsh_compare_func that orders variables A and B by their
    names. */
 int
@@ -333,10 +326,10 @@ hash_var_ptr_by_name (const void *v_, const void *aux UNUSED)
 }
 \f
 /* Returns the type of variable V. */
 }
 \f
 /* Returns the type of variable V. */
-enum var_type
+enum val_type
 var_get_type (const struct variable *v)
 {
 var_get_type (const struct variable *v)
 {
-  return var_type_from_width (v->width);
+  return val_type_from_width (v->width);
 }
 
 /* Returns the width of variable V. */
 }
 
 /* Returns the width of variable V. */
@@ -346,7 +339,8 @@ var_get_width (const struct variable *v)
   return v->width;
 }
 
   return v->width;
 }
 
-/* Sets the width of V to WIDTH. */
+/* Changes the width of V to NEW_WIDTH.
+   This function should be used cautiously. */
 void
 var_set_width (struct variable *v, int new_width)
 {
 void
 var_set_width (struct variable *v, int new_width)
 {
@@ -388,7 +382,7 @@ var_set_width (struct variable *v, int new_width)
 bool
 var_is_numeric (const struct variable *v)
 {
 bool
 var_is_numeric (const struct variable *v)
 {
-  return var_get_type (v) == VAR_NUMERIC;
+  return var_get_type (v) == VAL_NUMERIC;
 }
 
 /* Returns true if variable V is a string variable, false
 }
 
 /* Returns true if variable V is a string variable, false
@@ -396,7 +390,7 @@ var_is_numeric (const struct variable *v)
 bool
 var_is_alpha (const struct variable *v)
 {
 bool
 var_is_alpha (const struct variable *v)
 {
-  return var_get_type (v) == VAR_STRING;
+  return var_get_type (v) == VAL_STRING;
 }
 
 /* Returns true if variable V is a short string variable, false
 }
 
 /* Returns true if variable V is a short string variable, false
@@ -520,7 +514,7 @@ var_set_value_labels (struct variable *v, const struct val_labs *vls)
   if (vls != NULL)
     {
       assert (val_labs_can_set_width (vls, v->width));
   if (vls != NULL)
     {
       assert (val_labs_can_set_width (vls, v->width));
-      v->val_labs = val_labs_copy (vls);
+      v->val_labs = val_labs_clone (vls);
       val_labs_set_width (v->val_labs, v->width);
       dict_var_changed (v);
     }
       val_labs_set_width (v->val_labs, v->width);
       dict_var_changed (v);
     }
@@ -538,8 +532,7 @@ alloc_value_labels (struct variable *v)
 
 /* Attempts to add a value label with the given VALUE and LABEL
    to V.  Returns true if successful, false if VALUE has an
 
 /* 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. */
+   existing label or if V is a long string variable. */
 bool
 var_add_value_label (struct variable *v,
                      const union value *value, const char *label)
 bool
 var_add_value_label (struct variable *v,
                      const union value *value, const char *label)
@@ -550,7 +543,7 @@ var_add_value_label (struct variable *v,
 
 /* Adds or replaces a value label with the given VALUE and LABEL
    to V.
 
 /* Adds or replaces a value label with the given VALUE and LABEL
    to V.
-   V must not be a long string variable. */
+   Has no effect if V is a long string variable. */
 void
 var_replace_value_label (struct variable *v,
                          const union value *value, const char *label)
 void
 var_replace_value_label (struct variable *v,
                          const union value *value, const char *label)
@@ -768,7 +761,7 @@ var_set_alignment (struct variable *v, enum alignment alignment)
    case. */
 
 /* Returns true if variable V's value should be left 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. */
+   case, instead of being reset to system-missing or blanks. */
 bool
 var_get_leave (const struct variable *v)
 {
 bool
 var_get_leave (const struct variable *v)
 {
@@ -789,7 +782,7 @@ var_set_leave (struct variable *v, bool leave)
 bool
 var_must_leave (const struct variable *v)
 {
 bool
 var_must_leave (const struct variable *v)
 {
-  return dict_class_from_id (v->name) == DC_SCRATCH;
+  return var_get_dict_class (v) == DC_SCRATCH;
 }
 \f
 /* Returns the number of short names stored in VAR.
 }
 \f
 /* Returns the number of short names stored in VAR.
@@ -960,7 +953,8 @@ var_get_obs_vals (const struct variable *v)
   return v->obs_vals;
 }
 
   return v->obs_vals;
 }
 
-/* Sets V's observed categorical values to CAT_VALS. */
+/* Sets V's observed categorical values to CAT_VALS.
+   V becomes the owner of CAT_VALS. */
 void
 var_set_obs_vals (const struct variable *v_, struct cat_vals *cat_vals)
 {
 void
 var_set_obs_vals (const struct variable *v_, struct cat_vals *cat_vals)
 {
@@ -977,39 +971,6 @@ var_has_obs_vals (const struct variable *v)
   return v->obs_vals != NULL;
 }
 \f
   return v->obs_vals != NULL;
 }
 \f
-/* Returns the dictionary class corresponding to a variable named
-   NAME. */
-enum dict_class
-dict_class_from_id (const char *name)
-{
-  switch (name[0])
-    {
-    default:
-      return DC_ORDINARY;
-    case '$':
-      return DC_SYSTEM;
-    case '#':
-      return DC_SCRATCH;
-    }
-}
-
-/* Returns the name of dictionary class DICT_CLASS. */
-const char *
-dict_class_to_name (enum dict_class dict_class)
-{
-  switch (dict_class)
-    {
-    case DC_ORDINARY:
-      return _("ordinary");
-    case DC_SYSTEM:
-      return _("system");
-    case DC_SCRATCH:
-      return _("scratch");
-    default:
-      NOT_REACHED ();
-    }
-}
-\f
 /* Returns V's vardict structure. */
 const struct vardict_info *
 var_get_vardict (const struct variable *v)
 /* Returns V's vardict structure. */
 const struct vardict_info *
 var_get_vardict (const struct variable *v)
index 44cfba703fe56a162f9bd6f418cb311df95c27d1..66257e0e16437a72867df05db9b6c5b3e63e6c36 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#if !variable_h
-#define variable_h 1
+#ifndef DATA_VARIABLE_H
+#define DATA_VARIABLE_H 1
 
 #include <stddef.h>
 #include <stdbool.h>
 
 #include <stddef.h>
 #include <stdbool.h>
+#include <data/dict-class.h>
 #include <data/missing-values.h>
 #include <data/missing-values.h>
+#include <data/val-type.h>
 
 union value;
 
 
 union value;
 
-/* Variable type. */
-enum var_type
-  {
-    VAR_NUMERIC,                /* A numeric variable. */
-    VAR_STRING                 /* A string variable. */
-  };
-
-bool var_type_is_valid (enum var_type);
-enum var_type var_type_from_width (int width);
-
-/* Variables. */
+/* Variables.
+   These functions should rarely be called directly: use
+   dict_create_var, dict_clone_var, or dict_delete_var
+   instead. */
 struct variable *var_create (const char *name, int width);
 struct variable *var_clone (const struct variable *);
 void var_destroy (struct variable *);
 
 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
+/* Variable names. */
+#define VAR_NAME_LEN 64 /* Maximum length of variable name, in bytes. */
 
 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);
 
 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);
+enum dict_class var_get_dict_class (const struct variable *);
 
 int compare_vars_by_name (const void *, const void *, const void *);
 unsigned hash_var_by_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 *);
@@ -55,17 +48,16 @@ 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 *);
 
 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 *);
+/* Types and widths of values associated with a variable. */
+enum val_type var_get_type (const struct variable *);
 int var_get_width (const struct variable *);
 void var_set_width (struct variable *, int width);
 
 int var_get_width (const struct variable *);
 void var_set_width (struct variable *, int width);
 
-typedef bool var_predicate_func (const struct variable *);
-
 bool var_is_numeric (const struct variable *);
 bool var_is_alpha (const struct variable *);
 bool var_is_short_string (const struct variable *);
 bool var_is_long_string (const struct variable *);
 bool var_is_numeric (const struct variable *);
 bool var_is_alpha (const struct variable *);
 bool var_is_short_string (const struct variable *);
 bool var_is_long_string (const struct variable *);
+
 size_t var_get_value_cnt (const struct variable *);
 
 /* Variables' missing values. */
 size_t var_get_value_cnt (const struct variable *);
 
 /* Variables' missing values. */
@@ -80,17 +72,19 @@ bool var_is_num_missing (const struct variable *, double, enum mv_class);
 bool var_is_str_missing (const struct variable *, const char[], enum mv_class);
 
 /* Value labels. */
 bool var_is_str_missing (const struct variable *, const char[], enum mv_class);
 
 /* Value labels. */
-const struct val_labs *var_get_value_labels (const 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 *);
+
 bool var_has_value_labels (const struct variable *);
 bool var_has_value_labels (const struct variable *);
+const struct val_labs *var_get_value_labels (const struct variable *);
 void var_set_value_labels (struct variable *, const struct val_labs *);
 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 *);
 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 *);
 
 /* Print and write formats. */
 const struct fmt_spec *var_get_print_format (const struct variable *);
@@ -167,15 +161,7 @@ struct cat_vals *var_get_obs_vals (const struct variable *);
 void var_set_obs_vals (const struct variable *, struct cat_vals *);
 bool var_has_obs_vals (const struct variable *);
 
 void var_set_obs_vals (const struct variable *, struct cat_vals *);
 bool var_has_obs_vals (const struct variable *);
 
-/* Classes of variables. */
-enum dict_class
-  {
-    DC_ORDINARY,                /* Ordinary identifier. */
-    DC_SYSTEM,                  /* System variable. */
-    DC_SCRATCH                  /* Scratch variable. */
-  };
-
-enum dict_class dict_class_from_id (const char *name);
-const char *dict_class_to_name (enum dict_class dict_class);
+/* Function types. */
+typedef bool var_predicate_func (const struct variable *);
 
 
-#endif /* !variable.h */
+#endif /* data/variable.h */
index cc4c96f0ab8744538fafb4e4e35d9dd1e99bf832..fd65d284d43ea6d75d1db2885f1b9ad87d37bce9 100644 (file)
@@ -27,7 +27,7 @@
 /* Vector of variables. */
 struct vector
   {
 /* Vector of variables. */
 struct vector
   {
-    char name[LONG_NAME_LEN + 1];       /* Name. */
+    char name[VAR_NAME_LEN + 1];       /* Name. */
     struct variable **vars;             /* Set of variables. */
     size_t var_cnt;                     /* Number of variables. */
   };
     struct variable **vars;             /* Set of variables. */
     size_t var_cnt;                     /* Number of variables. */
   };
@@ -108,7 +108,7 @@ vector_get_name (const struct vector *vector)
 }
 
 /* Returns the type of the variables in VECTOR. */
 }
 
 /* Returns the type of the variables in VECTOR. */
-enum var_type vector_get_type (const struct vector *vector)
+enum val_type vector_get_type (const struct vector *vector)
 {
   return var_get_type (vector->vars[0]);
 }
 {
   return var_get_type (vector->vars[0]);
 }
index 0f4359826c5c3d22b331d0dbb0109d1fba4c3488..b009fcb2922f3ac4c7a67422e2089cef1311c5bf 100644 (file)
@@ -30,7 +30,7 @@ struct vector *vector_clone (const struct vector *old,
 void vector_destroy (struct vector *);
 
 const char *vector_get_name (const struct vector *);
 void vector_destroy (struct vector *);
 
 const char *vector_get_name (const struct vector *);
-enum var_type vector_get_type (const struct vector *);
+enum val_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 *);
 
 struct variable *vector_get_var (const struct vector *, size_t idx);
 size_t vector_get_var_cnt (const struct vector *);
 
index 4fea7a407038364aca731376c6c86d11d9e66caf..9e950e9ce69bd24799660908606a308962282e84 100644 (file)
@@ -65,7 +65,7 @@ struct dls_var_spec
     /* All parsers. */
     struct fmt_spec input;     /* Input format of this field. */
     int fv;                    /* First value in case. */
     /* All parsers. */
     struct fmt_spec input;     /* Input format of this field. */
     int fv;                    /* First value in case. */
-    char name[LONG_NAME_LEN + 1]; /* Var name for error messages and tables. */
+    char name[VAR_NAME_LEN + 1]; /* Var name for error messages and tables. */
 
     /* Fixed format only. */
     int record;                        /* Record number (1-based). */
 
     /* Fixed format only. */
     int record;                        /* Record number (1-based). */
index 35fabc08842a25dc79453f3597853ded2df2620f..af5fa3321fdfa2b25972cf0691bb3539bce2b689 100644 (file)
@@ -50,7 +50,7 @@
 int
 cmd_file_handle (struct lexer *lexer, struct dataset *ds)
 {
 int
 cmd_file_handle (struct lexer *lexer, struct dataset *ds)
 {
-  char handle_name[LONG_NAME_LEN + 1];
+  char handle_name[VAR_NAME_LEN + 1];
   struct cmd_file_handle cmd;
   struct file_handle *handle;
 
   struct cmd_file_handle cmd;
   struct file_handle *handle;
 
index d22a4e50ddd93911a64b514ea61bc76fa4eb0692..ed490cedda625e8254680334b491b4c0282de0d8 100644 (file)
@@ -735,8 +735,8 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds)
   bool saw_in = false;
   struct casereader *active_file = NULL;
 
   bool saw_in = false;
   struct casereader *active_file = NULL;
 
-  char first_name[LONG_NAME_LEN + 1] = "";
-  char last_name[LONG_NAME_LEN + 1] = "";
+  char first_name[VAR_NAME_LEN + 1] = "";
+  char last_name[VAR_NAME_LEN + 1] = "";
 
   struct taint *taint = NULL;
 
 
   struct taint *taint = NULL;
 
index 8b3eead83fb41c65ec697b74047a92cf4de44569..8e8bba9b69a281ae707cd021d2bd777e0176bf6f 100644 (file)
@@ -29,6 +29,7 @@
 #include <data/data-out.h>
 #include <data/format.h>
 #include <data/procedure.h>
 #include <data/data-out.h>
 #include <data/format.h>
 #include <data/procedure.h>
+#include <data/short-names.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/dictionary/split-file.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/dictionary/split-file.h>
@@ -150,7 +151,7 @@ cmd_list (struct lexer *lexer, struct dataset *ds)
     cmd.last = LONG_MAX;
   if (!cmd.sbc_variables)
     dict_get_vars (dict, &cmd.v_variables, &cmd.n_variables,
     cmd.last = LONG_MAX;
   if (!cmd.sbc_variables)
     dict_get_vars (dict, &cmd.v_variables, &cmd.n_variables,
-                  (1u << DC_SYSTEM) | (1u << DC_SCRATCH));
+                   DC_SYSTEM | DC_SCRATCH);
   if (cmd.n_variables == 0)
     {
       msg (SE, _("No variables specified."));
   if (cmd.n_variables == 0)
     {
       msg (SE, _("No variables specified."));
@@ -507,7 +508,7 @@ write_fallback_headers (struct outp_driver *d)
          }
 
          {
          }
 
          {
-           char varname[LONG_NAME_LEN + 2];
+           char varname[VAR_NAME_LEN + 2];
            snprintf (varname, sizeof varname,
                       " %s", var_get_name (cmd.v_variables[index]));
            write_varname (d, varname, leader_width);
            snprintf (varname, sizeof varname,
                       " %s", var_get_name (cmd.v_variables[index]));
            write_varname (d, varname, leader_width);
index 3be32e76c62f8ed452c5630f29e582e07376816c..d18606a5ce2eda8e4d9508e406e7170f7c3d9231 100644 (file)
@@ -91,7 +91,7 @@ internal_cmd_formats (struct lexer *lexer, struct dataset *ds, int which)
        }
       if (!parse_format_specifier (lexer, &f)
           || !fmt_check_output (&f)
        }
       if (!parse_format_specifier (lexer, &f)
           || !fmt_check_output (&f)
-          || !fmt_check_type_compat (&f, VAR_NUMERIC))
+          || !fmt_check_type_compat (&f, VAL_NUMERIC))
        goto fail;
 
       if (!lex_match (lexer, ')'))
        goto fail;
 
       if (!lex_match (lexer, ')'))
index 120953188ac87a2872b386430f06d668aebd5edc..d5bbf108832dc747fa6a9aec418898ac260bcea0 100644 (file)
@@ -88,7 +88,7 @@ cmd_missing_values (struct lexer *lexer, struct dataset *ds)
 
                   ok = (x == y
                         ? mv_add_num (&mv, x)
 
                   ok = (x == y
                         ? mv_add_num (&mv, x)
-                        : mv_add_num_range (&mv, x, y));
+                        : mv_add_range (&mv, x, y));
                   if (!ok)
                     deferred_errors = true;
 
                   if (!ok)
                     deferred_errors = true;
 
index 9fc6fa55c452c3a03ffeba7e7e6633c376f48bc2..cd5016910d61242c0c6afa8698a8f43553d38308 100644 (file)
@@ -138,7 +138,7 @@ cmd_modify_vars (struct lexer *lexer, struct dataset *ds)
                           "of variables."));
                      goto done;
                    }
                           "of variables."));
                      goto done;
                    }
-                 dict_get_vars_mutable (dataset_dict (ds), &v, &nv, 1u << DC_SYSTEM);
+                 dict_get_vars_mutable (dataset_dict (ds), &v, &nv, DC_SYSTEM);
                }
              else
                {
                }
              else
                {
@@ -367,7 +367,7 @@ compare_variables_given_ordering (const void *a_, const void *b_,
 struct var_renaming
   {
     struct variable *var;
 struct var_renaming
   {
     struct variable *var;
-    char new_name[LONG_NAME_LEN + 1];
+    char new_name[VAR_NAME_LEN + 1];
   };
 
 /* A algo_compare_func that compares new_name members in struct
   };
 
 /* A algo_compare_func that compares new_name members in struct
index e61ee53a44ce3f04c87d356c065c7c5198cab13c..1a616ab27ad858170f96ae7e99af12a91fe79c31 100644 (file)
@@ -135,7 +135,7 @@ cmd_vector (struct lexer *lexer, struct dataset *ds)
                   seen_format = true;
                   if (!parse_format_specifier (lexer, &format)
                       || !fmt_check_output (&format)
                   seen_format = true;
                   if (!parse_format_specifier (lexer, &format)
                       || !fmt_check_output (&format)
-                      || !fmt_check_type_compat (&format, VAR_NUMERIC))
+                      || !fmt_check_type_compat (&format, VAL_NUMERIC))
                     goto fail;
                 }
               else
                     goto fail;
                 }
               else
@@ -152,16 +152,16 @@ cmd_vector (struct lexer *lexer, struct dataset *ds)
             }
 
          /* Check that none of the variables exist and that
             }
 
          /* Check that none of the variables exist and that
-             their names are no more than LONG_NAME_LEN bytes
+             their names are no more than VAR_NAME_LEN bytes
              long. */
           for (i = 0; i < vector_cnt; i++)
            {
               int j;
              for (j = 0; j < var_cnt; j++)
                {
              long. */
           for (i = 0; i < vector_cnt; i++)
            {
               int j;
              for (j = 0; j < var_cnt; j++)
                {
-                  char name[LONG_NAME_LEN + INT_STRLEN_BOUND (int) + 1];
+                  char name[VAR_NAME_LEN + INT_STRLEN_BOUND (int) + 1];
                  sprintf (name, "%s%d", vectors[i], j + 1);
                  sprintf (name, "%s%d", vectors[i], j + 1);
-                  if (strlen (name) > LONG_NAME_LEN)
+                  if (strlen (name) > VAR_NAME_LEN)
                     {
                       msg (SE, _("%s is too long for a variable name."), name);
                       goto fail;
                     {
                       msg (SE, _("%s is too long for a variable name."), name);
                       goto fail;
@@ -181,7 +181,7 @@ cmd_vector (struct lexer *lexer, struct dataset *ds)
               int j;
              for (j = 0; j < var_cnt; j++)
                {
               int j;
              for (j = 0; j < var_cnt; j++)
                {
-                  char name[LONG_NAME_LEN + 1];
+                  char name[VAR_NAME_LEN + 1];
                  sprintf (name, "%s%d", vectors[i], j + 1);
                  vars[j] = dict_create_var_assert (dict, name, 0);
                   var_set_both_formats (vars[j], &format);
                  sprintf (name, "%s%d", vectors[i], j + 1);
                  vars[j] = dict_create_var_assert (dict, name, 0);
                   var_set_both_formats (vars[j], &format);
index 52dafef8c62edd7a939feb6735e18e0e798b1d23..a0a133ad66ebd8d483e97e57c86ecf87b5fef6b9 100644 (file)
@@ -126,7 +126,7 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
         dump_postfix = 1;
       else if (lex_match (lexer, '('))
         {
         dump_postfix = 1;
       else if (lex_match (lexer, '('))
         {
-          char name[LONG_NAME_LEN + 1];
+          char name[VAR_NAME_LEN + 1];
           struct variable *v;
           size_t old_value_cnt;
           int width;
           struct variable *v;
           size_t old_value_cnt;
           int width;
index 5ae4994484c685362d2daa689e79544c78a9f140..40b0a7ab53c1be8b25b515c021f244551e2002e7 100644 (file)
@@ -356,7 +356,7 @@ type_coercion_core (struct expression *e,
       msg_disable ();
       if ((*node)->type == OP_format
           && fmt_check_input (&(*node)->format.f)
       msg_disable ();
       if ((*node)->type == OP_format
           && fmt_check_input (&(*node)->format.f)
-          && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC))
+          && fmt_check_type_compat (&(*node)->format.f, VAL_NUMERIC))
         {
           msg_enable ();
           if (do_coercion)
         {
           msg_enable ();
           if (do_coercion)
@@ -370,7 +370,7 @@ type_coercion_core (struct expression *e,
       msg_disable ();
       if ((*node)->type == OP_format
           && fmt_check_output (&(*node)->format.f)
       msg_disable ();
       if ((*node)->type == OP_format
           && fmt_check_output (&(*node)->format.f)
-          && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC))
+          && fmt_check_type_compat (&(*node)->format.f, VAL_NUMERIC))
         {
           msg_enable ();
           if (do_coercion)
         {
           msg_enable ();
           if (do_coercion)
@@ -918,7 +918,7 @@ parse_vector_element (struct lexer *lexer, struct expression *e)
       || !lex_match (lexer, ')'))
     return NULL;
 
       || !lex_match (lexer, ')'))
     return NULL;
 
-  return expr_allocate_binary (e, (vector_get_type (vector) == VAR_NUMERIC
+  return expr_allocate_binary (e, (vector_get_type (vector) == VAL_NUMERIC
                                    ? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR),
                                element, expr_allocate_vector (e, vector));
 }
                                    ? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR),
                                element, expr_allocate_vector (e, vector));
 }
index 79657df7d52793ec2b9cc8f385947de13bac3203..ac0af60005edc2e97f3c7c491309ceca51af8a10 100644 (file)
@@ -52,7 +52,7 @@ struct lexer
   int token;      /* Current token. */
   double tokval;  /* T_POS_NUM, T_NEG_NUM: the token's value. */
 
   int token;      /* Current token. */
   double tokval;  /* T_POS_NUM, T_NEG_NUM: the token's value. */
 
-  char tokid [LONG_NAME_LEN + 1];   /* T_ID: the identifier. */
+  char tokid [VAR_NAME_LEN + 1];   /* T_ID: the identifier. */
 
   struct string tokstr;   /* T_ID, T_STRING: token string value.
                            For T_ID, this is not truncated as is
 
   struct string tokstr;   /* T_ID, T_STRING: token string value.
                            For T_ID, this is not truncated as is
index 3778156133d38daaadf13251ab568df32ab190fe..1194110efa3ac850ed1584451e2782ec12870b83 100644 (file)
@@ -405,8 +405,8 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
   int d1, d2;
   int n;
   size_t nvar, mvar;
   int d1, d2;
   int n;
   size_t nvar, mvar;
-  char name1[LONG_NAME_LEN + 1], name2[LONG_NAME_LEN + 1];
-  char root1[LONG_NAME_LEN + 1], root2[LONG_NAME_LEN + 1];
+  char name1[VAR_NAME_LEN + 1], name2[VAR_NAME_LEN + 1];
+  char root1[VAR_NAME_LEN + 1], root2[VAR_NAME_LEN + 1];
   int success = 0;
 
   assert (names != NULL);
   int success = 0;
 
   assert (names != NULL);
@@ -474,7 +474,7 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv
 
          for (n = n1; n <= n2; n++)
            {
 
          for (n = n1; n <= n2; n++)
            {
-              char name[LONG_NAME_LEN + 1];
+              char name[VAR_NAME_LEN + 1];
              sprintf (name, "%s%0*d", root1, d1, n);
              (*names)[nvar] = xstrdup (name);
              nvar++;
              sprintf (name, "%s%0*d", root1, d1, n);
              (*names)[nvar] = xstrdup (name);
              nvar++;
@@ -664,7 +664,7 @@ var_set_lookup_var_idx (const struct var_set *vs, const char *name,
 {
   assert (vs != NULL);
   assert (name != NULL);
 {
   assert (vs != NULL);
   assert (name != NULL);
-  assert (strlen (name) <= LONG_NAME_LEN);
+  assert (strlen (name) <= VAR_NAME_LEN);
 
   return vs->lookup_var_idx (vs, name, idx);
 }
 
   return vs->lookup_var_idx (vs, name, idx);
 }
index 18d78f238ae1f3038168cad0538d119c8903a0c5..f58b97cf8994c4eebcef4509c5cc1b8267f7f871 100644 (file)
@@ -92,7 +92,7 @@ struct agr_func
   {
     const char *name;          /* Aggregation function name. */
     size_t n_args;              /* Number of arguments. */
   {
     const char *name;          /* Aggregation function name. */
     size_t n_args;              /* Number of arguments. */
-    enum var_type alpha_type;   /* When given ALPHA arguments, output type. */
+    enum val_type alpha_type;   /* When given ALPHA arguments, output type. */
     struct fmt_spec format;    /* Format spec if alpha_type != ALPHA. */
   };
 
     struct fmt_spec format;    /* Format spec if alpha_type != ALPHA. */
   };
 
@@ -103,25 +103,25 @@ static const struct agr_func agr_func_tab[] =
     {"SUM",     0, -1,          {FMT_F, 8, 2}},
     {"MEAN",   0, -1,          {FMT_F, 8, 2}},
     {"SD",      0, -1,          {FMT_F, 8, 2}},
     {"SUM",     0, -1,          {FMT_F, 8, 2}},
     {"MEAN",   0, -1,          {FMT_F, 8, 2}},
     {"SD",      0, -1,          {FMT_F, 8, 2}},
-    {"MAX",     0, VAR_STRING,  {-1, -1, -1}},
-    {"MIN",     0, VAR_STRING,  {-1, -1, -1}},
-    {"PGT",     1, VAR_NUMERIC, {FMT_F, 5, 1}},
-    {"PLT",     1, VAR_NUMERIC, {FMT_F, 5, 1}},
-    {"PIN",     2, VAR_NUMERIC, {FMT_F, 5, 1}},
-    {"POUT",    2, VAR_NUMERIC, {FMT_F, 5, 1}},
-    {"FGT",     1, VAR_NUMERIC, {FMT_F, 5, 3}},
-    {"FLT",     1, VAR_NUMERIC, {FMT_F, 5, 3}},
-    {"FIN",     2, VAR_NUMERIC, {FMT_F, 5, 3}},
-    {"FOUT",    2, VAR_NUMERIC, {FMT_F, 5, 3}},
-    {"N",       0, VAR_NUMERIC, {FMT_F, 7, 0}},
-    {"NU",      0, VAR_NUMERIC, {FMT_F, 7, 0}},
-    {"NMISS",   0, VAR_NUMERIC, {FMT_F, 7, 0}},
-    {"NUMISS",  0, VAR_NUMERIC, {FMT_F, 7, 0}},
-    {"FIRST",   0, VAR_STRING,  {-1, -1, -1}},
-    {"LAST",    0, VAR_STRING,  {-1, -1, -1}},
+    {"MAX",     0, VAL_STRING,  {-1, -1, -1}},
+    {"MIN",     0, VAL_STRING,  {-1, -1, -1}},
+    {"PGT",     1, VAL_NUMERIC, {FMT_F, 5, 1}},
+    {"PLT",     1, VAL_NUMERIC, {FMT_F, 5, 1}},
+    {"PIN",     2, VAL_NUMERIC, {FMT_F, 5, 1}},
+    {"POUT",    2, VAL_NUMERIC, {FMT_F, 5, 1}},
+    {"FGT",     1, VAL_NUMERIC, {FMT_F, 5, 3}},
+    {"FLT",     1, VAL_NUMERIC, {FMT_F, 5, 3}},
+    {"FIN",     2, VAL_NUMERIC, {FMT_F, 5, 3}},
+    {"FOUT",    2, VAL_NUMERIC, {FMT_F, 5, 3}},
+    {"N",       0, VAL_NUMERIC, {FMT_F, 7, 0}},
+    {"NU",      0, VAL_NUMERIC, {FMT_F, 7, 0}},
+    {"NMISS",   0, VAL_NUMERIC, {FMT_F, 7, 0}},
+    {"NUMISS",  0, VAL_NUMERIC, {FMT_F, 7, 0}},
+    {"FIRST",   0, VAL_STRING,  {-1, -1, -1}},
+    {"LAST",    0, VAL_STRING,  {-1, -1, -1}},
     {NULL,      0, -1,          {-1, -1, -1}},
     {NULL,      0, -1,          {-1, -1, -1}},
-    {"N",       0, VAR_NUMERIC, {FMT_F, 7, 0}},
-    {"NU",      0, VAR_NUMERIC, {FMT_F, 7, 0}},
+    {"N",       0, VAL_NUMERIC, {FMT_F, 7, 0}},
+    {"NU",      0, VAL_NUMERIC, {FMT_F, 7, 0}},
   };
 
 /* Missing value types. */
   };
 
 /* Missing value types. */
@@ -478,12 +478,12 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, s
                if (lex_token (lexer) == T_STRING)
                  {
                    arg[i].c = ds_xstrdup (lex_tokstr (lexer));
                if (lex_token (lexer) == T_STRING)
                  {
                    arg[i].c = ds_xstrdup (lex_tokstr (lexer));
-                   type = VAR_STRING;
+                   type = VAL_STRING;
                  }
                else if (lex_is_number (lexer))
                  {
                    arg[i].f = lex_tokval (lexer);
                  }
                else if (lex_is_number (lexer))
                  {
                    arg[i].f = lex_tokval (lexer);
-                   type = VAR_NUMERIC;
+                   type = VAL_NUMERIC;
                  }
                 else
                   {
                  }
                 else
                   {
@@ -573,12 +573,12 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, s
                    v->string = xmalloc (var_get_width (src[i]));
                  }
 
                    v->string = xmalloc (var_get_width (src[i]));
                  }
 
-               if (function->alpha_type == VAR_STRING)
+               if (function->alpha_type == VAL_STRING)
                  destvar = dict_clone_var (agr->dict, v->src, dest[i]);
                else
                   {
                     assert (var_is_numeric (v->src)
                  destvar = dict_clone_var (agr->dict, v->src, dest[i]);
                else
                   {
                     assert (var_is_numeric (v->src)
-                            || function->alpha_type == VAR_NUMERIC);
+                            || function->alpha_type == VAL_NUMERIC);
                     destvar = dict_create_var (agr->dict, dest[i], 0);
                     if (destvar != NULL)
                       {
                     destvar = dict_create_var (agr->dict, dest[i], 0);
                     if (destvar != NULL)
                       {
index e1ca73bb3111e0b1e0c2a4b7a3d3ebb3ad0f7ec0..72f7476ae4e89fbc42c6ebe340c134b9b0353b2d 100644 (file)
@@ -123,7 +123,7 @@ static const struct dsc_statistic_info dsc_info[DSC_N_STATS] =
 struct dsc_var
   {
     const struct variable *v;         /* Variable to calculate on. */
 struct dsc_var
   {
     const struct variable *v;         /* Variable to calculate on. */
-    char z_name[LONG_NAME_LEN + 1]; /* Name for z-score variable. */
+    char z_name[VAR_NAME_LEN + 1]; /* Name for z-score variable. */
     double valid, missing;     /* Valid, missing counts. */
     struct moments *moments;    /* Moments. */
     double min, max;            /* Maximum and mimimum values. */
     double valid, missing;     /* Valid, missing counts. */
     struct moments *moments;    /* Moments. */
     double min, max;            /* Maximum and mimimum values. */
@@ -495,7 +495,7 @@ static bool
 generate_z_varname (const struct dictionary *dict, struct dsc_proc *dsc, char *z_name,
                     const char *var_name, int *z_cnt)
 {
 generate_z_varname (const struct dictionary *dict, struct dsc_proc *dsc, char *z_name,
                     const char *var_name, int *z_cnt)
 {
-  char name[LONG_NAME_LEN + 1];
+  char name[VAR_NAME_LEN + 1];
 
   /* Try a name based on the original variable name. */
   name[0] = 'Z';
 
   /* Try a name based on the original variable name. */
   name[0] = 'Z';
index 3fe43eb90858993a54b0f23bb6dc2ea07265c28f..6c49bd3798e5376555dd785ca85bab6ef61c7469 100644 (file)
@@ -28,6 +28,7 @@
 #include <data/dictionary.h>
 #include <data/procedure.h>
 #include <data/settings.h>
 #include <data/dictionary.h>
 #include <data/procedure.h>
 #include <data/settings.h>
+#include <data/short-names.h>
 #include <data/value.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <data/value.h>
 #include <data/variable.h>
 #include <language/command.h>
@@ -117,7 +118,7 @@ cmd_flip (struct lexer *lexer, struct dataset *ds)
       lex_match (lexer, '/');
     }
   else
       lex_match (lexer, '/');
     }
   else
-    dict_get_vars (dict, &flip->var, &flip->var_cnt, 1u << DC_SYSTEM);
+    dict_get_vars (dict, &flip->var, &flip->var_cnt, DC_SYSTEM);
   pool_register (flip->pool, free, flip->var);
 
   lex_match (lexer, '/');
   pool_register (flip->pool, free, flip->var);
 
   lex_match (lexer, '/');
index ce313678db2591d78dc6ab186cb8f8f48beb5aae..fdb19b0391f9c23dec4e036217e40b9bfa6af466 100644 (file)
@@ -636,12 +636,12 @@ postcalc (void)
 }
 
 /* Returns the comparison function that should be used for
 }
 
 /* Returns the comparison function that should be used for
-   sorting a frequency table by FRQ_SORT using VAR_TYPE
-   variables. */
+   sorting a frequency table by FRQ_SORT using VAL_TYPE
+   values. */
 static hsh_compare_func *
 static hsh_compare_func *
-get_freq_comparator (int frq_sort, enum var_type var_type)
+get_freq_comparator (int frq_sort, enum val_type val_type)
 {
 {
-  bool is_numeric = var_type == VAR_NUMERIC;
+  bool is_numeric = val_type == VAL_NUMERIC;
   switch (frq_sort)
     {
     case FRQ_AVALUE:
   switch (frq_sort)
     {
     case FRQ_AVALUE:
index 91520f5e011e2bbe2e4c819bb2ec830a7c8ec4d4..5bc88c4a97a84fe91aabf77fc897df9e30e4a9bf 100644 (file)
 #include <limits.h>
 #include <math.h>
 
 #include <limits.h>
 #include <math.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-ordering.h>
 #include <data/case.h>
 #include <data/casegrouper.h>
 #include <data/casereader.h>
 #include <data/casewriter.h>
 #include <data/case-ordering.h>
 #include <data/case.h>
 #include <data/casegrouper.h>
 #include <data/casereader.h>
 #include <data/casewriter.h>
+#include <data/dictionary.h>
+#include <data/format.h>
+#include <data/missing-values.h>
+#include <data/procedure.h>
+#include <data/short-names.h>
+#include <data/variable.h>
 #include <language/command.h>
 #include <language/stats/sort-criteria.h>
 #include <libpspp/compiler.h>
 #include <libpspp/taint.h>
 #include <math/sort.h>
 #include <language/command.h>
 #include <language/stats/sort-criteria.h>
 #include <libpspp/compiler.h>
 #include <libpspp/taint.h>
 #include <math/sort.h>
-#include <output/table.h>
 #include <output/manager.h>
 #include <output/manager.h>
+#include <output/table.h>
 
 #include <gsl/gsl_cdf.h>
 
 
 #include <gsl/gsl_cdf.h>
 
index e3b3f5ee9338b37ff671c55bce0cb83063129881..12a7cf5efca6ed103957768c9032bec9d1f611aa 100644 (file)
@@ -637,16 +637,16 @@ try_name (const struct dictionary *dict, const char *name)
 }
 
 static void
 }
 
 static void
-reg_get_name (const struct dictionary *dict, char name[LONG_NAME_LEN],
-             const char prefix[LONG_NAME_LEN])
+reg_get_name (const struct dictionary *dict, char name[VAR_NAME_LEN],
+             const char prefix[VAR_NAME_LEN])
 {
   int i = 1;
 
 {
   int i = 1;
 
-  snprintf (name, LONG_NAME_LEN, "%s%d", prefix, i);
+  snprintf (name, VAR_NAME_LEN, "%s%d", prefix, i);
   while (!try_name (dict, name))
     {
       i++;
   while (!try_name (dict, name))
     {
       i++;
-      snprintf (name, LONG_NAME_LEN, "%s%d", prefix, i);
+      snprintf (name, VAR_NAME_LEN, "%s%d", prefix, i);
     }
 }
 
     }
 }
 
@@ -656,7 +656,7 @@ reg_save_var (struct dataset *ds, const char *prefix, trns_proc_func * f,
 {
   struct dictionary *dict = dataset_dict (ds);
   static int trns_index = 1;
 {
   struct dictionary *dict = dataset_dict (ds);
   static int trns_index = 1;
-  char name[LONG_NAME_LEN];
+  char name[VAR_NAME_LEN];
   struct variable *new_var;
   struct reg_trns *t = NULL;
 
   struct variable *new_var;
   struct reg_trns *t = NULL;
 
@@ -1154,8 +1154,7 @@ run_regression (struct casereader *input, struct cmd_regression *cmd,
 
   if (!v_variables)
     {
 
   if (!v_variables)
     {
-      dict_get_vars (dataset_dict (ds), &v_variables, &n_variables,
-                    1u << DC_SYSTEM);
+      dict_get_vars (dataset_dict (ds), &v_variables, &n_variables, 0);
     }
 
   for (i = 0; i < cmd->n_dependent; i++)
     }
 
   for (i = 0; i < cmd->n_dependent; i++)
index 23237072c4651a24868e411fa60fb355b667b78d..c0e90705c3e1fae05af88fcfab7244226697f246 100644 (file)
@@ -147,7 +147,7 @@ struct pair
 
 static struct pair *pairs=0;
 
 
 static struct pair *pairs=0;
 
-static int parse_value (struct lexer *lexer, union value * v, enum var_type);
+static int parse_value (struct lexer *lexer, union value * v, enum val_type);
 
 /* Structures and Functions for the Statistics Summary Box */
 struct ssbox;
 
 /* Structures and Functions for the Statistics Summary Box */
 struct ssbox;
@@ -565,9 +565,9 @@ tts_custom_pairs (struct lexer *lexer, struct dataset *ds, struct cmd_t_test *cm
 /* Parses the current token (numeric or string, depending on type)
     value v and returns success. */
 static int
 /* 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, enum var_type type)
+parse_value (struct lexer *lexer, union value * v, enum val_type type)
 {
 {
-  if (type == VAR_NUMERIC)
+  if (type == VAL_NUMERIC)
     {
       if (!lex_force_num (lexer))
        return 0;
     {
       if (!lex_force_num (lexer))
        return 0;
index ec5a15a1f33f2a9d12f53cbd42e7d3c334ebbafe..f17798f77722a35cb2597a82f5ecaea4ccfcced7 100644 (file)
@@ -258,7 +258,7 @@ cmd_if (struct lexer *lexer, struct dataset *ds)
 static trns_proc_func *
 get_proc_func (const struct lvalue *lvalue)
 {
 static trns_proc_func *
 get_proc_func (const struct lvalue *lvalue)
 {
-  bool is_numeric = lvalue_get_type (lvalue) == VAR_NUMERIC;
+  bool is_numeric = lvalue_get_type (lvalue) == VAL_NUMERIC;
   bool is_vector = lvalue_is_vector (lvalue);
 
   return (is_numeric
   bool is_vector = lvalue_is_vector (lvalue);
 
   return (is_numeric
@@ -272,7 +272,7 @@ static struct expression *
 parse_rvalue (struct lexer *lexer,
              const struct lvalue *lvalue, struct dataset *ds)
 {
 parse_rvalue (struct lexer *lexer,
              const struct lvalue *lvalue, struct dataset *ds)
 {
-  bool is_numeric = lvalue_get_type (lvalue) == VAR_NUMERIC;
+  bool is_numeric = lvalue_get_type (lvalue) == VAL_NUMERIC;
 
   return expr_parse (lexer, ds, is_numeric ? EXPR_NUMBER : EXPR_STRING);
 }
 
   return expr_parse (lexer, ds, is_numeric ? EXPR_NUMBER : EXPR_STRING);
 }
index 1cb29b8440ab5c1eb51d806b3996ebc2bb1b2895..85fcb9ea01f72bd8ece9ecc8b76807c96910daba 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <data/case.h>
 #include <data/data-in.h>
 
 #include <data/case.h>
 #include <data/data-in.h>
+#include <data/format.h>
 #include <data/dictionary.h>
 #include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/dictionary.h>
 #include <data/procedure.h>
 #include <data/transformations.h>
@@ -90,8 +91,8 @@ struct recode_trns
     struct pool *pool;
 
     /* Variable types, for convenience. */
     struct pool *pool;
 
     /* Variable types, for convenience. */
-    enum var_type src_type;     /* src_vars[*]->type. */
-    enum var_type dst_type;     /* dst_vars[*]->type. */
+    enum val_type src_type;     /* src_vars[*] type. */
+    enum val_type dst_type;     /* dst_vars[*] type. */
 
     /* Variables. */
     const struct variable **src_vars;  /* Source variables. */
 
     /* Variables. */
     const struct variable **src_vars;  /* Source variables. */
@@ -112,7 +113,7 @@ static void add_mapping (struct recode_trns *,
                          size_t *map_allocated, const struct map_in *);
 
 static bool parse_map_in (struct lexer *lexer, struct map_in *, struct pool *,
                          size_t *map_allocated, const struct map_in *);
 
 static bool parse_map_in (struct lexer *lexer, struct map_in *, struct pool *,
-                          enum var_type src_type, size_t max_src_width);
+                          enum val_type src_type, size_t max_src_width);
 static void set_map_in_generic (struct map_in *, enum map_in_type);
 static void set_map_in_num (struct map_in *, enum map_in_type, double, double);
 static void set_map_in_str (struct map_in *, struct pool *,
 static void set_map_in_generic (struct map_in *, enum map_in_type);
 static void set_map_in_num (struct map_in *, enum map_in_type, double, double);
 static void set_map_in_str (struct map_in *, struct pool *,
@@ -153,7 +154,7 @@ cmd_recode (struct lexer *lexer, struct dataset *ds)
 
       /* Ensure that all the output strings are at least as wide
          as the widest destination variable. */
 
       /* Ensure that all the output strings are at least as wide
          as the widest destination variable. */
-      if (trns->dst_type == VAR_STRING)
+      if (trns->dst_type == VAL_STRING)
         enlarge_dst_widths (trns);
 
       /* Create destination variables, if needed.
         enlarge_dst_widths (trns);
 
       /* Create destination variables, if needed.
@@ -215,7 +216,7 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns)
     return false;
   do
     {
     return false;
   do
     {
-      enum var_type dst_type;
+      enum val_type dst_type;
 
       if (!lex_match_id (lexer, "CONVERT"))
         {
 
       if (!lex_match_id (lexer, "CONVERT"))
         {
@@ -239,7 +240,7 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns)
 
           if (!parse_map_out (lexer, trns->pool, &out))
             return false;
 
           if (!parse_map_out (lexer, trns->pool, &out))
             return false;
-          dst_type = var_type_from_width (out.width);
+          dst_type = val_type_from_width (out.width);
           if (have_dst_type && dst_type != trns->dst_type)
             {
               msg (SE, _("Inconsistent target variable types.  "
           if (have_dst_type && dst_type != trns->dst_type)
             {
               msg (SE, _("Inconsistent target variable types.  "
@@ -259,9 +260,9 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns)
           add_mapping (trns, &map_allocated, &in);
           set_map_out_num (&trns->mappings[trns->map_cnt - 1].out, 0.0);
 
           add_mapping (trns, &map_allocated, &in);
           set_map_out_num (&trns->mappings[trns->map_cnt - 1].out, 0.0);
 
-          dst_type = VAR_NUMERIC;
-          if (trns->src_type != VAR_STRING
-              || (have_dst_type && trns->dst_type != VAR_NUMERIC))
+          dst_type = VAL_NUMERIC;
+          if (trns->src_type != VAL_STRING
+              || (have_dst_type && trns->dst_type != VAL_NUMERIC))
             {
               msg (SE, _("CONVERT requires string input values and "
                          "numeric output values."));
             {
               msg (SE, _("CONVERT requires string input values and "
                          "numeric output values."));
@@ -286,11 +287,11 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns)
    false on parse error. */
 static bool
 parse_map_in (struct lexer *lexer, struct map_in *in, struct pool *pool,
    false on parse error. */
 static bool
 parse_map_in (struct lexer *lexer, struct map_in *in, struct pool *pool,
-              enum var_type src_type, size_t max_src_width)
+              enum val_type src_type, size_t max_src_width)
 {
   if (lex_match_id (lexer, "ELSE"))
     set_map_in_generic (in, MAP_ELSE);
 {
   if (lex_match_id (lexer, "ELSE"))
     set_map_in_generic (in, MAP_ELSE);
-  else if (src_type == VAR_NUMERIC)
+  else if (src_type == VAL_NUMERIC)
     {
       if (lex_match_id (lexer, "MISSING"))
         set_map_in_generic (in, MAP_MISSING);
     {
       if (lex_match_id (lexer, "MISSING"))
         set_map_in_generic (in, MAP_MISSING);
@@ -449,7 +450,7 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns,
         {
           const struct variable *v;
           v = trns->dst_vars[i] = dict_lookup_var (dict, trns->dst_names[i]);
         {
           const struct variable *v;
           v = trns->dst_vars[i] = dict_lookup_var (dict, trns->dst_names[i]);
-          if (v == NULL && trns->dst_type == VAR_STRING)
+          if (v == NULL && trns->dst_type == VAL_STRING)
             {
               msg (SE, _("There is no variable named "
                          "%s.  (All string variables specified "
             {
               msg (SE, _("There is no variable named "
                          "%s.  (All string variables specified "
@@ -468,8 +469,8 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns,
         {
           msg (SE, _("INTO is required with %s input values "
                      "and %s output values."),
         {
           msg (SE, _("INTO is required with %s input values "
                      "and %s output values."),
-               trns->src_type == VAR_NUMERIC ? _("numeric") : _("string"),
-               trns->dst_type == VAR_NUMERIC ? _("numeric") : _("string"));
+               trns->src_type == VAL_NUMERIC ? _("numeric") : _("string"),
+               trns->dst_type == VAL_NUMERIC ? _("numeric") : _("string"));
           return false;
         }
     }
           return false;
         }
     }
@@ -481,7 +482,7 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns,
         {
           msg (SE, _("Type mismatch.  Cannot store %s data in "
                      "%s variable %s."),
         {
           msg (SE, _("Type mismatch.  Cannot store %s data in "
                      "%s variable %s."),
-               trns->dst_type == VAR_STRING ? _("string") : _("numeric"),
+               trns->dst_type == VAL_STRING ? _("string") : _("numeric"),
                var_is_alpha (v) ? _("string") : _("numeric"),
                var_get_name (v));
           return false;
                var_is_alpha (v) ? _("string") : _("numeric"),
                var_get_name (v));
           return false;
@@ -640,12 +641,12 @@ recode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
 
       const struct map_out *out;
 
 
       const struct map_out *out;
 
-      if (trns->src_type == VAR_NUMERIC)
+      if (trns->src_type == VAL_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));
 
         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 == VAR_NUMERIC)
+      if (trns->dst_type == VAL_NUMERIC)
         {
           if (out != NULL)
             dst_data->f = !out->copy_input ? out->value.f : src_data->f;
         {
           if (out != NULL)
             dst_data->f = !out->copy_input ? out->value.f : src_data->f;
index 1026aa9c9bafd6e1ccfdb1326ead297c64b79803..cb51c485df27ae983104b7540888c1b6492bb16d 100644 (file)
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <sys/time.h>
 
 #include <string.h>
 #include <sys/time.h>
 
+#include <data/val-type.h>
 #include <libpspp/bit-vector.h>
 #include <libpspp/compiler.h>
 #include <libpspp/deque.h>
 #include <libpspp/bit-vector.h>
 #include <libpspp/compiler.h>
 #include <libpspp/deque.h>
index 1b91e84eb717296c5bbf1e57fe1477ab52f1b207..582b83468ca77f2516dc42b248e2dd6a8359fd44 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <config.h>
 #include "factor-stats.h"
 
 #include <config.h>
 #include "factor-stats.h"
+#include <data/val-type.h>
 #include <data/value.h>
 #include <libpspp/hash.h>
 #include <libpspp/array.h>
 #include <data/value.h>
 #include <libpspp/hash.h>
 #include <libpspp/array.h>
index a5be12e9cd0d53a108cd91ea98b3d85bd6daf4f3..084e6d8c8b22f24c469212fec682080c204da6d9 100644 (file)
@@ -20,6 +20,7 @@
 #include <math.h>
 #include <stdlib.h>
 #include <libpspp/misc.h>
 #include <math.h>
 #include <stdlib.h>
 #include <libpspp/misc.h>
+#include <data/val-type.h>
 #include <data/value.h>
 
 #include "xalloc.h"
 #include <data/value.h>
 
 #include "xalloc.h"
index 5c36fc14b1fcbfa2d4a48f308f61ad89b8ab5cab..aa7eead6c03980d9b1dc2bafca96777341678351 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <config.h>
 #include <assert.h>
 
 #include <config.h>
 #include <assert.h>
+#include <data/val-type.h>
 #include <libpspp/compiler.h>
 #include "factor-stats.h"
 #include "percentiles.h"
 #include <libpspp/compiler.h>
 #include "factor-stats.h"
 #include "percentiles.h"
index 3a350735b99f17bf207bc0b5c7221f107a1c57af..576701c127e6b51eff28c9730a7bbd773c96c653 100644 (file)
@@ -148,7 +148,7 @@ missing_val_dialog_accept (GtkWidget *w, gpointer data)
        g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->discrete)));
 
       mv_clear (&dialog->mvl);
        g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->discrete)));
 
       mv_clear (&dialog->mvl);
-      mv_add_num_range (&dialog->mvl, low_val.f, high_val.f);
+      mv_add_range (&dialog->mvl, low_val.f, high_val.f);
 
       if ( discrete_text && strlen (g_strstrip (discrete_text)) > 0 )
        {
 
       if ( discrete_text && strlen (g_strstrip (discrete_text)) > 0 )
        {
@@ -307,7 +307,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog)
       union value low, high;
       gchar *low_text;
       gchar *high_text;
       union value low, high;
       gchar *low_text;
       gchar *high_text;
-      mv_peek_range (&dialog->mvl, &low.f, &high.f);
+      mv_get_range (&dialog->mvl, &low.f, &high.f);
 
       low_text = value_to_text (low, *write_spec);
       high_text = value_to_text (high, *write_spec);
 
       low_text = value_to_text (low, *write_spec);
       high_text = value_to_text (high, *write_spec);
@@ -321,7 +321,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog)
        {
          gchar *text;
          union value value;
        {
          gchar *text;
          union value value;
-         mv_peek_value (&dialog->mvl, &value, 0);
+         mv_get_value (&dialog->mvl, &value, 0);
          text = value_to_text (value, *write_spec);
          gtk_entry_set_text (GTK_ENTRY (dialog->discrete), text);
          g_free (text);
          text = value_to_text (value, *write_spec);
          gtk_entry_set_text (GTK_ENTRY (dialog->discrete), text);
          g_free (text);
@@ -344,7 +344,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog)
              gchar *text ;
              union value value;
 
              gchar *text ;
              union value value;
 
-             mv_peek_value (&dialog->mvl, &value, i);
+             mv_get_value (&dialog->mvl, &value, i);
              text = value_to_text (value, *write_spec);
              gtk_entry_set_text (GTK_ENTRY (dialog->mv[i]), text);
              g_free (text);
              text = value_to_text (value, *write_spec);
              gtk_entry_set_text (GTK_ENTRY (dialog->mv[i]), text);
              g_free (text);
index 05068d0f964523a91df558a58230c8c928ebcb56..7e558eec3f8fb62fe5cf88fda95fda02a5ebc890 100644 (file)
@@ -519,7 +519,7 @@ val_labs_dialog_show (struct val_labs_dialog *dialog)
   value_labels = var_get_value_labels (dialog->pv);
 
   if (value_labels)
   value_labels = var_get_value_labels (dialog->pv);
 
   if (value_labels)
-    dialog->labs = val_labs_copy ( value_labels );
+    dialog->labs = val_labs_clone ( value_labels );
   else
     dialog->labs = val_labs_create ( var_get_width (dialog->pv));
 
   else
     dialog->labs = val_labs_create ( var_get_width (dialog->pv));
 
index 114156d7476a09e098f8ba9d34be4713bdc232a8..62c3eeee7e763e0747041723750d9a73fbdfdf18 100644 (file)
@@ -63,7 +63,7 @@ missing_values_to_string (const struct variable *pv, GError **err)
          for (i = 0 ; i < n; ++i )
            {
              union value v;
          for (i = 0 ; i < n; ++i )
            {
              union value v;
-             mv_peek_value (miss, &v, i);
+             mv_get_value (miss, &v, i);
              mv[i] = value_to_text (v, *fmt);
              if ( i > 0 )
                g_string_append (gstr, ", ");
              mv[i] = value_to_text (v, *fmt);
              if ( i > 0 )
                g_string_append (gstr, ", ");
@@ -78,7 +78,7 @@ missing_values_to_string (const struct variable *pv, GError **err)
          GString *gstr = g_string_sized_new (10);
          gchar *l, *h;
          union value low, high;
          GString *gstr = g_string_sized_new (10);
          gchar *l, *h;
          union value low, high;
-         mv_peek_range (miss, &low.f, &high.f);
+         mv_get_range (miss, &low.f, &high.f);
 
          l = value_to_text (low, *fmt);
          h = value_to_text (high, *fmt);
 
          l = value_to_text (low, *fmt);
          h = value_to_text (high, *fmt);
@@ -91,7 +91,7 @@ missing_values_to_string (const struct variable *pv, GError **err)
            {
              gchar *ss = 0;
              union value v;
            {
              gchar *ss = 0;
              union value v;
-             mv_peek_value (miss, &v, 0);
+             mv_get_value (miss, &v, 0);
 
              ss = value_to_text (v, *fmt);
 
 
              ss = value_to_text (v, *fmt);
 
index dfdd895f6192f9964bda5785b02748d85441fe29..bee65de8edc44e7febee965eeb030562f6f30c71 100644 (file)
@@ -790,14 +790,14 @@ on_var_type_ok_clicked (GtkWidget *w, gpointer data)
     gint decimals = atoi (gtk_entry_get_text
                         (GTK_ENTRY (dialog->entry_decimals)));
 
     gint decimals = atoi (gtk_entry_get_text
                         (GTK_ENTRY (dialog->entry_decimals)));
 
-    gint new_type = VAR_NUMERIC;
+    gint new_type = VAL_NUMERIC;
     gint new_width = 0;
     bool result = false;
     struct fmt_spec spec;
     switch (dialog->active_button)
       {
       case BUTTON_STRING:
     gint new_width = 0;
     bool result = false;
     struct fmt_spec spec;
     switch (dialog->active_button)
       {
       case BUTTON_STRING:
-       new_type = VAR_STRING;
+       new_type = VAL_STRING;
        new_width = width;
        result = make_output_format_try (&spec, FMT_A, width, 0);
        break;
        new_width = width;
        result = make_output_format_try (&spec, FMT_A, width, 0);
        break;