Basic Concepts
**************

This chapter introduces basic data structures and other concepts needed for developing in PSPP.

Values
======

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:

 -- Macro: int MAX_STRING
     Maximum width of a string value, in bytes, currently 32,767.

 -- Function: bool val_type_is_valid (enum val_type VAL_TYPE)
     Returns true if VAL_TYPE is a valid value type, that is, either VAL_NUMERIC or VAL_STRING.  Useful for assertions.

 -- Function: enum val_type val_type_from_width (int WIDTH)
     Returns VAL_NUMERIC if WIDTH is 0 and thus represents the width of a numeric value, otherwise VAL_STRING to indicate that WIDTH is the width of a string value.

The following subsections describe how values of each type are represented.

Numeric Values
--------------

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:

 -- Macro: double SYSMIS
     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 (PSPP Users Guide), for a PSPP user's view of missing values.

     PSPP currently defines SYSMIS as -DBL_MAX, that is, the greatest finite negative value of double.  It is best not to depend on this definition, because PSPP may transition to using an IEEE NaN (not a number) instead at some point in the future.

 -- Macro: double LOWEST
 -- Macro: double HIGHEST
     The greatest finite negative (except for SYSMIS) and positive values of double, respectively.  These values do not ordinarily appear in user data files.  Instead, they are used to implement endpoints of open-ended ranges that are occasionally permitted in PSPP syntax, e.g. 5 THRU HI as a range of missing values (see MISSING VALUES (PSPP Users Guide)).

String 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.

Runtime Typed Values
--------------------

When a value's type is only known at runtime, it is often represented as a value, defined in data/value.h.  A value does not identify the type or width of the data it contains.  Code that works with valuess must therefore have external knowledge of its content, often through the type and width of a variable (see Variables).

value has one member that clients are permitted to access directly, a double named f that stores the content of a numeric value.  It has other members that store the content of string value, but client code should use accessor functions instead of referring to these directly.

PSPP provides some functions for working with values.  The most useful are described below.  To use these functions, recall that a numeric value has a width of 0.

 -- Function: void value_init (union value *VALUE, int WIDTH)
     Initializes VALUE as a value of the given WIDTH.  After initialization, the data in VALUE are indeterminate; the caller is responsible for storing initial data in it.

 -- Function: void value_destroy (union value *VALUE, int WIDTH)
     Frees auxiliary storage associated with VALUE, which must have the given WIDTH.

 -- Function: bool value_needs_init (int WIDTH)
     For some widths, value_init and value_destroy do not actually do anything, because no additional storage is needed beyond the size of value.  This function returns true if WIDTH is such a width, which case there is no actual need to call those functions.  This can be a useful optimization if a large number of values of such a width are to be initialized or destroyed.

     This function returns false if value_init and value_destroy are actually required for the given WIDTH.

 -- Function: double value_num (const union value *VALUE)
     Returns the numeric value in VALUE, which must have been initialized as a numeric value.  Equivalent to VALUE->f.

 -- Function: const char * value_str (const union value *VALUE, int WIDTH)
 -- Function: char * value_str_rw (union value *VALUE, int WIDTH)
     Returns the string value in VALUE, which must have been initialized with positive width WIDTH.  The string returned is not null-terminated.  Only WIDTH bytes of returned data may be accessed.

     The two different functions exist only for const-correctness. Otherwise they are identical.

     It is important that WIDTH be the correct value that was passed to value_init.  Passing a smaller or larger value (e.g. because that number of bytes will be accessed) will not always work and should be avoided.

 -- Function: void value_copy (union value *DST,
     const union value *SRC,
     int WIDTH)
     Copies the contents of value SRC to DST.  Both DST and SRC must have been initialized with the specified WIDTH.

 -- Function: void value_set_missing (union value *VALUE, int WIDTH)
     Sets VALUE to SYSMIS if it is numeric or to all spaces if it is alphanumeric, according to WIDTH.  VALUE must have been initialized with the specified WIDTH.

 -- Function: bool value_is_resizable (const union value *VALUE, int OLD_WIDTH, int NEW_WIDTH)
     Determines whether VALUE, which must have been initialized with the specified OLD_WIDTH, may be resized 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_resizable and val_labs_can_set_width.

 -- Function: void value_resize (union value *VALUE, int OLD_WIDTH, int NEW_WIDTH)
     Resizes VALUE from OLD_WIDTH to NEW_WIDTH, which must be allowed by the rules stated above.  VALUE must have been initialized with the specified OLD_WIDTH before calling this function.  After resizing, VALUE has width NEW_WIDTH.

     If NEW_WIDTH is greater than OLD_WIDTH, VALUE will be padded on the right with spaces to the new width.  If NEW_WIDTH is less than OLD_WIDTH, the rightmost bytes of VALUE are truncated.

 -- Function: bool value_equal (const union value *A, const union value *B, int WIDTH)
     Compares of A and B, which must both have width WIDTH.  Returns true if their contents are the same, false if they differ.

 -- Function: int value_compare_3way (const union value *A, const union value *B, int WIDTH)
     Compares of A and B, which must both have width WIDTH.  Returns -1 if A is less than B, 0 if they are equal, or 1 if A is greater than B.

     Numeric values are compared numerically, with SYSMIS comparing less than any real number.  String values are compared lexicographically byte-by-byte.

 -- Function: size_t value_hash (const union value *VALUE, int WIDTH, unsigned int BASIS)
     Computes and returns a hash of VALUE, which must have the specified WIDTH.  The value in BASIS is folded into the hash.

Input and Output Formats
========================

Input and output formats specify how to convert data fields to and from data values (see Input and Output Formats (PSPP Users Guide)).  PSPP uses fmt_spec to represent input and output formats.

Function prototypes and other declarations related to formats are in the <data/format.h> header.

 -- Structure: struct fmt_spec
     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).

 -- Enumeration: enum fmt_type
     An enumerated type representing an input or output format type.  Each PSPP input and output format has a corresponding enumeration constant prefixed by 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.

Constructing and Verifying Formats
----------------------------------

