* 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.
Makefile
Makefile.in
ni.texi
+pspp-dev.info
pspp.info*
+stamp-1
stamp-vti
+version-dev.texi
version.texi
+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
## 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/data-file-format.texi \
doc/data-io.texi \
doc/data-selection.texi \
doc/expressions.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/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 \
- 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
+++ /dev/null
-@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
--- /dev/null
+@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
--- /dev/null
+@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
--- /dev/null
+@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.
--- /dev/null
+@node Presenting Output
+@chapter Presenting Output
--- /dev/null
+@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
--- /dev/null
+@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
--- /dev/null
+@node Parsing Command Syntax
+@chapter Parsing Command Syntax
--- /dev/null
+@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
@cindex unimplemented commands
@cindex commands, unimplemented
-@include ni.texi
+@include doc/ni.texi
@setfilename ignored
+++ /dev/null
-@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
--- /dev/null
+\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:
@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
* 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
@include configuring.texi
-@include portable-file-format.texi
-@include data-file-format.texi
-@include q2c.texi
-
@include fdl.texi
@bye
+++ /dev/null
-@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
@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
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
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"
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 ""
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 ""
-#: 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 ""
-#: src/data/data-in.c:280
+#: src/data/data-in.c:300
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 ""
-#: 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 ""
-#: src/data/data-in.c:320
+#: src/data/data-in.c:340
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/data-in.c:692
+#: src/data/data-in.c:726
#, 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 ""
-#: 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 ""
-#: src/data/data-in.c:840
+#: src/data/data-in.c:874
#, 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 ""
-#: src/data/data-in.c:868
+#: src/data/data-in.c:902
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 ""
-#: src/data/data-in.c:897
+#: src/data/data-in.c:931
#, 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 ""
-#: src/data/data-in.c:930
+#: src/data/data-in.c:964
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 ""
-#: 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 ""
-#: src/data/data-in.c:1128
+#: src/data/data-in.c:1162
#, 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"
-#: src/data/data-in.c:1171
+#: src/data/data-in.c:1205
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/dictionary.c:1059
+#: src/data/dictionary.c:1060
#, 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 ""
-#: 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 ""
-#: 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 ""
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"
-#: 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"
-#: 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/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"
-#: 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/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 "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 ""
-#: 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 ""
-#: src/data/por-file-reader.c:155
+#: src/data/por-file-reader.c:156
#, 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.
-#: 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)"
-#: 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 ""
-#: src/data/por-file-reader.c:296
+#: src/data/por-file-reader.c:297
msgid "Data record expected."
msgstr ""
-#: src/data/por-file-reader.c:378
+#: src/data/por-file-reader.c:379
msgid "Number expected."
msgstr ""
-#: src/data/por-file-reader.c:406
+#: src/data/por-file-reader.c:407
msgid "Missing numeric terminator."
msgstr ""
-#: src/data/por-file-reader.c:429
+#: src/data/por-file-reader.c:430
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 ""
-#: src/data/por-file-reader.c:501
+#: src/data/por-file-reader.c:502
#, 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 ""
-#: src/data/por-file-reader.c:526
+#: src/data/por-file-reader.c:527
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/por-file-reader.c:619
+#: src/data/por-file-reader.c:620
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 ""
-#: src/data/por-file-reader.c:633
+#: src/data/por-file-reader.c:634
#, 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 ""
-#: src/data/por-file-reader.c:652
+#: src/data/por-file-reader.c:653
#, 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 ""
-#: src/data/por-file-reader.c:664
+#: src/data/por-file-reader.c:665
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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."
#. 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 ""
#. 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)"
-#: 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 ""
-#: src/data/sys-file-reader.c:243
+#: src/data/sys-file-reader.c:244
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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:333
+#: src/data/sys-file-reader.c:334
#, 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."
-#: 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 ""
-#: src/data/sys-file-reader.c:496
+#: src/data/sys-file-reader.c:497
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:585
+#: src/data/sys-file-reader.c:586
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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
msgid "print"
msgstr "drucken"
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
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 ""
-#: src/data/sys-file-reader.c:662
+#: src/data/sys-file-reader.c:663
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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:688
+#: src/data/sys-file-reader.c:689
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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
msgid "little-endian"
msgstr ""
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:875
+#: src/data/sys-file-reader.c:876
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:995
+#: src/data/sys-file-reader.c:996
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:1223
+#: src/data/sys-file-reader.c:1224
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:1542
+#: src/data/sys-file-reader.c:1543
#, 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 ""
-#: src/data/sys-file-reader.c:1631
+#: src/data/sys-file-reader.c:1632
#, 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 "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 ""
-#: 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 ""
-#: 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."
-#: 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."
-#: 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 ""
-#: 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."
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
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 ""
-#: 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/language/data-io/print.c:400
+#: src/language/data-io/print.c:404
msgid "Format"
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 ""
-#: 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 ""
-#: 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 "
#. 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"
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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
-msgid "%s: Partial record at end of file."
+msgid "Corrupt record descriptor word at offset 0x%lx in %s."
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 ""
-#: src/language/data-io/data-reader.c:280
+#: src/language/data-io/data-reader.c:514
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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
-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 ""
-#: src/language/data-io/file-handle.q:102
+#: src/language/data-io/file-handle.q:134
#, 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 ""
-#: src/language/data-io/file-handle.q:147
+#: src/language/data-io/file-handle.q:176
msgid "file"
msgstr ""
-#: src/language/data-io/file-handle.q:149
+#: src/language/data-io/file-handle.q:178
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 ""
-#: 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 ""
+#: 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 ""
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 ""
"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 ""
"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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/language/data-io/list.q:210
+#: src/language/data-io/list.q:211
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 ""
"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 ""
-#: 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] ""
-#: 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] ""
-#: 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."
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 ""
-#: src/language/lexer/range-parser.c:114
+#: src/language/lexer/range-parser.c:115
msgid "expecting number or data string"
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 ""
-#: src/language/stats/flip.c:150
+#: src/language/stats/flip.c:151
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 ""
-#: src/language/stats/flip.c:261
+#: src/language/stats/flip.c:262
#, 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 ""
-#: src/language/stats/flip.c:393
+#: src/language/stats/flip.c:394
#, 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 ""
-#: src/language/stats/flip.c:413
+#: src/language/stats/flip.c:414
#, 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"
-#: src/language/stats/flip.c:431
+#: src/language/stats/flip.c:432
#, 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 ""
-#: src/language/stats/flip.c:450
+#: src/language/stats/flip.c:451
#, 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 ""
-#: src/language/stats/flip.c:487
+#: src/language/stats/flip.c:488
#, 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 "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 ""
-#: 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 "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 ""
"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 ""
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 ""
-#: src/language/stats/rank.q:225
+#: src/language/stats/rank.q:226
#, 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 ""
-#: src/language/stats/rank.q:694
+#: src/language/stats/rank.q:695
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 ""
-#: src/language/stats/rank.q:729
+#: src/language/stats/rank.q:730
#, 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 ""
-#: src/language/stats/rank.q:753
+#: src/language/stats/rank.q:754
#, 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 ""
-#: src/language/stats/rank.q:859
+#: src/language/stats/rank.q:860
#, 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 "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 ""
-#: src/language/xforms/recode.c:266
+#: src/language/xforms/recode.c:267
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 ""
-#: src/language/xforms/recode.c:390
+#: src/language/xforms/recode.c:391
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
msgid "hash table:"
msgstr ""
-#: src/math/percentiles.c:40
+#: src/math/percentiles.c:41
msgid "HAverage"
msgstr ""
-#: src/math/percentiles.c:41
+#: src/math/percentiles.c:42
msgid "Weighted Average"
msgstr ""
-#: src/math/percentiles.c:42
+#: src/math/percentiles.c:43
msgid "Rounded"
msgstr ""
-#: src/math/percentiles.c:43
+#: src/math/percentiles.c:44
msgid "Empirical"
msgstr ""
-#: src/math/percentiles.c:44
+#: src/math/percentiles.c:45
msgid "Empirical with averaging"
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 ""
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 ""
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."
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 ""
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 ""
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
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"
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"
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 ""
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 ""
-#: 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 ""
-#: src/data/data-in.c:280
+#: src/data/data-in.c:300
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 ""
-#: 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 ""
-#: src/data/data-in.c:320
+#: src/data/data-in.c:340
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/data-in.c:692
+#: src/data/data-in.c:726
#, 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 ""
-#: 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 ""
-#: src/data/data-in.c:840
+#: src/data/data-in.c:874
#, 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 ""
-#: src/data/data-in.c:868
+#: src/data/data-in.c:902
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 ""
-#: src/data/data-in.c:897
+#: src/data/data-in.c:931
#, 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 ""
-#: src/data/data-in.c:930
+#: src/data/data-in.c:964
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 ""
-#: 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 ""
-#: src/data/data-in.c:1128
+#: src/data/data-in.c:1162
#, 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 ""
-#: src/data/data-in.c:1171
+#: src/data/data-in.c:1205
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/dictionary.c:1059
+#: src/data/dictionary.c:1060
#, 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 ""
-#: 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 ""
-#: 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 ""
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 ""
-#: 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 ""
-#: 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/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 ""
-#: 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/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 "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 ""
-#: 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 ""
-#: src/data/por-file-reader.c:155
+#: src/data/por-file-reader.c:156
#, 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.
-#: 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 ""
-#: 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 ""
-#: src/data/por-file-reader.c:296
+#: src/data/por-file-reader.c:297
msgid "Data record expected."
msgstr ""
-#: src/data/por-file-reader.c:378
+#: src/data/por-file-reader.c:379
msgid "Number expected."
msgstr ""
-#: src/data/por-file-reader.c:406
+#: src/data/por-file-reader.c:407
msgid "Missing numeric terminator."
msgstr ""
-#: src/data/por-file-reader.c:429
+#: src/data/por-file-reader.c:430
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 ""
-#: src/data/por-file-reader.c:501
+#: src/data/por-file-reader.c:502
#, 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 ""
-#: src/data/por-file-reader.c:526
+#: src/data/por-file-reader.c:527
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/por-file-reader.c:619
+#: src/data/por-file-reader.c:620
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 ""
-#: src/data/por-file-reader.c:633
+#: src/data/por-file-reader.c:634
#, 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 ""
-#: src/data/por-file-reader.c:652
+#: src/data/por-file-reader.c:653
#, 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 ""
-#: src/data/por-file-reader.c:664
+#: src/data/por-file-reader.c:665
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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."
#. 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 ""
#. 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:243
+#: src/data/sys-file-reader.c:244
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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:333
+#: src/data/sys-file-reader.c:334
#, 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:496
+#: src/data/sys-file-reader.c:497
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:585
+#: src/data/sys-file-reader.c:586
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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
msgid "print"
msgstr ""
-#: src/data/sys-file-reader.c:640
+#: src/data/sys-file-reader.c:641
msgid "write"
msgstr ""
-#: src/data/sys-file-reader.c:644
+#: src/data/sys-file-reader.c:645
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 ""
-#: src/data/sys-file-reader.c:676
+#: src/data/sys-file-reader.c:677
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 ""
-#: src/data/sys-file-reader.c:688
+#: src/data/sys-file-reader.c:689
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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
msgid "little-endian"
msgstr ""
-#: src/data/sys-file-reader.c:813
+#: src/data/sys-file-reader.c:814
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:875
+#: src/data/sys-file-reader.c:876
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:995
+#: src/data/sys-file-reader.c:996
#, 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:1223
+#: src/data/sys-file-reader.c:1224
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/data/sys-file-reader.c:1542
+#: src/data/sys-file-reader.c:1543
#, 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 ""
-#: src/data/sys-file-reader.c:1631
+#: src/data/sys-file-reader.c:1632
#, 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 "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 ""
-#: 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 ""
-#: src/data/variable.c:271
+#: src/data/variable.c:257
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 ""
-#: 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 ""
-#: 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."
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
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 ""
-#: 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/language/data-io/print.c:400
+#: src/language/data-io/print.c:404
msgid "Format"
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 ""
-#: 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 ""
-#: 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 "
#. 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/language/data-io/data-reader.c:226
+#: src/language/data-io/data-reader.c:212
#, c-format
-msgid "%s: Partial record at end of file."
+msgid "Unexpected end of file reading %s."
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 ""
-#: src/language/data-io/data-reader.c:280
+#: src/language/data-io/data-reader.c:514
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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
-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 ""
-#: src/language/data-io/file-handle.q:102
+#: src/language/data-io/file-handle.q:134
#, 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 ""
-#: src/language/data-io/file-handle.q:147
+#: src/language/data-io/file-handle.q:176
msgid "file"
msgstr ""
-#: src/language/data-io/file-handle.q:149
+#: src/language/data-io/file-handle.q:178
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 ""
-#: 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 ""
+#: 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 ""
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 ""
"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 ""
"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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
-#: src/language/data-io/list.q:210
+#: src/language/data-io/list.q:211
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 ""
"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 ""
-#: 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] ""
-#: 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] ""
-#: 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."
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 ""
-#: src/language/lexer/range-parser.c:114
+#: src/language/lexer/range-parser.c:115
msgid "expecting number or data string"
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 ""
-#: src/language/stats/flip.c:150
+#: src/language/stats/flip.c:151
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 ""
-#: src/language/stats/flip.c:261
+#: src/language/stats/flip.c:262
#, 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 ""
-#: src/language/stats/flip.c:393
+#: src/language/stats/flip.c:394
#, 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 ""
-#: src/language/stats/flip.c:413
+#: src/language/stats/flip.c:414
#, 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 ""
-#: src/language/stats/flip.c:431
+#: src/language/stats/flip.c:432
#, 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 ""
-#: src/language/stats/flip.c:450
+#: src/language/stats/flip.c:451
#, 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 ""
-#: src/language/stats/flip.c:487
+#: src/language/stats/flip.c:488
#, 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 "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 ""
-#: 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 "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 ""
"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 ""
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 ""
-#: src/language/stats/rank.q:225
+#: src/language/stats/rank.q:226
#, 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 ""
-#: src/language/stats/rank.q:694
+#: src/language/stats/rank.q:695
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 ""
-#: src/language/stats/rank.q:729
+#: src/language/stats/rank.q:730
#, 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 ""
-#: src/language/stats/rank.q:753
+#: src/language/stats/rank.q:754
#, 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 ""
-#: src/language/stats/rank.q:859
+#: src/language/stats/rank.q:860
#, 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 "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 ""
-#: src/language/xforms/recode.c:266
+#: src/language/xforms/recode.c:267
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 ""
-#: src/language/xforms/recode.c:390
+#: src/language/xforms/recode.c:391
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 ""
-#: 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 ""
-#: 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 ""
-#: 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 ""
msgid "hash table:"
msgstr ""
-#: src/math/percentiles.c:40
+#: src/math/percentiles.c:41
msgid "HAverage"
msgstr ""
-#: src/math/percentiles.c:41
+#: src/math/percentiles.c:42
msgid "Weighted Average"
msgstr ""
-#: src/math/percentiles.c:42
+#: src/math/percentiles.c:43
msgid "Rounded"
msgstr ""
-#: src/math/percentiles.c:43
+#: src/math/percentiles.c:44
msgid "Empirical"
msgstr ""
-#: src/math/percentiles.c:44
+#: src/math/percentiles.c:45
msgid "Empirical with averaging"
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 ""
msgid "Paste"
msgstr ""
-#: src/ui/gui/psppire.c:197
-msgid "_Reset"
-msgstr ""
-
#: src/ui/gui/psppire-data-store.c:816
msgid "var"
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 ""
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 ""
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 ""
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
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"
+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.
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 \
#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)
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>
const union value *case_data_all (const struct ccase *);
union value *case_data_all_rw (struct ccase *);
-#endif /* case.h */
+#endif /* data/case.h */
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 <data/format.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 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);
-#endif /* data-in.h */
+#endif /* data/data-in.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/misc.h>
#include <libpspp/str.h>
#include "minmax.h"
--- /dev/null
+/* 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 ();
+ }
+}
--- /dev/null
+/* 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 */
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. */
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,
- 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
- 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,
- size_t *cnt, unsigned exclude_classes)
+ size_t *cnt, enum dict_class exclude)
{
size_t count;
size_t i;
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++)
{
- 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++;
}
*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);
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,
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++;
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)
{
assert (d != NULL);
assert (v == NULL || dict_contains_var (d, v));
+ assert (v == NULL || var_is_numeric (v));
d->filter = v;
/* 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);
/* 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);
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]);
}
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
-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. */
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
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 <data/case.h>
+#include <data/dict-class.h>
-/* Dictionary. */
-
-struct variable;
-struct dictionary;
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 *);
-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 *);
+/* 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 *);
-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,
- unsigned exclude_classes);
+ enum dict_class exclude);
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_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_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_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 *);
-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);
+
+/* 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);
-struct ccase;
-struct variable *dict_get_weight (const struct dictionary *);
+/* Weight variable. */
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 *);
+/* Filter 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 *);
+/* 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 *);
+/* 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);
-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 *);
-/* 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 *);
+
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);
-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);
-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 *);
+/* 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 *);
-#endif /* dictionary.h */
+#endif /* data/dictionary.h */
{
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,
}
/* 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
-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."),
- 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;
}
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 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
-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);
}
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,
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);
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>
-#include <stddef.h>
-#include <data/variable.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. */
FMT_CAT_STRING = 0x100 /* String formats. */
};
+/* Format type. */
enum fmt_type
{
#define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) FMT_##NAME,
int d; /* Number of implied decimal places. */
};
-union value;
-
/* Initialization. */
void fmt_init (void);
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_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 *);
-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. */
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 *);
-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
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 *);
+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);
-#endif /* format.h */
+#endif /* data/format.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>
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);
- 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;
-
- 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,
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
- 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));
+
+ *v = mv->values[0];
+ remove_element (mv->values, mv->type & 3, sizeof *mv->values, 0);
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
-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];
}
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
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
-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;
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
- 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)
{
- 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 >= 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
- explained for mv_is_resizable(). */
+ explained for mv_is_resizable. */
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;
}
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 "value.h"
+#include "data/value.h"
/* Missing values.
Opaque--use access functions defined below. */
{
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. */
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_copy (struct missing_values *, const 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 *);
+/* 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_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_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_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 */
#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>
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;
{
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'))
- mv_add_num_range (&miss, read_float (r), HIGHEST);
+ mv_add_range (&miss, read_float (r), HIGHEST);
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'))
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)
{
- 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);
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 */
#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>
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));
{
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++)
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;
- mv_peek_value (mv, &value, i);
+ mv_get_value (mv, &value, i);
write_value (w, &value, seg0_width);
}
--- /dev/null
+/* 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 */
/* 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;
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)
{
- 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)
{
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)
{
- struct int_val_lab *ivl;
- void **vlpp;
-
- assert (vls != NULL);
- assert (vls->width <= MAX_SHORT_STRING);
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;
}
-/* 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)
{
- 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
- 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)
{
- 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);
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);
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);
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. */
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 <data/value.h>
-struct val_labs;
-struct variable;
-
+/* One value 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_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 *);
-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);
+/* 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);
-char *val_labs_find (const struct val_labs *, union value);
+/* Iterating through value labels. */
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_labs_iterator **);
void val_labs_done (struct val_labs_iterator **);
-#endif /* value-labels.h */
+#endif /* data/value-labels.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>
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);
+}
/* 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
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 <stdbool.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)
-#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. */
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);
+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 */
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 *);
-/* 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);
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. */
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
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."),
- name, (int) LONG_NAME_LEN);
+ name, (int) VAR_NAME_LEN);
return false;
}
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
}
\f
/* Returns the type of variable V. */
-enum var_type
+enum val_type
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. */
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)
{
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
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
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);
}
/* 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)
/* 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)
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_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.
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)
{
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)
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 <data/dict-class.h>
#include <data/missing-values.h>
+#include <data/val-type.h>
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 *);
-/* 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);
+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_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);
-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 *);
+
size_t var_get_value_cnt (const struct variable *);
/* Variables' missing values. */
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 *);
+const struct val_labs *var_get_value_labels (const struct variable *);
void var_set_value_labels (struct variable *, const struct val_labs *);
+
bool var_add_value_label (struct variable *,
const union value *, const char *);
void var_replace_value_label (struct variable *,
const union value *, const char *);
void var_clear_value_labels (struct variable *);
-const char *var_lookup_value_label (const struct variable *,
- const union value *);
-const char *var_get_value_name (const struct variable *, const union value *);
/* Print and write formats. */
const struct fmt_spec *var_get_print_format (const struct variable *);
void var_set_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 */
/* 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. */
};
}
/* 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]);
}
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 *);
/* 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). */
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;
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;
#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>
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."));
}
{
- 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);
}
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, ')'))
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;
"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
{
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
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
}
/* 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++)
{
- 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);
- 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;
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);
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;
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_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)
|| !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));
}
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
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);
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++;
{
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);
}
{
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. */
};
{"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}},
- {"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. */
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);
- type = VAR_NUMERIC;
+ type = VAL_NUMERIC;
}
else
{
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)
- || function->alpha_type == VAR_NUMERIC);
+ || function->alpha_type == VAL_NUMERIC);
destvar = dict_create_var (agr->dict, dest[i], 0);
if (destvar != NULL)
{
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. */
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';
#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>
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, '/');
}
/* 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 *
-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:
#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/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 <output/table.h>
#include <output/manager.h>
+#include <output/table.h>
#include <gsl/gsl_cdf.h>
}
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;
- snprintf (name, LONG_NAME_LEN, "%s%d", prefix, i);
+ snprintf (name, VAR_NAME_LEN, "%s%d", prefix, 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);
}
}
{
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;
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++)
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;
/* 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;
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
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);
}
#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>
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. */
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 *,
/* 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.
return false;
do
{
- enum var_type dst_type;
+ enum val_type dst_type;
if (!lex_match_id (lexer, "CONVERT"))
{
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. "
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."));
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);
- 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);
{
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, _("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;
}
}
{
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;
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));
- 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;
#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 <config.h>
#include "factor-stats.h"
+#include <data/val-type.h>
#include <data/value.h>
#include <libpspp/hash.h>
#include <libpspp/array.h>
#include <math.h>
#include <stdlib.h>
#include <libpspp/misc.h>
+#include <data/val-type.h>
#include <data/value.h>
#include "xalloc.h"
#include <config.h>
#include <assert.h>
+#include <data/val-type.h>
#include <libpspp/compiler.h>
#include "factor-stats.h"
#include "percentiles.h"
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 )
{
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);
{
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);
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);
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));
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, ", ");
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);
{
gchar *ss = 0;
union value v;
- mv_peek_value (miss, &v, 0);
+ mv_get_value (miss, &v, 0);
ss = value_to_text (v, *fmt);
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:
- new_type = VAR_STRING;
+ new_type = VAL_STRING;
new_width = width;
result = make_output_format_try (&spec, FMT_A, width, 0);
break;