X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fvariable.c;h=0b8079ca534762c2a776739c6001b8327be2d335;hb=8cc788667db16517f96ba15979da3e3b9638dd3b;hp=22159d8765691747af4d29a990c9324727ca5fd8;hpb=04bbac9e357101873ccd9b5555e14f946d81b5ce;p=pspp-builds.git diff --git a/src/data/variable.c b/src/data/variable.c index 22159d87..0b8079ca 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -19,7 +19,6 @@ #include - #include "category.h" #include "data-out.h" #include "format.h" @@ -30,13 +29,14 @@ #include "vardict.h" #include -#include #include #include #include #include #include +#include "xalloc.h" + #include "gettext.h" #define _(msgid) gettext (msgid) @@ -44,7 +44,7 @@ struct variable { /* Dictionary information. */ - char name[LONG_NAME_LEN + 1]; /* Variable name. Mixed case. */ + char name[VAR_NAME_LEN + 1]; /* Variable name. Mixed case. */ int width; /* 0 for numeric, otherwise string width. */ struct missing_values miss; /* Missing values. */ struct fmt_spec print; /* Default format for PRINT. */ @@ -63,11 +63,10 @@ struct variable /* Data for use by containing dictionary. */ struct vardict_info vardict; - /* Short name, used only for system and portable file input - and output. Upper case only. Short names are not necessarily - unique. Any variable may have no short name, indicated by an - empty string. */ - char short_name[SHORT_NAME_LEN + 1]; + /* Used only for system and portable file input and output. + See short-names.h. */ + char **short_names; + size_t short_name_cnt; /* Each command may use these fields as needed. */ void *aux; @@ -78,20 +77,6 @@ struct variable have its values stored here. */ struct cat_vals *obs_vals; }; - -/* Returns true if VAR_TYPE is a valid variable type. */ -bool -var_type_is_valid (enum var_type var_type) -{ - return var_type == VAR_NUMERIC || var_type == VAR_STRING; -} - -/* Returns the variable type for the given width. */ -enum var_type -var_type_from_width (int width) -{ - return width != 0 ? VAR_STRING : VAR_NUMERIC; -} /* Creates and returns a new variable with the given NAME and WIDTH and other fields initialized to default values. The @@ -114,20 +99,20 @@ var_create (const char *name, int width) { v->print = fmt_for_output (FMT_F, 8, 2); v->alignment = ALIGN_RIGHT; - v->display_width = 8; v->measure = MEASURE_SCALE; } else { v->print = fmt_for_output (FMT_A, var_get_width (v), 0); v->alignment = ALIGN_LEFT; - v->display_width = 8; v->measure = MEASURE_NOMINAL; } + v->display_width = var_default_display_width (width); v->write = v->print; v->val_labs = NULL; v->label = NULL; - var_clear_short_name (v); + v->short_names = NULL; + v->short_name_cnt = 0; v->aux = NULL; v->aux_dtor = NULL; v->obs_vals = NULL; @@ -175,6 +160,7 @@ var_destroy (struct variable *v) { assert (!var_has_vardict (v)); cat_stored_values_destroy (v->obs_vals); + var_clear_short_names (v); var_clear_aux (v); val_labs_destroy (v->val_labs); var_clear_label (v); @@ -271,11 +257,11 @@ var_is_plausible_name (const char *name, bool issue_error) msg (SE, _("Variable name cannot be empty string.")); return false; } - else if (length > LONG_NAME_LEN) + else if (length > VAR_NAME_LEN) { if (issue_error) msg (SE, _("Variable name %s exceeds %d-character limit."), - name, (int) LONG_NAME_LEN); + name, (int) VAR_NAME_LEN); return false; } @@ -290,6 +276,13 @@ var_is_plausible_name (const char *name, bool issue_error) return true; } +/* Returns VAR's dictionary class. */ +enum dict_class +var_get_dict_class (const struct variable *var) +{ + return dict_class_from_id (var->name); +} + /* A hsh_compare_func that orders variables A and B by their names. */ int @@ -333,10 +326,10 @@ hash_var_ptr_by_name (const void *v_, const void *aux UNUSED) } /* Returns the type of variable V. */ -enum var_type +enum val_type var_get_type (const struct variable *v) { - return var_type_from_width (v->width); + return val_type_from_width (v->width); } /* Returns the width of variable V. */ @@ -346,7 +339,8 @@ var_get_width (const struct variable *v) return v->width; } -/* Sets the width of V to WIDTH. */ +/* Changes the width of V to NEW_WIDTH. + This function should be used cautiously. */ void var_set_width (struct variable *v, int new_width) { @@ -388,7 +382,7 @@ var_set_width (struct variable *v, int new_width) bool var_is_numeric (const struct variable *v) { - return var_get_type (v) == VAR_NUMERIC; + return var_get_type (v) == VAL_NUMERIC; } /* Returns true if variable V is a string variable, false @@ -396,7 +390,7 @@ var_is_numeric (const struct variable *v) bool var_is_alpha (const struct variable *v) { - return var_get_type (v) == VAR_STRING; + return var_get_type (v) == VAL_STRING; } /* Returns true if variable V is a short string variable, false @@ -520,7 +514,7 @@ var_set_value_labels (struct variable *v, const struct val_labs *vls) if (vls != NULL) { assert (val_labs_can_set_width (vls, v->width)); - v->val_labs = val_labs_copy (vls); + v->val_labs = val_labs_clone (vls); val_labs_set_width (v->val_labs, v->width); dict_var_changed (v); } @@ -538,8 +532,7 @@ alloc_value_labels (struct variable *v) /* Attempts to add a value label with the given VALUE and LABEL to V. Returns true if successful, false if VALUE has an - existing label. - V must not be a long string variable. */ + existing label or if V is a long string variable. */ bool var_add_value_label (struct variable *v, const union value *value, const char *label) @@ -550,7 +543,7 @@ var_add_value_label (struct variable *v, /* Adds or replaces a value label with the given VALUE and LABEL to V. - V must not be a long string variable. */ + Has no effect if V is a long string variable. */ void var_replace_value_label (struct variable *v, const union value *value, const char *label) @@ -574,23 +567,26 @@ var_lookup_value_label (const struct variable *v, const union value *value) return val_labs_find (v->val_labs, *value); } -/* 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) +/* Append STR with a string representing VALUE for variable V. + That is, if VALUE has a label, append that label, + otherwise format VALUE and append the formatted string. + STR must be a pointer to an initialised struct string. +*/ +void +var_append_value_name (const struct variable *v, const union value *value, + struct string *str) { 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; + char *s = ds_put_uninit (str, v->print.w); + data_out (value, &v->print, s); } - return name; + else + ds_put_cstr (str, name); } + /* Print and write formats. */ /* Returns V's print format specification. */ @@ -723,9 +719,6 @@ 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) @@ -733,6 +726,15 @@ 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); +} /* Returns true if A is a valid alignment, false otherwise. */ @@ -762,7 +764,7 @@ var_set_alignment (struct variable *v, enum alignment alignment) case. */ /* Returns true if variable V's value should be left from case to - case, instead of being reset to 0, system-missing, or blanks. */ + case, instead of being reset to system-missing or blanks. */ bool var_get_leave (const struct variable *v) { @@ -783,50 +785,83 @@ var_set_leave (struct variable *v, bool leave) bool var_must_leave (const struct variable *v) { - return dict_class_from_id (v->name) == DC_SCRATCH; + return var_get_dict_class (v) == DC_SCRATCH; } -/* Returns V's short name, if it has one, or a null pointer - otherwise. +/* 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). Any variable may have no short name, indicated - by returning a null pointer. */ + 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 *v) +var_get_short_name (const struct variable *var, size_t idx) { - return v->short_name[0] != '\0' ? v->short_name : NULL; + return idx < var->short_name_cnt ? var->short_names[idx] : NULL; } -/* Sets V's short_name 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 variable's short name. */ +/* 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 *v, const char *short_name) +var_set_short_name (struct variable *var, size_t idx, const char *short_name) { - assert (v != NULL); + assert (var != NULL); assert (short_name == NULL || var_is_plausible_name (short_name, false)); - if (short_name != NULL) + /* Clear old short name numbered IDX, if any. */ + if (idx < var->short_name_cnt) { - str_copy_trunc (v->short_name, sizeof v->short_name, short_name); - str_uppercase (v->short_name); + free (var->short_names[idx]); + var->short_names[idx] = NULL; } - else - v->short_name[0] = '\0'; - dict_var_changed (v); + + /* 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 name. */ +/* Clears V's short names. */ void -var_clear_short_name (struct variable *v) +var_clear_short_names (struct variable *v) { - assert (v != NULL); + size_t i; - v->short_name[0] = '\0'; + for (i = 0; i < v->short_name_cnt; i++) + free (v->short_names[i]); + free (v->short_names); + v->short_names = NULL; + v->short_name_cnt = 0; } /* Relationship with dictionary. */ @@ -921,7 +956,8 @@ var_get_obs_vals (const struct variable *v) return v->obs_vals; } -/* Sets V's observed categorical values to CAT_VALS. */ +/* Sets V's observed categorical values to CAT_VALS. + V becomes the owner of CAT_VALS. */ void var_set_obs_vals (const struct variable *v_, struct cat_vals *cat_vals) { @@ -938,39 +974,6 @@ var_has_obs_vals (const struct variable *v) return v->obs_vals != NULL; } -/* Returns the dictionary class corresponding to a variable named - NAME. */ -enum dict_class -dict_class_from_id (const char *name) -{ - switch (name[0]) - { - default: - return DC_ORDINARY; - case '$': - return DC_SYSTEM; - case '#': - return DC_SCRATCH; - } -} - -/* Returns the name of dictionary class DICT_CLASS. */ -const char * -dict_class_to_name (enum dict_class dict_class) -{ - switch (dict_class) - { - case DC_ORDINARY: - return _("ordinary"); - case DC_SYSTEM: - return _("system"); - case DC_SCRATCH: - return _("scratch"); - default: - NOT_REACHED (); - } -} - /* Returns V's vardict structure. */ const struct vardict_info * var_get_vardict (const struct variable *v)