These functions construct fmt_specs and verify that they are valid.

 -- Function: struct fmt_spec fmt_for_input (enum fmt_type TYPE, int W, int D)
 -- Function: struct fmt_spec fmt_for_output (enum fmt_type TYPE, int W, int D)
     Constructs a fmt_spec with the given TYPE, W, and D, asserts that the result is a valid input (or output) format, and returns it.

 -- Function: struct fmt_spec fmt_for_output_from_input (const struct fmt_spec *INPUT)
     Given INPUT, which must be a valid input format, returns the equivalent output format.  See Input and Output Formats (PSPP Users Guide), for the rules for converting input formats into output formats.

 -- Function: struct fmt_spec fmt_default_for_width (int WIDTH)
     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 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.

 -- Function: bool fmt_check (const struct fmt_spec *FORMAT, bool FOR_INPUT)
 -- Function: bool fmt_check_input (const struct fmt_spec *FORMAT)
 -- Function: bool fmt_check_output (const struct fmt_spec *FORMAT)
     Checks whether FORMAT is a valid input format (for fmt_check_input, or fmt_check if FOR_INPUT) or output format (for fmt_check_output, or fmt_check if not FOR_INPUT).

 -- Function: bool fmt_check_type_compat (const struct fmt_spec *FORMAT, enum val_type TYPE)
     Checks whether FORMAT matches the value type TYPE, that is, if TYPE is VAL_NUMERIC and FORMAT is a numeric format or TYPE is VAL_STRING and FORMAT is a string format.

 -- Function: bool fmt_check_width_compat (const struct fmt_spec *FORMAT, int WIDTH)
     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.

Format Utility Functions
------------------------

These functions work with fmt_specs.

 -- Function: int fmt_var_width (const struct fmt_spec *FORMAT)
     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.

 -- Function: char *fmt_to_string (const struct fmt_spec *FORMAT, char S[FMT_STRING_LEN_MAX + 1])
     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.

 -- Function: bool fmt_equal (const struct fmt_spec *A, const struct fmt_spec *B)
     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.

 -- Function: void fmt_resize (struct fmt_spec *FMT, int WIDTH)
     Sets the width of FMT to a valid format for a  value of size WIDTH.

Obtaining Properties of Format Types
------------------------------------

