From: Ben Pfaff Date: Sun, 11 Nov 2007 05:51:38 +0000 (+0000) Subject: Patch #6262. New developers guide and resulting fixes and cleanups. X-Git-Tag: v0.6.0~190 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp-builds.git;a=commitdiff_plain;h=a9acce47d67e0ab35ce1690e4f1b1ac0121c2d78 Patch #6262. New developers guide and resulting fixes and cleanups. * 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. --- diff --git a/doc/.cvsignore b/doc/.cvsignore index 6d2576fe..06eb3bb1 100644 --- a/doc/.cvsignore +++ b/doc/.cvsignore @@ -1,6 +1,9 @@ Makefile Makefile.in ni.texi +pspp-dev.info pspp.info* +stamp-1 stamp-vti +version-dev.texi version.texi diff --git a/doc/ChangeLog b/doc/ChangeLog index 8a52b3d8..c1fa40eb 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,36 @@ +2007-11-10 Ben Pfaff + + * 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 + + 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 * statistics.texi: Changed /CONTRASTS to /CONTRAST in ONEWAY which diff --git a/doc/automake.mk b/doc/automake.mk index 301757c8..9c73d344 100644 --- a/doc/automake.mk +++ b/doc/automake.mk @@ -1,13 +1,12 @@ ## 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 \ @@ -21,8 +20,6 @@ doc_pspp_TEXINFOS = doc/version.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 \ @@ -30,9 +27,18 @@ doc_pspp_TEXINFOS = doc/version.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 diff --git a/doc/data-file-format.texi b/doc/data-file-format.texi deleted file mode 100644 index c2fdacdc..00000000 --- a/doc/data-file-format.texi +++ /dev/null @@ -1,906 +0,0 @@ -@node System File Format -@appendix System File Format - -A system file encapsulates a set of cases and dictionary information -that describes how they may be interpreted. This chapter describes -the format of a system file. - -System files use three data types: 8-bit characters, 32-bit integers, -and 64-bit floating points, called here @code{char}, @code{int32}, and -@code{flt64}, respectively. Data is not necessarily aligned on a word -or double-word boundary: the long variable name record (@pxref{Long -Variable Names Record}) and very long string records (@pxref{Very Long -String Record}) have arbitrary byte length and can therefore cause all -data coming after them in the file to be misaligned. - -Integer data in system files may be big-endian or little-endian. A -reader may detect the endianness of a system file by examining -@code{layout_code} in the file header record -(@pxref{layout_code,,@code{layout_code}}). - -Floating-point data in system files may nominally be in IEEE 754, IBM, -or VAX formats. A reader may detect the floating-point format in use -by examining @code{bias} in the file header record -(@pxref{bias,,@code{bias}}). - -PSPP detects big-endian and little-endian integer formats in system -files and translates as necessary. PSPP also detects the -floating-point format in use, as well as the endianness of IEEE 754 -floating-point numbers, and translates as needed. However, only IEEE -754 numbers with the same endianness as integer data in the same file -has actually been observed in system files, and it is likely that -other formats are obsolete or were never used. - -The PSPP system-missing value is represented by the largest possible -negative number in the floating point format (@code{-DBL_MAX}). Two -other values are important for use as missing values: @code{HIGHEST}, -represented by the largest possible positive number (@code{DBL_MAX}), -and @code{LOWEST}, represented by the second-largest negative number -(in IEEE 754 format, @code{0xffeffffffffffffe}). - -System files are divided into records, each of which begins with a -4-byte record type, usually regarded as an @code{int32}. - -The records must appear in the following order: - -@itemize @bullet -@item -File header record. - -@item -Variable records. - -@item -All pairs of value labels records and value label variables records, -if present. - -@item -Document record, if present. - -@item -Any of the following records, if present, in any order: - -@itemize @minus -@item -Machine integer info record. - -@item -Machine floating-point info record. - -@item -Variable display parameter record. - -@item -Long variable names record. - -@item -Miscellaneous informational records. -@end itemize - -@item -Dictionary termination record. - -@item -Data record. -@end itemize - -Each type of record is described separately below. - -@menu -* File Header Record:: -* Variable Record:: -* Value Labels Records:: -* Document Record:: -* Machine Integer Info Record:: -* Machine Floating-Point Info Record:: -* Variable Display Parameter Record:: -* Long Variable Names Record:: -* Very Long String Record:: -* Miscellaneous Informational Records:: -* Dictionary Termination Record:: -* Data Record:: -@end menu - -@node File Header Record -@section File Header Record - -The file header is always the first record in the file. It has the -following format: - -@example -char rec_type[4]; -char prod_name[60]; -int32 layout_code; -int32 nominal_case_size; -int32 compressed; -int32 weight_index; -int32 ncases; -flt64 bias; -char creation_date[9]; -char creation_time[8]; -char file_label[64]; -char padding[3]; -@end example - -@table @code -@item char rec_type[4]; -Record type code, set to @samp{$FL2}. - -@item char prod_name[60]; -Product identification string. This always begins with the characters -@samp{@@(#) SPSS DATA FILE}. PSPP uses the remaining characters to -give its version and the operating system name; for example, @samp{GNU -pspp 0.1.4 - sparc-sun-solaris2.5.2}. The string is truncated if it -would be longer than 60 characters; otherwise it is padded on the right -with spaces. - -@anchor{layout_code} -@item int32 layout_code; -Normally set to 2, although a few system files have been spotted in -the wild with a value of 3 here. PSPP use this value to determine the -file's integer endianness (@pxref{System File Format}). - -@item int32 nominal_case_size; -Number of data elements per case. This is the number of variables, -except that long string variables add extra data elements (one for every -8 characters after the first 8). However, string variables do not -contribute to this value beyond the first 255 bytes. Further, system -files written by some systems set this value to -1. In general, it is -unsafe for systems reading system files to rely upon this value. - -@item int32 compressed; -Set to 1 if the data in the file is compressed, 0 otherwise. - -@item int32 weight_index; -If one of the variables in the data set is used as a weighting -variable, set to the dictionary index of that variable, plus 1 -(@pxref{Dictionary Index}). Otherwise, set to 0. - -@item int32 ncases; -Set to the number of cases in the file if it is known, or -1 otherwise. - -In the general case it is not possible to determine the number of cases -that will be output to a system file at the time that the header is -written. The way that this is dealt with is by writing the entire -system file, including the header, then seeking back to the beginning of -the file and writing just the @code{ncases} field. For `files' in which -this is not valid, the seek operation fails. In this case, -@code{ncases} remains -1. - -@anchor{bias} -@item flt64 bias; -Compression bias, ordinarily set to 100. Only integers between -@code{1 - bias} and @code{251 - bias} can be compressed. - -By assuming that its value is 100, PSPP uses @code{bias} to determine -the file's floating-point format and endianness (@pxref{System File -Format}). If the compression bias is not 100, PSPP cannot auto-detect -the floating-point format and assumes that it is IEEE 754 format with -the same endianness as the system file's integers, which is correct -for all known system files. - -@item char creation_date[9]; -Date of creation of the system file, in @samp{dd mmm yy} -format, with the month as standard English abbreviations, using an -initial capital letter and following with lowercase. If the date is not -available then this field is arbitrarily set to @samp{01 Jan 70}. - -@item char creation_time[8]; -Time of creation of the system file, in @samp{hh:mm:ss} -format and using 24-hour time. If the time is not available then this -field is arbitrarily set to @samp{00:00:00}. - -@item char file_label[64]; -File label declared by the user, if any (@pxref{FILE LABEL}). -Padded on the right with spaces. - -@item char padding[3]; -Ignored padding bytes to make the structure a multiple of 32 bits in -length. Set to zeros. -@end table - -@node Variable Record -@section Variable Record - -There must be one variable record for each numeric variable and each -string variable with width 8 bytes or less. String variables wider -than 8 bytes have one variable record for each 8 bytes, rounding up. -The first variable record for a long string specifies the variable's -correct dictionary information. Subsequent variable records for a -long string are filled with dummy information: a type of -1, no -variable label or missing values, print and write formats that are -ignored, and an empty string as name. A few system files have been -encountered that include a variable label on dummy variable records, -so readers should take care to parse dummy variable records in the -same way as other variable records. - -@anchor{Dictionary Index} -The @dfn{dictionary index} of a variable is its offset in the set of -variable records, including dummy variable records for long string -variables. The first variable record has a dictionary index of 0, the -second has a dictionary index of 1, and so on. - -The system file format does not directly support string variables -wider than 255 bytes. Such very long string variables are represented -by a number of narrower string variables. @xref{Very Long String -Record}, for details. - -@example -int32 rec_type; -int32 type; -int32 has_var_label; -int32 n_missing_values; -int32 print; -int32 write; -char name[8]; - -/* @r{Present only if @code{has_var_label} is 1.} */ -int32 label_len; -char label[]; - -/* @r{Present only if @code{n_missing_values} is nonzero}. */ -flt64 missing_values[]; -@end example - -@table @code -@item int32 rec_type; -Record type code. Always set to 2. - -@item int32 type; -Variable type code. Set to 0 for a numeric variable. For a short -string variable or the first part of a long string variable, this is set -to the width of the string. For the second and subsequent parts of a -long string variable, set to -1, and the remaining fields in the -structure are ignored. - -@item int32 has_var_label; -If this variable has a variable label, set to 1; otherwise, set to 0. - -@item int32 n_missing_values; -If the variable has no missing values, set to 0. If the variable has -one, two, or three discrete missing values, set to 1, 2, or 3, -respectively. If the variable has a range for missing variables, set to --2; if the variable has a range for missing variables plus a single -discrete value, set to -3. - -@item int32 print; -Print format for this variable. See below. - -@item int32 write; -Write format for this variable. See below. - -@item char name[8]; -Variable name. The variable name must begin with a capital letter or -the at-sign (@samp{@@}). Subsequent characters may also be digits, octothorpes -(@samp{#}), dollar signs (@samp{$}), underscores (@samp{_}), or full -stops (@samp{.}). The variable name is padded on the right with spaces. - -@item int32 label_len; -This field is present only if @code{has_var_label} is set to 1. It is -set to the length, in characters, of the variable label, which must be a -number between 0 and 120. - -@item char label[]; -This field is present only if @code{has_var_label} is set to 1. It has -length @code{label_len}, rounded up to the nearest multiple of 32 bits. -The first @code{label_len} characters are the variable's variable label. - -@item flt64 missing_values[]; -This field is present only if @code{n_missing_values} is not 0. It has -the same number of elements as the absolute value of -@code{n_missing_values}. For discrete missing values, each element -represents one missing value. When a range is present, the first -element denotes the minimum value in the range, and the second element -denotes the maximum value in the range. When a range plus a value are -present, the third element denotes the additional discrete missing -value. HIGHEST and LOWEST are indicated as described in the chapter -introduction. -@end table - -The @code{print} and @code{write} members of sysfile_variable are output -formats coded into @code{int32} types. The least-significant byte -of the @code{int32} represents the number of decimal places, and the -next two bytes in order of increasing significance represent field width -and format type, respectively. The most-significant byte is not -used and should be set to zero. - -Format types are defined as follows: - -@quotation -@multitable {Value} {@code{DATETIME}} -@headitem Value -@tab Meaning -@item 0 -@tab Not used. -@item 1 -@tab @code{A} -@item 2 -@tab @code{AHEX} -@item 3 -@tab @code{COMMA} -@item 4 -@tab @code{DOLLAR} -@item 5 -@tab @code{F} -@item 6 -@tab @code{IB} -@item 7 -@tab @code{PIBHEX} -@item 8 -@tab @code{P} -@item 9 -@tab @code{PIB} -@item 10 -@tab @code{PK} -@item 11 -@tab @code{RB} -@item 12 -@tab @code{RBHEX} -@item 13 -@tab Not used. -@item 14 -@tab Not used. -@item 15 -@tab @code{Z} -@item 16 -@tab @code{N} -@item 17 -@tab @code{E} -@item 18 -@tab Not used. -@item 19 -@tab Not used. -@item 20 -@tab @code{DATE} -@item 21 -@tab @code{TIME} -@item 22 -@tab @code{DATETIME} -@item 23 -@tab @code{ADATE} -@item 24 -@tab @code{JDATE} -@item 25 -@tab @code{DTIME} -@item 26 -@tab @code{WKDAY} -@item 27 -@tab @code{MONTH} -@item 28 -@tab @code{MOYR} -@item 29 -@tab @code{QYR} -@item 30 -@tab @code{WKYR} -@item 31 -@tab @code{PCT} -@item 32 -@tab @code{DOT} -@item 33 -@tab @code{CCA} -@item 34 -@tab @code{CCB} -@item 35 -@tab @code{CCC} -@item 36 -@tab @code{CCD} -@item 37 -@tab @code{CCE} -@item 38 -@tab @code{EDATE} -@item 39 -@tab @code{SDATE} -@end multitable -@end quotation - -@node Value Labels Records -@section Value Labels Records - -The value label record has the following format: - -@example -int32 rec_type; -int32 label_count; - -/* @r{Repeated @code{label_cnt} times}. */ -char value[8]; -char label_len; -char label[]; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 3. - -@item int32 label_count; -Number of value labels present in this record. -@end table - -The remaining fields are repeated @code{count} times. Each -repetition specifies one value label. - -@table @code -@item char value[8]; -A numeric value or a short string value padded as necessary to 8 bytes -in length. Its type and width cannot be determined until the -following value label variables record (see below) is read. - -@item char label_len; -The label's length, in bytes. - -@item char label[]; -@code{label_len} bytes of the actual label, followed by up to 7 bytes -of padding to bring @code{label} and @code{label_len} together to a -multiple of 8 bytes in length. -@end table - -The value label record is always immediately followed by a value label -variables record with the following format: - -@example -int32 rec_type; -int32 var_count; -int32 vars[]; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 4. - -@item int32 var_count; -Number of variables that the associated value labels from the value -label record are to be applied. - -@item int32 vars[]; -A list of dictionary indexes of variables to which to apply the value -labels (@pxref{Dictionary Index}). There are @code{var_count} -elements. - -String variables wider than 8 bytes may not have value labels. -@end table - -@node Document Record -@section Document Record - -The document record, if present, has the following format: - -@example -int32 rec_type; -int32 n_lines; -char lines[][80]; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 6. - -@item int32 n_lines; -Number of lines of documents present. - -@item char lines[][80]; -Document lines. The number of elements is defined by @code{n_lines}. -Lines shorter than 80 characters are padded on the right with spaces. -@end table - -@node Machine Integer Info Record -@section Machine Integer Info Record - -The integer info record, if present, has the following format: - -@example -/* @r{Header.} */ -int32 rec_type; -int32 subtype; -int32 size; -int32 count; - -/* @r{Data.} */ -int32 version_major; -int32 version_minor; -int32 version_revision; -int32 machine_code; -int32 floating_point_rep; -int32 compression_code; -int32 endianness; -int32 character_code; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 7. - -@item int32 subtype; -Record subtype. Always set to 3. - -@item int32 size; -Size of each piece of data in the data part, in bytes. Always set to 4. - -@item int32 count; -Number of pieces of data in the data part. Always set to 8. - -@item int32 version_major; -PSPP major version number. In version @var{x}.@var{y}.@var{z}, this -is @var{x}. - -@item int32 version_minor; -PSPP minor version number. In version @var{x}.@var{y}.@var{z}, this -is @var{y}. - -@item int32 version_revision; -PSPP version revision number. In version @var{x}.@var{y}.@var{z}, -this is @var{z}. - -@item int32 machine_code; -Machine code. PSPP always set this field to value to -1, but other -values may appear. - -@item int32 floating_point_rep; -Floating point representation code. For IEEE 754 systems this is 1. -IBM 370 sets this to 2, and DEC VAX E to 3. - -@item int32 compression_code; -Compression code. Always set to 1. - -@item int32 endianness; -Machine endianness. 1 indicates big-endian, 2 indicates little-endian. - -@item int32 character_code; -Character code. 1 indicates EBCDIC, 2 indicates 7-bit ASCII, 3 -indicates 8-bit ASCII, 4 indicates DEC Kanji. -Windows code page numbers are also valid. -@end table - -@node Machine Floating-Point Info Record -@section Machine Floating-Point Info Record - -The floating-point info record, if present, has the following format: - -@example -/* @r{Header.} */ -int32 rec_type; -int32 subtype; -int32 size; -int32 count; - -/* @r{Data.} */ -flt64 sysmis; -flt64 highest; -flt64 lowest; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 7. - -@item int32 subtype; -Record subtype. Always set to 4. - -@item int32 size; -Size of each piece of data in the data part, in bytes. Always set to 8. - -@item int32 count; -Number of pieces of data in the data part. Always set to 3. - -@item flt64 sysmis; -The system missing value. - -@item flt64 highest; -The value used for HIGHEST in missing values. - -@item flt64 lowest; -The value used for LOWEST in missing values. -@end table - -@node Variable Display Parameter Record -@section Variable Display Parameter Record - -The variable display parameter record, if present, has the following -format: - -@example -/* @r{Header.} */ -int32 rec_type; -int32 subtype; -int32 size; -int32 count; - -/* @r{Repeated @code{count} times}. */ -int32 measure; -int32 width; -int32 alignment; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 7. - -@item int32 subtype; -Record subtype. Always set to 11. - -@item int32 size; -The size of @code{int32}. Always set to 4. - -@item int32 count; -The number of sets of variable display parameters (ordinarily the -number of variables in the dictionary), times 3. -@end table - -The remaining members are repeated @code{count} times, in the same -order as the variable records. No element corresponds to variable -records that continue long string variables. The meanings of these -members are as follows: - -@table @code -@item int32 measure; -The measurement type of the variable: -@table @asis -@item 1 -Nominal Scale -@item 2 -Ordinal Scale -@item 3 -Continuous Scale -@end table - -SPSS 14 sometimes writes a @code{measure} of 0. PSPP interprets this -as nominal scale. - -@item int32 width; -The width of the display column for the variable in characters. - -@item int32 alignment; -The alignment of the variable for display purposes: - -@table @asis -@item 0 -Left aligned -@item 1 -Right aligned -@item 2 -Centre aligned -@end table -@end table - -@node Long Variable Names Record -@section Long Variable Names Record - -If present, the long variable names record has the following format: - -@example -/* @r{Header.} */ -int32 rec_type; -int32 subtype; -int32 size; -int32 count; - -/* @r{Exactly @code{count} bytes of data.} */ -char var_name_pairs[]; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 7. - -@item int32 subtype; -Record subtype. Always set to 13. - -@item int32 size; -The size of each element in the @code{var_name_pairs} member. Always set to 1. - -@item int32 count; -The total number of bytes in @code{var_name_pairs}. - -@item char var_name_pairs[]; -A list of @var{key}--@var{value} tuples, where @var{key} is the name -of a variable, and @var{value} is its long variable name. -The @var{key} field is at most 8 bytes long and must match the -name of a variable which appears in the variable record (@pxref{Variable -Record}). -The @var{value} field is at most 64 bytes long. -The @var{key} and @var{value} fields are separated by a @samp{=} byte. -Each tuple is separated by a byte whose value is 09. There is no -trailing separator following the last tuple. -The total length is @code{count} bytes. -@end table - -@node Very Long String Record -@section Very Long String Record - -Old versions of SPSS limited string variables to a width of 255 bytes. -For backward compatibility with these older versions, the system file -format represents a string longer than 255 bytes, called a @dfn{very -long string}, as a collection of strings no longer than 255 bytes -each. The strings concatenated to make a very long string are called -its @dfn{segments}; for consistency, variables other than very long -strings are considered to have a single segment. - -A very long string with a width of @var{w} has @var{n} = -(@var{w} + 251) / 252 segments, that is, one segment for every -252 bytes of width, rounding up. It would be logical, then, for each -of the segments except the last to have a width of 252 and the last -segment to have the remainder, but this is not the case. In fact, -each segment except the last has a width of 255 bytes. The last -segment has width @var{w} - (@var{n} - 1) * 252; some versions -of SPSS make it slightly wider, but not wide enough to make the last -segment require another 8 bytes of data. - -Data is packed tightly into segments of a very long string, 255 bytes -per segment. Because 255 bytes of segment data are allocated for -every 252 bytes of the very long string's width (approximately), some -unused space is left over at the end of the allocated segments. Data -in unused space is ignored. - -Example: Consider a very long string of width 20,000. Such a very -long string has 20,000 / 252 = 80 (rounding up) segments. The first -79 segments have width 255; the last segment has width 20,000 - 79 * -252 = 92 or slightly wider (up to 96 bytes, the next multiple of 8). -The very long string's data is actually stored in the 19,890 bytes in -the first 78 segments, plus the first 110 bytes of the 79th segment -(19,890 + 110 = 20,000). The remaining 145 bytes of the 79th segment -and all 92 bytes of the 80th segment are unused. - -The very long string record explains how to stitch together segments -to obtain very long string data. For each of the very long string -variables in the dictionary, it specifies the name of its first -segment's variable and the very long string variable's actual width. -The remaining segments immediately follow the named variable in the -system file's dictionary. - -The very long string record, which is present only if the system file -contains very long string variables, has the following format: - -@example -/* @r{Header.} */ -int32 rec_type; -int32 subtype; -int32 size; -int32 count; - -/* @r{Exactly @code{count} bytes of data.} */ -char string_lengths[]; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 7. - -@item int32 subtype; -Record subtype. Always set to 14. - -@item int32 size; -The size of each element in the @code{string_lengths} member. Always set to 1. - -@item int32 count; -The total number of bytes in @code{string_lengths}. - -@item char string_lengths[]; -A list of @var{key}--@var{value} tuples, where @var{key} is the name -of a variable, and @var{value} is its length. -The @var{key} field is at most 8 bytes long and must match the -name of a variable which appears in the variable record (@pxref{Variable -Record}). -The @var{value} field is exactly 5 bytes long. It is a zero-padded, -ASCII-encoded string that is the length of the variable. -The @var{key} and @var{value} fields are separated by a @samp{=} byte. -Tuples are delimited by a two-byte sequence @{00, 09@}. -After the last tuple, there may be a single byte 00, or @{00, 09@}. -The total length is @code{count} bytes. -@end table - -@node Miscellaneous Informational Records -@section Miscellaneous Informational Records - -Some specific types of miscellaneous informational records are -documented here, but others are known to exist. PSPP ignores unknown -miscellaneous informational records when reading system files. - -@example -/* @r{Header.} */ -int32 rec_type; -int32 subtype; -int32 size; -int32 count; - -/* @r{Exactly @code{size * count} bytes of data.} */ -char data[]; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 7. - -@item int32 subtype; -Record subtype. May take any value. According to Aapi -H@"am@"al@"ainen, value 5 indicates a set of grouped variables and 6 -indicates date info (probably related to USE). - -@item int32 size; -Size of each piece of data in the data part. Should have the value 1, -4, or 8, for @code{char}, @code{int32}, and @code{flt64} format data, -respectively. - -@item int32 count; -Number of pieces of data in the data part. - -@item char data[]; -Arbitrary data. There must be @code{size} times @code{count} bytes of -data. -@end table - -@node Dictionary Termination Record -@section Dictionary Termination Record - -The dictionary termination record separates all other records from the -data records. - -@example -int32 rec_type; -int32 filler; -@end example - -@table @code -@item int32 rec_type; -Record type. Always set to 999. - -@item int32 filler; -Ignored padding. Should be set to 0. -@end table - -@node Data Record -@section Data Record - -Data records must follow all other records in the system file. There must -be at least one data record in every system file. - -The format of data records varies depending on whether the data is -compressed. Regardless, the data is arranged in a series of 8-byte -elements. - -When data is not compressed, -each element corresponds to -the variable declared in the respective variable record (@pxref{Variable -Record}). Numeric values are given in @code{flt64} format; string -values are literal characters string, padded on the right when -necessary to fill out 8-byte units. - -Compressed data is arranged in the following manner: the first 8 bytes -in the data section is divided into a series of 1-byte command -codes. These codes have meanings as described below: - -@table @asis -@item 0 -Ignored. If the program writing the system file accumulates compressed -data in blocks of fixed length, 0 bytes can be used to pad out extra -bytes remaining at the end of a fixed-size block. - -@item 1 through 251 -A number with -value @var{code} - @var{bias}, where -@var{code} is the value of the compression code and @var{bias} is the -variable @code{bias} from the file header. For example, -code 105 with bias 100.0 (the normal value) indicates a numeric variable -of value 5. - -@item 252 -End of file. This code may or may not appear at the end of the data -stream. PSPP always outputs this code but its use is not required. - -@item 253 -A numeric or string value that is not -compressible. The value is stored in the 8 bytes following the -current block of command bytes. If this value appears twice in a block -of command bytes, then it indicates the second group of 8 bytes following the -command bytes, and so on. - -@item 254 -An 8-byte string value that is all spaces. - -@item 255 -The system-missing value. -@end table - -When the end of the an 8-byte group of command bytes is reached, any -blocks of non-compressible values indicated by code 253 are skipped, -and the next element of command bytes is read and interpreted, until -the end of the file or a code with value 252 is reached. -@setfilename ignored diff --git a/doc/dev/concepts.texi b/doc/dev/concepts.texi new file mode 100644 index 00000000..b1d8583b --- /dev/null +++ b/doc/dev/concepts.texi @@ -0,0 +1,2451 @@ +@node Basic Concepts +@chapter Basic Concepts + +This chapter introduces basic data structures and other concepts +needed for developing in PSPP. + +@menu +* Values:: +* Input and Output Formats:: +* User-Missing Values:: +* Value Labels:: +* Variables:: +* Dictionaries:: +* Coding Conventions:: +* Cases:: +* Data Sets:: +* Pools:: +@end menu + +@node Values +@section Values + +@cindex value +The unit of data in PSPP is a @dfn{value}. + +@cindex width +@cindex string value +@cindex numeric value +@cindex MAX_STRING +Values are classified by @dfn{type} and @dfn{width}. The +type of a value is either @dfn{numeric} or @dfn{string} (sometimes +called alphanumeric). The width of a string value ranges from 1 to +@code{MAX_STRING} bytes. The width of a numeric value is artificially +defined to be 0; thus, the type of a value can be inferred from its +width. + +Some support is provided for working with value types and widths, in +@file{data/val-type.h}: + +@deftypefn Macro int MAX_STRING +Maximum width of a string value, in bytes, currently 32,767. +@end deftypefn + +@deftypefun bool val_type_is_valid (enum val_type @var{val_type}) +Returns true if @var{val_type} is a valid value type, that is, +either @code{VAL_NUMERIC} or @code{VAL_STRING}. Useful for +assertions. +@end deftypefun + +@deftypefun {enum val_type} val_type_from_width (int @var{width}) +Returns @code{VAL_NUMERIC} if @var{width} is 0 and thus represents the +width of a numeric value, otherwise @code{VAL_STRING} to indicate that +@var{width} is the width of a string value. +@end deftypefun + +The following subsections describe how values of each type are +represented. + +@menu +* Numeric Values:: +* String Values:: +* Runtime Typed Values:: +@end menu + +@node Numeric Values +@subsection Numeric Values + +A value known to be numeric at compile time is represented as a +@code{double}. PSPP provides three values of @code{double} for +special purposes, defined in @file{data/val-type.h}: + +@deftypefn Macro double SYSMIS +The @dfn{system-missing value}, used to represent a datum whose true +value is unknown, such as a survey question that was not answered by +the respondent, or undefined, such as the result of division by zero. +PSPP propagates the system-missing value through calculations and +compensates for missing values in statistical analyses. @xref{Missing +Observations,,,pspp, PSPP Users Guide}, for a PSPP user's view of +missing values. + +PSPP currently defines @code{SYSMIS} as @code{-DBL_MAX}, that is, the +greatest finite negative value of @code{double}. It is best not to +depend on this definition, because PSPP may transition to using an +IEEE NaN (not a number) instead at some point in the future. +@end deftypefn + +@deftypefn Macro double LOWEST +@deftypefnx Macro double HIGHEST +The greatest finite negative (except for @code{SYSMIS}) and positive +values of @code{double}, respectively. These values do not ordinarily +appear in user data files. Instead, they are used to implement +endpoints of open-ended ranges that are occasionally permitted in PSPP +syntax, e.g.@: @code{5 THRU HI} as a range of missing values +(@pxref{MISSING VALUES,,,pspp, PSPP Users Guide}). +@end deftypefn + +@node String Values +@subsection String Values + +A value known at compile time to have string type is represented as an +array of @code{char}. String values do not necessarily represent +readable text strings and may contain arbitrary 8-bit data, including +null bytes, control codes, and bytes with the high bit set. Thus, +string values are not null-terminated strings, but rather opaque +arrays of bytes. + +@code{SYSMIS}, @code{LOWEST}, and @code{HIGHEST} have no equivalents +as string values. Usually, PSPP fills an unknown or undefined string +values with spaces, but PSPP does not treat such a string as a special +case when it processes it later. + +@cindex MAX_STRING +@code{MAX_STRING}, the maximum length of a string value, is defined in +@file{data/val-type.h}. + +@node Runtime Typed Values +@subsection Runtime Typed Values + +When a value's type is only known at runtime, it is often represented +as a @union{value}, defined in @file{data/value.h}. @union{value} has +two members: a @code{double} named @samp{f} to store a numeric value +and an array of @code{char} named @samp{s} to a store a string value. +A @union{value} does not identify the type or width of the data it +contains. Code that works with @union{values}s must therefore have +external knowledge of its content, often through the type and width of +a @struct{variable} (@pxref{Variables}). + +@cindex MAX_SHORT_STRING +@cindex short string +@cindex long string +@cindex string value +The array of @code{char} in @union{value} has only a small, fixed +capacity of @code{MAX_SHORT_STRING} bytes. A value that +fits within this capacity is called a @dfn{short string}. Any wider +string value, which must be represented by more than one +@union{value}, is called a @dfn{long string}. + +@deftypefn Macro int MAX_SHORT_STRING +Maximum width of a short string value, never less than 8 bytes. It is +wider than 8 bytes on systems where @code{double} is either larger +than 8 bytes or has stricter alignment than 8 bytes. +@end deftypefn + +@deftypefn Macro int MIN_LONG_STRING +Minimum width of a long string value, that is, @code{MAX_SHORT_STRING ++ 1}. +@end deftypefn + +Long string variables are slightly harder to work with than short +string values, because they cannot be conveniently and efficiently +allocated as block scope variables or structure members. The PSPP +language exposes this inconvenience to the user: there are many +circumstances in PSPP syntax where short strings are allowed but not +long strings. Short string variables, for example, may have +user-missing values, but long string variables may not (@pxref{Missing +Observations,,,pspp, PSPP Users Guide}). + +PSPP provides a few functions for working with @union{value}s. The +most useful are described below. To use these functions, recall that +a numeric value has a width of 0. + +@deftypefun size_t value_cnt_from_width (int @var{width}) +Returns the number of consecutive @union{value}s that must be +allocated to store a value of the given @var{width}. For a numeric or +short string value, the return value is 1; for long string +variables, it is greater than 1. +@end deftypefun + +@deftypefun void value_copy (union value *@var{dst}, @ + const union value *@var{src}, @ + int @var{width}) +Copies a value of the given @var{width} from the @union{value} array +starting at @var{src} to the one starting at @var{dst}. The two +arrays must not overlap. +@end deftypefun + +@deftypefun void value_set_missing (union value *@var{value}, int @var{width}) +Sets @var{value} to @code{SYSMIS} if it is numeric or to all spaces if +it is alphanumeric, according to @var{width}. @var{value} must point +to the start of a @union{value} array of the given @var{width}. +@end deftypefun + +@anchor{value_is_resizable} +@deftypefun bool value_is_resizable (const union value *@var{value}, int @var{old_width}, int @var{new_width}) +Determines whether @var{value} may be resized from @var{old_width} to +@var{new_width}. Resizing is possible if the following criteria are +met. First, @var{old_width} and @var{new_width} must be both numeric +or both string widths. Second, if @var{new_width} is a short string +width and less than @var{old_width}, resizing is allowed only if bytes +@var{new_width} through @var{old_width} in @var{value} contain only +spaces. + +These rules are part of those used by @func{mv_is_resizable} and +@func{val_labs_can_set_width}. +@end deftypefun + +@deftypefun void value_resize (union value *@var{value}, int @var{old_width}, int @var{new_width}) +Resizes @var{value} from @var{old_width} to @var{new_width}, which +must be allowed by the rules stated above. This has an effect only if +@var{new_width} is greater than @var{old_width}, in which case the +bytes newly added to @var{value} are cleared to spaces. +@end deftypefun + +@node Input and Output Formats +@section Input and Output Formats + +Input and output formats specify how to convert data fields to and +from data values (@pxref{Input and Output Formats,,,pspp, PSPP Users +Guide}). PSPP uses @struct{fmt_spec} to represent input and output +formats. + +Function prototypes and other declarations related to formats are in +the @file{} 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{} 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{} 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 } as its +first non-comment line. No @file{.h} file should include +@file{config.h}. + +This section needs to be finished. + +@node Cases +@section Cases + +This section needs to be written. + +@node Data Sets +@section Data Sets + +This section needs to be written. + +@node Pools +@section Pools + +This section needs to be written. + +@c LocalWords: bool diff --git a/doc/dev/data.texi b/doc/dev/data.texi new file mode 100644 index 00000000..356b5e03 --- /dev/null +++ b/doc/dev/data.texi @@ -0,0 +1,47 @@ +@node Processing Data +@chapter Processing Data + +Developer's Guide + +Proposed outline: + +@example +* Introduction +* Basic concepts +** Data sets +** Variables +** Dictionaries +** Coding conventions +** Pools +* Syntax parsing +* Data processing +** Reading data +*** Casereaders generalities +*** Casereaders from data files +*** Casereaders from the active file +*** Other casereaders +** Writing data +*** Casewriters generally +*** Casewriters to data files +*** Modifying the active file +**** Modifying cases obtained from active file casereaders has no real effect +**** Transformations; procedures that transform +** Transforming data +*** Sorting and merging +*** Filtering +*** Grouping +**** Ordering and interaction of filtering and grouping +*** Multiple passes over data +*** Counting cases and case weights +** Best practices +*** Multiple passes with filters versus single pass with loops +*** Sequential versus random access +*** Managing memory +*** Passing cases around +*** Renaming casereaders +*** Avoiding excessive buffering +*** Propagating errors +*** Avoid static/global data +*** Don't worry about null filters, groups, etc. +*** Be aware of reference counting semantics for cases +@end example diff --git a/doc/dev/intro.texi b/doc/dev/intro.texi new file mode 100644 index 00000000..15587451 --- /dev/null +++ b/doc/dev/intro.texi @@ -0,0 +1,22 @@ +@node Introduction +@chapter Introduction + +This manual is a guide to PSPP internals. Its intended audience is +developers who wish to modify or extend PSPP's capabilities. The use +of PSPP is documented in a separate manual. @xref{Top, , +Introduction, pspp, PSPP Users Guide}. + +This manual is both a tutorial and a reference manual for PSPP +developers. It is ultimately intended to cover everything that +developers who wish to implement new PSPP statistical procedures and +other commands should know. It is currently incomplete, partly +because existing developers have not yet spent enough time on writing, +and partly because the interfaces not yet documented are not yet +mature enough to making documenting them worthwhile. + +PSPP developers should have some familiarity with the basics of PSPP +from a user's perspective. This manual attempts to refer to the PSPP +user manual's descriptions of concepts that PSPP users should find +familiar at the time of their first reference. However, it is +probably a good idea to at least skim the PSPP manual before reading +this one, if you are not already familiar with PSPP. diff --git a/doc/dev/output.texi b/doc/dev/output.texi new file mode 100644 index 00000000..6fb8b608 --- /dev/null +++ b/doc/dev/output.texi @@ -0,0 +1,2 @@ +@node Presenting Output +@chapter Presenting Output diff --git a/doc/dev/portable-file-format.texi b/doc/dev/portable-file-format.texi new file mode 100644 index 00000000..31c1ac3a --- /dev/null +++ b/doc/dev/portable-file-format.texi @@ -0,0 +1,479 @@ +@node Portable File Format +@appendix Portable File Format + +These days, most computers use the same internal data formats for +integer and floating-point data, if one ignores little differences like +big- versus little-endian byte ordering. However, occasionally it is +necessary to exchange data between systems with incompatible data +formats. This is what portable files are designed to do. + +@strong{Please note:} This information is gleaned from examination of +ASCII-formatted portable files only, so some of it may be incorrect +for portable files formatted in EBCDIC or other character sets. + +@menu +* Portable File Characters:: +* Portable File Structure:: +* Portable File Header:: +* Version and Date Info Record:: +* Identification Records:: +* Variable Count Record:: +* Case Weight Variable Record:: +* Variable Records:: +* Value Label Records:: +* Portable File Document Record:: +* Portable File Data:: +@end menu + +@node Portable File Characters +@section Portable File Characters + +Portable files are arranged as a series of lines of 80 +characters each. Each line is terminated by a carriage-return, +line-feed sequence (``new-lines''). New-lines are only used to avoid +line length limits imposed by some OSes; they are not meaningful. + +Most lines in portable files are exactly 80 characters long. The only +exception is a line that ends in one or more spaces, in which the +spaces may optionally be omitted. Thus, a portable file reader must +act as though a line shorter than 80 characters is padded to that +length with spaces. + +The file must be terminated with a @samp{Z} character. In addition, if +the final line in the file does not have exactly 80 characters, then it +is padded on the right with @samp{Z} characters. (The file contents may +be in any character set; the file contains a description of its own +character set, as explained in the next section. Therefore, the +@samp{Z} character is not necessarily an ASCII @samp{Z}.) + +For the rest of the description of the portable file format, new-lines +and the trailing @samp{Z}s will be ignored, as if they did not exist, +because they are not an important part of understanding the file +contents. + +@node Portable File Structure +@section Portable File Structure + +Every portable file consists of the following records, in sequence: + +@itemize @bullet + +@item +File header. + +@item +Version and date info. + +@item +Product identification. + +@item +Author identification (optional). + +@item +Subproduct identification (optional). + +@item +Variable count. + +@item +Case weight variable (optional). + +@item +Variables. Each variable record may optionally be followed by a +missing value record and a variable label record. + +@item +Value labels (optional). + +@item +Documents (optional). + +@item +Data. +@end itemize + +Most records are identified by a single-character tag code. The file +header and version info record do not have a tag. + +Other than these single-character codes, there are three types of fields +in a portable file: floating-point, integer, and string. Floating-point +fields have the following format: + +@itemize @bullet + +@item +Zero or more leading spaces. + +@item +Optional asterisk (@samp{*}), which indicates a missing value. The +asterisk must be followed by a single character, generally a period +(@samp{.}), but it appears that other characters may also be possible. +This completes the specification of a missing value. + +@item +Optional minus sign (@samp{-}) to indicate a negative number. + +@item +A whole number, consisting of one or more base-30 digits: @samp{0} +through @samp{9} plus capital letters @samp{A} through @samp{T}. + +@item +Optional fraction, consisting of a radix point (@samp{.}) followed by +one or more base-30 digits. + +@item +Optional exponent, consisting of a plus or minus sign (@samp{+} or +@samp{-}) followed by one or more base-30 digits. + +@item +A forward slash (@samp{/}). +@end itemize + +Integer fields take a form identical to floating-point fields, but they +may not contain a fraction. + +String fields take the form of a integer field having value @var{n}, +followed by exactly @var{n} characters, which are the string content. + +@node Portable File Header +@section Portable File Header + +Every portable file begins with a 464-byte header, consisting of a +200-byte collection of vanity splash strings, followed by a 256-byte +character set translation table, followed by an 8-byte tag string. + +The 200-byte segment is divided into five 40-byte sections, each of +which represents the string @code{@var{charset} SPSS PORT FILE} in a +different character set encoding, where @var{charset} is the name of +the character set used in the file, e.g.@: @code{ASCII} or +@code{EBCDIC}. Each string is padded on the right with spaces in its +respective character set. + +It appears that these strings exist only to inform those who might view +the file on a screen, and that they are not parsed by SPSS products. +Thus, they can be safely ignored. For those interested, the strings are +supposed to be in the following character sets, in the specified order: +EBCDIC, 7-bit ASCII, CDC 6-bit ASCII, 6-bit ASCII, Honeywell 6-bit +ASCII. + +The 256-byte segment describes a mapping from the character set used in +the portable file to an arbitrary character set having characters at the +following positions: + +@table @asis +@item 0--60 + +Control characters. Not important enough to describe in full here. + +@item 61--63 + +Reserved. + +@item 64--73 + +Digits @samp{0} through @samp{9}. + +@item 74--99 + +Capital letters @samp{A} through @samp{Z}. + +@item 100--125 + +Lowercase letters @samp{a} through @samp{z}. + +@item 126 + +Space. + +@item 127--130 + +Symbols @code{.<(+} + +@item 131 + +Solid vertical pipe. + +@item 132--142 + +Symbols @code{&[]!$*);^-/} + +@item 143 + +Broken vertical pipe. + +@item 144--150 + +Symbols @code{,%_>}?@code{`:} @c @code{?} is an inverted question mark + +@item 151 + +British pound symbol. + +@item 152--155 + +Symbols @code{@@'="}. + +@item 156 + +Less than or equal symbol. + +@item 157 + +Empty box. + +@item 158 + +Plus or minus. + +@item 159 + +Filled box. + +@item 160 + +Degree symbol. + +@item 161 + +Dagger. + +@item 162 + +Symbol @samp{~}. + +@item 163 + +En dash. + +@item 164 + +Lower left corner box draw. + +@item 165 + +Upper left corner box draw. + +@item 166 + +Greater than or equal symbol. + +@item 167--176 + +Superscript @samp{0} through @samp{9}. + +@item 177 + +Lower right corner box draw. + +@item 178 + +Upper right corner box draw. + +@item 179 + +Not equal symbol. + +@item 180 + +Em dash. + +@item 181 + +Superscript @samp{(}. + +@item 182 + +Superscript @samp{)}. + +@item 183 + +Horizontal dagger (?). + +@item 184--186 + +Symbols @samp{@{@}\}. +@item 187 + +Cents symbol. + +@item 188 + +Centered dot, or bullet. + +@item 189--255 + +Reserved. +@end table + +Symbols that are not defined in a particular character set are set to +the same value as symbol 64; i.e., to @samp{0}. + +The 8-byte tag string consists of the exact characters @code{SPSSPORT} +in the portable file's character set, which can be used to verify that +the file is indeed a portable file. + +@node Version and Date Info Record +@section Version and Date Info Record + +This record does not have a tag code. It has the following structure: + +@itemize @bullet +@item +A single character identifying the file format version. The letter A +represents version 0, and so on. + +@item +An 8-character string field giving the file creation date in the format +YYYYMMDD. + +@item +A 6-character string field giving the file creation time in the format +HHMMSS. +@end itemize + +@node Identification Records +@section Identification Records + +The product identification record has tag code @samp{1}. It consists of +a single string field giving the name of the product that wrote the +portable file. + +The author identification record has tag code @samp{2}. It is +optional. If present, it consists of a single string field giving the +name of the person who caused the portable file to be written. + +The subproduct identification record has tag code @samp{3}. It is +optional. If present, it consists of a single string field giving +additional information on the product that wrote the portable file. + +@node Variable Count Record +@section Variable Count Record + +The variable count record has tag code @samp{4}. It consists of two +integer fields. The first contains the number of variables in the file +dictionary. The purpose of the second is unknown; it contains the value +161 in all portable files examined so far. + +@node Case Weight Variable Record +@section Case Weight Variable Record + +The case weight variable record is optional. If it is present, it +indicates the variable used for weighting cases; if it is absent, +cases are unweighted. It has tag code @samp{6}. It consists of a +single string field that names the weighting variable. + +@node Variable Records +@section Variable Records + +Each variable record represents a single variable. Variable records +have tag code @samp{7}. They have the following structure: + +@itemize @bullet + +@item +Width (integer). This is 0 for a numeric variable, and a number between 1 +and 255 for a string variable. + +@item +Name (string). 1--8 characters long. Must be in all capitals. + +A few portable files that contain duplicate variable names have been +spotted in the wild. PSPP handles these by renaming the duplicates +with numeric extensions: @code{@var{var}_1}, @code{@var{var}_2}, and +so on. + +@item +Print format. This is a set of three integer fields: + +@itemize @minus + +@item +Format type (@pxref{Variable Record}). + +@item +Format width. 1--40. + +@item +Number of decimal places. 1--40. +@end itemize + +A few portable files with invalid format types or formats that are not +of the appropriate width for their variables have been spotted in the +wild. PSPP assigns a default F or A format to a variable with an +invalid format. + +@item +Write format. Same structure as the print format described above. +@end itemize + +Each variable record can optionally be followed by a missing value +record, which has tag code @samp{8}. A missing value record has one +field, the missing value itself (a floating-point or string, as +appropriate). Up to three of these missing value records can be used. + +There is also a record for missing value ranges, which has tag code +@samp{B}. It is followed by two fields representing the range, which +are floating-point or string as appropriate. If a missing value range +is present, it may be followed by a single missing value record. + +Tag codes @samp{9} and @samp{A} represent @code{LO THRU @var{x}} and +@code{@var{x} THRU HI} ranges, respectively. Each is followed by a +single field representing @var{x}. If one of the ranges is present, it +may be followed by a single missing value record. + +In addition, each variable record can optionally be followed by a +variable label record, which has tag code @samp{C}. A variable label +record has one field, the variable label itself (string). + +@node Value Label Records +@section Value Label Records + +Value label records have tag code @samp{D}. They have the following +format: + +@itemize @bullet +@item +Variable count (integer). + +@item +List of variables (strings). The variable count specifies the number in +the list. Variables are specified by their names. All variables must +be of the same type (numeric or string), but string variables do not +necessarily have the same width. + +@item +Label count (integer). + +@item +List of (value, label) tuples. The label count specifies the number of +tuples. Each tuple consists of a value, which is numeric or string as +appropriate to the variables, followed by a label (string). +@end itemize + +A few portable files that specify duplicate value labels, that is, two +different labels for a single value of a single variable, have been +spotted in the wild. PSPP uses the last value label specified in +these cases. + +@node Portable File Document Record +@section Document Record + +One document record may optionally follow the value label record. The +document record consists of tag code @samp{E}, following by the number +of document lines as an integer, followed by that number of strings, +each of which represents one document line. Document lines must be 80 +bytes long or shorter. + +@node Portable File Data +@section Portable File Data + +The data record has tag code @samp{F}. There is only one tag for all +the data; thus, all the data must follow the dictionary. The data is +terminated by the end-of-file marker @samp{Z}, which is not valid as the +beginning of a data element. + +Data elements are output in the same order as the variable records +describing them. String variables are output as string fields, and +numeric variables are output as floating-point fields. +@setfilename ignored diff --git a/doc/dev/q2c.texi b/doc/dev/q2c.texi new file mode 100644 index 00000000..af6b1da9 --- /dev/null +++ b/doc/dev/q2c.texi @@ -0,0 +1,300 @@ +@node q2c Input Format +@appendix @code{q2c} Input Format + +PSPP statistical procedures have a bizarre and somewhat irregular +syntax. Despite this, a parser generator has been written that +adequately addresses many of the possibilities and tries to provide +hooks for the exceptional cases. This parser generator is named +@code{q2c}. + +@menu +* Invoking q2c:: q2c command-line syntax. +* q2c Input Structure:: High-level layout of the input file. +* Grammar Rules:: Syntax of the grammar rules. +@end menu + +@node Invoking q2c +@section Invoking q2c + +@example +q2c @var{input.q} @var{output.c} +@end example + +@code{q2c} translates a @samp{.q} file into a @samp{.c} file. It takes +exactly two command-line arguments, which are the input file name and +output file name, respectively. @code{q2c} does not accept any +command-line options. + +@node q2c Input Structure +@section @code{q2c} Input Structure + +@code{q2c} input files are divided into two sections: the grammar rules +and the supporting code. The @dfn{grammar rules}, which make up the +first part of the input, are used to define the syntax of the +statistical procedure to be parsed. The @dfn{supporting code}, +following the grammar rules, are copied largely unchanged to the output +file, except for certain escapes. + +The most important lines in the grammar rules are used for defining +procedure syntax. These lines can be prefixed with a dollar sign +(@samp{$}), which prevents Emacs' CC-mode from munging them. Besides +this, a bang (@samp{!}) at the beginning of a line causes the line, +minus the bang, to be written verbatim to the output file (useful for +comments). As a third special case, any line that begins with the exact +characters @code{/* *INDENT} is ignored and not written to the output. +This allows @code{.q} files to be processed through @code{indent} +without being munged. + +The syntax of the grammar rules themselves is given in the following +sections. + +The supporting code is passed into the output file largely unchanged. +However, the following escapes are supported. Each escape must appear +on a line by itself. + +@table @code +@item /* (header) */ + +Expands to a series of C @code{#include} directives which include the +headers that are required for the parser generated by @code{q2c}. + +@item /* (decls @var{scope}) */ + +Expands to C variable and data type declarations for the variables and +@code{enum}s input and output by the @code{q2c} parser. @var{scope} +must be either @code{local} or @code{global}. @code{local} causes the +declarations to be output as function locals. @code{global} causes them +to be declared as @code{static} module variables; thus, @code{global} is +a bit of a misnomer. + +@item /* (parser) */ + +Expands to the entire parser. Must be enclosed within a C function. + +@item /* (free) */ + +Expands to a set of calls to the @code{free} function for variables +declared by the parser. Only needs to be invoked if subcommands of type +@code{string} are used in the grammar rules. +@end table + +@node Grammar Rules +@section Grammar Rules + +The grammar rules describe the format of the syntax that the parser +generated by @code{q2c} will understand. The way that the grammar rules +are included in @code{q2c} input file are described above. + +The grammar rules are divided into tokens of the following types: + +@table @asis +@item Identifier (@code{ID}) + +An identifier token is a sequence of letters, digits, and underscores +(@samp{_}). Identifiers are @emph{not} case-sensitive. + +@item String (@code{STRING}) + +String tokens are initiated by a double-quote character (@samp{"}) and +consist of all the characters between that double quote and the next +double quote, which must be on the same line as the first. Within a +string, a backslash can be used as a ``literal escape''. The only +reasons to use a literal escape are to include a double quote or a +backslash within a string. + +@item Special character + +Other characters, other than white space, constitute tokens in +themselves. + +@end table + +The syntax of the grammar rules is as follows: + +@example +grammar-rules ::= command-name opt-prefix : subcommands . +command-name ::= ID + ::= STRING +opt-prefix ::= + ::= ( ID ) +subcommands ::= subcommand + ::= subcommands ; subcommand +@end example + +The syntax begins with an ID token that gives the name of the +procedure to be parsed. For command names that contain multiple +words, a STRING token may be used instead, e.g.@: @samp{"FILE +HANDLE"}. Optionally, an ID in parentheses specifies a prefix used +for all file-scope identifiers declared by the emitted code. + +The rest of the syntax consists of subcommands separated by semicolons +(@samp{;}) and terminated with a full stop (@samp{.}). + +@example +subcommand ::= default-opt arity-opt ID sbc-defn +default-opt ::= + ::= * +arity-opt ::= + ::= + + ::= ^ +sbc-defn ::= opt-prefix = specifiers + ::= [ ID ] = array-sbc + ::= opt-prefix = sbc-special-form +@end example + +A subcommand that begins with an asterisk (@samp{*}) is the default +subcommand. The keyword used for the default subcommand can be omitted +in the PSPP syntax file. + +A plus sign (@samp{+}) indicates that a subcommand can appear more than +once. A caret (@samp{^}) indicate that a subcommand must appear exactly +once. A subcommand marked with neither character may appear once or not +at all, but not more than once. + +The subcommand name appears after the leading option characters. + +There are three forms of subcommands. The first and most common form +simply gives an equals sign (@samp{=}) and a list of specifiers, which +can each be set to a single setting. The second form declares an array, +which is a set of flags that can be individually turned on by the user. +There are also several special forms that do not take a list of +specifiers. + +Arrays require an additional @code{ID} argument. This is used as a +prefix, prepended to the variable names constructed from the +specifiers. The other forms also allow an optional prefix to be +specified. + +@example +array-sbc ::= alternatives + ::= array-sbc , alternatives +alternatives ::= ID + ::= alternatives | ID +@end example + +An array subcommand is a set of Boolean values that can independently be +turned on by the user, listed separated by commas (@samp{,}). If an value has more +than one name then these names are separated by pipes (@samp{|}). + +@example +specifiers ::= specifier + ::= specifiers , specifier +specifier ::= opt-id : settings +opt-id ::= + ::= ID +@end example + +Ordinary subcommands (other than arrays and special forms) require a +list of specifiers. Each specifier has an optional name and a list of +settings. If the name is given then a correspondingly named variable +will be used to store the user's choice of setting. If no name is given +then there is no way to tell which setting the user picked; in this case +the settings should probably have values attached. + +@example +settings ::= setting + ::= settings / setting +setting ::= setting-options ID setting-value +setting-options ::= + ::= * + ::= ! + ::= * ! +@end example + +Individual settings are separated by forward slashes (@samp{/}). Each +setting can be as little as an @code{ID} token, but options and values +can optionally be included. The @samp{*} option means that, for this +setting, the @code{ID} can be omitted. The @samp{!} option means that +this option is the default for its specifier. + +@example +setting-value ::= + ::= ( setting-value-2 ) + ::= setting-value-2 +setting-value-2 ::= setting-value-options setting-value-type : ID + setting-value-restriction +setting-value-options ::= + ::= * +setting-value-type ::= N + ::= D + ::= S +setting-value-restriction ::= + ::= , STRING +@end example + +Settings may have values. If the value must be enclosed in parentheses, +then enclose the value declaration in parentheses. Declare the setting +type as @samp{n}, @samp{d}, or @samp{s} for integer, floating-point, +or string type, respectively. The given @code{ID} is used to +construct a variable name. +If option @samp{*} is given, then the value is optional; otherwise it +must be specified whenever the corresponding setting is specified. A +``restriction'' can also be specified which is a string giving a C +expression limiting the valid range of the value. The special escape +@code{%s} should be used within the restriction to refer to the +setting's value variable. + +@example +sbc-special-form ::= VAR + ::= VARLIST varlist-options + ::= INTEGER opt-list + ::= DOUBLE opt-list + ::= PINT + ::= STRING @r{(the literal word STRING)} string-options + ::= CUSTOM +varlist-options ::= + ::= ( STRING ) +opt-list ::= + ::= LIST +string-options ::= + ::= ( STRING STRING ) +@end example + +The special forms are of the following types: + +@table @code +@item VAR + +A single variable name. + +@item VARLIST + +A list of variables. If given, the string can be used to provide +@code{PV_@var{*}} options to the call to @code{parse_variables}. + +@item INTEGER + +A single integer value. + +@item INTEGER LIST + +A list of integers separated by spaces or commas. + +@item DOUBLE + +A single floating-point value. + +@item DOUBLE LIST + +A list of floating-point values. + +@item PINT + +A single positive integer value. + +@item STRING + +A string value. If the options are given then the first string is an +expression giving a restriction on the value of the string; the second +string is an error message to display when the restriction is violated. + +@item CUSTOM + +A custom function is used to parse this subcommand. The function must +have prototype @code{int custom_@var{name} (void)}. It should return 0 +on failure (when it has already issued an appropriate diagnostic), 1 on +success, or 2 if it fails and the calling function should issue a syntax +error on behalf of the custom handler. + +@end table +@setfilename ignored diff --git a/doc/dev/syntax.texi b/doc/dev/syntax.texi new file mode 100644 index 00000000..81d34c0f --- /dev/null +++ b/doc/dev/syntax.texi @@ -0,0 +1,2 @@ +@node Parsing Command Syntax +@chapter Parsing Command Syntax diff --git a/doc/dev/system-file-format.texi b/doc/dev/system-file-format.texi new file mode 100644 index 00000000..193c6601 --- /dev/null +++ b/doc/dev/system-file-format.texi @@ -0,0 +1,906 @@ +@node System File Format +@appendix System File Format + +A system file encapsulates a set of cases and dictionary information +that describes how they may be interpreted. This chapter describes +the format of a system file. + +System files use three data types: 8-bit characters, 32-bit integers, +and 64-bit floating points, called here @code{char}, @code{int32}, and +@code{flt64}, respectively. Data is not necessarily aligned on a word +or double-word boundary: the long variable name record (@pxref{Long +Variable Names Record}) and very long string records (@pxref{Very Long +String Record}) have arbitrary byte length and can therefore cause all +data coming after them in the file to be misaligned. + +Integer data in system files may be big-endian or little-endian. A +reader may detect the endianness of a system file by examining +@code{layout_code} in the file header record +(@pxref{layout_code,,@code{layout_code}}). + +Floating-point data in system files may nominally be in IEEE 754, IBM, +or VAX formats. A reader may detect the floating-point format in use +by examining @code{bias} in the file header record +(@pxref{bias,,@code{bias}}). + +PSPP detects big-endian and little-endian integer formats in system +files and translates as necessary. PSPP also detects the +floating-point format in use, as well as the endianness of IEEE 754 +floating-point numbers, and translates as needed. However, only IEEE +754 numbers with the same endianness as integer data in the same file +has actually been observed in system files, and it is likely that +other formats are obsolete or were never used. + +The PSPP system-missing value is represented by the largest possible +negative number in the floating point format (@code{-DBL_MAX}). Two +other values are important for use as missing values: @code{HIGHEST}, +represented by the largest possible positive number (@code{DBL_MAX}), +and @code{LOWEST}, represented by the second-largest negative number +(in IEEE 754 format, @code{0xffeffffffffffffe}). + +System files are divided into records, each of which begins with a +4-byte record type, usually regarded as an @code{int32}. + +The records must appear in the following order: + +@itemize @bullet +@item +File header record. + +@item +Variable records. + +@item +All pairs of value labels records and value label variables records, +if present. + +@item +Document record, if present. + +@item +Any of the following records, if present, in any order: + +@itemize @minus +@item +Machine integer info record. + +@item +Machine floating-point info record. + +@item +Variable display parameter record. + +@item +Long variable names record. + +@item +Miscellaneous informational records. +@end itemize + +@item +Dictionary termination record. + +@item +Data record. +@end itemize + +Each type of record is described separately below. + +@menu +* File Header Record:: +* Variable Record:: +* Value Labels Records:: +* Document Record:: +* Machine Integer Info Record:: +* Machine Floating-Point Info Record:: +* Variable Display Parameter Record:: +* Long Variable Names Record:: +* Very Long String Record:: +* Miscellaneous Informational Records:: +* Dictionary Termination Record:: +* Data Record:: +@end menu + +@node File Header Record +@section File Header Record + +The file header is always the first record in the file. It has the +following format: + +@example +char rec_type[4]; +char prod_name[60]; +int32 layout_code; +int32 nominal_case_size; +int32 compressed; +int32 weight_index; +int32 ncases; +flt64 bias; +char creation_date[9]; +char creation_time[8]; +char file_label[64]; +char padding[3]; +@end example + +@table @code +@item char rec_type[4]; +Record type code, set to @samp{$FL2}. + +@item char prod_name[60]; +Product identification string. This always begins with the characters +@samp{@@(#) SPSS DATA FILE}. PSPP uses the remaining characters to +give its version and the operating system name; for example, @samp{GNU +pspp 0.1.4 - sparc-sun-solaris2.5.2}. The string is truncated if it +would be longer than 60 characters; otherwise it is padded on the right +with spaces. + +@anchor{layout_code} +@item int32 layout_code; +Normally set to 2, although a few system files have been spotted in +the wild with a value of 3 here. PSPP use this value to determine the +file's integer endianness (@pxref{System File Format}). + +@item int32 nominal_case_size; +Number of data elements per case. This is the number of variables, +except that long string variables add extra data elements (one for every +8 characters after the first 8). However, string variables do not +contribute to this value beyond the first 255 bytes. Further, system +files written by some systems set this value to -1. In general, it is +unsafe for systems reading system files to rely upon this value. + +@item int32 compressed; +Set to 1 if the data in the file is compressed, 0 otherwise. + +@item int32 weight_index; +If one of the variables in the data set is used as a weighting +variable, set to the dictionary index of that variable, plus 1 +(@pxref{Dictionary Index}). Otherwise, set to 0. + +@item int32 ncases; +Set to the number of cases in the file if it is known, or -1 otherwise. + +In the general case it is not possible to determine the number of cases +that will be output to a system file at the time that the header is +written. The way that this is dealt with is by writing the entire +system file, including the header, then seeking back to the beginning of +the file and writing just the @code{ncases} field. For `files' in which +this is not valid, the seek operation fails. In this case, +@code{ncases} remains -1. + +@anchor{bias} +@item flt64 bias; +Compression bias, ordinarily set to 100. Only integers between +@code{1 - bias} and @code{251 - bias} can be compressed. + +By assuming that its value is 100, PSPP uses @code{bias} to determine +the file's floating-point format and endianness (@pxref{System File +Format}). If the compression bias is not 100, PSPP cannot auto-detect +the floating-point format and assumes that it is IEEE 754 format with +the same endianness as the system file's integers, which is correct +for all known system files. + +@item char creation_date[9]; +Date of creation of the system file, in @samp{dd mmm yy} +format, with the month as standard English abbreviations, using an +initial capital letter and following with lowercase. If the date is not +available then this field is arbitrarily set to @samp{01 Jan 70}. + +@item char creation_time[8]; +Time of creation of the system file, in @samp{hh:mm:ss} +format and using 24-hour time. If the time is not available then this +field is arbitrarily set to @samp{00:00:00}. + +@item char file_label[64]; +File label declared by the user, if any (@pxref{FILE LABEL,,,pspp, +PSPP Users Guide}). Padded on the right with spaces. + +@item char padding[3]; +Ignored padding bytes to make the structure a multiple of 32 bits in +length. Set to zeros. +@end table + +@node Variable Record +@section Variable Record + +There must be one variable record for each numeric variable and each +string variable with width 8 bytes or less. String variables wider +than 8 bytes have one variable record for each 8 bytes, rounding up. +The first variable record for a long string specifies the variable's +correct dictionary information. Subsequent variable records for a +long string are filled with dummy information: a type of -1, no +variable label or missing values, print and write formats that are +ignored, and an empty string as name. A few system files have been +encountered that include a variable label on dummy variable records, +so readers should take care to parse dummy variable records in the +same way as other variable records. + +@anchor{Dictionary Index} +The @dfn{dictionary index} of a variable is its offset in the set of +variable records, including dummy variable records for long string +variables. The first variable record has a dictionary index of 0, the +second has a dictionary index of 1, and so on. + +The system file format does not directly support string variables +wider than 255 bytes. Such very long string variables are represented +by a number of narrower string variables. @xref{Very Long String +Record}, for details. + +@example +int32 rec_type; +int32 type; +int32 has_var_label; +int32 n_missing_values; +int32 print; +int32 write; +char name[8]; + +/* @r{Present only if @code{has_var_label} is 1.} */ +int32 label_len; +char label[]; + +/* @r{Present only if @code{n_missing_values} is nonzero}. */ +flt64 missing_values[]; +@end example + +@table @code +@item int32 rec_type; +Record type code. Always set to 2. + +@item int32 type; +Variable type code. Set to 0 for a numeric variable. For a short +string variable or the first part of a long string variable, this is set +to the width of the string. For the second and subsequent parts of a +long string variable, set to -1, and the remaining fields in the +structure are ignored. + +@item int32 has_var_label; +If this variable has a variable label, set to 1; otherwise, set to 0. + +@item int32 n_missing_values; +If the variable has no missing values, set to 0. If the variable has +one, two, or three discrete missing values, set to 1, 2, or 3, +respectively. If the variable has a range for missing variables, set to +-2; if the variable has a range for missing variables plus a single +discrete value, set to -3. + +@item int32 print; +Print format for this variable. See below. + +@item int32 write; +Write format for this variable. See below. + +@item char name[8]; +Variable name. The variable name must begin with a capital letter or +the at-sign (@samp{@@}). Subsequent characters may also be digits, octothorpes +(@samp{#}), dollar signs (@samp{$}), underscores (@samp{_}), or full +stops (@samp{.}). The variable name is padded on the right with spaces. + +@item int32 label_len; +This field is present only if @code{has_var_label} is set to 1. It is +set to the length, in characters, of the variable label, which must be a +number between 0 and 120. + +@item char label[]; +This field is present only if @code{has_var_label} is set to 1. It has +length @code{label_len}, rounded up to the nearest multiple of 32 bits. +The first @code{label_len} characters are the variable's variable label. + +@item flt64 missing_values[]; +This field is present only if @code{n_missing_values} is not 0. It has +the same number of elements as the absolute value of +@code{n_missing_values}. For discrete missing values, each element +represents one missing value. When a range is present, the first +element denotes the minimum value in the range, and the second element +denotes the maximum value in the range. When a range plus a value are +present, the third element denotes the additional discrete missing +value. HIGHEST and LOWEST are indicated as described in the chapter +introduction. +@end table + +The @code{print} and @code{write} members of sysfile_variable are output +formats coded into @code{int32} types. The least-significant byte +of the @code{int32} represents the number of decimal places, and the +next two bytes in order of increasing significance represent field width +and format type, respectively. The most-significant byte is not +used and should be set to zero. + +Format types are defined as follows: + +@quotation +@multitable {Value} {@code{DATETIME}} +@headitem Value +@tab Meaning +@item 0 +@tab Not used. +@item 1 +@tab @code{A} +@item 2 +@tab @code{AHEX} +@item 3 +@tab @code{COMMA} +@item 4 +@tab @code{DOLLAR} +@item 5 +@tab @code{F} +@item 6 +@tab @code{IB} +@item 7 +@tab @code{PIBHEX} +@item 8 +@tab @code{P} +@item 9 +@tab @code{PIB} +@item 10 +@tab @code{PK} +@item 11 +@tab @code{RB} +@item 12 +@tab @code{RBHEX} +@item 13 +@tab Not used. +@item 14 +@tab Not used. +@item 15 +@tab @code{Z} +@item 16 +@tab @code{N} +@item 17 +@tab @code{E} +@item 18 +@tab Not used. +@item 19 +@tab Not used. +@item 20 +@tab @code{DATE} +@item 21 +@tab @code{TIME} +@item 22 +@tab @code{DATETIME} +@item 23 +@tab @code{ADATE} +@item 24 +@tab @code{JDATE} +@item 25 +@tab @code{DTIME} +@item 26 +@tab @code{WKDAY} +@item 27 +@tab @code{MONTH} +@item 28 +@tab @code{MOYR} +@item 29 +@tab @code{QYR} +@item 30 +@tab @code{WKYR} +@item 31 +@tab @code{PCT} +@item 32 +@tab @code{DOT} +@item 33 +@tab @code{CCA} +@item 34 +@tab @code{CCB} +@item 35 +@tab @code{CCC} +@item 36 +@tab @code{CCD} +@item 37 +@tab @code{CCE} +@item 38 +@tab @code{EDATE} +@item 39 +@tab @code{SDATE} +@end multitable +@end quotation + +@node Value Labels Records +@section Value Labels Records + +The value label record has the following format: + +@example +int32 rec_type; +int32 label_count; + +/* @r{Repeated @code{label_cnt} times}. */ +char value[8]; +char label_len; +char label[]; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 3. + +@item int32 label_count; +Number of value labels present in this record. +@end table + +The remaining fields are repeated @code{count} times. Each +repetition specifies one value label. + +@table @code +@item char value[8]; +A numeric value or a short string value padded as necessary to 8 bytes +in length. Its type and width cannot be determined until the +following value label variables record (see below) is read. + +@item char label_len; +The label's length, in bytes. + +@item char label[]; +@code{label_len} bytes of the actual label, followed by up to 7 bytes +of padding to bring @code{label} and @code{label_len} together to a +multiple of 8 bytes in length. +@end table + +The value label record is always immediately followed by a value label +variables record with the following format: + +@example +int32 rec_type; +int32 var_count; +int32 vars[]; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 4. + +@item int32 var_count; +Number of variables that the associated value labels from the value +label record are to be applied. + +@item int32 vars[]; +A list of dictionary indexes of variables to which to apply the value +labels (@pxref{Dictionary Index}). There are @code{var_count} +elements. + +String variables wider than 8 bytes may not have value labels. +@end table + +@node Document Record +@section Document Record + +The document record, if present, has the following format: + +@example +int32 rec_type; +int32 n_lines; +char lines[][80]; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 6. + +@item int32 n_lines; +Number of lines of documents present. + +@item char lines[][80]; +Document lines. The number of elements is defined by @code{n_lines}. +Lines shorter than 80 characters are padded on the right with spaces. +@end table + +@node Machine Integer Info Record +@section Machine Integer Info Record + +The integer info record, if present, has the following format: + +@example +/* @r{Header.} */ +int32 rec_type; +int32 subtype; +int32 size; +int32 count; + +/* @r{Data.} */ +int32 version_major; +int32 version_minor; +int32 version_revision; +int32 machine_code; +int32 floating_point_rep; +int32 compression_code; +int32 endianness; +int32 character_code; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 7. + +@item int32 subtype; +Record subtype. Always set to 3. + +@item int32 size; +Size of each piece of data in the data part, in bytes. Always set to 4. + +@item int32 count; +Number of pieces of data in the data part. Always set to 8. + +@item int32 version_major; +PSPP major version number. In version @var{x}.@var{y}.@var{z}, this +is @var{x}. + +@item int32 version_minor; +PSPP minor version number. In version @var{x}.@var{y}.@var{z}, this +is @var{y}. + +@item int32 version_revision; +PSPP version revision number. In version @var{x}.@var{y}.@var{z}, +this is @var{z}. + +@item int32 machine_code; +Machine code. PSPP always set this field to value to -1, but other +values may appear. + +@item int32 floating_point_rep; +Floating point representation code. For IEEE 754 systems this is 1. +IBM 370 sets this to 2, and DEC VAX E to 3. + +@item int32 compression_code; +Compression code. Always set to 1. + +@item int32 endianness; +Machine endianness. 1 indicates big-endian, 2 indicates little-endian. + +@item int32 character_code; +Character code. 1 indicates EBCDIC, 2 indicates 7-bit ASCII, 3 +indicates 8-bit ASCII, 4 indicates DEC Kanji. +Windows code page numbers are also valid. +@end table + +@node Machine Floating-Point Info Record +@section Machine Floating-Point Info Record + +The floating-point info record, if present, has the following format: + +@example +/* @r{Header.} */ +int32 rec_type; +int32 subtype; +int32 size; +int32 count; + +/* @r{Data.} */ +flt64 sysmis; +flt64 highest; +flt64 lowest; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 7. + +@item int32 subtype; +Record subtype. Always set to 4. + +@item int32 size; +Size of each piece of data in the data part, in bytes. Always set to 8. + +@item int32 count; +Number of pieces of data in the data part. Always set to 3. + +@item flt64 sysmis; +The system missing value. + +@item flt64 highest; +The value used for HIGHEST in missing values. + +@item flt64 lowest; +The value used for LOWEST in missing values. +@end table + +@node Variable Display Parameter Record +@section Variable Display Parameter Record + +The variable display parameter record, if present, has the following +format: + +@example +/* @r{Header.} */ +int32 rec_type; +int32 subtype; +int32 size; +int32 count; + +/* @r{Repeated @code{count} times}. */ +int32 measure; +int32 width; +int32 alignment; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 7. + +@item int32 subtype; +Record subtype. Always set to 11. + +@item int32 size; +The size of @code{int32}. Always set to 4. + +@item int32 count; +The number of sets of variable display parameters (ordinarily the +number of variables in the dictionary), times 3. +@end table + +The remaining members are repeated @code{count} times, in the same +order as the variable records. No element corresponds to variable +records that continue long string variables. The meanings of these +members are as follows: + +@table @code +@item int32 measure; +The measurement type of the variable: +@table @asis +@item 1 +Nominal Scale +@item 2 +Ordinal Scale +@item 3 +Continuous Scale +@end table + +SPSS 14 sometimes writes a @code{measure} of 0. PSPP interprets this +as nominal scale. + +@item int32 width; +The width of the display column for the variable in characters. + +@item int32 alignment; +The alignment of the variable for display purposes: + +@table @asis +@item 0 +Left aligned +@item 1 +Right aligned +@item 2 +Centre aligned +@end table +@end table + +@node Long Variable Names Record +@section Long Variable Names Record + +If present, the long variable names record has the following format: + +@example +/* @r{Header.} */ +int32 rec_type; +int32 subtype; +int32 size; +int32 count; + +/* @r{Exactly @code{count} bytes of data.} */ +char var_name_pairs[]; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 7. + +@item int32 subtype; +Record subtype. Always set to 13. + +@item int32 size; +The size of each element in the @code{var_name_pairs} member. Always set to 1. + +@item int32 count; +The total number of bytes in @code{var_name_pairs}. + +@item char var_name_pairs[]; +A list of @var{key}--@var{value} tuples, where @var{key} is the name +of a variable, and @var{value} is its long variable name. +The @var{key} field is at most 8 bytes long and must match the +name of a variable which appears in the variable record (@pxref{Variable +Record}). +The @var{value} field is at most 64 bytes long. +The @var{key} and @var{value} fields are separated by a @samp{=} byte. +Each tuple is separated by a byte whose value is 09. There is no +trailing separator following the last tuple. +The total length is @code{count} bytes. +@end table + +@node Very Long String Record +@section Very Long String Record + +Old versions of SPSS limited string variables to a width of 255 bytes. +For backward compatibility with these older versions, the system file +format represents a string longer than 255 bytes, called a @dfn{very +long string}, as a collection of strings no longer than 255 bytes +each. The strings concatenated to make a very long string are called +its @dfn{segments}; for consistency, variables other than very long +strings are considered to have a single segment. + +A very long string with a width of @var{w} has @var{n} = +(@var{w} + 251) / 252 segments, that is, one segment for every +252 bytes of width, rounding up. It would be logical, then, for each +of the segments except the last to have a width of 252 and the last +segment to have the remainder, but this is not the case. In fact, +each segment except the last has a width of 255 bytes. The last +segment has width @var{w} - (@var{n} - 1) * 252; some versions +of SPSS make it slightly wider, but not wide enough to make the last +segment require another 8 bytes of data. + +Data is packed tightly into segments of a very long string, 255 bytes +per segment. Because 255 bytes of segment data are allocated for +every 252 bytes of the very long string's width (approximately), some +unused space is left over at the end of the allocated segments. Data +in unused space is ignored. + +Example: Consider a very long string of width 20,000. Such a very +long string has 20,000 / 252 = 80 (rounding up) segments. The first +79 segments have width 255; the last segment has width 20,000 - 79 * +252 = 92 or slightly wider (up to 96 bytes, the next multiple of 8). +The very long string's data is actually stored in the 19,890 bytes in +the first 78 segments, plus the first 110 bytes of the 79th segment +(19,890 + 110 = 20,000). The remaining 145 bytes of the 79th segment +and all 92 bytes of the 80th segment are unused. + +The very long string record explains how to stitch together segments +to obtain very long string data. For each of the very long string +variables in the dictionary, it specifies the name of its first +segment's variable and the very long string variable's actual width. +The remaining segments immediately follow the named variable in the +system file's dictionary. + +The very long string record, which is present only if the system file +contains very long string variables, has the following format: + +@example +/* @r{Header.} */ +int32 rec_type; +int32 subtype; +int32 size; +int32 count; + +/* @r{Exactly @code{count} bytes of data.} */ +char string_lengths[]; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 7. + +@item int32 subtype; +Record subtype. Always set to 14. + +@item int32 size; +The size of each element in the @code{string_lengths} member. Always set to 1. + +@item int32 count; +The total number of bytes in @code{string_lengths}. + +@item char string_lengths[]; +A list of @var{key}--@var{value} tuples, where @var{key} is the name +of a variable, and @var{value} is its length. +The @var{key} field is at most 8 bytes long and must match the +name of a variable which appears in the variable record (@pxref{Variable +Record}). +The @var{value} field is exactly 5 bytes long. It is a zero-padded, +ASCII-encoded string that is the length of the variable. +The @var{key} and @var{value} fields are separated by a @samp{=} byte. +Tuples are delimited by a two-byte sequence @{00, 09@}. +After the last tuple, there may be a single byte 00, or @{00, 09@}. +The total length is @code{count} bytes. +@end table + +@node Miscellaneous Informational Records +@section Miscellaneous Informational Records + +Some specific types of miscellaneous informational records are +documented here, but others are known to exist. PSPP ignores unknown +miscellaneous informational records when reading system files. + +@example +/* @r{Header.} */ +int32 rec_type; +int32 subtype; +int32 size; +int32 count; + +/* @r{Exactly @code{size * count} bytes of data.} */ +char data[]; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 7. + +@item int32 subtype; +Record subtype. May take any value. According to Aapi +H@"am@"al@"ainen, value 5 indicates a set of grouped variables and 6 +indicates date info (probably related to USE). + +@item int32 size; +Size of each piece of data in the data part. Should have the value 1, +4, or 8, for @code{char}, @code{int32}, and @code{flt64} format data, +respectively. + +@item int32 count; +Number of pieces of data in the data part. + +@item char data[]; +Arbitrary data. There must be @code{size} times @code{count} bytes of +data. +@end table + +@node Dictionary Termination Record +@section Dictionary Termination Record + +The dictionary termination record separates all other records from the +data records. + +@example +int32 rec_type; +int32 filler; +@end example + +@table @code +@item int32 rec_type; +Record type. Always set to 999. + +@item int32 filler; +Ignored padding. Should be set to 0. +@end table + +@node Data Record +@section Data Record + +Data records must follow all other records in the system file. There must +be at least one data record in every system file. + +The format of data records varies depending on whether the data is +compressed. Regardless, the data is arranged in a series of 8-byte +elements. + +When data is not compressed, +each element corresponds to +the variable declared in the respective variable record (@pxref{Variable +Record}). Numeric values are given in @code{flt64} format; string +values are literal characters string, padded on the right when +necessary to fill out 8-byte units. + +Compressed data is arranged in the following manner: the first 8 bytes +in the data section is divided into a series of 1-byte command +codes. These codes have meanings as described below: + +@table @asis +@item 0 +Ignored. If the program writing the system file accumulates compressed +data in blocks of fixed length, 0 bytes can be used to pad out extra +bytes remaining at the end of a fixed-size block. + +@item 1 through 251 +A number with +value @var{code} - @var{bias}, where +@var{code} is the value of the compression code and @var{bias} is the +variable @code{bias} from the file header. For example, +code 105 with bias 100.0 (the normal value) indicates a numeric variable +of value 5. + +@item 252 +End of file. This code may or may not appear at the end of the data +stream. PSPP always outputs this code but its use is not required. + +@item 253 +A numeric or string value that is not +compressible. The value is stored in the 8 bytes following the +current block of command bytes. If this value appears twice in a block +of command bytes, then it indicates the second group of 8 bytes following the +command bytes, and so on. + +@item 254 +An 8-byte string value that is all spaces. + +@item 255 +The system-missing value. +@end table + +When the end of the an 8-byte group of command bytes is reached, any +blocks of non-compressible values indicated by code 253 are skipped, +and the next element of command bytes is read and interpreted, until +the end of the file or a code with value 252 is reached. +@setfilename ignored diff --git a/doc/not-implemented.texi b/doc/not-implemented.texi index 57060687..0dd77d49 100644 --- a/doc/not-implemented.texi +++ b/doc/not-implemented.texi @@ -7,6 +7,6 @@ implemented. @cindex unimplemented commands @cindex commands, unimplemented -@include ni.texi +@include doc/ni.texi @setfilename ignored diff --git a/doc/portable-file-format.texi b/doc/portable-file-format.texi deleted file mode 100644 index d58a987f..00000000 --- a/doc/portable-file-format.texi +++ /dev/null @@ -1,480 +0,0 @@ -@node Portable File Format -@appendix Portable File Format - -These days, most computers use the same internal data formats for -integer and floating-point data, if one ignores little differences like -big- versus little-endian byte ordering. However, occasionally it is -necessary to exchange data between systems with incompatible data -formats. This is what portable files are designed to do. - -@strong{Please note:} Although all of the following information is -correct, as far as the author has been able to ascertain, it is gleaned -from examination of ASCII-formatted portable files only, so some of it -may be incorrect in the general case. - -@menu -* Portable File Characters:: -* Portable File Structure:: -* Portable File Header:: -* Version and Date Info Record:: -* Identification Records:: -* Variable Count Record:: -* Case Weight Variable Record:: -* Variable Records:: -* Value Label Records:: -* Portable File Document Record:: -* Portable File Data:: -@end menu - -@node Portable File Characters -@section Portable File Characters - -Portable files are arranged as a series of lines of 80 -characters each. Each line is terminated by a carriage-return, -line-feed sequence (``new-lines''). New-lines are only used to avoid -line length limits imposed by some OSes; they are not meaningful. - -Most lines in portable files are exactly 80 characters long. The only -exception is a line that ends in one or more spaces, in which the -spaces may optionally be omitted. Thus, a portable file reader must -act as though a line shorter than 80 characters is padded to that -length with spaces. - -The file must be terminated with a @samp{Z} character. In addition, if -the final line in the file does not have exactly 80 characters, then it -is padded on the right with @samp{Z} characters. (The file contents may -be in any character set; the file contains a description of its own -character set, as explained in the next section. Therefore, the -@samp{Z} character is not necessarily an ASCII @samp{Z}.) - -For the rest of the description of the portable file format, new-lines -and the trailing @samp{Z}s will be ignored, as if they did not exist, -because they are not an important part of understanding the file -contents. - -@node Portable File Structure -@section Portable File Structure - -Every portable file consists of the following records, in sequence: - -@itemize @bullet - -@item -File header. - -@item -Version and date info. - -@item -Product identification. - -@item -Author identification (optional). - -@item -Subproduct identification (optional). - -@item -Variable count. - -@item -Case weight variable (optional). - -@item -Variables. Each variable record may optionally be followed by a -missing value record and a variable label record. - -@item -Value labels (optional). - -@item -Documents (optional). - -@item -Data. -@end itemize - -Most records are identified by a single-character tag code. The file -header and version info record do not have a tag. - -Other than these single-character codes, there are three types of fields -in a portable file: floating-point, integer, and string. Floating-point -fields have the following format: - -@itemize @bullet - -@item -Zero or more leading spaces. - -@item -Optional asterisk (@samp{*}), which indicates a missing value. The -asterisk must be followed by a single character, generally a period -(@samp{.}), but it appears that other characters may also be possible. -This completes the specification of a missing value. - -@item -Optional minus sign (@samp{-}) to indicate a negative number. - -@item -A whole number, consisting of one or more base-30 digits: @samp{0} -through @samp{9} plus capital letters @samp{A} through @samp{T}. - -@item -Optional fraction, consisting of a radix point (@samp{.}) followed by -one or more base-30 digits. - -@item -Optional exponent, consisting of a plus or minus sign (@samp{+} or -@samp{-}) followed by one or more base-30 digits. - -@item -A forward slash (@samp{/}). -@end itemize - -Integer fields take a form identical to floating-point fields, but they -may not contain a fraction. - -String fields take the form of a integer field having value @var{n}, -followed by exactly @var{n} characters, which are the string content. - -@node Portable File Header -@section Portable File Header - -Every portable file begins with a 464-byte header, consisting of a -200-byte collection of vanity splash strings, followed by a 256-byte -character set translation table, followed by an 8-byte tag string. - -The 200-byte segment is divided into five 40-byte sections, each of -which represents the string @code{@var{charset} SPSS PORT FILE} in a -different character set encoding, where @var{charset} is the name of -the character set used in the file, e.g.@: @code{ASCII} or -@code{EBCDIC}. Each string is padded on the right with spaces in its -respective character set. - -It appears that these strings exist only to inform those who might view -the file on a screen, and that they are not parsed by SPSS products. -Thus, they can be safely ignored. For those interested, the strings are -supposed to be in the following character sets, in the specified order: -EBCDIC, 7-bit ASCII, CDC 6-bit ASCII, 6-bit ASCII, Honeywell 6-bit -ASCII. - -The 256-byte segment describes a mapping from the character set used in -the portable file to an arbitrary character set having characters at the -following positions: - -@table @asis -@item 0--60 - -Control characters. Not important enough to describe in full here. - -@item 61--63 - -Reserved. - -@item 64--73 - -Digits @samp{0} through @samp{9}. - -@item 74--99 - -Capital letters @samp{A} through @samp{Z}. - -@item 100--125 - -Lowercase letters @samp{a} through @samp{z}. - -@item 126 - -Space. - -@item 127--130 - -Symbols @code{.<(+} - -@item 131 - -Solid vertical pipe. - -@item 132--142 - -Symbols @code{&[]!$*);^-/} - -@item 143 - -Broken vertical pipe. - -@item 144--150 - -Symbols @code{,%_>}?@code{`:} @c @code{?} is an inverted question mark - -@item 151 - -British pound symbol. - -@item 152--155 - -Symbols @code{@@'="}. - -@item 156 - -Less than or equal symbol. - -@item 157 - -Empty box. - -@item 158 - -Plus or minus. - -@item 159 - -Filled box. - -@item 160 - -Degree symbol. - -@item 161 - -Dagger. - -@item 162 - -Symbol @samp{~}. - -@item 163 - -En dash. - -@item 164 - -Lower left corner box draw. - -@item 165 - -Upper left corner box draw. - -@item 166 - -Greater than or equal symbol. - -@item 167--176 - -Superscript @samp{0} through @samp{9}. - -@item 177 - -Lower right corner box draw. - -@item 178 - -Upper right corner box draw. - -@item 179 - -Not equal symbol. - -@item 180 - -Em dash. - -@item 181 - -Superscript @samp{(}. - -@item 182 - -Superscript @samp{)}. - -@item 183 - -Horizontal dagger (?). - -@item 184--186 - -Symbols @samp{@{@}\}. -@item 187 - -Cents symbol. - -@item 188 - -Centered dot, or bullet. - -@item 189--255 - -Reserved. -@end table - -Symbols that are not defined in a particular character set are set to -the same value as symbol 64; i.e., to @samp{0}. - -The 8-byte tag string consists of the exact characters @code{SPSSPORT} -in the portable file's character set, which can be used to verify that -the file is indeed a portable file. - -@node Version and Date Info Record -@section Version and Date Info Record - -This record does not have a tag code. It has the following structure: - -@itemize @bullet -@item -A single character identifying the file format version. The letter A -represents version 0, and so on. - -@item -An 8-character string field giving the file creation date in the format -YYYYMMDD. - -@item -A 6-character string field giving the file creation time in the format -HHMMSS. -@end itemize - -@node Identification Records -@section Identification Records - -The product identification record has tag code @samp{1}. It consists of -a single string field giving the name of the product that wrote the -portable file. - -The author identification record has tag code @samp{2}. It is -optional. If present, it consists of a single string field giving the -name of the person who caused the portable file to be written. - -The subproduct identification record has tag code @samp{3}. It is -optional. If present, it consists of a single string field giving -additional information on the product that wrote the portable file. - -@node Variable Count Record -@section Variable Count Record - -The variable count record has tag code @samp{4}. It consists of two -integer fields. The first contains the number of variables in the file -dictionary. The purpose of the second is unknown; it contains the value -161 in all portable files examined so far. - -@node Case Weight Variable Record -@section Case Weight Variable Record - -The case weight variable record is optional. If it is present, it -indicates the variable used for weighting cases; if it is absent, -cases are unweighted. It has tag code @samp{6}. It consists of a -single string field that names the weighting variable. - -@node Variable Records -@section Variable Records - -Each variable record represents a single variable. Variable records -have tag code @samp{7}. They have the following structure: - -@itemize @bullet - -@item -Width (integer). This is 0 for a numeric variable, and a number between 1 -and 255 for a string variable. - -@item -Name (string). 1--8 characters long. Must be in all capitals. - -A few portable files that contain duplicate variable names have been -spotted in the wild. PSPP handles these by renaming the duplicates -with numeric extensions: @code{@var{var}_1}, @code{@var{var}_2}, and -so on. - -@item -Print format. This is a set of three integer fields: - -@itemize @minus - -@item -Format type (@pxref{Variable Record}). - -@item -Format width. 1--40. - -@item -Number of decimal places. 1--40. -@end itemize - -A few portable files with invalid format types or formats that are not -of the appropriate width for their variables have been spotted in the -wild. PSPP assigns a default F or A format to a variable with an -invalid format. - -@item -Write format. Same structure as the print format described above. -@end itemize - -Each variable record can optionally be followed by a missing value -record, which has tag code @samp{8}. A missing value record has one -field, the missing value itself (a floating-point or string, as -appropriate). Up to three of these missing value records can be used. - -There is also a record for missing value ranges, which has tag code -@samp{B}. It is followed by two fields representing the range, which -are floating-point or string as appropriate. If a missing value range -is present, it may be followed by a single missing value record. - -Tag codes @samp{9} and @samp{A} represent @code{LO THRU @var{x}} and -@code{@var{x} THRU HI} ranges, respectively. Each is followed by a -single field representing @var{x}. If one of the ranges is present, it -may be followed by a single missing value record. - -In addition, each variable record can optionally be followed by a -variable label record, which has tag code @samp{C}. A variable label -record has one field, the variable label itself (string). - -@node Value Label Records -@section Value Label Records - -Value label records have tag code @samp{D}. They have the following -format: - -@itemize @bullet -@item -Variable count (integer). - -@item -List of variables (strings). The variable count specifies the number in -the list. Variables are specified by their names. All variables must -be of the same type (numeric or string), but string variables do not -necessarily have the same width. - -@item -Label count (integer). - -@item -List of (value, label) tuples. The label count specifies the number of -tuples. Each tuple consists of a value, which is numeric or string as -appropriate to the variables, followed by a label (string). -@end itemize - -A few portable files that specify duplicate value labels, that is, two -different labels for a single value of a single variable, have been -spotted in the wild. PSPP uses the last value label specified in -these cases. - -@node Portable File Document Record -@section Document Record - -One document record may optionally follow the value label record. The -document record consists of tag code @samp{E}, following by the number -of document lines as an integer, followed by that number of strings, -each of which represents one document line. Document lines must be 80 -bytes long or shorter. - -@node Portable File Data -@section Portable File Data - -The data record has tag code @samp{F}. There is only one tag for all -the data; thus, all the data must follow the dictionary. The data is -terminated by the end-of-file marker @samp{Z}, which is not valid as the -beginning of a data element. - -Data elements are output in the same order as the variable records -describing them. String variables are output as string fields, and -numeric variables are output as floating-point fields. -@setfilename ignored diff --git a/doc/pspp-dev.texinfo b/doc/pspp-dev.texinfo new file mode 100644 index 00000000..991b04b2 --- /dev/null +++ b/doc/pspp-dev.texinfo @@ -0,0 +1,113 @@ +\input texinfo @c -*- texinfo -*- +@c %**start of header +@setfilename pspp-dev.info +@settitle PSPP +@c For double-sided printing, uncomment: +@c @setchapternewpage odd +@c %**end of header + +@include version-dev.texi + +@macro cmd{CMDNAME} +\CMDNAME\ +@end macro +@macro struct{TAG} +@code{struct \TAG\} +@end macro +@macro union{TAG} +@code{union \TAG\} +@end macro +@macro enum{TAG} +@code{enum \TAG\} +@end macro +@macro func{NAME} +@code{\NAME\} +@end macro + +@iftex +@finalout +@end iftex + +@dircategory Math +@direntry +* PSPP Developers Guide: (pspp-dev). Tutorial and reference for PSPP developers. +@end direntry + +@copying +This manual is for GNU PSPP version @value{VERSION}, +software for statistical analysis. + +Copyright @copyright{} 1997, 1998, 2004, 2005, 2007 Free Software Foundation, Inc. + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,'' +and with the Back-Cover Texts as in (a) below. A copy of the +license is included in the section entitled ``GNU Free Documentation +License.'' + +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify +this GNU Manual, like GNU software. Copies published by the Free +Software Foundation raise funds for GNU development.'' +@end quotation +@end copying + +@titlepage +@title PSPP Developers Guide +@subtitle GNU PSPP Statistical Analysis Software +@subtitle Release @value{VERSION} +@author +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + + +@ifnottex +@node Top +@top GNU PSPP Developers Guide + +@insertcopying +@end ifnottex + +@menu +* Introduction:: Introduction to PSPP development. +* Basic Concepts:: Data structures and concepts. +* Parsing Command Syntax:: How to parse command syntax. +* Processing Data:: Data input, output, and processing. +* Presenting Output:: Producing machine- and human-readable output. + +* Function Index:: Index of PSPP functions. +* Concept Index:: Index of concepts. + +* Portable File Format:: Format of PSPP portable files. +* System File Format:: Format of PSPP system files. +* q2c Input Format:: Format of syntax accepted by q2c. + +* GNU Free Documentation License:: License for copying this manual. +@end menu + +@include dev/intro.texi +@include dev/concepts.texi +@include dev/syntax.texi +@include dev/data.texi +@include dev/output.texi + +@include function-index.texi +@include concept-index.texi + +@include dev/portable-file-format.texi +@include dev/system-file-format.texi +@include dev/q2c.texi + +@include fdl.texi + +@bye + +@c Local Variables: +@c compile-command: "makeinfo pspp-dev.texinfo" +@c End: diff --git a/doc/pspp.texinfo b/doc/pspp.texinfo index 9698cc58..b0759dd4 100644 --- a/doc/pspp.texinfo +++ b/doc/pspp.texinfo @@ -43,9 +43,10 @@ Software Foundation raise funds for GNU development.'' @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 @@ -87,10 +88,6 @@ Software Foundation raise funds for GNU development.'' * 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 @@ -117,10 +114,6 @@ Software Foundation raise funds for GNU development.'' @include configuring.texi -@include portable-file-format.texi -@include data-file-format.texi -@include q2c.texi - @include fdl.texi @bye diff --git a/doc/q2c.texi b/doc/q2c.texi deleted file mode 100644 index fb61173e..00000000 --- a/doc/q2c.texi +++ /dev/null @@ -1,300 +0,0 @@ -@node q2c Input Format -@appendix @code{q2c} Input Format - -PSPP statistical procedures have a bizarre and somewhat irregular -syntax. Despite this, a parser generator has been written that -adequately addresses many of the possibilities and tries to provide -hooks for the exceptional cases. This parser generator is named -@code{q2c}. - -@menu -* Invoking q2c:: q2c command-line syntax. -* q2c Input Structure:: High-level layout of the input file. -* Grammar Rules:: Syntax of the grammar rules. -@end menu - -@node Invoking q2c -@section Invoking q2c - -@example -q2c @var{input.q} @var{output.c} -@end example - -@code{q2c} translates a @samp{.q} file into a @samp{.c} file. It takes -exactly two command-line arguments, which are the input file name and -output file name, respectively. @code{q2c} does not accept any -command-line options. - -@node q2c Input Structure -@section @code{q2c} Input Structure - -@code{q2c} input files are divided into two sections: the grammar rules -and the supporting code. The @dfn{grammar rules}, which make up the -first part of the input, are used to define the syntax of the -statistical procedure to be parsed. The @dfn{supporting code}, -following the grammar rules, are copied largely unchanged to the output -file, except for certain escapes. - -The most important lines in the grammar rules are used for defining -procedure syntax. These lines can be prefixed with a dollar sign -(@samp{$}), which prevents Emacs' CC-mode from munging them. Besides -this, a bang (@samp{!}) at the beginning of a line causes the line, -minus the bang, to be written verbatim to the output file (useful for -comments). As a third special case, any line that begins with the exact -characters @code{/* *INDENT} is ignored and not written to the output. -This allows @code{.q} files to be processed through @code{indent} -without being munged. - -The syntax of the grammar rules themselves is given in the following -sections. - -The supporting code is passed into the output file largely unchanged. -However, the following escapes are supported. Each escape must appear -on a line by itself. - -@table @code -@item /* (header) */ - -Expands to a series of C @code{#include} directives which include the -headers that are required for the parser generated by @code{q2c}. - -@item /* (decls @var{scope}) */ - -Expands to C variable and data type declarations for the variables and -@code{enum}s input and output by the @code{q2c} parser. @var{scope} -must be either @code{local} or @code{global}. @code{local} causes the -declarations to be output as function locals. @code{global} causes them -to be declared as @code{static} module variables; thus, @code{global} is -a bit of a misnomer. - -@item /* (parser) */ - -Expands to the entire parser. Must be enclosed within a C function. - -@item /* (free) */ - -Expands to a set of calls to the @code{free} function for variables -declared by the parser. Only needs to be invoked if subcommands of type -@code{string} are used in the grammar rules. -@end table - -@node Grammar Rules -@section Grammar Rules - -The grammar rules describe the format of the syntax that the parser -generated by @code{q2c} will understand. The way that the grammar rules -are included in @code{q2c} input file are described above. - -The grammar rules are divided into tokens of the following types: - -@table @asis -@item Identifier (@code{ID}) - -An identifier token is a sequence of letters, digits, and underscores -(@samp{_}). Identifiers are @emph{not} case-sensitive. - -@item String (@code{STRING}) - -String tokens are initiated by a double-quote character (@samp{"}) and -consist of all the characters between that double quote and the next -double quote, which must be on the same line as the first. Within a -string, a backslash can be used as a ``literal escape''. The only -reasons to use a literal escape are to include a double quote or a -backslash within a string. - -@item Special character - -Other characters, other than white space, constitute tokens in -themselves. - -@end table - -The syntax of the grammar rules is as follows: - -@example -grammar-rules ::= command-name opt-prefix : subcommands . -command-name ::= ID - ::= STRING -opt-prefix ::= - ::= ( ID ) -subcommands ::= subcommand - ::= subcommands ; subcommand -@end example - -The syntax begins with an ID token that gives the name of the -procedure to be parsed. For command names that contain multiple -words, a STRING token may be used instead, e.g.@: @samp{"FILE -HANDLE"}. Optionally, an ID in parentheses specifies a prefix used -for all file-scope identifiers declared by the emitted code. - -The rest of the syntax consists of subcommands separated by semicolons -(@samp{;}) and terminated with a full stop (@samp{.}). - -@example -subcommand ::= default-opt arity-opt ID sbc-defn -default-opt ::= - ::= * -arity-opt ::= - ::= + - ::= ^ -sbc-defn ::= opt-prefix = specifiers - ::= [ ID ] = array-sbc - ::= opt-prefix = sbc-special-form -@end example - -A subcommand that begins with an asterisk (@samp{*}) is the default -subcommand. The keyword used for the default subcommand can be omitted -in the PSPP syntax file. - -A plus sign (@samp{+}) indicates that a subcommand can appear more than -once. A caret (@samp{^}) indicate that a subcommand must appear exactly -once. A subcommand marked with neither character may appear once or not -at all, but not more than once. - -The subcommand name appears after the leading option characters. - -There are three forms of subcommands. The first and most common form -simply gives an equals sign (@samp{=}) and a list of specifiers, which -can each be set to a single setting. The second form declares an array, -which is a set of flags that can be individually turned on by the user. -There are also several special forms that do not take a list of -specifiers. - -Arrays require an additional @code{ID} argument. This is used as a -prefix, prepended to the variable names constructed from the -specifiers. The other forms also allow an optional prefix to be -specified. - -@example -array-sbc ::= alternatives - ::= array-sbc , alternatives -alternatives ::= ID - ::= alternatives | ID -@end example - -An array subcommand is a set of Boolean values that can independently be -turned on by the user, listed separated by commas (@samp{,}). If an value has more -than one name then these names are separated by pipes (@samp{|}). - -@example -specifiers ::= specifier - ::= specifiers , specifier -specifier ::= opt-id : settings -opt-id ::= - ::= ID -@end example - -Ordinary subcommands (other than arrays and special forms) require a -list of specifiers. Each specifier has an optional name and a list of -settings. If the name is given then a correspondingly named variable -will be used to store the user's choice of setting. If no name is given -then there is no way to tell which setting the user picked; in this case -the settings should probably have values attached. - -@example -settings ::= setting - ::= settings / setting -setting ::= setting-options ID setting-value -setting-options ::= - ::= * - ::= ! - ::= * ! -@end example - -Individual settings are separated by forward slashes (@samp{/}). Each -setting can be as little as an @code{ID} token, but options and values -can optionally be included. The @samp{*} option means that, for this -setting, the @code{ID} can be omitted. The @samp{!} option means that -this option is the default for its specifier. - -@example -setting-value ::= - ::= ( setting-value-2 ) - ::= setting-value-2 -setting-value-2 ::= setting-value-options setting-value-type : ID - setting-value-restriction -setting-value-options ::= - ::= * -setting-value-type ::= N - ::= D - ::= S -setting-value-restriction ::= - ::= , STRING -@end example - -Settings may have values. If the value must be enclosed in parentheses, -then enclose the value declaration in parentheses. Declare the setting -type as @samp{n}, @samp{d}, or @samp{s} for integer, floating-point, -or string type, respectively. The given @code{ID} is used to -construct a variable name. -If option @samp{*} is given, then the value is optional; otherwise it -must be specified whenever the corresponding setting is specified. A -``restriction'' can also be specified which is a string giving a C -expression limiting the valid range of the value. The special escape -@code{%s} should be used within the restriction to refer to the -setting's value variable. - -@example -sbc-special-form ::= VAR - ::= VARLIST varlist-options - ::= INTEGER opt-list - ::= DOUBLE opt-list - ::= PINT - ::= STRING @r{(the literal word STRING)} string-options - ::= CUSTOM -varlist-options ::= - ::= ( STRING ) -opt-list ::= - ::= LIST -string-options ::= - ::= ( STRING STRING ) -@end example - -The special forms are of the following types: - -@table @code -@item VAR - -A single variable name. - -@item VARLIST - -A list of variables. If given, the string can be used to provide -@code{PV_@var{*}} options to the call to @code{parse_variables}. - -@item INTEGER - -A single integer value. - -@item INTEGER LIST - -A list of integers separated by spaces or commas. - -@item DOUBLE - -A single floating-point value. - -@item DOUBLE LIST - -A list of floating-point values. - -@item PINT - -A single positive integer value. - -@item STRING - -A string value. If the options are given then the first string is an -expression giving a restriction on the value of the string; the second -string is an error message to display when the restriction is violated. - -@item CUSTOM - -A custom function is used to parse this subcommand. The function must -have prototype @code{int custom_@var{name} (void)}. It should return 0 -on failure (when it has already issued an appropriate diagnostic), 1 on -success, or 2 if it fails and the calling function should issue a syntax -error on behalf of the custom handler. - -@end table -@setfilename ignored diff --git a/doc/utilities.texi b/doc/utilities.texi index 94fa5074..314c435e 100644 --- a/doc/utilities.texi +++ b/doc/utilities.texi @@ -406,6 +406,7 @@ files. The data input subcommands are @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 diff --git a/doc/variables.texi b/doc/variables.texi index 46c6df8f..a66e4232 100644 --- a/doc/variables.texi +++ b/doc/variables.texi @@ -378,7 +378,7 @@ statistical procedures. To assign a variable label to a group of variables, specify a list of variable names and the variable label as a string. To assign different labels to different variables in the same command, -preceed the subsequent variable list with a slash (@samp{/}). +precede the subsequent variable list with a slash (@samp{/}). @node VARIABLE ALIGNMENT diff --git a/po/de.po b/po/de.po index 0e91bb1a..3c374e70 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: PSPP 0.4.3\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"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 \n" "Language-Team: German \n" @@ -47,12 +47,6 @@ msgstr "Tag %d muß zwischen 0 bit 31 sein." msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15." msgstr "" -#: 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 "" @@ -73,157 +67,163 @@ msgstr "plotzlich ist der Datei beendet" 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 "" @@ -305,33 +305,33 @@ msgstr[1] "" 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" @@ -405,150 +405,150 @@ 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 "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." @@ -578,7 +578,7 @@ msgstr "" #. 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 "" @@ -588,299 +588,299 @@ 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 %." 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" @@ -899,44 +899,32 @@ 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 "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." @@ -1175,7 +1163,7 @@ msgid "" 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 @@ -1183,17 +1171,17 @@ msgstr "" msgid "Variable" msgstr "" -#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:398 +#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:402 msgid "Record" msgstr "" -#: 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 "" @@ -1213,17 +1201,17 @@ 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 " @@ -1232,98 +1220,128 @@ msgstr "" #. 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 "" @@ -1334,7 +1352,7 @@ 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 "" @@ -1413,11 +1431,6 @@ msgid "" "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 "" @@ -1435,39 +1448,39 @@ msgid "" "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 "" @@ -1511,39 +1524,39 @@ msgid "" "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." @@ -2302,11 +2315,11 @@ msgstr "" msgid "LO or LOWEST must be part of a range." msgstr "" -#: src/language/lexer/range-parser.c:106 +#: src/language/lexer/range-parser.c:107 msgid "System-missing value is not valid here." msgstr "" -#: src/language/lexer/range-parser.c:114 +#: src/language/lexer/range-parser.c:115 msgid "expecting number or data string" msgstr "" @@ -3045,73 +3058,73 @@ 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 "" @@ -3198,11 +3211,11 @@ 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 "" @@ -3214,6 +3227,22 @@ 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 "" @@ -3238,22 +3267,6 @@ msgid "" "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 "" @@ -3349,56 +3362,56 @@ 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 "" @@ -3880,44 +3893,44 @@ 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 "" @@ -3948,23 +3961,23 @@ 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 "" @@ -5014,7 +5027,7 @@ 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 "" @@ -5189,10 +5202,6 @@ msgstr "xyzzy" 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 "" @@ -5202,6 +5211,28 @@ 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." @@ -5445,24 +5476,6 @@ msgstr "" msgid "Search backward" msgstr "" -#: src/ui/gui/psppire-var-store.c:479 src/ui/gui/var-display.c:14 -msgid "None" -msgstr "Keine" - -#: src/ui/gui/psppire-var-store.c:489 -msgid "Scientific" -msgstr "Wissenschäflich" - -#: src/ui/gui/psppire-var-store.c:492 -msgid "Custom" -msgstr "Spezial" - -#: src/ui/gui/psppire-var-store.c:563 src/ui/gui/psppire-var-store.c:573 -#: src/ui/gui/psppire-var-store.c:583 -#, c-format -msgid "%d" -msgstr "" - #: src/ui/gui/rank.glade:111 msgid "By:" msgstr "" @@ -5627,6 +5640,11 @@ 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 "" @@ -5661,10 +5679,25 @@ 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 @@ -5696,26 +5729,6 @@ msgstr "Werten" 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" diff --git a/po/en_GB.po b/po/en_GB.po index 758a4e8f..fbafcf76 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -7,7 +7,7 @@ msgid "" 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 \n" "Language-Team: John Darrington \n" @@ -44,12 +44,6 @@ msgstr "" msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15." msgstr "" -#: src/data/casereader-filter.c:221 -msgid "" -"At least one case in the data read had a weight value that was user-missing, " -"system-missing, zero, or negative. These case(s) were ignored." -msgstr "" - #: src/data/case-tmpfile.c:57 msgid "failed to create temporary file" msgstr "" @@ -70,157 +64,163 @@ 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 "" @@ -302,33 +302,33 @@ msgstr[1] "" 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 "" @@ -402,149 +402,149 @@ 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." @@ -574,7 +574,7 @@ msgstr "" #. 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 "" @@ -584,297 +584,297 @@ 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 %." 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 "" @@ -893,44 +893,32 @@ 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." @@ -1169,7 +1157,7 @@ msgid "" 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 @@ -1177,17 +1165,17 @@ msgstr "" msgid "Variable" msgstr "" -#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:398 +#: src/language/data-io/data-list.c:435 src/language/data-io/print.c:402 msgid "Record" msgstr "" -#: 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 "" @@ -1207,17 +1195,17 @@ 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 " @@ -1226,97 +1214,127 @@ msgstr "" #. 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 "" @@ -1327,7 +1345,7 @@ 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 "" @@ -1406,11 +1424,6 @@ msgid "" "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 "" @@ -1428,39 +1441,39 @@ msgid "" "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 "" @@ -1504,39 +1517,39 @@ msgid "" "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." @@ -2295,11 +2308,11 @@ msgstr "" msgid "LO or LOWEST must be part of a range." msgstr "" -#: src/language/lexer/range-parser.c:106 +#: src/language/lexer/range-parser.c:107 msgid "System-missing value is not valid here." msgstr "" -#: src/language/lexer/range-parser.c:114 +#: src/language/lexer/range-parser.c:115 msgid "expecting number or data string" msgstr "" @@ -3038,73 +3051,73 @@ 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 "" @@ -3191,11 +3204,11 @@ 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 "" @@ -3207,6 +3220,22 @@ 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 "" @@ -3231,22 +3260,6 @@ msgid "" "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 "" @@ -3342,56 +3355,56 @@ 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 "" @@ -3873,44 +3886,44 @@ 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 "" @@ -3941,23 +3954,23 @@ 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 "" @@ -4976,7 +4989,7 @@ 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 "" @@ -5142,10 +5155,6 @@ msgstr "" msgid "Paste" msgstr "" -#: src/ui/gui/psppire.c:197 -msgid "_Reset" -msgstr "" - #: src/ui/gui/psppire-data-store.c:816 msgid "var" msgstr "" @@ -5155,6 +5164,28 @@ 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 "" @@ -5382,24 +5413,6 @@ 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 "" @@ -5556,6 +5569,11 @@ 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 "" @@ -5588,9 +5606,24 @@ 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 @@ -5622,26 +5655,6 @@ msgstr "" msgid "%s %s\n" msgstr "" -#: src/ui/gui/var-sheet.c:65 -msgid "Name" -msgstr "" - -#: src/ui/gui/var-sheet.c:68 -msgid "Decimals" -msgstr "" - -#: src/ui/gui/var-sheet.c:70 -msgid "Values" -msgstr "" - -#: src/ui/gui/var-sheet.c:73 -msgid "Align" -msgstr "" - -#: src/ui/gui/var-sheet.c:74 -msgid "Measure" -msgstr "" - #: src/ui/gui/weight-cases-dialog.c:88 #, c-format msgid "Weight cases by %s" diff --git a/src/data/ChangeLog b/src/data/ChangeLog index 7ddf9fd2..05bafc37 100644 --- a/src/data/ChangeLog +++ b/src/data/ChangeLog @@ -1,3 +1,80 @@ +2007-11-10 Ben Pfaff + + 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 * data-in.c: Make formatted data parsing locale-independent. diff --git a/src/data/automake.mk b/src/data/automake.mk index 112dc3b0..dc28a7f8 100644 --- a/src/data/automake.mk +++ b/src/data/automake.mk @@ -42,6 +42,8 @@ src_data_libdata_a_SOURCES = \ 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 \ diff --git a/src/data/calendar.c b/src/data/calendar.c index 7330b1a6..ac37f869 100644 --- a/src/data/calendar.c +++ b/src/data/calendar.c @@ -2,8 +2,8 @@ #include "calendar.h" #include #include -#include "settings.h" -#include "value.h" +#include +#include #include "gettext.h" #define _(msgid) gettext (msgid) diff --git a/src/data/case.h b/src/data/case.h index 10963a6e..aa5b9dd0 100644 --- a/src/data/case.h +++ b/src/data/case.h @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef HEADER_CASE -#define HEADER_CASE +#ifndef DATA_CASE_H +#define DATA_CASE_H 1 #include #include @@ -82,4 +82,4 @@ int case_compare_2dict (const struct ccase *, const struct ccase *, const union value *case_data_all (const struct ccase *); union value *case_data_all_rw (struct ccase *); -#endif /* case.h */ +#endif /* data/case.h */ diff --git a/src/data/data-in.h b/src/data/data-in.h index 19812886..d66b1c64 100644 --- a/src/data/data-in.h +++ b/src/data/data-in.h @@ -14,16 +14,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#if !data_in_h -#define data_in_h 1 +#ifndef DATA_DATA_IN_H +#define DATA_DATA_IN_H 1 -#include #include +#include #include #include #include #include -#include "format.h" enum integer_format data_in_get_integer_format (void); void data_in_set_integer_format (enum integer_format); @@ -31,8 +30,9 @@ void data_in_set_integer_format (enum integer_format); enum float_format data_in_get_float_format (void); void data_in_set_float_format (enum float_format); +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 */ diff --git a/src/data/data-out.c b/src/data/data-out.c index 02ff0657..26abc7cc 100644 --- a/src/data/data-out.c +++ b/src/data/data-out.c @@ -25,17 +25,16 @@ #include #include -#include "calendar.h" -#include "format.h" -#include "settings.h" -#include "value.h" +#include +#include +#include +#include #include #include #include #include #include -#include #include #include "minmax.h" diff --git a/src/data/dict-class.c b/src/data/dict-class.c new file mode 100644 index 00000000..c79b29a2 --- /dev/null +++ b/src/data/dict-class.c @@ -0,0 +1,60 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +/* Returns the dictionary class corresponding to a variable named + NAME. */ +enum dict_class +dict_class_from_id (const char *name) +{ + switch (name[0]) + { + default: + return DC_ORDINARY; + case '$': + return DC_SYSTEM; + case '#': + return DC_SCRATCH; + } +} + +/* Returns the name of dictionary class DICT_CLASS. + + This function should probably not be used in new code as it + can lead to difficulties for internationalization. */ +const char * +dict_class_to_name (enum dict_class dict_class) +{ + switch (dict_class) + { + case DC_ORDINARY: + return _("ordinary"); + case DC_SYSTEM: + return _("system"); + case DC_SCRATCH: + return _("scratch"); + default: + NOT_REACHED (); + } +} diff --git a/src/data/dict-class.h b/src/data/dict-class.h new file mode 100644 index 00000000..e3872e81 --- /dev/null +++ b/src/data/dict-class.h @@ -0,0 +1,42 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* 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 */ diff --git a/src/data/dictionary.c b/src/data/dictionary.c index 0f3e25e3..94a0292e 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -53,7 +53,7 @@ struct dictionary size_t split_cnt; /* SPLIT FILE count. */ struct variable *weight; /* WEIGHT variable. */ struct variable *filter; /* FILTER variable. */ - size_t 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. */ @@ -257,21 +257,26 @@ dict_get_var (const struct dictionary *d, size_t idx) return d->var[idx]; } -inline void +/* Sets *VARS to an array of pointers to variables in D and *CNT + to the number of variables in *D. All variables are returned + except for those, if any, in the classes indicated by EXCLUDE. + (There is no point in putting DC_SYSTEM in EXCLUDE as + dictionaries never include system variables.) */ +void dict_get_vars (const struct dictionary *d, const struct variable ***vars, - 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; @@ -279,15 +284,13 @@ dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars, assert (d != NULL); assert (vars != NULL); assert (cnt != NULL); - assert ((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++; } @@ -295,8 +298,8 @@ dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars, *cnt = 0; for (i = 0; i < d->var_cnt; i++) { - 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); @@ -480,7 +483,7 @@ reindex_vars (struct dictionary *d, size_t from, size_t to) active on the dictionary's dataset, because those transformations might reference the deleted variable. The safest time to delete a variable is just after a procedure has - 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, @@ -567,7 +570,7 @@ dict_delete_scratch_vars (struct dictionary *d) 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++; @@ -734,11 +737,12 @@ dict_get_weight (const struct dictionary *d) 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) @@ -798,6 +802,7 @@ dict_set_filter (struct dictionary *d, struct variable *v) { assert (d != NULL); assert (v == NULL || dict_contains_var (d, v)); + assert (v == NULL || var_is_numeric (v)); d->filter = v; @@ -809,7 +814,7 @@ dict_set_filter (struct dictionary *d, struct variable *v) /* Returns the case limit for dictionary D, or zero if the number of cases is unlimited. */ -size_t +casenumber dict_get_case_limit (const struct dictionary *d) { assert (d != NULL); @@ -820,7 +825,7 @@ dict_get_case_limit (const struct dictionary *d) /* Sets CASE_LIMIT as the case limit for dictionary D. Use 0 for CASE_LIMIT to indicate no limit. */ void -dict_set_case_limit (struct dictionary *d, size_t case_limit) +dict_set_case_limit (struct dictionary *d, casenumber case_limit) { assert (d != NULL); @@ -913,7 +918,7 @@ dict_count_values (const struct dictionary *d, unsigned int exclude_classes) cnt = 0; for (i = 0; i < d->var_cnt; i++) { - 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]); } @@ -941,20 +946,25 @@ dict_get_split_cnt (const struct dictionary *d) 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. */ @@ -999,16 +1009,7 @@ dict_set_label (struct dictionary *d, const char *label) assert (d != NULL); free (d->label); - if (label == NULL) - d->label = NULL; - else if (strlen (label) < 60) - d->label = xstrdup (label); - else - { - d->label = xmalloc (61); - memcpy (d->label, label, 60); - d->label[60] = '\0'; - } + d->label = label != NULL ? xstrndup (label, 60) : NULL; } /* Returns the documents for D, or a null pointer if D has no diff --git a/src/data/dictionary.h b/src/data/dictionary.h index 581a49d8..167487fb 100644 --- a/src/data/dictionary.h +++ b/src/data/dictionary.h @@ -14,132 +14,148 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef DICTIONARY_H -#define DICTIONARY_H +#ifndef DATA_DICTIONARY_H +#define DATA_DICTIONARY_H 1 #include #include +#include +#include -/* 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 */ diff --git a/src/data/format.c b/src/data/format.c index 54c62817..c90ff95b 100644 --- a/src/data/format.c +++ b/src/data/format.c @@ -66,7 +66,7 @@ fmt_done (void) { 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, @@ -305,18 +305,18 @@ fmt_check_output (const struct fmt_spec *spec) } /* 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; } @@ -329,7 +329,7 @@ fmt_check_type_compat (const struct fmt_spec *format, enum var_type var_type) bool fmt_check_width_compat (const struct fmt_spec *format, int width) { - 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) { @@ -342,14 +342,13 @@ fmt_check_width_compat (const struct fmt_spec *format, int 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); } @@ -499,7 +498,8 @@ fmt_max_output_decimals (enum fmt_type type, int width) 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, @@ -868,9 +868,9 @@ fmt_set_style (enum fmt_type type, struct fmt_number_style *style) assert (ss_length (style->suffix) <= FMT_STYLE_AFFIX_MAX); assert (ss_length (style->neg_suffix) <= FMT_STYLE_AFFIX_MAX); assert (style->decimal == '.' || style->decimal == ','); - assert (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); diff --git a/src/data/format.h b/src/data/format.h index fbaf0625..d00cb1d9 100644 --- a/src/data/format.h +++ b/src/data/format.h @@ -14,17 +14,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef FORMAT_H -#define FORMAT_H 1 +#ifndef DATA_FORMAT_H +#define DATA_FORMAT_H 1 /* Display format types. */ #include -#include -#include #include +#include -/* 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. */ @@ -41,6 +45,7 @@ enum fmt_category FMT_CAT_STRING = 0x100 /* String formats. */ }; +/* Format type. */ enum fmt_type { #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) FMT_##NAME, @@ -64,8 +69,6 @@ struct fmt_spec int d; /* Number of implied decimal places. */ }; -union value; - /* Initialization. */ void fmt_init (void); void fmt_done (void); @@ -74,13 +77,13 @@ void fmt_done (void); struct fmt_spec fmt_for_input (enum fmt_type, int w, int d) PURE_FUNCTION; struct fmt_spec fmt_for_output (enum fmt_type, int w, int d) PURE_FUNCTION; struct fmt_spec fmt_for_output_from_input (const struct fmt_spec *); -struct fmt_spec fmt_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. */ @@ -108,11 +111,11 @@ bool fmt_is_numeric (enum fmt_type) PURE_FUNCTION; enum fmt_category fmt_get_category (enum fmt_type) PURE_FUNCTION; enum fmt_type fmt_input_to_output (enum fmt_type) PURE_FUNCTION; +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 *); @@ -134,15 +137,15 @@ struct fmt_number_style struct fmt_number_style *fmt_number_style_create (void); void fmt_number_style_destroy (struct fmt_number_style *); -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 */ diff --git a/src/data/missing-values.c b/src/data/missing-values.c index c4d40baa..07ebb77a 100644 --- a/src/data/missing-values.c +++ b/src/data/missing-values.c @@ -18,6 +18,7 @@ #include "missing-values.h" #include #include +#include #include #include "variable.h" #include @@ -129,27 +130,18 @@ mv_add_num (struct missing_values *mv, double d) missing values MV. Returns true if successful, false if MV has no room for a range, or if LOW > HIGH. */ bool -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, @@ -157,44 +149,36 @@ mv_add_num_range (struct missing_values *mv, double low, double high) bool mv_has_value (const struct missing_values *mv) { - 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]; } @@ -222,19 +206,7 @@ mv_n_values (const struct missing_values *mv) bool mv_has_range (const struct missing_values *mv) { - switch (mv->type) - { - case MVT_RANGE: - case MVT_RANGE_1: - return true; - - case MVT_NONE: - case MVT_1: - case MVT_2: - case MVT_3: - return false; - } - NOT_REACHED (); + return mv->type == MVT_RANGE || mv->type == MVT_RANGE_1; } /* Removes the numeric range from MV and stores it in *LOW and @@ -249,12 +221,11 @@ mv_pop_range (struct missing_values *mv, double *low, double *high) 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; @@ -288,65 +259,39 @@ using_element (unsigned type, int idx) 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; } diff --git a/src/data/missing-values.h b/src/data/missing-values.h index 4f87f543..b504f8c7 100644 --- a/src/data/missing-values.h +++ b/src/data/missing-values.h @@ -14,11 +14,27 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#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 -#include "value.h" +#include "data/value.h" /* Missing values. Opaque--use access functions defined below. */ @@ -26,7 +42,7 @@ struct missing_values { int type; /* Types of missing values, one of MVT_*. */ int width; /* 0=numeric, otherwise string width. */ - 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. */ @@ -38,41 +54,44 @@ enum mv_class 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 */ diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c index ce1f562f..b5486a4a 100644 --- a/src/data/por-file-reader.c +++ b/src/data/por-file-reader.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -669,8 +670,8 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) 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; @@ -692,12 +693,12 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) { 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')) diff --git a/src/data/procedure.c b/src/data/procedure.c index e446a659..278077e7 100644 --- a/src/data/procedure.c +++ b/src/data/procedure.c @@ -664,10 +664,10 @@ static trns_free_func case_limit_trns_free; 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); diff --git a/src/data/short-names.h b/src/data/short-names.h index d5bbb205..2bce53e9 100644 --- a/src/data/short-names.h +++ b/src/data/short-names.h @@ -33,6 +33,9 @@ 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 */ diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c index b00a7b23..1d172ade 100644 --- a/src/data/sys-file-reader.c +++ b/src/data/sys-file-reader.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -263,8 +264,8 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, for (i = 0; i < dict_get_var_cnt (*dict); i++) { struct variable *var = dict_get_var (*dict, i); - 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)); @@ -542,7 +543,7 @@ read_variable_record (struct sfm_reader *r, struct dictionary *dict, { 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++) diff --git a/src/data/sys-file-writer.c b/src/data/sys-file-writer.c index 3e0d3499..acf9d5c0 100644 --- a/src/data/sys-file-writer.c +++ b/src/data/sys-file-writer.c @@ -445,14 +445,14 @@ write_variable (struct sfm_writer *w, const struct variable *v) 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); } diff --git a/src/data/val-type.h b/src/data/val-type.h new file mode 100644 index 00000000..27139af9 --- /dev/null +++ b/src/data/val-type.h @@ -0,0 +1,55 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef DATA_VAL_TYPE_H +#define DATA_VAL_TYPE_H 1 + +#include +#include +#include + +/* 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 */ diff --git a/src/data/value-labels.c b/src/data/value-labels.c index b9acc2bd..6387f72f 100644 --- a/src/data/value-labels.c +++ b/src/data/value-labels.c @@ -66,7 +66,7 @@ val_labs_create (int width) /* 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; @@ -82,46 +82,29 @@ val_labs_copy (const struct val_labs *vls) 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) { @@ -186,64 +169,61 @@ create_int_val_lab (struct val_labs *vls, union value value, const char *label) 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); @@ -298,7 +278,10 @@ val_labs_first (const struct val_labs *vls, struct val_labs_iterator **ip) assert (ip != NULL); if (vls->labels == NULL || vls->width > MAX_SHORT_STRING) - return NULL; + { + *ip = NULL; + return NULL; + } i = *ip = xmalloc (sizeof *i); i->labels = hsh_data_copy (vls->labels); @@ -322,7 +305,10 @@ val_labs_first_sorted (const struct val_labs *vls, assert (ip != NULL); if (vls->labels == NULL || vls->width > MAX_SHORT_STRING) - return NULL; + { + *ip = NULL; + return NULL; + } i = *ip = xmalloc (sizeof *i); i->lp = i->labels = hsh_sort_copy (vls->labels); @@ -367,15 +353,13 @@ val_labs_next (const struct val_labs *vls, struct val_labs_iterator **ip) void val_labs_done (struct val_labs_iterator **ip) { - 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; + } } /* Compares two value labels and returns a strcmp()-type result. */ diff --git a/src/data/value-labels.h b/src/data/value-labels.h index ce863a40..fb7ec22b 100644 --- a/src/data/value-labels.h +++ b/src/data/value-labels.h @@ -14,39 +14,49 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#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 #include - #include -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 *, @@ -55,4 +65,4 @@ struct val_lab *val_labs_next (const struct val_labs *, struct val_labs_iterator **); void val_labs_done (struct val_labs_iterator **); -#endif /* value-labels.h */ +#endif /* data/value-labels.h */ diff --git a/src/data/value.c b/src/data/value.c index cd52f147..34e3fe58 100644 --- a/src/data/value.c +++ b/src/data/value.c @@ -15,8 +15,9 @@ along with this program. If not, see . */ #include -#include "value.h" +#include +#include #include #include @@ -83,3 +84,32 @@ value_set_missing (union value *v, int width) else memset (v->s, ' ', width); } + +/* Tests whether VALUE may be resized from OLD_WIDTH to + NEW_WIDTH, using the following rules that match those for + resizing missing values and value labels. First, OLD_WIDTH + and NEW_WIDTH must be both numeric or both string. Second, if + NEW_WIDTH is less than OLD_WIDTH, then the bytes that would be + trimmed off the right end of VALUE must be all spaces. */ +bool +value_is_resizable (const union value *value, int old_width, int new_width) +{ + int i; + + if (val_type_from_width (old_width) != val_type_from_width (new_width)) + return false; + for (i = new_width; i < old_width; i++) + if (value->s[i] != ' ') + return false; + return true; +} + +/* Resizes VALUE from OLD_WIDTH to NEW_WIDTH. The arguments must + satisfy the rules specified above for value_is_resizable. */ +void +value_resize (union value *value, int old_width, int new_width) +{ + assert (value_is_resizable (value, old_width, new_width)); + if (new_width > old_width) + memset (&value->s[old_width], ' ', new_width - old_width); +} diff --git a/src/data/value.h b/src/data/value.h index b7a7ee70..cb66cb08 100644 --- a/src/data/value.h +++ b/src/data/value.h @@ -1,5 +1,5 @@ /* 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 @@ -14,35 +14,18 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#if !value_h -#define value_h 1 +#ifndef DATA_VALUE_H +#define DATA_VALUE_H 1 -#include -#include #include +#include #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. */ @@ -58,7 +41,18 @@ union value *value_create (int width); int compare_values (const union value *, const union value *, int width); unsigned hash_value (const union value *, int width); +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 */ diff --git a/src/data/vardict.h b/src/data/vardict.h index aaf8ba05..35440a0d 100644 --- a/src/data/vardict.h +++ b/src/data/vardict.h @@ -31,13 +31,14 @@ struct vardict_info 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); diff --git a/src/data/variable.c b/src/data/variable.c index 4a2e4405..4623b77b 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -44,7 +44,7 @@ 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. */ @@ -77,20 +77,6 @@ struct variable 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; -} /* Creates and returns a new variable with the given NAME and WIDTH and other fields initialized to default values. The @@ -271,11 +257,11 @@ var_is_plausible_name (const char *name, bool issue_error) msg (SE, _("Variable name cannot be empty string.")); return false; } - 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; } @@ -290,6 +276,13 @@ var_is_plausible_name (const char *name, bool issue_error) 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 @@ -333,10 +326,10 @@ hash_var_ptr_by_name (const void *v_, const void *aux UNUSED) } /* 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. */ @@ -346,7 +339,8 @@ var_get_width (const struct 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) { @@ -388,7 +382,7 @@ 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 @@ -396,7 +390,7 @@ var_is_numeric (const struct variable *v) bool var_is_alpha (const struct variable *v) { - return var_get_type (v) == VAR_STRING; + return var_get_type (v) == VAL_STRING; } /* Returns true if variable V is a short string variable, false @@ -520,7 +514,7 @@ var_set_value_labels (struct variable *v, const struct val_labs *vls) if (vls != NULL) { assert (val_labs_can_set_width (vls, v->width)); - 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); } @@ -538,8 +532,7 @@ alloc_value_labels (struct variable *v) /* Attempts to add a value label with the given VALUE and LABEL to V. Returns true if successful, false if VALUE has an - 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) @@ -550,7 +543,7 @@ var_add_value_label (struct variable *v, /* Adds or replaces a value label with the given VALUE and LABEL to V. - 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) @@ -768,7 +761,7 @@ var_set_alignment (struct variable *v, enum alignment alignment) case. */ /* Returns true if variable V's value should be left from case to - case, 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) { @@ -789,7 +782,7 @@ var_set_leave (struct variable *v, bool leave) 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; } /* Returns the number of short names stored in VAR. @@ -960,7 +953,8 @@ var_get_obs_vals (const struct variable *v) return v->obs_vals; } -/* 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) { @@ -977,39 +971,6 @@ var_has_obs_vals (const struct variable *v) return v->obs_vals != NULL; } -/* Returns the dictionary class corresponding to a variable named - NAME. */ -enum dict_class -dict_class_from_id (const char *name) -{ - 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 (); - } -} - /* Returns V's vardict structure. */ const struct vardict_info * var_get_vardict (const struct variable *v) diff --git a/src/data/variable.h b/src/data/variable.h index 44cfba70..66257e0e 100644 --- a/src/data/variable.h +++ b/src/data/variable.h @@ -14,40 +14,33 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#if !variable_h -#define variable_h 1 +#ifndef DATA_VARIABLE_H +#define DATA_VARIABLE_H 1 #include #include +#include #include +#include 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 *); @@ -55,17 +48,16 @@ unsigned hash_var_by_name (const void *, const void *); int compare_var_ptrs_by_name (const void *, const void *, const void *); unsigned hash_var_ptr_by_name (const void *, const void *); -/* 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. */ @@ -80,17 +72,19 @@ bool var_is_num_missing (const struct variable *, double, enum mv_class); bool var_is_str_missing (const struct variable *, const char[], enum mv_class); /* Value labels. */ -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 *); @@ -167,15 +161,7 @@ struct cat_vals *var_get_obs_vals (const struct variable *); void var_set_obs_vals (const struct variable *, struct cat_vals *); bool var_has_obs_vals (const struct variable *); -/* 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 */ diff --git a/src/data/vector.c b/src/data/vector.c index cc4c96f0..fd65d284 100644 --- a/src/data/vector.c +++ b/src/data/vector.c @@ -27,7 +27,7 @@ /* 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. */ }; @@ -108,7 +108,7 @@ vector_get_name (const struct vector *vector) } /* Returns the type of the variables in VECTOR. */ -enum var_type vector_get_type (const struct vector *vector) +enum val_type vector_get_type (const struct vector *vector) { return var_get_type (vector->vars[0]); } diff --git a/src/data/vector.h b/src/data/vector.h index 0f435982..b009fcb2 100644 --- a/src/data/vector.h +++ b/src/data/vector.h @@ -30,7 +30,7 @@ struct vector *vector_clone (const struct vector *old, void vector_destroy (struct vector *); const char *vector_get_name (const struct vector *); -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 *); diff --git a/src/language/data-io/data-list.c b/src/language/data-io/data-list.c index 4fea7a40..9e950e9c 100644 --- a/src/language/data-io/data-list.c +++ b/src/language/data-io/data-list.c @@ -65,7 +65,7 @@ struct dls_var_spec /* All parsers. */ struct fmt_spec input; /* Input format of this field. */ int fv; /* First value in case. */ - 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). */ diff --git a/src/language/data-io/file-handle.q b/src/language/data-io/file-handle.q index 35fabc08..af5fa332 100644 --- a/src/language/data-io/file-handle.q +++ b/src/language/data-io/file-handle.q @@ -50,7 +50,7 @@ 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; diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index d22a4e50..ed490ced 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -735,8 +735,8 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) 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; diff --git a/src/language/data-io/list.q b/src/language/data-io/list.q index 8b3eead8..8e8bba9b 100644 --- a/src/language/data-io/list.q +++ b/src/language/data-io/list.q @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -150,7 +151,7 @@ cmd_list (struct lexer *lexer, struct dataset *ds) cmd.last = LONG_MAX; if (!cmd.sbc_variables) dict_get_vars (dict, &cmd.v_variables, &cmd.n_variables, - (1u << DC_SYSTEM) | (1u << DC_SCRATCH)); + DC_SYSTEM | DC_SCRATCH); if (cmd.n_variables == 0) { msg (SE, _("No variables specified.")); @@ -507,7 +508,7 @@ write_fallback_headers (struct outp_driver *d) } { - char varname[LONG_NAME_LEN + 2]; + char varname[VAR_NAME_LEN + 2]; snprintf (varname, sizeof varname, " %s", var_get_name (cmd.v_variables[index])); write_varname (d, varname, leader_width); diff --git a/src/language/dictionary/formats.c b/src/language/dictionary/formats.c index 3be32e76..d18606a5 100644 --- a/src/language/dictionary/formats.c +++ b/src/language/dictionary/formats.c @@ -91,7 +91,7 @@ internal_cmd_formats (struct lexer *lexer, struct dataset *ds, int which) } if (!parse_format_specifier (lexer, &f) || !fmt_check_output (&f) - || !fmt_check_type_compat (&f, VAR_NUMERIC)) + || !fmt_check_type_compat (&f, VAL_NUMERIC)) goto fail; if (!lex_match (lexer, ')')) diff --git a/src/language/dictionary/missing-values.c b/src/language/dictionary/missing-values.c index 12095318..d5bbf108 100644 --- a/src/language/dictionary/missing-values.c +++ b/src/language/dictionary/missing-values.c @@ -88,7 +88,7 @@ cmd_missing_values (struct lexer *lexer, struct dataset *ds) 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; diff --git a/src/language/dictionary/modify-variables.c b/src/language/dictionary/modify-variables.c index 9fc6fa55..cd501691 100644 --- a/src/language/dictionary/modify-variables.c +++ b/src/language/dictionary/modify-variables.c @@ -138,7 +138,7 @@ cmd_modify_vars (struct lexer *lexer, struct dataset *ds) "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 { @@ -367,7 +367,7 @@ compare_variables_given_ordering (const void *a_, const void *b_, 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 diff --git a/src/language/dictionary/vector.c b/src/language/dictionary/vector.c index e61ee53a..1a616ab2 100644 --- a/src/language/dictionary/vector.c +++ b/src/language/dictionary/vector.c @@ -135,7 +135,7 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) seen_format = true; if (!parse_format_specifier (lexer, &format) || !fmt_check_output (&format) - || !fmt_check_type_compat (&format, VAR_NUMERIC)) + || !fmt_check_type_compat (&format, VAL_NUMERIC)) goto fail; } else @@ -152,16 +152,16 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) } /* 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; @@ -181,7 +181,7 @@ cmd_vector (struct lexer *lexer, struct dataset *ds) 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); diff --git a/src/language/expressions/evaluate.c b/src/language/expressions/evaluate.c index 52dafef8..a0a133ad 100644 --- a/src/language/expressions/evaluate.c +++ b/src/language/expressions/evaluate.c @@ -126,7 +126,7 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED) 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; diff --git a/src/language/expressions/parse.c b/src/language/expressions/parse.c index 5ae49944..40b0a7ab 100644 --- a/src/language/expressions/parse.c +++ b/src/language/expressions/parse.c @@ -356,7 +356,7 @@ type_coercion_core (struct expression *e, msg_disable (); if ((*node)->type == OP_format && fmt_check_input (&(*node)->format.f) - && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC)) + && fmt_check_type_compat (&(*node)->format.f, VAL_NUMERIC)) { msg_enable (); if (do_coercion) @@ -370,7 +370,7 @@ type_coercion_core (struct expression *e, msg_disable (); if ((*node)->type == OP_format && fmt_check_output (&(*node)->format.f) - && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC)) + && fmt_check_type_compat (&(*node)->format.f, VAL_NUMERIC)) { msg_enable (); if (do_coercion) @@ -918,7 +918,7 @@ parse_vector_element (struct lexer *lexer, struct expression *e) || !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)); } diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 79657df7..ac0af600 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -52,7 +52,7 @@ struct lexer 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 diff --git a/src/language/lexer/variable-parser.c b/src/language/lexer/variable-parser.c index 37781561..1194110e 100644 --- a/src/language/lexer/variable-parser.c +++ b/src/language/lexer/variable-parser.c @@ -405,8 +405,8 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv int d1, d2; int n; size_t nvar, mvar; - 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); @@ -474,7 +474,7 @@ parse_DATA_LIST_vars (struct lexer *lexer, char ***names, size_t *nnames, int pv 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++; @@ -664,7 +664,7 @@ var_set_lookup_var_idx (const struct var_set *vs, const char *name, { 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); } diff --git a/src/language/stats/aggregate.c b/src/language/stats/aggregate.c index 18d78f23..f58b97cf 100644 --- a/src/language/stats/aggregate.c +++ b/src/language/stats/aggregate.c @@ -92,7 +92,7 @@ struct agr_func { 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. */ }; @@ -103,25 +103,25 @@ static const struct agr_func agr_func_tab[] = {"SUM", 0, -1, {FMT_F, 8, 2}}, {"MEAN", 0, -1, {FMT_F, 8, 2}}, {"SD", 0, -1, {FMT_F, 8, 2}}, - {"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. */ @@ -478,12 +478,12 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, s if (lex_token (lexer) == T_STRING) { arg[i].c = ds_xstrdup (lex_tokstr (lexer)); - 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 { @@ -573,12 +573,12 @@ parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, s 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) { diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index e1ca73bb..72f7476a 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -123,7 +123,7 @@ static const struct dsc_statistic_info dsc_info[DSC_N_STATS] = struct dsc_var { const struct variable *v; /* Variable to calculate on. */ - 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. */ @@ -495,7 +495,7 @@ static bool generate_z_varname (const struct dictionary *dict, struct dsc_proc *dsc, char *z_name, const char *var_name, int *z_cnt) { - char name[LONG_NAME_LEN + 1]; + char name[VAR_NAME_LEN + 1]; /* Try a name based on the original variable name. */ name[0] = 'Z'; diff --git a/src/language/stats/flip.c b/src/language/stats/flip.c index 3fe43eb9..6c49bd37 100644 --- a/src/language/stats/flip.c +++ b/src/language/stats/flip.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -117,7 +118,7 @@ cmd_flip (struct lexer *lexer, struct dataset *ds) 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, '/'); diff --git a/src/language/stats/frequencies.q b/src/language/stats/frequencies.q index ce313678..fdb19b03 100644 --- a/src/language/stats/frequencies.q +++ b/src/language/stats/frequencies.q @@ -636,12 +636,12 @@ postcalc (void) } /* 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: diff --git a/src/language/stats/rank.q b/src/language/stats/rank.q index 91520f5e..5bc88c4a 100644 --- a/src/language/stats/rank.q +++ b/src/language/stats/rank.q @@ -19,23 +19,24 @@ #include #include -#include -#include -#include -#include -#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include #include #include -#include #include +#include #include diff --git a/src/language/stats/regression.q b/src/language/stats/regression.q index e3b3f5ee..12a7cf5e 100644 --- a/src/language/stats/regression.q +++ b/src/language/stats/regression.q @@ -637,16 +637,16 @@ try_name (const struct dictionary *dict, const char *name) } 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); } } @@ -656,7 +656,7 @@ reg_save_var (struct dataset *ds, const char *prefix, trns_proc_func * f, { struct dictionary *dict = dataset_dict (ds); static int trns_index = 1; - char name[LONG_NAME_LEN]; + char name[VAR_NAME_LEN]; struct variable *new_var; struct reg_trns *t = NULL; @@ -1154,8 +1154,7 @@ run_regression (struct casereader *input, struct cmd_regression *cmd, if (!v_variables) { - 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++) diff --git a/src/language/stats/t-test.q b/src/language/stats/t-test.q index 23237072..c0e90705 100644 --- a/src/language/stats/t-test.q +++ b/src/language/stats/t-test.q @@ -147,7 +147,7 @@ struct pair 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; @@ -565,9 +565,9 @@ tts_custom_pairs (struct lexer *lexer, struct dataset *ds, struct cmd_t_test *cm /* Parses the current token (numeric or string, depending on type) value v and returns success. */ static int -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; diff --git a/src/language/xforms/compute.c b/src/language/xforms/compute.c index ec5a15a1..f17798f7 100644 --- a/src/language/xforms/compute.c +++ b/src/language/xforms/compute.c @@ -258,7 +258,7 @@ cmd_if (struct lexer *lexer, struct dataset *ds) static trns_proc_func * get_proc_func (const struct lvalue *lvalue) { - bool is_numeric = lvalue_get_type (lvalue) == VAR_NUMERIC; + bool is_numeric = lvalue_get_type (lvalue) == VAL_NUMERIC; bool is_vector = lvalue_is_vector (lvalue); return (is_numeric @@ -272,7 +272,7 @@ static struct expression * parse_rvalue (struct lexer *lexer, const struct lvalue *lvalue, struct dataset *ds) { - 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); } diff --git a/src/language/xforms/recode.c b/src/language/xforms/recode.c index 1cb29b84..85fcb9ea 100644 --- a/src/language/xforms/recode.c +++ b/src/language/xforms/recode.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -90,8 +91,8 @@ struct recode_trns 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. */ @@ -112,7 +113,7 @@ static void add_mapping (struct recode_trns *, size_t *map_allocated, const struct map_in *); static bool parse_map_in (struct lexer *lexer, struct map_in *, struct pool *, - 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 *, @@ -153,7 +154,7 @@ cmd_recode (struct lexer *lexer, struct dataset *ds) /* Ensure that all the output strings are at least as wide as the widest destination variable. */ - if (trns->dst_type == VAR_STRING) + if (trns->dst_type == VAL_STRING) enlarge_dst_widths (trns); /* Create destination variables, if needed. @@ -215,7 +216,7 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns) return false; do { - enum var_type dst_type; + enum val_type dst_type; if (!lex_match_id (lexer, "CONVERT")) { @@ -239,7 +240,7 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns) if (!parse_map_out (lexer, trns->pool, &out)) return false; - 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. " @@ -259,9 +260,9 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns) add_mapping (trns, &map_allocated, &in); set_map_out_num (&trns->mappings[trns->map_cnt - 1].out, 0.0); - 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.")); @@ -286,11 +287,11 @@ parse_mappings (struct lexer *lexer, struct recode_trns *trns) false on parse error. */ static bool parse_map_in (struct lexer *lexer, struct map_in *in, struct pool *pool, - 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); @@ -449,7 +450,7 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns, { const struct variable *v; v = trns->dst_vars[i] = dict_lookup_var (dict, trns->dst_names[i]); - 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 " @@ -468,8 +469,8 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns, { msg (SE, _("INTO is required with %s input values " "and %s output values."), - 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; } } @@ -481,7 +482,7 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns, { msg (SE, _("Type mismatch. Cannot store %s data in " "%s variable %s."), - 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; @@ -640,12 +641,12 @@ recode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED) 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; diff --git a/src/libpspp/model-checker.c b/src/libpspp/model-checker.c index 1026aa9c..cb51c485 100644 --- a/src/libpspp/model-checker.c +++ b/src/libpspp/model-checker.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include diff --git a/src/math/factor-stats.c b/src/math/factor-stats.c index 1b91e84e..582b8346 100644 --- a/src/math/factor-stats.c +++ b/src/math/factor-stats.c @@ -16,6 +16,7 @@ #include #include "factor-stats.h" +#include #include #include #include diff --git a/src/math/moments.c b/src/math/moments.c index a5be12e9..084e6d8c 100644 --- a/src/math/moments.c +++ b/src/math/moments.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "xalloc.h" diff --git a/src/math/percentiles.c b/src/math/percentiles.c index 5c36fc14..aa7eead6 100644 --- a/src/math/percentiles.c +++ b/src/math/percentiles.c @@ -16,6 +16,7 @@ #include #include +#include #include #include "factor-stats.h" #include "percentiles.h" diff --git a/src/ui/gui/missing-val-dialog.c b/src/ui/gui/missing-val-dialog.c index 3a350735..576701c1 100644 --- a/src/ui/gui/missing-val-dialog.c +++ b/src/ui/gui/missing-val-dialog.c @@ -148,7 +148,7 @@ missing_val_dialog_accept (GtkWidget *w, gpointer data) g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->discrete))); mv_clear (&dialog->mvl); - 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 ) { @@ -307,7 +307,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog) 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); @@ -321,7 +321,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog) { 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); @@ -344,7 +344,7 @@ missing_val_dialog_show (struct missing_val_dialog *dialog) 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); diff --git a/src/ui/gui/val-labs-dialog.c b/src/ui/gui/val-labs-dialog.c index 05068d0f..7e558eec 100644 --- a/src/ui/gui/val-labs-dialog.c +++ b/src/ui/gui/val-labs-dialog.c @@ -519,7 +519,7 @@ val_labs_dialog_show (struct val_labs_dialog *dialog) 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)); diff --git a/src/ui/gui/var-display.c b/src/ui/gui/var-display.c index 114156d7..62c3eeee 100644 --- a/src/ui/gui/var-display.c +++ b/src/ui/gui/var-display.c @@ -63,7 +63,7 @@ missing_values_to_string (const struct variable *pv, GError **err) 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, ", "); @@ -78,7 +78,7 @@ missing_values_to_string (const struct variable *pv, GError **err) GString *gstr = g_string_sized_new (10); gchar *l, *h; union value low, high; - 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); @@ -91,7 +91,7 @@ missing_values_to_string (const struct variable *pv, GError **err) { gchar *ss = 0; union value v; - mv_peek_value (miss, &v, 0); + mv_get_value (miss, &v, 0); ss = value_to_text (v, *fmt); diff --git a/src/ui/gui/var-type-dialog.c b/src/ui/gui/var-type-dialog.c index dfdd895f..bee65de8 100644 --- a/src/ui/gui/var-type-dialog.c +++ b/src/ui/gui/var-type-dialog.c @@ -790,14 +790,14 @@ on_var_type_ok_clicked (GtkWidget *w, gpointer data) gint decimals = atoi (gtk_entry_get_text (GTK_ENTRY (dialog->entry_decimals))); - gint 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;