q2c Input Format
This manual is for GNU PSPP version 0.6.0, software for statistical analysis.
Copyright © 1997, 1998, 2004, 2005, 2007 Free Software Foundation, Inc.
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 the freedom to copy and modify this GNU manual.”
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. See Introduction.
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.
This chapter introduces basic data structures and other concepts needed for developing in PSPP.
The unit of data in PSPP is a value.
Values are classified by type and width. The
type of a value is either numeric or string (sometimes
called alphanumeric). The width of a string value ranges from 1 to
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 data/val-type.h:
Returns true if val_type is a valid value type, that is, either
VAL_NUMERICorVAL_STRING. Useful for assertions.
Returns
VAL_NUMERICif width is 0 and thus represents the width of a numeric value, otherwiseVAL_STRINGto indicate that width is the width of a string value.
The following subsections describe how values of each type are represented.
A value known to be numeric at compile time is represented as a
double. PSPP provides three values of double for
special purposes, defined in data/val-type.h:
The 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. See Missing Observations, for a PSPP user's view of missing values.
PSPP currently defines
SYSMISas-DBL_MAX, that is, the greatest finite negative value ofdouble. 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.
The greatest finite negative (except for
SYSMIS) and positive values ofdouble, 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.5 THRU HIas a range of missing values (see MISSING VALUES).
A value known at compile time to have string type is represented as an
array of 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.
SYSMIS, LOWEST, and 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.
MAX_STRING, the maximum length of a string value, is defined in
data/val-type.h.
When a value's type is only known at runtime, it is often represented
as a union value, defined in data/value.h. union value has
two members: a double named `f' to store a numeric value
and an array of char named `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 valuess must therefore have
external knowledge of its content, often through the type and width of
a struct variable (see Variables).
The array of char in union value has only a small, fixed
capacity of MAX_SHORT_STRING bytes. A value that
fits within this capacity is called a short string. Any wider
string value, which must be represented by more than one
union value, is called a long string.
Maximum width of a short string value, never less than 8 bytes. It is wider than 8 bytes on systems where
doubleis either larger than 8 bytes or has stricter alignment than 8 bytes.
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 (see Missing Observations).
PSPP provides a few functions for working with union values. The
most useful are described below. To use these functions, recall that
a numeric value has a width of 0.
Returns the number of consecutive
union values that must be allocated to store a value of the given width. For a numeric or short string value, the return value is 1; for long string variables, it is greater than 1.
Copies a value of the given width from the
union valuearray starting at src to the one starting at dst. The two arrays must not overlap.
Sets value to
SYSMISif it is numeric or to all spaces if it is alphanumeric, according to width. value must point to the start of aunion valuearray of the given width.
Determines whether value may be resized from old_width to new_width. Resizing is possible if the following criteria are met. First, old_width and new_width must be both numeric or both string widths. Second, if new_width is a short string width and less than old_width, resizing is allowed only if bytes new_width through old_width in value contain only spaces.
These rules are part of those used by
mv_is_resizableandval_labs_can_set_width.
Resizes value from old_width to new_width, which must be allowed by the rules stated above. This has an effect only if new_width is greater than old_width, in which case the bytes newly added to value are cleared to spaces.
Input and output formats specify how to convert data fields to and
from data values (see Input and Output Formats). PSPP uses struct fmt_spec to represent input and output
formats.
Function prototypes and other declarations related to formats are in the <data/format.h> header.
An input or output format, with the following members:
enum fmt_type type- The format type (see below).
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 fmt_max_input_width, fmt_max_output_width).
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
d(see fmt_max_input_decimals, fmt_max_output_decimals).
An enumerated type representing an input or output format type. Each PSPP input and output format has a corresponding enumeration constant prefixed by `FMT':
FMT_F,FMT_COMMA,FMT_DOT, and so on.
The following sections describe functions for manipulating formats and the data in fields represented by formats.
These functions construct struct fmt_specs and verify that they are
valid.
Constructs a
struct fmt_specwith the given type, w, and d, asserts that the result is a valid input (or output) format, and returns it.
Given input, which must be a valid input format, returns the equivalent output format. See Input and Output Formats, for the rules for converting input formats into output formats.
Returns the default output format for a variable of the given width. For a numeric variable, this is F8.2 format; for a string variable, it is the A format of the given width.
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
msg. To suppress error output, enclose a call to one of these
functions by a msg_disable/msg_enable pair.
Checks whether format is a valid input format (for
fmt_check_input, orfmt_checkif for_input) or output format (forfmt_check_output, orfmt_checkif not for_input).
Checks whether format matches the value type type, that is, if type is
VAL_NUMERICand format is a numeric format or type isVAL_STRINGand format is a string format.
Checks whether format may be used as an output format for a value of the given width.
fmt_var_width, described in the following section, can be also be used to determine the value width needed by a format.
These functions work with struct fmt_specs.
Returns the width for values associated with format. If format is a numeric format, the width is 0; if format is an A format, then the width format
->w; otherwise, format is an AHEX format and its width is format->w / 2.
Converts format to a human-readable format specifier in s and returns s. 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 format has decimals, they are included in the output string, even if format's type does not allow decimals, to allow accurately presenting incorrect formats to the user.
Compares a and b memberwise and returns true if they are identical, false otherwise. format need not be a valid input or output format specifier.
Sets the width of fmt to a valid format for a
union valueof size width.
These functions work with enum fmt_types instead of the higher-level
struct fmt_specs. 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.
Returns the name for the given type, e.g.
"COMMA"forFMT_COMMA.
Tries to find the
enum fmt_typeassociated with name. If successful, sets*type to the type and returns true; otherwise, returns false without modifying*type.
The functions below query basic limits on width and decimal places for each kind of format.
Returns true if a format of the given type is allowed to have a nonzero number of decimal places (the
dmember ofstruct fmt_spec), false if not.
Returns the minimum or maximum width (the
wmember ofstruct fmt_spec) allowed for an input or output format of the specified type.
Returns the maximum number of decimal places allowed for an input or output format, respectively, of the given type and width. Returns 0 if the specified type does not allow any decimal places or if width is too narrow to allow decimal places.
Returns the “width step” for a
struct fmt_specof the given type. Astruct 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.
These functions allow clients to broadly determine how each kind of input or output format behaves.
Returns true if type is a format for numeric or string values, respectively, false otherwise.
Returns the category within which type falls.
— 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 (see Input and Output Formats).
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.
if (fmt_get_category (type) & (FMT_CAT_DATE | FMT_CAT_TIME)) { /* ...typeis a date or time format... */ }The format categories are:
FMT_CAT_BASIC- Basic numeric formats.
FMT_CAT_CUSTOM- Custom currency formats.
FMT_CAT_LEGACY- Legacy numeric formats.
FMT_CAT_BINARY- Binary formats.
FMT_CAT_HEXADECIMAL- Hexadecimal formats.
FMT_CAT_DATE- Date formats.
FMT_CAT_TIME- Time formats.
FMT_CAT_DATE_COMPONENT- Date component formats.
FMT_CAT_STRING- String formats.
The PSPP input and output routines use the following pair of functions
to convert enum fmt_types to and from the separate set of codes used
in system and portable files:
Returns the format code used in system and portable files that corresponds to type.
Converts io, a format code used in system and portable files, into a
enum fmt_typein*type. Returns true if successful, false if io is not valid.
These functions reflect the relationship between input and output formats.
Returns the output format type that is used by default by DATA LIST and other input procedures when type is specified as an input format. The conversion from input format to output format is more complicated than simply changing the format. See fmt_for_output_from_input, for a function that performs the entire conversion.
Returns true if 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.
The final group of format type property functions obtain human-readable templates that illustrate the formats graphically.
Returns a formatting template for type, which must be a date or time format type. These formats are used by
data_inanddata_outto guide parsing and formatting date and time data.
Returns a string of the form
$#,###.##according to format, which must be of typeFMT_DOLLAR. The caller must free the string withfree.
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.
A structure type with the following members:
struct substring neg_prefixstruct substring prefixstruct substring suffixstruct 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
FMT_STYLE_AFFIX_MAXbytes (currently 16) bytes in length. These strings must be freed withss_deallocwhen no longer needed.decimal- The character used as a decimal point. It must be either `.' or `,'.
grouping- The character used for grouping digits to the left of the decimal point. It may be `.' or `,', in which case it must not be equal to
decimal, or it may be set to 0 to disable grouping.
The following functions are provided for working with numeric formatting styles.
Initialises a
struct fmt_number_stylewith all of the prefixes and suffixes set to the empty string, `.' as the decimal point character, and grouping disables.
Destroys style, freeing its storage.
A function which creates an array of all the styles used by pspp, and calls fmt_number_style_init on each of them.
A wrapper function which takes an array of
struct fmt_number_style, calls fmt_number_style_destroy on each of them, and then frees the array.
Returns the total length of style's
prefixandsuffix.
Returns the total length of style's
neg_prefixandneg_suffix.
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:
Returns the numeric style for the given format type.
Asserts that style is self consistent.
These functions provide the ability to convert data fields into
union values and vice versa.
Parses input as a field containing data in the given format type. The resulting value is stored in output, which has the given width. For consistency, width must be 0 if type is a numeric format type and greater than 0 if type is a string format type.
Ordinarily legacy_encoding should be
LEGACY_NATIVE, indicating that input is encoded in the character set conventionally used on the host machine. It may be set toLEGACY_EBCDICto cause input to be re-encoded from EBCDIC during data parsing.If input is the empty string (with length 0), output is set to the value set on SET BLANKS (see SET BLANKS) for a numeric value, or to all spaces for a string value. This applies regardless of the usual parsing requirements for type.
If implied_decimals is greater than zero, then the numeric result is shifted right by implied_decimals decimal places if 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, implied_decimals has no effect. DATA LIST FIXED is the primary user of this feature (see DATA LIST FIXED). Other callers should generally specify 0 for implied_decimals, to disable this feature.
When input contains invalid input data,
data_inoutputs a message usingmsg. If 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 first_column + input - 1. To suppress error output, enclose the call todata_inby calls tomsg_disableandmsg_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 data/data-in.h.
Converts the data pointed to by input into a data field in output according to output format specifier format, which must be a valid output format. Exactly format
->wbytes are written to output. The width of input is also inferred from format using an algorithm equivalent tofmt_var_width.If
data_outis called, ordata_out_legacyis called with legacy_encoding set toLEGACY_NATIVE, output will be encoded in the character set conventionally used on the host machine. If legacy_encoding is set toLEGACY_EBCDIC, output will be re-encoded from EBCDIC during data output.When input contains data that cannot be represented in the given format,
data_outmay output a message usingmsg, although the current implementation does not consistently do so. To suppress error output, enclose the call todata_outby calls tomsg_disableandmsg_enable.This function is declared in data/data-out.h.
In addition to the system-missing value for numeric values, each
variable has a set of user-missing values (see MISSING VALUES). 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. See Variable Missing Values, for details.
A struct missing_values is essentially a set of union values that
have a common value width (see 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:
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 data/missing-values.h.
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.
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 (see Variable Missing Values).
Tests whether value is in one of the categories of missing values given by class. Returns true if so, false otherwise.
mv determines the width of value and provides the set of user-missing values to test.
The only difference among these functions in the form in which value is provided, so you may use whichever function is most convenient.
The class argument determines the exact kinds of missing values that the functions test for:
— Enumeration: enum mv_class
- MV_USER
- Returns true if value is in the set of user-missing values given by mv.
- MV_SYSTEM
- Returns true if value is system-missing. (If mv represents a set of string values, then value is never system-missing.)
- MV_ANY
- MV_USER | MV_SYSTEM
- Returns true if value is user-missing or system-missing.
- MV_NONE
- Always returns false, that is, value is never considered missing.
Initializes mv as a set of user-missing values. The set is initially empty. Any values added to it must have the specified width.
Initializes mv as a copy of the existing set of user-missing values old.
Empties the user-missing value set mv, retaining its existing 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 var_set_missing_values, which uses
mv_resize internally to resize the new set of missing values to
the required width, may be used instead.
See var_set_missing_values, for more information.
Tests whether mv's width may be changed to new_width using
mv_resize. Returns true if it is allowed, false otherwise.If new_width is a long string width, mv may be resized only if it is empty. Otherwise, if mv contains any missing values, then it may be resized only if each missing value may be resized, as determined by
value_is_resizable(see value_is_resizable).
Changes mv's width to width. mv and 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.
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:
Returns true if mv contains no user-missing values, false if it contains at least one user-missing value (either a discrete value or a numeric range).
Returns the width of the user-missing values that mv represents.
Returns the number of discrete user-missing values included in 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.
Returns true if mv has at least one discrete user-missing values, that is, if
mv_n_valueswould return nonzero for mv.
Copies the discrete user-missing value in mv with the given index into value. The index must be less than the number of discrete user-missing values in mv, as reported by
mv_n_values.
The second set of functions inspects the single range of values that numeric sets of user-missing values may contain:
Returns true if mv includes a range, false otherwise.
Stores the low endpoint of mv's range in
*low and the high endpoint of the range in*high. mv must include a range.
These functions modify the contents of struct missing_values
objects.
The first set of functions applies to all sets of user-missing values:
Attempts to add the given discrete value to set of user-missing values mv. value must have the same width as mv. Returns true if value was successfully added, false if the set could not accept any more discrete values. (Always returns false if mv is a set of long string user-missing values.)
These functions are equivalent, except for the form in which value is provided, so you may use whichever function is most convenient.
Removes a discrete value from mv (which must contain at least one discrete value) and stores it in value.
Replaces the discrete value with the given index in mv (which must contain at least index + 1 discrete values) with value.
The second set of functions applies only to numeric sets of user-missing values:
Attempts to add a numeric range covering low...high (inclusive on both ends) to mv, which must be a numeric set of user-missing values. Returns true if the range is successful added, false on failure. Fails if mv already contains a range, or if mv contains more than one discrete value, or if low > high.
Given mv, which must be a numeric set of user-missing values that contains a range, removes that range from mv and stores its low endpoint in
*low and its high endpoint in*high.
Each variable has a set of value labels (see VALUE LABELS), represented as struct val_labs. A
struct val_labs is essentially a map from union values 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. See Variable Value Labels, for
details.
Function prototypes and other declarations related to missing values are declared in data/value-labels.h.
The most often useful function for value labels is
val_labs_find, for looking up the label associated with a
value.
Looks in val_labs for a label for the given value. Returns the label, if one is found, or a null pointer otherwise.
Several other functions for working with value labels are described in the following section, but these are more rarely useful.
These functions create and destroy struct val_labs objects.
Creates and returns an initially empty set of value labels with the given width.
Creates and returns a set of value labels whose width and contents are the same as those of var_labs.
Destroys var_labs, which must not be referenced again.
These functions inspect and manipulate basic properties of
struct val_labs objects.
Returns the number of value labels in val_labs.
Tests whether val_labs's width may be changed to new_width using
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
value_is_resizable(see value_is_resizable).
Changes the width of val_labs's values to new_width, which must be a valid new width as determined by
val_labs_can_set_width.If new_width is a long string width, this function deletes all value labels from val_labs.
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.
Adds label to in var_labs as a label for value, which must have the same width as the set of value labels. Returns true if successful, false if value already has a label or if val_labs has long string width.
Adds label to in var_labs as a label for value, which must have the same width as the set of value labels. If value already has a label in var_labs, it is replaced. Has no effect if var_labs has long string width.
Removes from val_labs any label for value, which must have the same width as the set of value labels. Returns true if a label was removed, false otherwise.
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 for loop:
struct val_labs val_labs;
struct val_labs_iterator *i;
struct val_lab *vl;
...
for (vl = val_labs_first (val_labs, &i); vl != NULL;
vl = val_labs_next (val_labs, &i))
{
...do something with vl...
}
The value labels in a struct val_labs must not be modified as it is
undergoing iteration.
Represents a value label for iteration purposes, with two client-visible members:
union value value- Value being labeled, of the same width as the
struct val_labsbeing iterated.const char *label- The label, as a null-terminated string.
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
val_labs_done.
If val_labs contains at least one value label, starts an iteration through val_labs, initializes
*iterator to point to a newly allocated iterator, and returns the first value label in val_labs. If val_labs is empty, sets*iterator to null and returns a null pointer.This function creates iterators that traverse sets of value labels in no particular order.
Same as
val_labs_first, except that the created iterator traverses the set of value labels in ascending order of value.
Advances an iterator created with
val_labs_firstorval_labs_first_sortedto the next value label, which is returned. If the set of value labels is exhausted, returns a null pointer after freeing*iterator and setting it to a null pointer.
Frees
*iterator and sets it to a null pointer. Does not need to be called explicitly ifval_labs_nextreturns a null pointer, indicating that all value labels have been visited.
A PSPP variable is represented by struct variable, an opaque type
declared in data/variable.h along with related declarations.
See Variables, 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 (see Cases). The set of variables in a case, in turn, are ordinarily part of a dictionary (see Dictionaries).
Every variable has several attributes, most of which correspond directly to one of the variable attributes visible to PSPP users (see Attributes).
The following sections describe variable-related functions and macros.
A variable name is a string between 1 and VAR_NAME_LEN bytes
long that satisfies the rules for PSPP identifiers
(see Tokens). Variable names are
mixed-case and treated case-insensitively.
Only one commonly useful function relates to variable names:
Returns var's variable name as a C string.
A few other functions are much more rarely used. Some of these functions are used internally by the dictionary implementation:
Changes the name of var to 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
dict_rename_varinstead (see Dictionary Renaming Variables).
Tests name for validity or “plausibility.” Returns true if the name is acceptable, false otherwise. If the name is not acceptable and 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 (see Tokens). 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.
Returns the dictionary class of var's name (see Dictionary Class).
A variable's type and width are the type and width of its values (see Values).
Returns the type of variable var.
Sets the width of variable var to 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.
Returns true if var is a numeric variable, false otherwise.
Returns true if var is an alphanumeric (string) variable, false otherwise.
Returns true if var is a string variable of width
MAX_SHORT_STRINGor less, false otherwise.
Returns true if var is a string variable of width greater than
MAX_SHORT_STRING, false otherwise.
Returns the number of
union values needed to hold an instance of variable var.var_get_value_cnt (var)is equivalent tovalue_cnt_from_width (var_get_width (var)).
A numeric or short string variable may have a set of user-missing
values (see MISSING VALUES), represented
as a struct missing_values (see User-Missing Values).
The most frequent operation on a variable's missing values is to query whether a value is user- or system-missing:
Tests whether value is a missing value of the given class for variable var and returns true if so, false otherwise.
var_is_num_missingmay only be applied to numeric variables;var_is_str_missingmay only be applied to string variables. For string variables, value must contain exactly as many characters as var's width.
var_is_type_missing (var,value,class)is equivalent tomv_is_type_missing (var_get_missing_values (var),value,class).
In addition, a few functions are provided to work more directly with a
variable's struct missing_values:
Returns the
struct missing_valuesassociated with var. The caller must not modify the returned structure. The return value is always non-null.
Changes var's missing values to a copy of miss, or if miss is a null pointer, clears var's missing values. If miss is non-null, it must have the same width as var or be resizable to var's width (see mv_resize). The caller retains ownership of miss.
b
Clears var's missing values. Equivalent to
var_set_missing_values (var, NULL).
Returns true if var has any missing values, false if it has none. Equivalent to
mv_is_empty (var_get_missing_values (var)).
A numeric or short string variable may have a set of value labels
(see VALUE LABELS), represented as a
struct val_labs (see Value Labels). The most commonly useful
functions for value labels return the value label associated with a
value:
Looks for a label for value in var's set of value labels. Returns the label if one exists, otherwise a null pointer.
Looks for a label for value in var's set of value labels. If a label exists, it will be appended to the string pointed to by str. Otherwise, it formats value using var's print format (see Input and Output Formats) and appends the formatted string.
The underlying struct val_labs structure may also be accessed
directly using the functions described below.
Returns true if var has at least one value label, false otherwise.
Returns the
struct val_labsassociated with var. If 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.
Replaces var's value labels by a copy of val_labs. The caller retains ownership of val_labs. If val_labs is a null pointer, then var's value labels, if any, are deleted.
Deletes var's value labels. Equivalent to
var_set_value_labels (var, NULL).
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):
Attempts to add a copy of label as a label for value for the given var. If 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 value or if var is a long string variable. Either way, the caller retains ownership of value and label.
Attempts to add a copy of label as a label for value for the given var. If value already has a label, then label replaces the old label. Either way, the caller retains ownership of value and label.
If var is a long string variable, this function has no effect.
Each variable has an associated pair of output formats, called its print format and write format. See Input and Output Formats, for an introduction to formats. See 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 (see WRITE). 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.
Returns var's print or write format, respectively.
Sets var's print format, write format, or both formats, respectively, to a copy of format.
A variable label is a string that describes a variable. Variable labels may contain spaces and punctuation not allowed in variable names. See VARIABLE LABELS, for a user-level description of variable labels.
The most commonly useful functions for variable labels are those to retrieve a variable's label:
Returns var's variable label, if it has one, otherwise 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.
Returns var's variable label, if it has one, or a null pointer otherwise.
A few other variable label functions are also provided:
Sets var's variable label to a copy of label, or removes any label from var if 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.
Returns true if var has a variable label, false otherwise.
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.
Measurement level. Available values are:
MEASURE_NOMINAL- Numeric data values are arbitrary. Arithmetic operations and numerical comparisons of such data are not meaningful.
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.
MEASURE_SCALE- Ratios, sums, etc. of numeric data values have meaningful interpretations.
PSPP does not have a separate category for interval data, which would naturally fall between the ordinal and scale measurement levels.
Returns true if measure is a valid level of measurement, that is, if it is one of the
enum measureconstants listed above, and false otherwise.
Gets or sets var's measurement level.
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.
Gets or sets var's display width.
Returns the default display width for a variable with the given width. The default width of a numeric variable is 8. The default width of a string variable is width or 32, whichever is less.
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.
Text justification. Possible values are
ALIGN_LEFT,ALIGN_RIGHT, andALIGN_CENTRE.
Returns true if alignment is a valid alignment, that is, if it is one of the
enum alignmentconstants listed above, and false otherwise.
Gets or sets var's alignment.
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:
COMPUTE X = X + 1.
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, Y is
set only for the first 10 cases:
DO IF #CASENUM <= 10.
+ COMPUTE Y = 1.
END IF.
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 (see LEAVE). The initial value of such a variable is 0 if it is numeric and spaces if it is a string. If the command `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 (see Scratch Variables) are always left from one case to another.
The following functions work with a variable's leave status.
Returns true if var's value is to be retained from case to case, false if it is reinitialized to system-missing or spaces.
If leave is true, marks var to be left from case to case; if leave is false, marks var to be reinitialized for each case.
If var is a scratch variable, leave must be true.
Returns true if var must be left from case to case, that is, if var is a scratch variable.
Occasionally it is useful to classify variables into 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 <data/dict-class.h> header.
The dictionary classes are:
DC_ORDINARY- An ordinary variable, one whose name does not begin with `$' or `#'.
DC_SYSTEM- A system variable, one whose name begins with `$'. See System Variables.
DC_SCRATCH- A scratch variable, one whose name begins with `#'. See Scratch Variables.
The values for dictionary classes are bitwise disjoint, which allows them to be used in bit-masks. An extra enumeration constant
DC_ALL, whose value is the bitwise-or of all of the above constants, is provided to aid in this purpose.
One example use of dictionary classes arises in connection with PSPP
syntax that uses a TO b to name the variables in a
dictionary from a to b (see Sets of Variables). This syntax requires a and 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.
Returns the “dictionary class” for the given variable name, by looking at its first letter.
Returns a name for the given dict_class as an adjective, e.g.
"scratch".This function should probably not be used in new code as it can lead to difficulties for internationalization.
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.
Creates and returns a new variable with the given name and width. The new variable is not part of any dictionary. Use
dict_create_var, instead, to create a variable in a dictionary (see Dictionary Creating Variables).name should be a valid variable name and must be a “plausible” variable name (see Variable Name). width must be between 0 and
MAX_STRING, inclusive (see 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
var_default_display_width(see var_default_display_width).The new variable initially has no short name (see Variable Short Names) and no auxiliary data (see Variable Auxiliary Data).
Creates and returns a new variable with the same attributes as old_var, with a few exceptions. First, the new variable is not part of any dictionary, regardless of whether old_var was in a dictionary. Use
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 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 (see Variable Short Names).
Finally, old_var's auxiliary data, if any, is not copied to the new variable (see Variable Auxiliary Data).
Destroys var and frees all associated storage, including its auxiliary data, if any. var must not be part of a dictionary. To delete a variable from a dictionary and destroy it, use
dict_delete_var(see Dictionary Deleting Variables).
PSPP variable names may be up to 64 (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
(see 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.
Returns var's short name, or a null pointer if var has not been assigned a short name.
Sets var's short name to short_name, or removes var's short name if short_name is a null pointer. If it is non-null, then short_name must be a plausible name for a variable (see var_is_plausible_name). The name will be truncated to 8 bytes in length and converted to all-uppercase.
Variables have close relationships with dictionaries (see Dictionaries) and cases (see 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.
Returns 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 (see dict_reorder_var).
Returns var's index within a case. The case index is an index into an array of
union valuelarge enough to contain all the data in the dictionary.The returned case index can be used to access the value of var within a case for its dictionary, as in e.g.
case_data_idx (case, var_get_case_index (var)), but ordinarily it is more convenient to use the data access functions that do variable-to-index translation internally, as in e.g.case_data (case,var).
Each struct variable can have a single pointer to auxiliary data of
type 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.
Returns var's auxiliary data, or a null pointer if none has been assigned.
Sets var's auxiliary data to aux, which must not be null. var must not already have auxiliary data.
Before var's auxiliary data is cleared by
var_clear_aux, aux_dtor, if non-null, will be called with var as its argument. It should free any storage associated with aux, if necessary.var_dtor_freemay be appropriate for use as aux_dtor:
Removes auxiliary data, if any, from var, first calling the destructor passed to
var_attach_aux, if one was provided.Use
dict_clear_auxto remove auxiliary data from every variable in a dictionary.
Removes auxiliary data, if any, from var, and returns it. Returns a null pointer if var had no auxiliary data.
Any destructor passed to
var_attach_auxis not called, so the caller is responsible for freeing storage associated with the returned auxiliary data.
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.
Returns var's set of categorical values. Yields undefined behavior if var does not have any categorical values.
Destroys var's categorical values, if any, and replaces them by cat_vals, ownership of which is transferred to var. If cat_vals is a null pointer, then var's categorical values are cleared.
Returns true if var has a set of categorical values, false otherwise.
Each data file in memory or on disk has an associated dictionary, whose primary purpose is to describe the data in the file. See Variables, 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 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 (see Cases), although in fact these mappings are stored within individual variables.
System variables are not members of any dictionary (see System Variables).
Dictionaries are represented by struct dictionary. Declarations
related to dictionaries are in the <data/dictionary.h> header.
The following sections describe functions for use with dictionaries.
The most common operations on a dictionary simply retrieve a
struct variable * of an individual variable based on its name
or position.
Looks up and returns the variable with the given name within dict. Name lookup is not case-sensitive.
dict_lookup_varreturns a null pointer if dict does not contain a variable named name.dict_lookup_var_assertasserts that such a variable exists.
Returns the variable at the given position in dict. position must be less than the number of variables in dict (see below).
Returns the number of variables in dict.
Another pair of functions allows retrieving a number of variables at once. These functions are more rarely useful.
Retrieves all of the variables in dict, in their original order, except that any variables in the dictionary classes specified exclude, if any, are excluded (see Dictionary Class). Pointers to the variables are stored in an array allocated with
malloc, and a pointer to the first element of this array is stored in*vars. The caller is responsible for freeing this memory when it is no longer needed. The number of variables retrieved is stored in*cnt.The presence or absence of
DC_SYSTEMin exclude has no effect, because dictionaries never include system variables.
One additional function is available. This function is most often used in assertions, but it is not restricted to such use.
Tests whether var is one of the variables in dict. Returns true if so, false otherwise.
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.
If a variable with the same name already exists in the dictionary, the
non-assert variants of these functions return a null pointer,
without modifying the dictionary. The assert variants, on the
other hand, assert that no duplicate name exists.
A variable may be in only one dictionary at any given time.
Creates a new variable with the given name and width, as if through a call to
var_createwith those arguments (see var_create), appends the new variable to dict's array of variables, and returns the new variable.
Creates a new variable as a clone of var, inserts the new variable into dict, and returns the new variable. The new variable is named name. Other properties of the new variable are copied from old_var, except for those not copied by
var_clone(see var_clone).var does not need to be a member of any dictionary.
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 DELETE VARIABLES.
Deleting a variable automatically removes references to that variable from elsewhere in the dictionary as a weighting variable, filter variable, 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.
Deletes var from dict, of which it must be a member.
Deletes the count variables in array vars from dict. All of the variables in vars must be members of dict. No variable may be included in vars more than once.
Deletes the variables in sequential positions idx...idx + count (exclusive) from dict, which must contain at least idx + count variables.
Deletes all scratch variables from dict.
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.
Moves var, which must be in dict, so that it is at position new_index in dict's array of variables. Other variables in dict, if any, retain their relative positions. new_index must be less than the number of variables in dict.
Moves the count variables in new_order to the beginning of dict's array of variables in the specified order. Other variables in dict, if any, retain their relative positions.
All of the variables in new_order must be in dict. No duplicates are allowed within new_order, which means that count must be no greater than the number of variables in dict.
These functions change the names of variables within a dictionary.
The var_set_name function (see var_set_name) cannot be
applied directly to a variable that is in a dictionary, because
struct dictionary contains an index by name that 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.
Changes the name of var, which must be in dict, to new_name. A variable named new_name must not already be in dict, unless new_name is the same as var's current name.
Renames each of the count variables in vars to the name in the corresponding position of 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
*err_name, if err_name is non-null. Otherwise, the renaming is successful, and true is returned.
A data set's cases may optionally be weighted by the value of a numeric variable. See WEIGHT, 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.
Retrieves and returns the value of the weighting variable specified by dict from case. Returns 1.0 if dict has no weighting variable.
Returns 0.0 if c's weight value is user- or system-missing, zero, or negative. In such a case, if warn_on_invalid is non-null and
*warn_on_invalid is true,dict_get_case_weightalso issues an error message and sets*warn_on_invalid to false. To disable error reporting, pass a null pointer or a pointer to false as warn_on_invalid or use amsg_disable/msg_enablepair.
The dictionary also has a pair of functions for getting and setting the weight variable.
Returns dict's current weighting variable, or a null pointer if the dictionary does not have a weighting variable.
Sets dict's weighting variable to var. If var is non-null, it must be a numeric variable in dict. If var is null, then dict's weighting variable, if any, is cleared.
When the active file is read by a procedure, cases can be excluded from analysis based on the values of a filter variable. See FILTER, 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.
Returns dict's current filter variable, or a null pointer if the dictionary does not have a filter variable.
Sets dict's filter variable to var. If var is non-null, it must be a numeric variable in dict. If var is null, then dict's filter variable, if any, is cleared.
The limit on cases analyzed by a procedure, set by the N OF CASES command (see N OF CASES), 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.
Returns the current case limit for dict.
Sets dict's case limit to limit.
The user may use the SPLIT FILE command (see SPLIT FILE) 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
casegrouper_create_splits.
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.
Returns the number of split variables.
The following functions are also available for working with split variables.
Sets dict's split variables to the cnt variables in vars. If cnt is 0, then dict will not have any split variables. The caller retains ownership of vars.
Removes var, which must be a variable in dict, from dict's split of split variables.
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 FILE LABEL command (see FILE LABEL).
These functions set and retrieve the file label.
Returns dict's file label. If dict does not have a label, returns a null pointer.
Sets dict's label to label. If label is non-null, then its content, truncated to at most 60 bytes, becomes the new file label. If label is null, then dict's label is removed.
The caller retains ownership of label.
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 DOCUMENT (see DOCUMENT), ADD DOCUMENT (see ADD DOCUMENT), and DROP DOCUMENTS (see DROP DOCUMENTS) commands to manipulate documents.
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 DOC_LINE_LENGTH
bytes in length.
Returns the documents in dict, or a null pointer if dict has no documents.
Sets dict's documents to new_documents. If new_documents is a null pointer or an empty string, then dict's documents are cleared. The caller retains ownership of new_documents.
The following functions work with individual lines in a dictionary's set of documents.
Appends content to the documents in dict. The text in content will be truncated or padded with spaces as necessary to make it exactly
DOC_LINE_LENGTHbytes long. The caller retains ownership of content.If content is over
DOC_LINE_LENGTH, this function also issues a warning usingmsg. To suppress the warning, enclose a call to one of this function in amsg_disable/msg_enablepair.
Returns the number of line of documents in dict. If the dictionary contains no documents, returns 0.
Replaces the text in content (which must already have been initialized by the caller) by the document line in dict numbered idx, which must be less than the number of lines of documents in dict. Any trailing white space in the document line is trimmed, so that content will have a length between 0 and
DOC_LINE_LENGTH.
Every .c file should have `#include <config.h>' as its first non-comment line. No .h file should include config.h.
This section needs to be finished.
This section needs to be written.
This section needs to be written.
This section needs to be written.
Developer's Guide
Proposed outline:
* 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
*fmt_create: Numeric Formatting Styles*fmt_dollar_template: Obtaining Properties of Format Types*fmt_to_string: Format Utility Functionsalignment: Variable GUI Attributesalignment_is_valid: Variable GUI Attributeschar: Obtaining Properties of Format Typesdata_in: Formatted Data Input and Outputdata_out: Formatted Data Input and Outputdata_out_legacy: Formatted Data Input and Outputdict_add_document_line: Dictionary Documentsdict_class_from_id: Dictionary Classdict_class_to_name: Dictionary Classdict_clear_documents: Dictionary Documentsdict_clone_var: Dictionary Creating Variablesdict_clone_var_assert: Dictionary Creating Variablesdict_contains_var: Dictionary Variable Accessdict_create_var: Dictionary Creating Variablesdict_create_var_assert: Dictionary Creating Variablesdict_delete_consecutive_vars: Dictionary Deleting Variablesdict_delete_scratch_vars: Dictionary Deleting Variablesdict_delete_var: Dictionary Deleting Variablesdict_delete_vars: Dictionary Deleting Variablesdict_get_case_limit: Dictionary Case Limitdict_get_case_weight: Dictionary Weight Variabledict_get_document_line: Dictionary Documentsdict_get_document_line_cnt: Dictionary Documentsdict_get_documents: Dictionary Documentsdict_get_filter: Dictionary Filter Variabledict_get_label: Dictionary File Labeldict_get_split_cnt: Dictionary Split Variablesdict_get_split_vars: Dictionary Split Variablesdict_get_var: Dictionary Variable Accessdict_get_var_cnt: Dictionary Variable Accessdict_get_vars: Dictionary Variable Accessdict_get_vars_mutable: Dictionary Variable Accessdict_get_weight: Dictionary Weight Variabledict_lookup_var: Dictionary Variable Accessdict_lookup_var_assert: Dictionary Variable Accessdict_rename_var: Dictionary Renaming Variablesdict_rename_vars: Dictionary Renaming Variablesdict_reorder_var: Dictionary Reordering Variablesdict_reorder_vars: Dictionary Reordering Variablesdict_set_case_limit: Dictionary Case Limitdict_set_documents: Dictionary Documentsdict_set_filter: Dictionary Filter Variabledict_set_label: Dictionary File Labeldict_set_split_vars: Dictionary Split Variablesdict_set_weight: Dictionary Weight Variabledict_unset_split_var: Dictionary Split VariablesDOC_LINE_LENGTH: Dictionary Documentsfmt_affix_width: Numeric Formatting Stylesfmt_category: Obtaining Properties of Format Typesfmt_check: Constructing and Verifying Formatsfmt_check_input: Constructing and Verifying Formatsfmt_check_output: Constructing and Verifying Formatsfmt_check_style: Numeric Formatting Stylesfmt_check_type_compat: Constructing and Verifying Formatsfmt_check_width_compat: Constructing and Verifying Formatsfmt_default_for_width: Constructing and Verifying Formatsfmt_done: Numeric Formatting Stylesfmt_equal: Format Utility Functionsfmt_for_input: Constructing and Verifying Formatsfmt_for_output: Constructing and Verifying Formatsfmt_for_output_from_input: Constructing and Verifying Formatsfmt_from_io: Obtaining Properties of Format Typesfmt_from_name: Obtaining Properties of Format Typesfmt_get_style: Numeric Formatting Stylesfmt_is_numeric: Obtaining Properties of Format Typesfmt_is_string: Obtaining Properties of Format Typesfmt_max_input_decimals: Obtaining Properties of Format Typesfmt_max_input_width: Obtaining Properties of Format Typesfmt_max_output_decimals: Obtaining Properties of Format Typesfmt_max_output_width: Obtaining Properties of Format Typesfmt_min_input_width: Obtaining Properties of Format Typesfmt_min_output_width: Obtaining Properties of Format Typesfmt_name: Numeric Formatting Stylesfmt_neg_affix_width: Numeric Formatting Stylesfmt_number_style_destroy: Numeric Formatting Stylesfmt_number_style_init: Numeric Formatting Stylesfmt_resize: Format Utility Functionsfmt_step_width: Obtaining Properties of Format Typesfmt_takes_decimals: Obtaining Properties of Format Typesfmt_to_io: Obtaining Properties of Format Typesfmt_type: Obtaining Properties of Format Typesfmt_usable_for_input: Obtaining Properties of Format Typesfmt_var_width: Format Utility FunctionsHIGHEST: Numeric ValuesLOWEST: Numeric ValuesMAX_SHORT_STRING: Runtime Typed ValuesMAX_STRING: Valuesmeasure: Variable GUI Attributesmeasure_is_valid: Variable GUI AttributesMIN_LONG_STRING: Runtime Typed Valuesmv_add_num: Modifying User-Missing Value Setsmv_add_range: Modifying User-Missing Value Setsmv_add_str: Modifying User-Missing Value Setsmv_add_value: Modifying User-Missing Value Setsmv_clear: Initializing User-Missing Value Setsmv_copy: Initializing User-Missing Value Setsmv_get_range: Inspecting User-Missing Value Setsmv_get_value: Inspecting User-Missing Value Setsmv_get_width: Inspecting User-Missing Value Setsmv_has_range: Inspecting User-Missing Value Setsmv_has_value: Inspecting User-Missing Value Setsmv_init: Initializing User-Missing Value Setsmv_is_empty: Inspecting User-Missing Value Setsmv_is_num_missing: Testing for Missing Valuesmv_is_resizable: Changing User-Missing Value Set Widthmv_is_str_missing: Testing for Missing Valuesmv_is_value_missing: Testing for Missing Valuesmv_n_values: Inspecting User-Missing Value Setsmv_pop_range: Modifying User-Missing Value Setsmv_pop_value: Modifying User-Missing Value Setsmv_replace_value: Modifying User-Missing Value Setsmv_resize: Changing User-Missing Value Set WidthSHORT_NAME_LEN: Variable Short NamesSYSMIS: Numeric Valuesval_labs_add: Value Labels Adding and Removing Labelsval_labs_can_set_width: Value Labels Propertiesval_labs_clear: Value Labels Creation and Destructionval_labs_clone: Value Labels Creation and Destructionval_labs_count: Value Labels Propertiesval_labs_create: Value Labels Creation and Destructionval_labs_destroy: Value Labels Creation and Destructionval_labs_done: Value Labels Iterationval_labs_find: Value Labelsval_labs_first: Value Labels Iterationval_labs_first_sorted: Value Labels Iterationval_labs_next: Value Labels Iterationval_labs_remove: Value Labels Adding and Removing Labelsval_labs_replace: Value Labels Adding and Removing Labelsval_labs_set_width: Value Labels Propertiesval_type_from_width: Valuesval_type_is_valid: Valuesvalue_cnt_from_width: Runtime Typed Valuesvalue_copy: Runtime Typed Valuesvalue_is_resizable: Runtime Typed Valuesvalue_resize: Runtime Typed Valuesvalue_set_missing: Runtime Typed Valuesvar_add_value_label: Variable Value Labelsvar_append_value_name: Variable Value Labelsvar_attach_aux: Variable Auxiliary Datavar_clear_aux: Variable Auxiliary Datavar_clear_label: Variable Labelsvar_clear_missing_values: Variable Missing Valuesvar_clear_short_name: Variable Short Namesvar_clear_value_labels: Variable Value Labelsvar_clone: Variable Creation and Destructionvar_create: Variable Creation and Destructionvar_default_display_width: Variable GUI Attributesvar_destroy: Variable Creation and Destructionvar_detach_aux: Variable Auxiliary Datavar_get_aux: Variable Auxiliary Datavar_get_case_index: Variable Relationshipsvar_get_dict_class: Variable Namevar_get_dict_index: Variable Relationshipsvar_get_display_width: Variable GUI Attributesvar_get_label: Variable Labelsvar_get_leave: Variable Leave Statusvar_get_missing_values: Variable Missing Valuesvar_get_name: Variable Namevar_get_obs_vals: Variable Categorical Valuesvar_get_print_format: Variable Print and Write Formatsvar_get_short_name: Variable Short Namesvar_get_type: Variable Type and Widthvar_get_value_cnt: Variable Type and Widthvar_get_value_labels: Variable Value Labelsvar_get_width: Variable Type and Widthvar_get_write_format: Variable Print and Write Formatsvar_has_label: Variable Labelsvar_has_missing_values: Variable Missing Valuesvar_has_obs_vals: Variable Categorical Valuesvar_has_value_labels: Variable Value Labelsvar_is_alpha: Variable Type and Widthvar_is_long_string: Variable Type and Widthvar_is_num_missing: Variable Missing Valuesvar_is_numeric: Variable Type and Widthvar_is_plausible_name: Variable Namevar_is_short_string: Variable Type and Widthvar_is_str_missing: Variable Missing Valuesvar_is_valid_name: Variable Namevar_is_value_missing: Variable Missing Valuesvar_lookup_value_label: Variable Value Labelsvar_must_leave: Variable Leave StatusVAR_NAME_LEN: Variable Namevar_replace_value_label: Variable Value Labelsvar_set_alignment: Variable GUI Attributesvar_set_both_formats: Variable Print and Write Formatsvar_set_display_width: Variable GUI Attributesvar_set_label: Variable Labelsvar_set_leave: Variable Leave Statusvar_set_measure: Variable GUI Attributesvar_set_missing_values: Variable Missing Valuesvar_set_name: Variable Namevar_set_obs_vals: Variable Categorical Valuesvar_set_print_format: Variable Print and Write Formatsvar_set_short_name: Variable Short Namesvar_set_value_labels: Variable Value Labelsvar_set_width: Variable Type and Widthvar_set_write_format: Variable Print and Write Formatsvar_to_string: Variable Labelsvoid: Variable Auxiliary DataThese 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.
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.
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 `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 `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 `Z' character is not necessarily an ASCII `Z'.)
For the rest of the description of the portable file format, new-lines and the trailing `Z's will be ignored, as if they did not exist, because they are not an important part of understanding the file contents.
Every portable file consists of the following records, in sequence:
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:
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 n, followed by exactly n characters, which are the string content.
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 charset SPSS PORT FILE in a
different character set encoding, where charset is the name of
the character set used in the file, e.g. ASCII or
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:
.<(+
&[]!$*);^-/
,%_>?`:
@'=".
Symbols that are not defined in a particular character set are set to the same value as symbol 64; i.e., to `0'.
The 8-byte tag string consists of the exact characters SPSSPORT
in the portable file's character set, which can be used to verify that
the file is indeed a portable file.
This record does not have a tag code. It has the following structure:
The product identification record has tag code `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 `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 `3'. It is optional. If present, it consists of a single string field giving additional information on the product that wrote the portable file.
The variable count record has tag code `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.
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 `6'. It consists of a single string field that names the weighting variable.
Each variable record represents a single variable. Variable records have tag code `7'. They have the following structure:
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: var_1, var_2, and
so on.
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.
Each variable record can optionally be followed by a missing value record, which has tag code `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 `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 `9' and `A' represent LO THRU x and
x THRU HI ranges, respectively. Each is followed by a
single field representing 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 `C'. A variable label record has one field, the variable label itself (string).
Value label records have tag code `D'. They have the following format:
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.
One document record may optionally follow the value label record. The document record consists of tag code `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.
The data record has tag code `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 `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.
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 char, int32, and
flt64, respectively. Data is not necessarily aligned on a word
or double-word boundary: the long variable name record (see Long Variable Names Record) and very long string records (see 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
layout_code in the file header record
(see 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 bias in the file header record
(see 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 (-DBL_MAX). Two
other values are important for use as missing values: HIGHEST,
represented by the largest possible positive number (DBL_MAX),
and LOWEST, represented by the second-largest negative number
(in IEEE 754 format, 0xffeffffffffffffe).
System files are divided into records, each of which begins with a
4-byte record type, usually regarded as an int32.
The records must appear in the following order:
Each type of record is described separately below.
The file header is always the first record in the file. It has the following format:
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];
char rec_type[4];char prod_name[60];int32 layout_code;int32 nominal_case_size;int32 compressed;int32 weight_index;int32 ncases;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 ncases field. For `files' in which
this is not valid, the seek operation fails. In this case,
ncases remains -1.
flt64 bias;1 - bias and 251 - bias can be compressed.
By assuming that its value is 100, PSPP uses bias to determine
the file's floating-point format and endianness (see 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.
char creation_date[9];char creation_time[8];char file_label[64];char padding[3];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.
The 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. See Very Long String Record, for details.
int32 rec_type;
int32 type;
int32 has_var_label;
int32 n_missing_values;
int32 print;
int32 write;
char name[8];
/* Present only if has_var_label is 1. */
int32 label_len;
char label[];
/* Present only if n_missing_values is nonzero. */
flt64 missing_values[];
int32 rec_type;int32 type;int32 has_var_label;int32 n_missing_values;int32 print;int32 write;char name[8];int32 label_len;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.
char label[];has_var_label is set to 1. It has
length label_len, rounded up to the nearest multiple of 32 bits.
The first label_len characters are the variable's variable label.
flt64 missing_values[];n_missing_values is not 0. It has
the same number of elements as the absolute value of
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.
The print and write members of sysfile_variable are output
formats coded into int32 types. The least-significant byte
of the 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:
Value Meaning 0 Not used. 1 A2 AHEX3 COMMA4 DOLLAR5 F6 IB7 PIBHEX8 P9 PIB10 PK11 RB12 RBHEX13 Not used. 14 Not used. 15 Z16 N17 E18 Not used. 19 Not used. 20 DATE21 TIME22 DATETIME23 ADATE24 JDATE25 DTIME26 WKDAY27 MONTH28 MOYR29 QYR30 WKYR31 PCT32 DOT33 CCA34 CCB35 CCC36 CCD37 CCE38 EDATE39 SDATE
The value label record has the following format:
int32 rec_type;
int32 label_count;
/* Repeated label_cnt times. */
char value[8];
char label_len;
char label[];
int32 rec_type;int32 label_count;The remaining fields are repeated count times. Each
repetition specifies one value label.
char value[8];char label_len;char label[];label_len bytes of the actual label, followed by up to 7 bytes
of padding to bring label and label_len together to a
multiple of 8 bytes in length.
The value label record is always immediately followed by a value label variables record with the following format:
int32 rec_type;
int32 var_count;
int32 vars[];
int32 rec_type;int32 var_count;int32 vars[];var_count
elements.
String variables wider than 8 bytes may not have value labels.
The document record, if present, has the following format:
int32 rec_type;
int32 n_lines;
char lines[][80];
int32 rec_type;int32 n_lines;char lines[][80];n_lines.
Lines shorter than 80 characters are padded on the right with spaces.
The integer info record, if present, has the following format:
/* Header. */ int32 rec_type; int32 subtype; int32 size; int32 count; /* 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;
int32 rec_type;int32 subtype;int32 size;int32 count;int32 version_major;int32 version_minor;int32 version_revision;int32 machine_code;int32 floating_point_rep;int32 compression_code;int32 endianness;int32 character_code;The floating-point info record, if present, has the following format:
/* Header. */ int32 rec_type; int32 subtype; int32 size; int32 count; /* Data. */ flt64 sysmis; flt64 highest; flt64 lowest;
int32 rec_type;int32 subtype;int32 size;int32 count;flt64 sysmis;flt64 highest;flt64 lowest;The variable display parameter record, if present, has the following format:
/* Header. */
int32 rec_type;
int32 subtype;
int32 size;
int32 count;
/* Repeated count times. */
int32 measure;
int32 width; /* Not always present. */
int32 alignment;
int32 rec_type;int32 subtype;int32 size;int32. Always set to 4.
int32 count;The remaining members are repeated 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:
int32 measure;SPSS 14 sometimes writes a measure of 0. PSPP interprets this
as nominal scale.
int32 width;This field is present if count is 3 times the number of
variables in the dictionary. It is omitted if count is 2 times
the number of variables.
int32 alignment;If present, the long variable names record has the following format:
/* Header. */
int32 rec_type;
int32 subtype;
int32 size;
int32 count;
/* Exactly count bytes of data. */
char var_name_pairs[];
int32 rec_type;int32 subtype;int32 size;var_name_pairs member. Always set to 1.
int32 count;var_name_pairs.
char var_name_pairs[];count bytes.
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 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 segments; for consistency, variables other than very long strings are considered to have a single segment.
A very long string with a width of w has n = (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 w - (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:
/* Header. */
int32 rec_type;
int32 subtype;
int32 size;
int32 count;
/* Exactly count bytes of data. */
char string_lengths[];
int32 rec_type;int32 subtype;int32 size;string_lengths member. Always set to 1.
int32 count;string_lengths.
char string_lengths[];count bytes.
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.
/* Header. */
int32 rec_type;
int32 subtype;
int32 size;
int32 count;
/* Exactly size * count bytes of data. */
char data[];
int32 rec_type;int32 subtype;int32 size;char, int32, and flt64 format data,
respectively.
int32 count;char data[];size times count bytes of
data.
The dictionary termination record separates all other records from the data records.
int32 rec_type;
int32 filler;
int32 rec_type;int32 filler;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 (see Variable Record). Numeric values are given in 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:
bias from the file header. For example,
code 105 with bias 100.0 (the normal value) indicates a numeric variable
of value 5.
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.
q2c Input FormatPSPP 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
q2c.
q2c input.q output.c
q2c translates a `.q' file into a `.c' file. It takes
exactly two command-line arguments, which are the input file name and
output file name, respectively. q2c does not accept any
command-line options.
q2c Input Structureq2c input files are divided into two sections: the grammar rules
and the supporting code. The 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 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
(`$'), which prevents Emacs' CC-mode from munging them. Besides
this, a bang (`!') 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 /* *INDENT is ignored and not written to the output.
This allows .q files to be processed through 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.
/* (header) */#include directives which include the
headers that are required for the parser generated by q2c.
/* (decls scope) */enums input and output by the q2c parser. scope
must be either local or global. local causes the
declarations to be output as function locals. global causes them
to be declared as static module variables; thus, global is
a bit of a misnomer.
/* (parser) *//* (free) */free function for variables
declared by the parser. Only needs to be invoked if subcommands of type
string are used in the grammar rules.
The grammar rules describe the format of the syntax that the parser
generated by q2c will understand. The way that the grammar rules
are included in q2c input file are described above.
The grammar rules are divided into tokens of the following types:
ID)STRING)The syntax of the grammar rules is as follows:
grammar-rules ::= command-name opt-prefix : subcommands .
command-name ::= ID
::= STRING
opt-prefix ::=
::= ( ID )
subcommands ::= subcommand
::= subcommands ; subcommand
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. `"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 (`;') and terminated with a full stop (`.').
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
A subcommand that begins with an asterisk (`*') is the default subcommand. The keyword used for the default subcommand can be omitted in the PSPP syntax file.
A plus sign (`+') indicates that a subcommand can appear more than once. A caret (`^') 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 (`=') 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 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.
array-sbc ::= alternatives
::= array-sbc , alternatives
alternatives ::= ID
::= alternatives | ID
An array subcommand is a set of Boolean values that can independently be turned on by the user, listed separated by commas (`,'). If an value has more than one name then these names are separated by pipes (`|').
specifiers ::= specifier
::= specifiers , specifier
specifier ::= opt-id : settings
opt-id ::=
::= ID
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.
settings ::= setting
::= settings / setting
setting ::= setting-options ID setting-value
setting-options ::=
::= *
::= !
::= * !
Individual settings are separated by forward slashes (`/'). Each
setting can be as little as an ID token, but options and values
can optionally be included. The `*' option means that, for this
setting, the ID can be omitted. The `!' option means that
this option is the default for its specifier.
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
Settings may have values. If the value must be enclosed in parentheses,
then enclose the value declaration in parentheses. Declare the setting
type as `n', `d', or `s' for integer, floating-point,
or string type, respectively. The given ID is used to
construct a variable name.
If option `*' 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
%s should be used within the restriction to refer to the
setting's value variable.
sbc-special-form ::= VAR
::= VARLIST varlist-options
::= INTEGER opt-list
::= DOUBLE opt-list
::= PINT
::= STRING (the literal word STRING) string-options
::= CUSTOM
varlist-options ::=
::= ( STRING )
opt-list ::=
::= LIST
string-options ::=
::= ( STRING STRING )
The special forms are of the following types:
VARVARLISTPV_* options to the call to parse_variables.
INTEGERINTEGER LISTDOUBLEDOUBLE LISTPINTSTRINGCUSTOMint custom_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.
Copyright © 2000,2001,2002 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.
This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.
A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.
The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.
The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.
A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”.
Examples of suitable formats for Transparent copies include plain ascii without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.
The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.
A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition.
The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display copies.
If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.
You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements.”
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.
To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:
Copyright (C) year your name.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license is included in the section entitled ``GNU
Free Documentation License''.
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with...Texts.” line with this:
with the Invariant Sections being list their titles, with
the Front-Cover Texts being list, and with the Back-Cover Texts
being list.
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.