These functions work with fmt_types instead of the higher-level 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.

 -- Function: const char *fmt_name (enum fmt_type TYPE)
     Returns the name for the given TYPE, e.g. "COMMA" for FMT_COMMA.

 -- Function: bool fmt_from_name (const char *NAME, enum fmt_type *TYPE)
     Tries to find the fmt_type associated 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.

 -- Function: bool fmt_takes_decimals (enum fmt_type TYPE)
     Returns true if a format of the given TYPE is allowed to have a nonzero number of decimal places (the d member of fmt_spec), false if not.

 -- Function: int fmt_min_input_width (enum fmt_type TYPE)
 -- Function: int fmt_max_input_width (enum fmt_type TYPE)
 -- Function: int fmt_min_output_width (enum fmt_type TYPE)
 -- Function: int fmt_max_output_width (enum fmt_type TYPE)
     Returns the minimum or maximum width (the w member of fmt_spec) allowed for an input or output format of the specified TYPE.

 -- Function: int fmt_max_input_decimals (enum fmt_type TYPE, int WIDTH)
 -- Function: int fmt_max_output_decimals (enum fmt_type TYPE, int WIDTH)
     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.

 -- Function: int fmt_step_width (enum fmt_type TYPE)
     Returns the ``width step'' for a fmt_spec of the given TYPE.  A 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.

 -- Function: bool fmt_is_string (enum fmt_type TYPE)
 -- Function: bool fmt_is_numeric (enum fmt_type TYPE)
     Returns true if TYPE is a format for numeric or string values, respectively, false otherwise.

 -- Function: enum fmt_category fmt_get_category (enum fmt_type TYPE)
     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 (PSPP Users Guide)).

          Each format is in exactly one category.  The categories have bitwise disjoint values to make it easy to test whether a format type is in one of multiple categories, e.g.

               if (fmt_get_category (type) & (FMT_CAT_DATE | FMT_CAT_TIME))
                 {
                   /* ...type is 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 fmt_types to and from the separate set of codes used in system and portable files:

 -- Function: int fmt_to_io (enum fmt_type TYPE)
     Returns the format code used in system and portable files that corresponds to TYPE.

 -- Function: bool fmt_from_io (int IO, enum fmt_type *TYPE)
     Converts IO, a format code used in system and portable files, into a fmt_type in *TYPE.  Returns true if successful, false if IO is not valid.

These functions reflect the relationship between input and output formats.

 -- Function: enum fmt_type fmt_input_to_output (enum fmt_type TYPE)
     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.

 -- Function: bool fmt_usable_for_input (enum fmt_type TYPE)
     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.

 -- Function: const char *fmt_date_template (enum fmt_type TYPE)
     Returns a formatting template for TYPE, which must be a date or time format type.  These formats are used by data_in and data_out to guide parsing and formatting date and time data.

 -- Function: char *fmt_dollar_template (const struct fmt_spec *FORMAT)
     Returns a string of the form $#,###.## according to FORMAT, which must be of type FMT_DOLLAR.  The caller must free the string with free.

Numeric Formatting Styles
-------------------------

Each of the basic numeric formats (F, E, COMMA, DOT, DOLLAR, PCT) and custom currency formats (CCA, CCB, CCC, CCD, CCE) has an associated numeric formatting style, represented by 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.

 -- Structure: struct fmt_number_style
     A structure type with the following members:

     struct substring neg_prefix
     struct substring prefix
     struct substring suffix
     struct substring neg_suffix
          A set of strings used a prefix to negative numbers, a prefix to every number, a suffix to every number, and a suffix to negative numbers, respectively.  Each of these strings is no more than FMT_STYLE_AFFIX_MAX bytes (currently 16) bytes in length. These strings must be freed with ss_dealloc when 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.

 -- Function: void fmt_number_style_init (struct fmt_number_style *STYLE)
     Initialises a fmt_number_style with all of the prefixes and suffixes set to the empty string, . as the decimal point character, and grouping disables.

 -- Function: void fmt_number_style_destroy (struct fmt_number_style *STYLE)
     Destroys STYLE, freeing its storage.

 -- Function: struct fmt_number_style *fmt_create (void)
     A function which creates an array of all the styles used by pspp, and calls fmt_number_style_init on each of them.

 -- Function: void fmt_done (struct fmt_number_style *STYLES)
     A wrapper function which takes an array of fmt_number_style, calls fmt_number_style_destroy on each of them, and then frees the array.

 -- Function: int fmt_affix_width (const struct fmt_number_style *STYLE)
     Returns the total length of STYLE's prefix and suffix.

 -- Function: int fmt_neg_affix_width (const struct fmt_number_style *STYLE)
     Returns the total length of STYLE's neg_prefix and neg_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:

 -- Function: const struct fmt_number_style * fmt_get_style (enum fmt_type TYPE)
     Returns the numeric style for the given format TYPE.

 -- Function: void fmt_check_style (const struct fmt_number_style *STYLE)
     Asserts that style is self consistent.

 -- Function: const char * fmt_name (enum fmt_type TYPE)
     Returns the name of the given format TYPE.

Formatted Data Input and Output
-------------------------------

These functions provide the ability to convert data fields into values and vice versa.

 -- Function: bool data_in (struct substring INPUT, const char *ENCODING, enum fmt_type TYPE, int IMPLIED_DECIMALS, int FIRST_COLUMN, const struct dictionary *DICT, union value *OUTPUT, int WIDTH)
     Parses INPUT as a field containing data in the given format TYPE.  The resulting value is stored in OUTPUT, which the caller must have initialized with 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. ENCODING should be set to indicate the character encoding of INPUT. DICT must be a pointer to the dictionary with which OUTPUT is associated.

     If INPUT is the empty string (with length 0), OUTPUT is set to the value set on SET BLANKS (see SET BLANKS (PSPP Users Guide)) 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 (PSPP Users Guide)).  Other callers should generally specify 0 for IMPLIED_DECIMALS, to disable this feature.

     When INPUT contains invalid input data, data_in outputs a message using msg. 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 to data_in by calls to msg_disable and msg_enable.

     This function returns true on success, false if a message was output (even if suppressed).  Overflow and underflow provoke warnings but are not propagated to the caller as errors.

     This function is declared in data/data-in.h.

 -- Function: char * data_out (const union value *INPUT, const struct fmt_spec *FORMAT)
 -- Function: char * data_out_legacy (const union value *INPUT, const char *ENCODING, const struct fmt_spec *FORMAT)
     Converts the data pointed to by INPUT into a string value, which will be encoded in UTF-8,  according to output format specifier FORMAT. Format must be a valid output format.   The width of INPUT is inferred from FORMAT using an algorithm equivalent to fmt_var_width.

     When INPUT contains data that cannot be represented in the given FORMAT, data_out may output a message using msg, although the current implementation does not consistently do so.  To suppress error output, enclose the call to data_out by calls to msg_disable and msg_enable.

     This function is declared in data/data-out.h.

User-Missing Values
===================

In addition to the system-missing value for numeric values, each variable has a set of user-missing values (see MISSING VALUES (PSPP Users Guide)).  A set of user-missing values is represented by missing_values.

It is rarely necessary to interact directly with a 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 variable.  See Variable Missing Values, for details.

A missing_values is essentially a set of 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.

Function prototypes and other declarations related to missing values are declared in data/missing-values.h.

 -- Structure: struct missing_values
     Opaque type that represents a set of missing values.

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.  A set of numeric missing values may contain up to three discrete numeric values, or a range of numeric values (which includes both ends of the range), or a range plus one discrete numeric value. A set of string missing values may contain up to three discrete string values (with the same width as the set), but ranges are not supported.

In addition, values in string missing values wider than MV_MAX_STRING bytes may contain non-space characters only in their first MV_MAX_STRING bytes; all the bytes after the first MV_MAX_STRING must be spaces.  See mv_is_acceptable, for a function that tests a value against these constraints.

 -- Macro: int MV_MAX_STRING
     Number of bytes in a string missing value that are not required to be spaces.  The current value is 8, a value which is fixed by the system file format.  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.

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 missing_values objects are described afterward, but these functions are much more rarely useful.

Testing for Missing Values
--------------------------

The most often useful functions for missing values are those for testing whether a given value is missing, described here.  However, using one of the corresponding missing value testing functions for variables can be even easier (see Variable Missing Values).

 -- Function: bool mv_is_value_missing (const struct missing_values *MV, const union value *VALUE, enum mv_class CLASS)
 -- Function: bool mv_is_num_missing (const struct missing_values *MV, double VALUE, enum mv_class CLASS)
 -- Function: bool mv_is_str_missing (const struct missing_values *MV, const char VALUE[], enum mv_class CLASS)
     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.

Creation and Destruction
------------------------

These functions create and destroy missing_values objects.

 -- Function: void mv_init (struct missing_values *MV, int WIDTH)
     Initializes MV as a set of user-missing values.  The set is initially empty.  Any values added to it must have the specified WIDTH.

 -- Function: void mv_destroy (struct missing_values *MV)
     Destroys MV, which must not be referred to again.

 -- Function: void mv_copy (struct missing_values *MV, const struct missing_values *OLD)
     Initializes MV as a copy of the existing set of user-missing values OLD.

 -- Function: void mv_clear (struct missing_values *MV)
     Empties the user-missing value set MV, retaining its existing width.

Changing User-Missing Value Set Width
-------------------------------------

A few PSPP language constructs copy sets of user-missing values from one variable to another.  When the source and target variables have the same width, this is simple.  But when the target variable's width might be different from the source variable's, it takes a little more work.  The functions described here can help.

In fact, it is usually unnecessary to call these functions directly. Most of the time 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.

 -- Function: bool mv_is_resizable (const struct missing_values *MV, int NEW_WIDTH)
     Tests whether MV's width may be changed to NEW_WIDTH using mv_resize.  Returns true if it is allowed, false 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).

 -- Function: void mv_resize (struct missing_values *MV, int WIDTH)
     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.

Inspecting User-Missing Value Sets
----------------------------------

These functions inspect the properties and contents of missing_values objects.

The first set of functions inspects the discrete values that sets of user-missing values may contain:

 -- Function: bool mv_is_empty (const struct missing_values *MV)
     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).

 -- Function: int mv_get_width (const struct missing_values *MV)
     Returns the width of the user-missing values that MV represents.

 -- Function: int mv_n_values (const struct missing_values *MV)
     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.

 -- Function: bool mv_has_value (const struct missing_values *MV)
     Returns true if MV has at least one discrete user-missing values, that is, if mv_n_values would return nonzero for MV.

 -- Function: const union value * mv_get_value (const struct missing_values *MV, int INDEX)
     Returns the discrete user-missing value in MV with the given INDEX.  The caller must not modify or free the returned value or refer to it after modifying or freeing MV.  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:

 -- Function: bool mv_has_range (const struct missing_values *MV)
     Returns true if MV includes a range, false otherwise.

 -- Function: void mv_get_range (const struct missing_values *MV, double *LOW, double *HIGH)
     Stores the low endpoint of MV's range in *LOW and the high endpoint of the range in *HIGH.  MV must include a range.

Modifying User-Missing Value Sets
---------------------------------

These functions modify the contents of missing_values objects.

The next set of functions applies to all sets of user-missing values:

 -- Function: bool mv_add_value (struct missing_values *MV, const union value *VALUE)
 -- Function: bool mv_add_str (struct missing_values *MV, const char VALUE[])
 -- Function: bool mv_add_num (struct missing_values *MV, double VALUE)
     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 or if VALUE is not an acceptable user-missing value (see mv_is_acceptable below).

     These functions are equivalent, except for the form in which VALUE is provided, so you may use whichever function is most convenient.

 -- Function: void mv_pop_value (struct missing_values *MV, union value *VALUE)
     Removes a discrete value from MV (which must contain at least one discrete value) and stores it in VALUE.

 -- Function: bool mv_replace_value (struct missing_values *MV, const union value *VALUE, int INDEX)
     Attempts to replace the discrete value with the given INDEX in MV (which must contain at least INDEX + 1 discrete values) by VALUE.  Returns true if successful, false if VALUE is not an acceptable user-missing value (see mv_is_acceptable below).

 -- Function: bool mv_is_acceptable (const union value *VALUE, int WIDTH)
     Returns true if VALUE, which must have the specified WIDTH, may be added to a missing value set of the same WIDTH, false if it cannot.  As described above, all numeric values and string values of width MV_MAX_STRING or less may be added, but string value of greater width may be added only if bytes beyond the first MV_MAX_STRING are all spaces.

The second set of functions applies only to numeric sets of user-missing values:

 -- Function: bool mv_add_range (struct missing_values *MV, double LOW, double HIGH)
     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.

 -- Function: void mv_pop_range (struct missing_values *MV, double *LOW, double *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.

Value Labels
============

Each variable has a set of value labels (see VALUE LABELS (PSPP Users Guide)), represented as val_labs.  A val_labs is essentially a map from 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.

Sets of value labels may contain any number of entries.

It is rarely necessary to interact directly with a 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 variable.  See Variable Value Labels, for details.

Function prototypes and other declarations related to missing values are declared in data/value-labels.h.

 -- Structure: struct val_labs
     Opaque type that represents a set of value labels.

The most often useful function for value labels is val_labs_find, for looking up the label associated with a value.

 -- Function: char * val_labs_find (const struct val_labs *VAL_LABS, union value 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.

Creation and Destruction
------------------------

These functions create and destroy val_labs objects.

 -- Function: struct val_labs * val_labs_create (int WIDTH)
     Creates and returns an initially empty set of value labels with the given WIDTH.

 -- Function: struct val_labs * val_labs_clone (const struct val_labs *VAL_LABS)
     Creates and returns a set of value labels whose width and contents are the same as those of VAR_LABS.

 -- Function: void val_labs_clear (struct val_labs *VAR_LABS)
     Deletes all value labels from VAR_LABS.

 -- Function: void val_labs_destroy (struct val_labs *VAR_LABS)
     Destroys VAR_LABS, which must not be referenced again.

Value Labels Properties
-----------------------

These functions inspect and manipulate basic properties of val_labs objects.

 -- Function: size_t val_labs_count (const struct val_labs *VAL_LABS)
     Returns the number of value labels in VAL_LABS.

 -- Function: bool val_labs_can_set_width (const struct val_labs *VAL_LABS, int NEW_WIDTH)
     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).

 -- Function: void val_labs_set_width (struct val_labs *VAL_LABS, int NEW_WIDTH)
     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.

Adding and Removing Labels
--------------------------

These functions add and remove value labels from a val_labs object.

 -- Function: bool val_labs_add (struct val_labs *VAL_LABS, union value VALUE, const char *LABEL)
     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.

 -- Function: void val_labs_replace (struct val_labs *VAL_LABS, union value VALUE, const char *LABEL)
     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.

 -- Function: bool val_labs_remove (struct val_labs *VAL_LABS, union value VALUE)
     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.

Iterating through Value Labels
------------------------------

These functions allow iteration through the set of value labels represented by a val_labs object.  They may be used in the context of a for loop:

     struct val_labs val_labs;
     const struct val_lab *vl;

     ...

     for (vl = val_labs_first (val_labs); vl != NULL;
          vl = val_labs_next (val_labs, vl))
       {
         ...do something with vl...
       }

Value labels should not be added or deleted from a val_labs as it is undergoing iteration.

 -- Function: const struct val_lab * val_labs_first (const struct val_labs *VAL_LABS)
     Returns the first value label in VAR_LABS, if it contains at least one value label, or a null pointer if it does not contain any value labels.

 -- Function: const struct val_lab * val_labs_next (const struct val_labs *VAL_LABS, const struct val_labs_iterator **VL)
     Returns the value label in VAR_LABS following VL, if VL is not the last value label in VAL_LABS, or a null pointer if there are no value labels following VL.

 -- Function: const struct val_lab ** val_labs_sorted (const struct val_labs *VAL_LABS)
     Allocates and returns an array of pointers to value labels, which are sorted in increasing order by value.  The array has val_labs_count (VAL_LABS) elements.  The caller is responsible for freeing the array with free (but must not free any of the val_lab elements that the array points to).

The iteration functions above work with pointers to val_lab which is an opaque data structure that users of val_labs must not modify or free directly.  The following functions work with objects of this type:

 -- Function: const union value * val_lab_get_value (const struct val_lab *VL)
     Returns the value of value label VL.  The caller must not modify or free the returned value.  (To achieve a similar result, remove the value label with val_labs_remove, then add the new value with val_labs_add.)

     The width of the returned value cannot be determined directly from VL.  It may be obtained by calling val_labs_get_width on the val_labs that VL is in.

 -- Function: const char * val_lab_get_label (const struct val_lab *VL)
     Returns the label in VL as a null-terminated string.  The caller must not modify or free the returned string.  (Use val_labs_replace to change a value label.)

Variables
=========

A PSPP variable is represented by variable, an opaque type declared in data/variable.h along with related declarations. See Variables (PSPP Users Guide), for a description of PSPP variables from a user perspective.

PSPP is unusual among computer languages in that, by itself, a PSPP variable does not have a value.  Instead, a variable in PSPP takes on a value only in the context of a case, which supplies one value for each variable in a set of variables (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 (PSPP Users Guide)).

The following sections describe variable-related functions and macros.

Variable Name
-------------

A variable name is a string between 1 and VAR_NAME_LEN bytes long that satisfies the rules for PSPP identifiers (see Tokens (PSPP Users Guide)).  Variable names are mixed-case and treated case-insensitively.

 -- Macro: int VAR_NAME_LEN
     Maximum length of a variable name, in bytes, currently 64.

Only one commonly useful function relates to variable names:

 -- Function: const char * var_get_name (const struct variable *VAR)
     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:

 -- Function: void var_set_name (struct variable *VAR, const char *NEW_NAME)
     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_var instead (see Dictionary Renaming Variables).

 -- Function: bool var_is_valid_name (const char *NAME, bool ISSUE_ERROR)
 -- Function: bool var_is_plausible_name (const char *NAME, bool ISSUE_ERROR)
     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 (PSPP Users Guide)).  A ``plausible'' name is simply a string whose length is in the valid range and that is not a reserved word.  PSPP accepts plausible but invalid names as variable names in some contexts where the character encoding scheme is ambiguous, as when reading variable names from system files.

 -- Function: enum dict_class var_get_dict_class (const struct variable *VAR)
     Returns the dictionary class of VAR's name (see Dictionary Class).

Variable Type and Width
-----------------------

A variable's type and width are the type and width of its values (see Values).

 -- Function: enum val_type var_get_type (const struct variable *VAR)
     Returns the type of variable VAR.

 -- Function: int var_get_width (const struct variable *VAR)
     Returns the width of variable VAR.

 -- Function: void var_set_width (struct variable *VAR, int WIDTH)
     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.

 -- Function: bool var_is_numeric (const struct variable *VAR)
     Returns true if VAR is a numeric variable, false otherwise.

 -- Function: bool var_is_alpha (const struct variable *VAR)
     Returns true if VAR is an alphanumeric (string) variable, false otherwise.

Variable Missing Values
-----------------------

A numeric or short string variable may have a set of user-missing values (see MISSING VALUES (PSPP Users Guide)), represented as a 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:

 -- Function: bool var_is_value_missing (const struct variable *VAR, const union value *VALUE, enum mv_class CLASS)
 -- Function: bool var_is_num_missing (const struct variable *VAR, double VALUE, enum mv_class CLASS)
 -- Function: bool var_is_str_missing (const struct variable *VAR, const char VALUE[], enum mv_class CLASS)
     Tests whether VALUE is a missing value of the given CLASS for variable VAR and returns true if so, false otherwise. var_is_num_missing may only be applied to numeric variables; var_is_str_missing may only be applied to string variables. VALUE must have been initialized with the same width as VAR.

     var_is_TYPE_missing (VAR, VALUE, CLASS) is equivalent to mv_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 missing_values:

 -- Function: const struct missing_values * var_get_missing_values (const struct variable *VAR)
     Returns the missing_values associated with VAR.  The caller must not modify the returned structure.  The return value is always non-null.

 -- Function: void var_set_missing_values (struct variable *VAR, const struct missing_values *MISS)
     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.

 -- Function: void var_clear_missing_values (struct variable *VAR)
     Clears VAR's missing values.  Equivalent to var_set_missing_values (VAR, NULL).

 -- Function: bool var_has_missing_values (const struct variable *VAR)
     Returns true if VAR has any missing values, false if it has none.  Equivalent to mv_is_empty (var_get_missing_values (VAR)).

Variable Value Labels
---------------------

A numeric or short string variable may have a set of value labels (see VALUE LABELS (PSPP Users Guide)), represented as a val_labs (see Value Labels).  The most commonly useful functions for value labels return the value label associated with a value:

 -- Function: const char * var_lookup_value_label (const struct variable *VAR, const union value *VALUE)
     Looks for a label for VALUE in VAR's set of value labels. VALUE must have the same width as VAR.  Returns the label if one exists, otherwise a null pointer.

 -- Function: void var_append_value_name (const struct variable *VAR, const union value *VALUE, struct string *STR)
     Looks for a label for VALUE in VAR's set of value labels. VALUE must have the same width as VAR. 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 val_labs structure may also be accessed directly using the functions described below.

 -- Function: bool var_has_value_labels (const struct variable *VAR)
     Returns true if VAR has at least one value label, false otherwise.

 -- Function: const struct val_labs * var_get_value_labels (const struct variable *VAR)
     Returns the val_labs associated 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 val_labs, which the caller must not attempt to modify.

 -- Function: void var_set_value_labels (struct variable *VAR, const struct val_labs *VAL_LABS)
     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.

 -- Function: void var_clear_value_labels (struct variable *VAR)
     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):

 -- Function: bool var_add_value_label (struct variable *VAR, const union value *VALUE, const char *LABEL)
     Attempts to add a copy of LABEL as a label for VALUE for the given VAR.  VALUE must have the same width as 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.  Either way, the caller retains ownership of VALUE and LABEL.

 -- Function: void var_replace_value_label (struct variable *VAR, const union value *VALUE, const char *LABEL)
     Attempts to add a copy of LABEL as a label for VALUE for the given VAR.  VALUE must have the same width as VAR.  If VALUE already has a label, then LABEL replaces the old label.  Either way, the caller retains ownership of VALUE and LABEL.

Variable Print and Write Formats
--------------------------------

Each variable has an associated pair of output formats, called its print format and write format.  See Input and Output Formats (PSPP Users Guide), 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 (PSPP Users Guide)).  Most often a variable's print and write formats are the same.

A newly created variable by default has format F8.2 if it is numeric or an A format with the same width as the variable if it is string. Many creators of variables override these defaults.

Both the print format and write format are output formats.  Input formats are not part of variable.  Instead, input programs and transformations keep track of variable input formats themselves.

The following functions work with variable print and write formats.

 -- Function: const struct fmt_spec * var_get_print_format (const struct variable *VAR)
 -- Function: const struct fmt_spec * var_get_write_format (const struct variable *VAR)
     Returns VAR's print or write format, respectively.

 -- Function: void var_set_print_format (struct variable *VAR, const struct fmt_spec *FORMAT)
 -- Function: void var_set_write_format (struct variable *VAR, const struct fmt_spec *FORMAT)
 -- Function: void var_set_both_formats (struct variable *VAR, const struct fmt_spec *FORMAT)
     Sets VAR's print format, write format, or both formats, respectively, to a copy of FORMAT.

Variable Labels
---------------

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 (PSPP Users Guide), for a user-level description of variable labels.

The most commonly useful functions for variable labels are those to retrieve a variable's label:

 -- Function: const char * var_to_string (const struct variable *VAR)
     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.

 -- Function: const char * var_get_label (const struct variable *VAR)
     Returns VAR's variable label, if it has one, or a null pointer otherwise.

A few other variable label functions are also provided:

 -- Function: void var_set_label (struct variable *VAR, const char *LABEL)
     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.

 -- Function: void var_clear_label (struct variable *VAR)
     Removes any variable label from VAR.

 -- Function: bool var_has_label (const struct variable *VAR)
     Returns true if VAR has a variable label, false otherwise.

GUI Attributes
--------------

These functions and types access and set attributes that are mainly used by graphical user interfaces.  Their values are also stored in and retrieved from system files (but not portable files).

The first group of functions relate to the measurement level of numeric data.  New variables are assigned a nominal level of measurement by default.

 -- Enumeration: enum measure
     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.

 -- Function: bool measure_is_valid (enum measure MEASURE)
     Returns true if MEASURE is a valid level of measurement, that is, if it is one of the enum measure constants listed above, and false otherwise.

 -- Function: enum measure var_get_measure (const struct variable *VAR)
 -- Function: void var_set_measure (struct variable *VAR, enum measure MEASURE)
     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.

 -- Function: int var_get_display_width (const struct variable *VAR)
 -- Function: void var_set_display_width (struct variable *VAR, int DISPLAY_WIDTH)
     Gets or sets VAR's display width.

 -- Function: int var_default_display_width (int 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.

 -- Enumeration: enum alignment
     Text justification.  Possible values are ALIGN_LEFT, ALIGN_RIGHT, and ALIGN_CENTRE.

 -- Function: bool alignment_is_valid (enum alignment ALIGNMENT)
     Returns true if ALIGNMENT is a valid alignment, that is, if it is one of the enum alignment constants listed above, and false otherwise.

 -- Function: enum alignment var_get_alignment (const struct variable *VAR)
 -- Function: void var_set_alignment (struct variable *VAR, enum alignment ALIGNMENT)
     Gets or sets VAR's alignment.

Variable Leave Status
---------------------

Commonly, most or all data in a case come from an input file, read with a command such as DATA LIST or GET, but data can also be generated with transformations such as COMPUTE.  In the latter case the question of a datum's ``initial value'' can arise.  For example, the value of a piece of generated data can recursively depend on its own value:

     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 (PSPP Users Guide)).  The initial value of such a variable is 0 if it is numeric and spaces if it is a string.  If the command 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 (PSPP Users Guide)) are always left from one case to another.

The following functions work with a variable's leave status.

 -- Function: bool var_get_leave (const struct variable *VAR)
     Returns true if VAR's value is to be retained from case to case, false if it is reinitialized to system-missing or spaces.

 -- Function: void var_set_leave (struct variable *VAR, bool LEAVE)
     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.

 -- Function: bool var_must_leave (const struct variable *VAR)
     Returns true if VAR must be left from case to case, that is, if VAR is a scratch variable.

Dictionary Class
----------------

Occasionally it is useful to classify variables into dictionary classes based on their names.  Dictionary classes are represented by dict_class.  This type and other declarations for dictionary classes are in the <data/dict-class.h> header.

 -- Enumeration: enum dict_class
     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 (PSPP Users Guide).

     DC_SCRATCH
          A scratch variable, one whose name begins with #. See Scratch Variables (PSPP Users Guide).

     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 (PSPP Users Guide)).  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.

 -- Function: enum dict_class dict_class_from_id (const char *NAME)
     Returns the ``dictionary class'' for the given variable NAME, by looking at its first letter.

 -- Function: const char * dict_class_to_name (enum dict_class DICT_CLASS)
     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.

Variable Creation and Destruction
---------------------------------

Only rarely should PSPP code create or destroy variables directly. Ordinarily, variables are created within a dictionary and destroying by individual deletion from the dictionary or by destroying the entire dictionary at once.  The functions here enable the exceptional case, of creation and destruction of variables that are not associated with any dictionary.  These functions are used internally in the dictionary implementation.

 -- Function: struct variable * var_create (const char *NAME, int WIDTH)
     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).

 -- Function: struct variable * var_clone (const struct variable *OLD_VAR)
     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).

 -- Function: void var_destroy (struct variable *VAR)
     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).

Variable Short Names
--------------------

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 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.

 -- Macro: SHORT_NAME_LEN
     Maximum length of a short name, in bytes.  Its value is 8.

 -- Function: const char * var_get_short_name (const struct variable *VAR)
     Returns VAR's short name, or a null pointer if VAR has not been assigned a short name.

 -- Function: void var_set_short_name (struct variable *VAR, const char *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.

 -- Function: void var_clear_short_name (struct variable *VAR)
     Removes VAR's short name.

Variable Relationships
----------------------

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.

 -- Function: size_t var_get_dict_index (const struct variable *VAR)
     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).

 -- Function: size_t var_get_case_index (const struct variable *VAR)
     Returns VAR's index within a case.  The case index is an index into an array of value large 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).

Variable Auxiliary Data
-----------------------

Each 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.

 -- Function: void * var_get_aux (const struct variable *VAR)
     Returns VAR's auxiliary data, or a null pointer if none has been assigned.

 -- Function: void * var_attach_aux (const struct variable *VAR, void *AUX, void (*AUX_DTOR) (struct variable *))
     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_free may be appropriate for use as AUX_DTOR:

      -- Function: void var_dtor_free (struct variable *VAR)
          Frees VAR's auxiliary data by calling free.

 -- Function: void var_clear_aux (struct variable *VAR)
     Removes auxiliary data, if any, from VAR, first calling the destructor passed to var_attach_aux, if one was provided.

     Use dict_clear_aux to remove auxiliary data from every variable in a dictionary.

 -- Function: void * var_detach_aux (struct variable *VAR)
     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_aux is not called, so the caller is responsible for freeing storage associated with the returned auxiliary data.

Variable Categorical Values
---------------------------

Some statistical procedures require a list of all the values that a categorical variable takes on.  Arranging such a list requires making a pass through the data, so PSPP caches categorical values in 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.

 -- Function: struct cat_vals * var_get_obs_vals (const struct variable *VAR)
     Returns VAR's set of categorical values.  Yields undefined behavior if VAR does not have any categorical values.

 -- Function: void var_set_obs_vals (const struct variable *VAR, struct cat_vals *CAT_VALS)
     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.

 -- Function: bool var_has_obs_vals (const struct variable *VAR)
     Returns true if VAR has a set of categorical values, false otherwise.

Dictionaries
============

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 (PSPP Users Guide), for a PSPP user's view of a dictionary.

A data file stored in a PSPP format, either as a system or portable file, has a representation of its dictionary embedded in it.  Other kinds of data files are usually not self-describing enough to construct a dictionary unassisted, so the dictionaries for these files must be specified explicitly with PSPP commands such as 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 (PSPP Users Guide)).

Dictionaries are represented by dictionary.  Declarations related to dictionaries are in the <data/dictionary.h> header.

The following sections describe functions for use with dictionaries.

Accessing Variables
-------------------

The most common operations on a dictionary simply retrieve a struct variable * of an individual variable based on its name or position.

 -- Function: struct variable * dict_lookup_var (const struct dictionary *DICT, const char *NAME)
 -- Function: struct variable * dict_lookup_var_assert (const struct dictionary *DICT, const char *NAME)
     Looks up and returns the variable with the given NAME within DICT.  Name lookup is not case-sensitive.

     dict_lookup_var returns a null pointer if DICT does not contain a variable named NAME.  dict_lookup_var_assert asserts that such a variable exists.

 -- Function: struct variable * dict_get_var (const struct dictionary *DICT, size_t POSITION)
     Returns the variable at the given POSITION in DICT. POSITION must be less than the number of variables in DICT (see below).

 -- Function: size_t dict_get_var_cnt (const struct dictionary *DICT)
     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.

 -- Function: void dict_get_vars (const struct dictionary *DICT, const struct variable ***VARS, size_t *CNT, enum dict_class EXCLUDE)
 -- Function: void dict_get_vars_mutable (const struct dictionary *DICT, struct variable ***VARS, size_t *CNT, enum dict_class EXCLUDE)
     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_SYSTEM in 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.

 -- Function: bool dict_contains_var (const struct dictionary *DICT, const struct variable *VAR)
     Tests whether VAR is one of the variables in DICT. Returns true if so, false otherwise.

Creating Variables
------------------

These functions create a new variable and insert it into a dictionary in a single step.

There is no provision for inserting an already created variable into a dictionary.  There is no reason that such a function could not be written, but so far there has been no need for one.

The names provided to one of these functions should be valid variable names and must be plausible variable names.

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.

 -- Function: struct variable * dict_create_var (struct dictionary *DICT, const char *NAME, int WIDTH)
 -- Function: struct variable * dict_create_var_assert (struct dictionary *DICT, const char *NAME, int WIDTH)
     Creates a new variable with the given NAME and WIDTH, as if through a call to var_create with those arguments (see var_create), appends the new variable to DICT's array of variables, and returns the new variable.

 -- Function: struct variable * dict_clone_var (struct dictionary *DICT, const struct variable *OLD_VAR, const char *NAME)
 -- Function: struct variable * dict_clone_var_assert (struct dictionary *DICT, const struct variable *OLD_VAR, const char *NAME)
     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.

Deleting Variables
------------------

These functions remove variables from a dictionary's array of variables.  They also destroy the removed variables and free their associated storage.

Deleting a variable to which there might be external pointers is a bad idea.  In particular, deleting variables from the active file dictionary is a risky proposition, because transformations can retain references to arbitrary variables.  Therefore, no variable should be deleted from the active file dictionary when any transformations are active, because those transformations might reference the variable to be deleted.  The safest time to delete a variable is just after a procedure has been executed, as done by 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.

 -- Function: void dict_delete_var (struct dictionary *DICT, struct variable *VAR)
     Deletes VAR from DICT, of which it must be a member.

 -- Function: void dict_delete_vars (struct dictionary *DICT, struct variable *const *VARS, size_t COUNT)
     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.

 -- Function: void dict_delete_consecutive_vars (struct dictionary *DICT, size_t IDX, size_t COUNT)
     Deletes the variables in sequential positions IDX...IDX + COUNT (exclusive) from DICT, which must contain at least IDX + COUNT variables.

 -- Function: void dict_delete_scratch_vars (struct dictionary *DICT)
     Deletes all scratch variables from DICT.

Changing Variable Order
-----------------------

The variables in a dictionary are stored in an array.  These functions change the order of a dictionary's array of variables without changing which variables are in the dictionary.

 -- Function: void dict_reorder_var (struct dictionary *DICT, struct variable *VAR, size_t NEW_INDEX)
     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.

 -- Function: void dict_reorder_vars (struct dictionary *DICT, struct variable *const *NEW_ORDER, size_t COUNT)
     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.

Renaming Variables
------------------

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 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.

 -- Function: void dict_rename_var (struct dictionary *DICT, struct variable *VAR, const char *NEW_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.

 -- Function: bool dict_rename_vars (struct dictionary *DICT, struct variable **VARS, char **NEW_NAMES, size_t COUNT, char **ERR_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.

Weight Variable
---------------

A data set's cases may optionally be weighted by the value of a numeric variable.  See WEIGHT (PSPP Users Guide), for a user view of weight variables.

The weight variable is written to and read from system and portable files.

The most commonly useful function related to weighting is a convenience function to retrieve a weighting value from a case.

 -- Function: double dict_get_case_weight (const struct dictionary *DICT, const struct ccase *CASE, bool *WARN_ON_INVALID)
     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_weight also 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 a msg_disable/msg_enable pair.

The dictionary also has a pair of functions for getting and setting the weight variable.

 -- Function: struct variable * dict_get_weight (const struct dictionary *DICT)
     Returns DICT's current weighting variable, or a null pointer if the dictionary does not have a weighting variable.

 -- Function: void dict_set_weight (struct dictionary *DICT, struct variable *VAR)
     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.

Filter Variable
---------------

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 (PSPP Users Guide), for a user view of filtering.

These functions store and retrieve the filter variable.  They are rarely useful, because the data analysis framework automatically excludes from analysis the cases that should be filtered.

 -- Function: struct variable * dict_get_filter (const struct dictionary *DICT)
     Returns DICT's current filter variable, or a null pointer if the dictionary does not have a filter variable.

 -- Function: void dict_set_filter (struct dictionary *DICT, struct variable *VAR)
     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.

Case Limit
----------

The limit on cases analyzed by a procedure, set by the N OF CASES command (see N OF CASES (PSPP Users Guide)), is stored as part of the dictionary.  The dictionary does not, on the other hand, play any role in enforcing the case limit (a job done by data analysis framework code).

A case limit of 0 means that the number of cases is not limited.

These functions are rarely useful, because the data analysis framework automatically excludes from analysis any cases beyond the limit.

 -- Function: casenumber dict_get_case_limit (const struct dictionary *DICT)
     Returns the current case limit for DICT.

 -- Function: void dict_set_case_limit (struct dictionary *DICT, casenumber LIMIT)
     Sets DICT's case limit to LIMIT.

Split Variables
---------------

The user may use the SPLIT FILE command (see SPLIT FILE (PSPP Users Guide)) to select a set of variables on which to split the active file into groups of cases to be analyzed independently in each statistical procedure.  The set of split variables is stored as part of the dictionary, although the effect on data analysis is implemented by each individual statistical procedure.

Split variables may be numeric or short or long string variables.

The most useful functions for split variables are those to retrieve them.  Even these functions are rarely useful directly: for the purpose of breaking cases into groups based on the values of the split variables, it is usually easier to use casegrouper_create_splits.

 -- Function: const struct variable *const * dict_get_split_vars (const struct dictionary *DICT)
     Returns a pointer to an array of pointers to split variables.  If and only if there are no split variables, returns a null pointer.  The caller must not modify or free the returned array.

 -- Function: size_t dict_get_split_cnt (const struct dictionary *DICT)
     Returns the number of split variables.

The following functions are also available for working with split variables.

 -- Function: void dict_set_split_vars (struct dictionary *DICT, struct variable *const *VARS, size_t CNT)
     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.

 -- Function: void dict_unset_split_var (struct dictionary *DICT, struct variable *VAR)
     Removes VAR, which must be a variable in DICT, from DICT's split of split variables.

File Label
----------

A dictionary may optionally have an associated string that describes its contents, called its file label.  The user may set the file label with the FILE LABEL command (see FILE LABEL (PSPP Users Guide)).

These functions set and retrieve the file label.

 -- Function: const char * dict_get_label (const struct dictionary *DICT)
     Returns DICT's file label.  If DICT does not have a label, returns a null pointer.

 -- Function: void dict_set_label (struct dictionary *DICT, const char *LABEL)
     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.

Documents
---------

A dictionary may include an arbitrary number of lines of explanatory text, called the dictionary's documents.  For compatibility, document lines have a fixed width, and lines that are not exactly this width are truncated or padded with spaces as necessary to bring them to the correct width.

PSPP users can use the DOCUMENT (see DOCUMENT (PSPP Users Guide)), ADD DOCUMENT (see ADD DOCUMENT (PSPP Users Guide)), and DROP DOCUMENTS (see DROP DOCUMENTS (PSPP Users Guide)) commands to manipulate documents.

 -- Macro: int DOC_LINE_LENGTH
     The fixed length of a document line, in bytes, defined to 80.

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.

 -- Function: const char * dict_get_documents (const struct dictionary *DICT)
     Returns the documents in DICT, or a null pointer if DICT has no documents.

 -- Function: void dict_set_documents (struct dictionary *DICT, const char *NEW_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.

 -- Function: void dict_clear_documents (struct dictionary *DICT)
     Clears the documents from DICT.

The following functions work with individual lines in a dictionary's set of documents.

 -- Function: void dict_add_document_line (struct dictionary *DICT, const char *CONTENT)
     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_LENGTH bytes long.  The caller retains ownership of CONTENT.

     If CONTENT is over DOC_LINE_LENGTH, this function also issues a warning using msg.  To suppress the warning, enclose a call to one of this function in a msg_disable/msg_enable pair.

 -- Function: size_t dict_get_document_line_cnt (const struct dictionary *DICT)
     Returns the number of line of documents in DICT.  If the dictionary contains no documents, returns 0.

 -- Function: void dict_get_document_line (const struct dictionary *DICT, size_t IDX, struct string *CONTENT)
     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.

Coding Conventions
==================

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.

Cases
=====

This section needs to be written.

Data Sets
=========

This section needs to be written.

Pools
=====

This section needs to be written.