X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fvars-atr.c;h=5e34cb5946aa410aca09a922a1642ebea90d1e09;hb=3fb611d221aa070458c81c6ca8b1c78fbad9a0ab;hp=9ed5fcbc4f252b786408fcd12c95b756d6c176a8;hpb=4fdeb2145d081ff1b84e3f6c99f9d1c048c0d64a;p=pspp diff --git a/src/vars-atr.c b/src/vars-atr.c index 9ed5fcbc4f..5e34cb5946 100644 --- a/src/vars-atr.c +++ b/src/vars-atr.c @@ -34,8 +34,14 @@ #include "value-labels.h" #include "vfm.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) + #include "debug-print.h" +/* 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. */ void * var_attach_aux (struct variable *v, void *aux, void (*aux_dtor) (struct variable *)) @@ -47,6 +53,8 @@ var_attach_aux (struct variable *v, return aux; } +/* Remove auxiliary data, if any, from V, and returns it, without + calling any associated destructor. */ void * var_detach_aux (struct variable *v) { @@ -56,6 +64,8 @@ var_detach_aux (struct variable *v) return aux; } +/* Clears auxiliary data, if any, from V, and calls any + associated destructor. */ void var_clear_aux (struct variable *v) { @@ -68,6 +78,9 @@ var_clear_aux (struct variable *v) } } +/* 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) { @@ -128,109 +141,6 @@ discard_variables (void) pgm_state = STATE_INIT; } - -/* Return nonzero only if X is a user-missing value for numeric - variable V. */ -inline int -is_num_user_missing (double x, const struct variable *v) -{ - switch (v->miss_type) - { - case MISSING_NONE: - return 0; - case MISSING_1: - return x == v->missing[0].f; - case MISSING_2: - return x == v->missing[0].f || x == v->missing[1].f; - case MISSING_3: - return (x == v->missing[0].f || x == v->missing[1].f - || x == v->missing[2].f); - case MISSING_RANGE: - return x >= v->missing[0].f && x <= v->missing[1].f; - case MISSING_LOW: - return x <= v->missing[0].f; - case MISSING_HIGH: - return x >= v->missing[0].f; - case MISSING_RANGE_1: - return ((x >= v->missing[0].f && x <= v->missing[1].f) - || x == v->missing[2].f); - case MISSING_LOW_1: - return x <= v->missing[0].f || x == v->missing[1].f; - case MISSING_HIGH_1: - return x >= v->missing[0].f || x == v->missing[1].f; - default: - assert (0); - } - abort (); -} - -/* Return nonzero only if string S is a user-missing variable for - string variable V. */ -inline int -is_str_user_missing (const unsigned char s[], const struct variable *v) -{ - /* FIXME: should these be memcmp()? */ - switch (v->miss_type) - { - case MISSING_NONE: - return 0; - case MISSING_1: - return !strncmp (s, v->missing[0].s, v->width); - case MISSING_2: - return (!strncmp (s, v->missing[0].s, v->width) - || !strncmp (s, v->missing[1].s, v->width)); - case MISSING_3: - return (!strncmp (s, v->missing[0].s, v->width) - || !strncmp (s, v->missing[1].s, v->width) - || !strncmp (s, v->missing[2].s, v->width)); - default: - assert (0); - } - abort (); -} - -/* Return nonzero only if value VAL is system-missing for variable - V. */ -int -is_system_missing (const union value *val, const struct variable *v) -{ - return v->type == NUMERIC && val->f == SYSMIS; -} - -/* Return nonzero only if value VAL is system- or user-missing for - variable V. */ -int -is_missing (const union value *val, const struct variable *v) -{ - switch (v->type) - { - case NUMERIC: - if (val->f == SYSMIS) - return 1; - return is_num_user_missing (val->f, v); - case ALPHA: - return is_str_user_missing (val->s, v); - default: - assert (0); - } - abort (); -} - -/* Return nonzero only if value VAL is user-missing for variable V. */ -int -is_user_missing (const union value *val, const struct variable *v) -{ - switch (v->type) - { - case NUMERIC: - return is_num_user_missing (val->f, v); - case ALPHA: - return is_str_user_missing (val->s, v); - default: - assert (0); - } - abort (); -} /* Returns true if NAME is an acceptable name for a variable, false otherwise. If ISSUE_ERROR is true, issues an @@ -246,14 +156,14 @@ var_is_valid_name (const char *name, bool issue_error) if (length < 1) { if (issue_error) - msg (SE, _("Variable names must be at least 1 character long.")); + msg (SE, _("Variable name cannot be empty string.")); return false; } - else if (length > SHORT_NAME_LEN) + else if (length > LONG_NAME_LEN) { if (issue_error) msg (SE, _("Variable name %s exceeds %d-character limit."), - (int) SHORT_NAME_LEN); + name, (int) LONG_NAME_LEN); return false; } @@ -263,7 +173,7 @@ var_is_valid_name (const char *name, bool issue_error) if (issue_error) msg (SE, _("Character `%c' (in %s) may not appear in " "a variable name."), - name); + name[i], name); return false; } @@ -271,7 +181,8 @@ var_is_valid_name (const char *name, bool issue_error) { if (issue_error) msg (SE, _("Character `%c' (in %s), may not appear " - "as the first character in a variable name."), name); + "as the first character in a variable name."), + name[0], name); return false; } @@ -294,7 +205,7 @@ compare_var_names (const void *a_, const void *b_, void *foo UNUSED) const struct variable *a = a_; const struct variable *b = b_; - return strcmp (a->name, b->name); + return strcasecmp (a->name, b->name); } /* A hsh_hash_func that hashes variable V based on its name. */ @@ -303,7 +214,7 @@ hash_var_name (const void *v_, void *foo UNUSED) { const struct variable *v = v_; - return hsh_hash_string (v->name); + return hsh_hash_case_string (v->name); } /* A hsh_compare_func that orders pointers to variables A and B @@ -314,7 +225,7 @@ compare_var_ptr_names (const void *a_, const void *b_, void *foo UNUSED) struct variable *const *a = a_; struct variable *const *b = b_; - return strcmp ((*a)->name, (*b)->name); + return strcasecmp ((*a)->name, (*b)->name); } /* A hsh_hash_func that hashes pointer to variable V based on its @@ -324,5 +235,66 @@ hash_var_ptr_name (const void *v_, void *foo UNUSED) { struct variable *const *v = v_; - return hsh_hash_string ((*v)->name); + return hsh_hash_case_string ((*v)->name); +} + +/* Sets V's short_name to SHORT_NAME, truncating it to + SHORT_NAME_LEN characters and converting it to uppercase in + the process. */ +void +var_set_short_name (struct variable *v, const char *short_name) +{ + assert (v != NULL); + assert (short_name[0] == '\0' || var_is_valid_name (short_name, false)); + + str_copy_trunc (v->short_name, sizeof v->short_name, short_name); + str_uppercase (v->short_name); +} + +/* Clears V's short name. */ +void +var_clear_short_name (struct variable *v) +{ + assert (v != NULL); + + v->short_name[0] = '\0'; +} + +/* Sets V's short name to BASE, followed by a suffix of the form + _A, _B, _C, ..., _AA, _AB, etc. according to the value of + SUFFIX. Truncates BASE as necessary to fit. */ +void +var_set_short_name_suffix (struct variable *v, const char *base, int suffix) +{ + char string[SHORT_NAME_LEN + 1]; + char *start, *end; + int len, ofs; + + assert (v != NULL); + assert (suffix >= 0); + assert (strlen (v->short_name) > 0); + + /* Set base name. */ + var_set_short_name (v, base); + + /* Compose suffix_string. */ + start = end = string + sizeof string - 1; + *end = '\0'; + do + { + *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix % 26]; + if (start <= string + 1) + msg (SE, _("Variable suffix too large.")); + suffix /= 26; + } + while (suffix > 0); + *--start = '_'; + + /* Append suffix_string to V's short name. */ + len = end - start; + if (len + strlen (v->short_name) > SHORT_NAME_LEN) + ofs = SHORT_NAME_LEN - len; + else + ofs = strlen (v->short_name); + strcpy (v->short_name + ofs, start); }