X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fvars-prs.c;h=2a5309f7e489e99e1f52dfd4937bb2dbc51f01ff;hb=a2222a2ddac2f12d38ae62bc7a769ed6d1ae1b46;hp=288e0510312f6111ac87ee58743640d26a0cad55;hpb=2bfc3a138f308ffb38634a92b23bdc7b62592324;p=pspp-builds.git diff --git a/src/vars-prs.c b/src/vars-prs.c index 288e0510..2a5309f7 100644 --- a/src/vars-prs.c +++ b/src/vars-prs.c @@ -14,155 +14,238 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ -/* AIX requires this to be the first thing in the file. */ #include -#if __GNUC__ -#define alloca __builtin_alloca -#else -#if HAVE_ALLOCA_H -#include -#else -#ifdef _AIX -#pragma alloca -#else -#ifndef alloca /* predefined by HP cc +Olibcalls */ -char *alloca (); -#endif -#endif -#endif -#endif - -#include +#include "var.h" #include #include #include "alloc.h" #include "bitvector.h" +#include "dictionary.h" #include "error.h" #include "hash.h" #include "lexer.h" #include "misc.h" #include "str.h" -#include "var.h" -/* Allocates an array at *V to contain all the variables in - default_dict. If FV_NO_SYSTEM is set in FLAGS then system - variables will not be included. If FV_NO_SCRATCH is set in FLAGS - then scratch variables will not be included. *C is set to the - number of variables in *V. */ -void -fill_all_vars (struct variable ***varlist, int *c, int flags) +/* Parses a name as a variable within VS and returns the + variable's index if successful. On failure emits an error + message and returns a null pointer. */ +static int +parse_vs_variable_idx (const struct var_set *vs) { - int i; + int idx; - *varlist = xmalloc (default_dict.nvar * sizeof **varlist); - if (flags == FV_NONE) + if (token != T_ID) { - *c = default_dict.nvar; - for (i = 0; i < default_dict.nvar; i++) - (*varlist)[i] = default_dict.var[i]; - } - else - { - *c = 0; - - for (i = 0; i < default_dict.nvar; i++) - { - struct variable *v = default_dict.var[i]; - - if ((flags & FV_NO_SYSTEM) && v->name[0] == '$') - continue; - if ((flags & FV_NO_SCRATCH) && v->name[0] == '#') - continue; - - (*varlist)[*c] = v; - (*c)++; - } - - if (*c != default_dict.nvar) - *varlist = xrealloc (*varlist, *c * sizeof **varlist); + lex_error (_("expecting variable name")); + return -1; } + + idx = var_set_lookup_var_idx (vs, tokid); + if (idx < 0) + msg (SE, _("%s is not a variable name."), tokid); + lex_get (); + + return idx; } -int -is_varname (const char *s) +/* Parses a name as a variable within VS and returns the variable + if successful. On failure emits an error message and returns + a null pointer. */ +static struct variable * +parse_vs_variable (const struct var_set *vs) { - return hsh_find (default_dict.name_tab, s) != NULL; + int idx = parse_vs_variable_idx (vs); + return idx >= 0 ? var_set_get_var (vs, idx) : NULL; } -int -is_dict_varname (const struct dictionary *dict, const char *s) +/* Parses a variable name in dictionary D and returns the + variable if successful. On failure emits an error message and + returns a null pointer. */ +struct variable * +parse_dict_variable (const struct dictionary *d) { - return hsh_find (dict->name_tab, s) != NULL; + struct var_set *vs = var_set_create_from_dict (d); + struct variable *var = parse_vs_variable (vs); + var_set_destroy (vs); + return var; } +/* Parses a variable name in default_dict and returns the + variable if successful. On failure emits an error message and + returns a null pointer. */ struct variable * parse_variable (void) { - struct variable *vp; + return parse_dict_variable (default_dict); +} - if (token != T_ID) +/* Returns the dictionary class corresponding to a variable named + NAME. */ +enum dict_class +dict_class_from_id (const char *name) +{ + assert (name != NULL); + + switch (name[0]) { - lex_error ("expecting variable name"); - return NULL; + default: + return DC_ORDINARY; + case '$': + return DC_SYSTEM; + case '#': + return DC_SCRATCH; } - vp = find_variable (tokid); - if (!vp) - msg (SE, _("%s is not declared as a variable."), tokid); - lex_get (); - return vp; } -struct variable * -parse_dict_variable (struct dictionary * dict) +/* Returns the name of dictionary class DICT_CLASS. */ +const char * +dict_class_to_name (enum dict_class dict_class) { - struct variable *vp; - - if (token != T_ID) + switch (dict_class) { - lex_error ("expecting variable name"); - return NULL; + case DC_ORDINARY: + return _("ordinary"); + case DC_SYSTEM: + return _("system"); + case DC_SCRATCH: + return _("scratch"); + default: + assert (0); + abort (); } +} - vp = hsh_find (dict->name_tab, tokid); - if (!vp) - msg (SE, _("%s is not a variable name."), tokid); - lex_get (); +/* Parses a set of variables from dictionary D given options + OPTS. Resulting list of variables stored in *VAR and the + number of variables into *CNT. Returns nonzero only if + successful. */ +int +parse_variables (const struct dictionary *d, struct variable ***var, + int *cnt, int opts) +{ + struct var_set *vs; + int success; + + assert (d != NULL); + assert (var != NULL); + assert (cnt != NULL); + + + vs = var_set_create_from_dict (d); + success = parse_var_set_vars (vs, var, cnt, opts); + if ( success == 0 ) + free ( *var ) ; + var_set_destroy (vs); + return success; +} + +/* Parses a variable name from VS. If successful, sets *IDX to + the variable's index in VS, *CLASS to the variable's + dictionary class, and returns nonzero. Returns zero on + failure. */ +static int +parse_var_idx_class (const struct var_set *vs, int *idx, + enum dict_class *class) +{ + *idx = parse_vs_variable_idx (vs); + if (*idx < 0) + return 0; + + *class = dict_class_from_id (var_set_get_var (vs, *idx)->name); + return 1; +} + +/* Add the variable from VS with index IDX to the list of + variables V that has *NV elements and room for *MV. + Uses and updates INCLUDED to avoid duplicates if indicated by + PV_OPTS, which also affects what variables are allowed in + appropriate ways. */ +static void +add_variable (struct variable ***v, int *nv, int *mv, + char *included, int pv_opts, + const struct var_set *vs, int idx) +{ + struct variable *add = var_set_get_var (vs, idx); + + if ((pv_opts & PV_NUMERIC) && add->type != NUMERIC) + msg (SW, _("%s is not a numeric variable. It will not be " + "included in the variable list."), add->name); + else if ((pv_opts & PV_STRING) && add->type != ALPHA) + msg (SE, _("%s is not a string variable. It will not be " + "included in the variable list."), add->name); + else if ((pv_opts & PV_NO_SCRATCH) + && dict_class_from_id (add->name) == DC_SCRATCH) + msg (SE, _("Scratch variables (such as %s) are not allowed " + "here."), add->name); + else if ((pv_opts & PV_SAME_TYPE) && *nv && add->type != (*v)[0]->type) + msg (SE, _("%s and %s are not the same type. All variables in " + "this variable list must be of the same type. %s " + "will be omitted from list."), + (*v)[0]->name, add->name, add->name); + else if ((pv_opts & PV_NO_DUPLICATE) && included[idx]) + msg (SE, _("Variable %s appears twice in variable list."), add->name); + else + { + if (*nv >= *mv) + { + *mv = 2 * (*nv + 1); + *v = xrealloc (*v, *mv * sizeof **v); + } + + if ((pv_opts & PV_DUPLICATE) || !included[idx]) + { + (*v)[(*nv)++] = add; + if (!(pv_opts & PV_DUPLICATE)) + included[idx] = 1; + } + } +} - return vp; +/* Adds the variables in VS with indexes FIRST_IDX through + LAST_IDX, inclusive, to the list of variables V that has *NV + elements and room for *MV. Uses and updates INCLUDED to avoid + duplicates if indicated by PV_OPTS, which also affects what + variables are allowed in appropriate ways. */ +static void +add_variables (struct variable ***v, int *nv, int *mv, char *included, + int pv_opts, + const struct var_set *vs, int first_idx, int last_idx, + enum dict_class class) +{ + int i; + + for (i = first_idx; i <= last_idx; i++) + if (dict_class_from_id (var_set_get_var (vs, i)->name) == class) + add_variable (v, nv, mv, included, pv_opts, vs, i); } -/* Returns the dictionary class of an identifier based on its - first letter: `X' if is an ordinary identifier, `$' if it - designates a system variable, `#' if it designates a scratch - variable. */ -#define id_dict(C) \ - ((C) == '$' ? '$' : ((C) == '#' ? '#' : 'X')) - -/* FIXME: One interesting variation in the case of PV_APPEND would be - to keep the bitmap, reducing time required to an actual O(n log n) - instead of having to reproduce the bitmap *every* *single* *time*. - Later though. (Another idea would be to keep a marker bit in each - variable.) */ /* Note that if parse_variables() returns 0, *v is free()'d. Conversely, if parse_variables() returns non-zero, then *nv is nonzero and *v is non-NULL. */ int -parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int pv_opts) +parse_var_set_vars (const struct var_set *vs, + struct variable ***v, int *nv, + int pv_opts) { - int i; - int nbytes; - unsigned char *bits; + int mv; + char *included; + + assert (vs != NULL); + assert (v != NULL); + assert (nv != NULL); - struct variable *v1, *v2; - int count, mv; - int scratch; /* Dictionary we're reading from. */ - int delayed_fail = 0; + /* At most one of PV_NUMERIC, PV_STRING, PV_SAME_TYPE may be + specified. */ + assert ((((pv_opts & PV_NUMERIC) != 0) + + ((pv_opts & PV_STRING) != 0) + + ((pv_opts & PV_SAME_TYPE) != 0)) <= 1); - if (dict == NULL) - dict = &default_dict; + /* PV_DUPLICATE and PV_NO_DUPLICATE are incompatible. */ + assert (!(pv_opts & PV_DUPLICATE) || !(pv_opts & PV_NO_DUPLICATE)); if (!(pv_opts & PV_APPEND)) { @@ -173,166 +256,92 @@ parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int p else mv = *nv; -#if GLOBAL_DEBUGGING - { - int corrupt = 0; - int i; - - for (i = 0; i < dict->nvar; i++) - if (dict->var[i]->index != i) - { - printf ("%s index corruption: variable %s\n", - dict == &default_dict ? "default_dict" : "aux dict", - dict->var[i]->name); - corrupt = 1; - } - - assert (!corrupt); - } -#endif - - nbytes = DIV_RND_UP (dict->nvar, 8); if (!(pv_opts & PV_DUPLICATE)) { - bits = local_alloc (nbytes); - memset (bits, 0, nbytes); + int i; + + included = xcalloc (var_set_get_cnt (vs)); for (i = 0; i < *nv; i++) - SET_BIT (bits, (*v)[i]->index); + included[(*v)[i]->index] = 1; } + else + included = NULL; - do +if (lex_match (T_ALL)) + add_variables (v, nv, &mv, included, pv_opts, + vs, 0, var_set_get_cnt (vs) - 1, DC_ORDINARY); + else { - if (lex_match (T_ALL)) - { - v1 = dict->var[0]; - v2 = dict->var[dict->nvar - 1]; - count = dict->nvar; - scratch = id_dict ('X'); - } - else - { - v1 = parse_dict_variable (dict); - if (!v1) - goto fail; - - if (lex_match (T_TO)) - { - v2 = parse_dict_variable (dict); - if (!v2) - { - lex_error ("expecting variable name"); - goto fail; - } - - count = v2->index - v1->index + 1; - if (count < 1) - { - msg (SE, _("%s TO %s is not valid syntax since %s " - "precedes %s in the dictionary."), - v1->name, v2->name, v2->name, v1->name); - goto fail; - } - - scratch = id_dict (v1->name[0]); - if (scratch != id_dict (v2->name[0])) - { - msg (SE, _("When using the TO keyword to specify several " - "variables, both variables must be from " - "the same variable dictionaries, of either " - "ordinary, scratch, or system variables. " - "%s and %s are from different dictionaries."), - v1->name, v2->name); - goto fail; - } - } - else - { - v2 = v1; - count = 1; - scratch = id_dict (v1->name[0]); - } - if (scratch == id_dict ('#') && (pv_opts & PV_NO_SCRATCH)) - { - msg (SE, _("Scratch variables (such as %s) are not allowed " - "here."), v1->name); - goto fail; - } - } - - if (*nv + count > mv) - { - mv += ROUND_UP (count, 16); - *v = xrealloc (*v, mv * sizeof **v); - } - - for (i = v1->index; i <= v2->index; i++) - { - struct variable *add = dict->var[i]; - - /* Skip over other dictionaries. */ - if (scratch != id_dict (add->name[0])) - continue; - - if ((pv_opts & PV_NUMERIC) && add->type != NUMERIC) - { - delayed_fail = 1; - msg (SW, _("%s is not a numeric variable. It will not be " - "included in the variable list."), add->name); - } - else if ((pv_opts & PV_STRING) && add->type != ALPHA) - { - delayed_fail = 1; - msg (SE, _("%s is not a string variable. It will not be " - "included in the variable list."), add->name); - } - else if ((pv_opts & PV_SAME_TYPE) && *nv && add->type != (*v)[0]->type) - { - delayed_fail = 1; - msg (SE, _("%s and %s are not the same type. All variables in " - "this variable list must be of the same type. %s " - "will be omitted from list."), - (*v)[0]->name, add->name, add->name); - } - else if ((pv_opts & PV_NO_DUPLICATE) && TEST_BIT (bits, add->index)) - { - delayed_fail = 1; - msg (SE, _("Variable %s appears twice in variable list."), - add->name); - } - else if ((pv_opts & PV_DUPLICATE) || !TEST_BIT (bits, add->index)) - { - (*v)[(*nv)++] = dict->var[i]; - if (!(pv_opts & PV_DUPLICATE)) - SET_BIT (bits, add->index); - } - } - - if (pv_opts & PV_SINGLE) - { - if (delayed_fail) - goto fail; - else - return 1; - } - lex_match (','); + do + { + enum dict_class class; + int first_idx; + + if (!parse_var_idx_class (vs, &first_idx, &class)) + goto fail; + + if (!lex_match (T_TO)) + add_variable (v, nv, &mv, included, pv_opts, + vs, first_idx); + else + { + int last_idx; + enum dict_class last_class; + struct variable *first_var, *last_var; + + if (!parse_var_idx_class (vs, &last_idx, &last_class)) + goto fail; + + first_var = var_set_get_var (vs, first_idx); + last_var = var_set_get_var (vs, last_idx); + + if (last_idx < first_idx) + { + msg (SE, _("%s TO %s is not valid syntax since %s " + "precedes %s in the dictionary."), + first_var->name, last_var->name, + first_var->name, last_var->name); + goto fail; + } + if (class != last_class) + { + msg (SE, _("When using the TO keyword to specify several " + "variables, both variables must be from " + "the same variable dictionaries, of either " + "ordinary, scratch, or system variables. " + "%s is a %s variable, whereas %s is %s."), + first_var->name, dict_class_to_name (class), + last_var->name, dict_class_to_name (last_class)); + goto fail; + } + + add_variables (v, nv, &mv, included, pv_opts, + vs, first_idx, last_idx, class); + } + if (pv_opts & PV_SINGLE) + break; + lex_match (','); + } + while (token == T_ID && var_set_lookup_var (vs, tokid) != NULL); } - while ((token == T_ID && is_dict_varname (dict, tokid)) || token == T_ALL); - - if (!(pv_opts & PV_DUPLICATE)) - local_free (bits); - if (!nv) + + if (*nv == 0) goto fail; + + free (included); return 1; fail: + free (included); free (*v); *v = NULL; *nv = 0; - if (!(pv_opts & PV_DUPLICATE)) - local_free (bits); return 0; } +/* Extracts a numeric suffix from variable name S, copying it + into string R. Sets *D to the length of R and *N to its + value. */ static int extract_num (char *s, char *r, int *n, int *d) { @@ -386,6 +395,12 @@ parse_DATA_LIST_vars (char ***names, int *nnames, int pv_opts) char *root1, *root2; int success = 0; + assert (names != NULL); + assert (nnames != NULL); + assert ((pv_opts & ~(PV_APPEND | PV_SINGLE + | PV_NO_SCRATCH | PV_NO_DUPLICATE)) == 0); + /* FIXME: PV_NO_DUPLICATE is not implemented. */ + if (pv_opts & PV_APPEND) nvar = mvar = *nnames; else @@ -394,10 +409,10 @@ parse_DATA_LIST_vars (char ***names, int *nnames, int pv_opts) *names = NULL; } - name1 = xmalloc (36); - name2 = &name1[1 * 9]; - root1 = &name1[2 * 9]; - root2 = &name1[3 * 9]; + name1 = xmalloc (4 * (SHORT_NAME_LEN + 1)); + name2 = &name1[1 * SHORT_NAME_LEN + 1]; + root1 = &name1[2 * SHORT_NAME_LEN + 1]; + root2 = &name1[3 * SHORT_NAME_LEN + 1]; do { if (token != T_ID) @@ -405,7 +420,8 @@ parse_DATA_LIST_vars (char ***names, int *nnames, int pv_opts) lex_error ("expecting variable name"); goto fail; } - if (tokid[0] == '#' && (pv_opts & PV_NO_SCRATCH)) + if (dict_class_from_id (tokid) == DC_SCRATCH + && (pv_opts & PV_NO_SCRATCH)) { msg (SE, _("Scratch variables not allowed here.")); goto fail; @@ -448,7 +464,7 @@ parse_DATA_LIST_vars (char ***names, int *nnames, int pv_opts) for (n = n1; n <= n2; n++) { - (*names)[nvar] = xmalloc (9); + (*names)[nvar] = xmalloc (SHORT_NAME_LEN + 1); sprintf ((*names)[nvar], "%s%0*d", root1, d1, n); nvar++; } @@ -488,12 +504,16 @@ fail: /* Parses a list of variables where some of the variables may be existing and the rest are to be created. Same args as - parse_variables(). */ + parse_DATA_LIST_vars(). */ int parse_mixed_vars (char ***names, int *nnames, int pv_opts) { int i; + assert (names != NULL); + assert (nnames != NULL); + assert ((pv_opts & ~PV_APPEND) == 0); + if (!(pv_opts & PV_APPEND)) { *names = NULL; @@ -501,12 +521,12 @@ parse_mixed_vars (char ***names, int *nnames, int pv_opts) } while (token == T_ID || token == T_ALL) { - if (token == T_ALL || is_varname (tokid)) + if (token == T_ALL || dict_lookup_var (default_dict, tokid) != NULL) { struct variable **v; int nv; - if (!parse_variables (NULL, &v, &nv, PV_NONE)) + if (!parse_variables (default_dict, &v, &nv, PV_NONE)) goto fail; *names = xrealloc (*names, (*nnames + nv) * sizeof **names); for (i = 0; i < nv; i++) @@ -527,3 +547,233 @@ fail: *nnames = 0; return 0; } + +/* A set of variables. */ +struct var_set + { + size_t (*get_cnt) (const struct var_set *); + struct variable *(*get_var) (const struct var_set *, size_t idx); + int (*lookup_var_idx) (const struct var_set *, const char *); + void (*destroy) (struct var_set *); + void *aux; + }; + +/* Returns the number of variables in VS. */ +size_t +var_set_get_cnt (const struct var_set *vs) +{ + assert (vs != NULL); + + return vs->get_cnt (vs); +} + +/* Return variable with index IDX in VS. + IDX must be less than the number of variables in VS. */ +struct variable * +var_set_get_var (const struct var_set *vs, size_t idx) +{ + assert (vs != NULL); + assert (idx < var_set_get_cnt (vs)); + + return vs->get_var (vs, idx); +} + +/* Returns the variable in VS named NAME, or a null pointer if VS + contains no variable with that name. */ +struct variable * +var_set_lookup_var (const struct var_set *vs, const char *name) +{ + int idx = var_set_lookup_var_idx (vs, name); + return idx >= 0 ? var_set_get_var (vs, idx) : NULL; +} + +/* Returns the index in VS of the variable named NAME, or -1 if + VS contains no variable with that name. */ +int +var_set_lookup_var_idx (const struct var_set *vs, const char *name) +{ + assert (vs != NULL); + assert (name != NULL); + assert (strlen (name) <= LONG_NAME_LEN ); + + return vs->lookup_var_idx (vs, name); +} + +/* Destroys VS. */ +void +var_set_destroy (struct var_set *vs) +{ + if (vs != NULL) + vs->destroy (vs); +} + +/* Returns the number of variables in VS. */ +static size_t +dict_var_set_get_cnt (const struct var_set *vs) +{ + struct dictionary *d = vs->aux; + + return dict_get_var_cnt (d); +} + +/* Return variable with index IDX in VS. + IDX must be less than the number of variables in VS. */ +static struct variable * +dict_var_set_get_var (const struct var_set *vs, size_t idx) +{ + struct dictionary *d = vs->aux; + + return dict_get_var (d, idx); +} + +/* Returns the index of the variable in VS named NAME, or -1 if + VS contains no variable with that name. */ +static int +dict_var_set_lookup_var_idx (const struct var_set *vs, const char *name) +{ + struct dictionary *d = vs->aux; + struct variable *v = dict_lookup_var (d, name); + return v != NULL ? v->index : -1; +} + +/* Destroys VS. */ +static void +dict_var_set_destroy (struct var_set *vs) +{ + free (vs); +} + +/* Returns a variable set based on D. */ +struct var_set * +var_set_create_from_dict (const struct dictionary *d) +{ + struct var_set *vs = xmalloc (sizeof *vs); + vs->get_cnt = dict_var_set_get_cnt; + vs->get_var = dict_var_set_get_var; + vs->lookup_var_idx = dict_var_set_lookup_var_idx; + vs->destroy = dict_var_set_destroy; + vs->aux = (void *) d; + return vs; +} + +/* A variable set based on an array. */ +struct array_var_set + { + struct variable *const *var;/* Array of variables. */ + size_t var_cnt; /* Number of elements in var. */ + struct hsh_table *name_tab; /* Hash from variable names to variables. */ + struct hsh_table *longname_tab; /* Hash of short names indexed by long names */ + }; + +/* Returns the number of variables in VS. */ +static size_t +array_var_set_get_cnt (const struct var_set *vs) +{ + struct array_var_set *avs = vs->aux; + + return avs->var_cnt; +} + +/* Return variable with index IDX in VS. + IDX must be less than the number of variables in VS. */ +static struct variable * +array_var_set_get_var (const struct var_set *vs, size_t idx) +{ + struct array_var_set *avs = vs->aux; + + return (struct variable *) avs->var[idx]; +} + +/* Returns the index of the variable in VS named NAME, or -1 if + VS contains no variable with that name. */ +static int +array_var_set_lookup_var_idx (const struct var_set *vs, const char *name) +{ + char *short_name ; + struct array_var_set *avs = vs->aux; + struct variable v, *vp, *const *vpp; + + struct name_table_entry key; + key.longname = name; + + struct name_table_entry *nte; + + assert (avs->longname_tab); + + + nte = hsh_find (avs->longname_tab, &key); + + if (!nte) + return -1; + + short_name = nte->name; + + strcpy (v.name, short_name); + vp = &v; + vpp = hsh_find (avs->name_tab, &vp); + return vpp != NULL ? vpp - avs->var : -1; +} + +/* Destroys VS. */ +static void +array_var_set_destroy (struct var_set *vs) +{ + struct array_var_set *avs = vs->aux; + + hsh_destroy (avs->name_tab); + hsh_destroy (avs->longname_tab); + free (avs); + free (vs); +} + +/* Returns a variable set based on the VAR_CNT variables in + VAR. */ +struct var_set * +var_set_create_from_array (struct variable *const *var, size_t var_cnt) +{ + struct var_set *vs; + struct array_var_set *avs; + size_t i; + + vs = xmalloc (sizeof *vs); + vs->get_cnt = array_var_set_get_cnt; + vs->get_var = array_var_set_get_var; + vs->lookup_var_idx = array_var_set_lookup_var_idx; + vs->destroy = array_var_set_destroy; + vs->aux = avs = xmalloc (sizeof *avs); + avs->var = var; + avs->var_cnt = var_cnt; + avs->name_tab = hsh_create (2 * var_cnt, + compare_var_ptr_names, hash_var_ptr_name, + NULL, NULL); + + avs->longname_tab = hsh_create (2 * var_cnt, + compare_long_names, hash_long_name, + (hsh_free_func *) free_nte, + NULL); + + for (i = 0; i < var_cnt; i++) + { + struct name_table_entry *nte ; + + if (hsh_insert (avs->name_tab, &var[i]) != NULL) + { + var_set_destroy (vs); + return NULL; + } + + nte = xmalloc (sizeof (*nte)); + nte->name = strdup(var[i]->name); + nte->longname = strdup(var[i]->longname); + + if (hsh_insert (avs->longname_tab, nte) != NULL) + { + var_set_destroy (vs); + free (nte); + return NULL; + } + + } + + return vs; +}