+/* Get a string representing VALUE for variable V.
+ That is, if VALUE has a label, return that label,
+ otherwise format VALUE and return the formatted string. */
+const char *
+var_get_value_name (const struct variable *v, const union value *value)
+{
+ const char *name = var_lookup_value_label (v, value);
+ if (name == NULL)
+ {
+ static char buf[MAX_STRING + 1];
+ data_out (value, &v->print, buf);
+ buf[v->print.w] = '\0';
+ name = buf;
+ }
+ return name;
+}
+\f
+/* Print and write formats. */
+
+/* Returns V's print format specification. */
+const struct fmt_spec *
+var_get_print_format (const struct variable *v)
+{
+ return &v->print;
+}
+
+/* Sets V's print format specification to PRINT, which must be a
+ valid format specification for outputting a variable of V's
+ width. */
+void
+var_set_print_format (struct variable *v, const struct fmt_spec *print)
+{
+ assert (fmt_check_width_compat (print, v->width));
+ v->print = *print;
+ dict_var_changed (v);
+}
+
+/* Returns V's write format specification. */
+const struct fmt_spec *
+var_get_write_format (const struct variable *v)
+{
+ return &v->write;
+}
+
+/* Sets V's write format specification to WRITE, which must be a
+ valid format specification for outputting a variable of V's
+ width. */
+void
+var_set_write_format (struct variable *v, const struct fmt_spec *write)
+{
+ assert (fmt_check_width_compat (write, v->width));
+ v->write = *write;
+ dict_var_changed (v);
+}
+
+/* Sets V's print and write format specifications to FORMAT,
+ which must be a valid format specification for outputting a
+ variable of V's width. */
+void
+var_set_both_formats (struct variable *v, const struct fmt_spec *format)
+{
+ var_set_print_format (v, format);
+ var_set_write_format (v, format);
+}
+\f
+/* Return a string representing this variable, in the form most
+ appropriate from a human factors perspective, that is, its
+ variable label if it has one, otherwise its name. */
+const char *
+var_to_string (const struct variable *v)
+{
+ return v->label != NULL ? v->label : v->name;
+}
+
+/* Returns V's variable label, or a null pointer if it has none. */
+const char *
+var_get_label (const struct variable *v)
+{
+ return v->label;
+}
+
+/* Sets V's variable label to LABEL, stripping off leading and
+ trailing white space and truncating to 255 characters.
+ If LABEL is a null pointer or if LABEL is an empty string
+ (after stripping white space), then V's variable label (if
+ any) is removed. */
+void
+var_set_label (struct variable *v, const char *label)
+{
+ free (v->label);
+ v->label = NULL;
+
+ if (label != NULL)
+ {
+ struct substring s = ss_cstr (label);
+ ss_trim (&s, ss_cstr (CC_SPACES));
+ ss_truncate (&s, 255);
+ if (!ss_is_empty (s))
+ v->label = ss_xstrdup (s);
+ dict_var_changed (v);
+ }
+}
+
+/* Removes any variable label from V. */
+void
+var_clear_label (struct variable *v)
+{
+ var_set_label (v, NULL);
+}
+
+/* Returns true if V has a variable V,
+ false otherwise. */
+bool
+var_has_label (const struct variable *v)
+{
+ return v->label != NULL;
+}
+\f
+/* Returns true if M is a valid variable measurement level,
+ false otherwise. */
+bool
+measure_is_valid (enum measure m)
+{
+ return m == MEASURE_NOMINAL || m == MEASURE_ORDINAL || m == MEASURE_SCALE;
+}
+
+/* Returns V's measurement level. */
+enum measure
+var_get_measure (const struct variable *v)
+{
+ return v->measure;
+}
+
+/* Sets V's measurement level to MEASURE. */
+void
+var_set_measure (struct variable *v, enum measure measure)
+{
+ assert (measure_is_valid (measure));
+ v->measure = measure;
+ dict_var_changed (v);
+}
+\f
+/* Returns V's display width, which applies only to GUIs. */
+int
+var_get_display_width (const struct variable *v)
+{
+ return v->display_width;
+}
+
+/* Sets V's display width to DISPLAY_WIDTH. */
+void
+var_set_display_width (struct variable *v, int display_width)
+{
+ v->display_width = display_width;
+ dict_var_changed (v);
+}
+
+/* Returns the default display width for a variable of the given
+ WIDTH, as set by var_create. The return value can be used to
+ reset a variable's display width to the default. */
+int
+var_default_display_width (int width)
+{
+ return width == 0 ? 8 : MIN (width, 32);
+}
+\f
+/* Returns true if A is a valid alignment,
+ false otherwise. */
+bool
+alignment_is_valid (enum alignment a)
+{
+ return a == ALIGN_LEFT || a == ALIGN_RIGHT || a == ALIGN_CENTRE;
+}
+
+/* Returns V's display alignment, which applies only to GUIs. */
+enum alignment
+var_get_alignment (const struct variable *v)
+{
+ return v->alignment;
+}
+
+/* Sets V's display alignment to ALIGNMENT. */
+void
+var_set_alignment (struct variable *v, enum alignment alignment)
+{
+ assert (alignment_is_valid (alignment));
+ v->alignment = alignment;
+ dict_var_changed (v);
+}
+\f
+/* Whether variables' values should be preserved from case to
+ case. */
+
+/* Returns true if variable V's value should be left from case to
+ case, instead of being reset to 0, system-missing, or blanks. */
+bool
+var_get_leave (const struct variable *v)
+{
+ return v->leave;
+}
+
+/* Sets V's leave setting to LEAVE. */
+void
+var_set_leave (struct variable *v, bool leave)
+{
+ assert (leave || !var_must_leave (v));
+ v->leave = leave;
+ dict_var_changed (v);
+}
+
+/* Returns true if V must be left from case to case,
+ false if it can be set either way. */
+bool
+var_must_leave (const struct variable *v)
+{
+ return dict_class_from_id (v->name) == DC_SCRATCH;
+}
+\f
+/* Returns the number of short names stored in VAR.
+
+ Short names are used only for system and portable file input
+ and output. They are upper-case only, not necessarily unique,
+ and limited to SHORT_NAME_LEN characters (plus a null
+ terminator). Ordinarily a variable has at most one short
+ name, but very long string variables (longer than 255 bytes)
+ may have more. A variable might not have any short name at
+ all if it hasn't been saved to or read from a system or
+ portable file. */
+size_t
+var_get_short_name_cnt (const struct variable *var)
+{
+ return var->short_name_cnt;
+}
+
+/* Returns VAR's short name with the given IDX, if it has one
+ with that index, or a null pointer otherwise. Short names may
+ be sparse: even if IDX is less than the number of short names
+ in VAR, this function may return a null pointer. */
+const char *
+var_get_short_name (const struct variable *var, size_t idx)
+{
+ return idx < var->short_name_cnt ? var->short_names[idx] : NULL;
+}
+
+/* Sets VAR's short name with the given IDX to SHORT_NAME,
+ truncating it to SHORT_NAME_LEN characters and converting it
+ to uppercase in the process. Specifying a null pointer for
+ SHORT_NAME clears the specified short name. */
+void
+var_set_short_name (struct variable *var, size_t idx, const char *short_name)
+{
+ assert (var != NULL);
+ assert (short_name == NULL || var_is_plausible_name (short_name, false));
+
+ /* Clear old short name numbered IDX, if any. */
+ if (idx < var->short_name_cnt)
+ {
+ free (var->short_names[idx]);
+ var->short_names[idx] = NULL;
+ }
+
+ /* Install new short name for IDX. */
+ if (short_name != NULL)
+ {
+ if (idx >= var->short_name_cnt)
+ {
+ size_t old_cnt = var->short_name_cnt;
+ size_t i;
+
+ var->short_name_cnt = MAX (idx * 2, 1);
+ var->short_names = xnrealloc (var->short_names, var->short_name_cnt,
+ sizeof *var->short_names);
+ for (i = old_cnt; i < var->short_name_cnt; i++)
+ var->short_names[i] = NULL;
+ }
+ var->short_names[idx] = xstrndup (short_name, MAX_SHORT_STRING);
+ str_uppercase (var->short_names[idx]);
+ }
+
+ dict_var_changed (var);
+}
+
+/* Clears V's short names. */
+void
+var_clear_short_names (struct variable *v)
+{
+ size_t i;
+
+ for (i = 0; i < v->short_name_cnt; i++)
+ free (v->short_names[i]);
+ v->short_names = NULL;
+ v->short_name_cnt = 0;
+}
+\f
+/* Relationship with dictionary. */
+
+/* Returns V's index within its dictionary, the value
+ for which "dict_get_var (dict, index)" will return V.
+ V must be in a dictionary. */
+size_t
+var_get_dict_index (const struct variable *v)
+{
+ assert (v->vardict.dict_index != -1);
+ return v->vardict.dict_index;
+}
+
+/* Returns V's index within the case represented by its
+ dictionary, that is, the value for which "case_data_idx (case,
+ index)" will return the data for V in that case.
+ V must be in a dictionary. */
+size_t
+var_get_case_index (const struct variable *v)
+{
+ assert (v->vardict.case_index != -1);
+ return v->vardict.case_index;
+}
+\f
+/* Returns V's auxiliary data, or a null pointer if none has been
+ attached. */
+void *
+var_get_aux (const struct variable *v)
+{
+ return v->aux;
+}
+
+/* Assign auxiliary data AUX to variable V, which must not
+ already have auxiliary data. Before V's auxiliary data is
+ cleared, AUX_DTOR(V) will be called. (var_dtor_free, below,
+ may be appropriate for use as AUX_DTOR.) */
+void *
+var_attach_aux (const struct variable *v_,
+ void *aux, void (*aux_dtor) (struct variable *))
+{
+ struct variable *v = (struct variable *) v_ ; /* cast away const */
+ assert (v->aux == NULL);
+ assert (aux != NULL);
+ v->aux = aux;
+ v->aux_dtor = aux_dtor;
+ return aux;
+}
+
+/* Remove auxiliary data, if any, from V, and return it, without
+ calling any associated destructor. */
+void *
+var_detach_aux (struct variable *v)
+{
+ void *aux = v->aux;
+ assert (aux != NULL);
+ v->aux = NULL;
+ return aux;
+}
+
+/* Clears auxiliary data, if any, from V, and calls any
+ associated destructor. */
+void
+var_clear_aux (struct variable *v)
+{
+ assert (v != NULL);
+ if (v->aux != NULL)
+ {
+ if (v->aux_dtor != NULL)
+ v->aux_dtor (v);
+ v->aux = NULL;
+ }
+}
+
+/* This function is appropriate for use an auxiliary data
+ destructor (passed as AUX_DTOR to var_attach_aux()) for the
+ case where the auxiliary data should be passed to free(). */
+void
+var_dtor_free (struct variable *v)
+{
+ free (v->aux);
+}
+\f
+/* Observed categorical values. */
+
+/* Returns V's observed categorical values,
+ which V must have. */
+struct cat_vals *
+var_get_obs_vals (const struct variable *v)
+{
+ assert (v->obs_vals != NULL);
+ return v->obs_vals;
+}
+
+/* Sets V's observed categorical values to CAT_VALS. */
+void
+var_set_obs_vals (const struct variable *v_, struct cat_vals *cat_vals)
+{
+ struct variable *v = (struct variable *) v_ ; /* cast away const */
+ cat_stored_values_destroy (v->obs_vals);
+ v->obs_vals = cat_vals;
+}
+
+/* Returns true if V has observed categorical values,
+ false otherwise. */
+bool
+var_has_obs_vals (const struct variable *v)
+{
+ return v->obs_vals != NULL;
+}
+\f