+\f
+/* 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);
+}
+\f
+/* 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;
+}
+\f
+/* 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. */
+ };
+
+/* 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)
+{
+ struct array_var_set *avs = vs->aux;
+ struct variable v, *vp, *const *vpp;
+
+ strcpy (v.name, 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);
+ 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);
+ for (i = 0; i < var_cnt; i++)
+ if (hsh_insert (avs->name_tab, (void *) &var[i]) != NULL)
+ {
+ var_set_destroy (vs);
+ return NULL;
+ }
+
+ return vs;
+}