+/* Looks up the N_VS var syntax structs in VS in DICT, translating them to an
+ array of variables. If successful, initializes *VARS to the beginning of an
+ array of pointers to variables and *N_VARS to the length of the array and
+ returns true. On error, sets *VARS to NULL and *N_VARS to 0.
+
+ For the moment, only honors PV_NUMERIC in OPTS. */
+bool
+var_syntax_evaluate (const struct var_syntax *vs, size_t n_vs,
+ const struct dictionary *dict,
+ struct variable ***vars, size_t *n_vars, int opts)
+{
+ assert (!(opts & ~PV_NUMERIC));
+
+ *vars = NULL;
+ *n_vars = 0;
+
+ size_t allocated_vars = 0;
+ for (size_t i = 0; i < n_vs; i++)
+ {
+ struct variable *first = dict_lookup_var (dict, vs[i].first);
+ if (!first)
+ {
+ msg (SE, _("%s is not a variable name."), vs[i].first);
+ goto error;
+ }
+
+ struct variable *last = (vs[i].last
+ ? dict_lookup_var (dict, vs[i].last)
+ : first);
+ if (!last)
+ {
+ msg (SE, _("%s is not a variable name."), vs[i].last);
+ goto error;
+ }
+
+ size_t first_idx = var_get_dict_index (first);
+ size_t last_idx = var_get_dict_index (last);
+ if (last_idx < first_idx)
+ {
+ msg (SE, _("%s TO %s is not valid syntax since %s "
+ "precedes %s in the dictionary."),
+ vs[i].first, vs[i].last,
+ vs[i].first, vs[i].last);
+ goto error;
+ }
+
+ for (size_t j = first_idx; j <= last_idx; j++)
+ {
+ struct variable *v = dict_get_var (dict, j);
+ if (opts & PV_NUMERIC && !var_is_numeric (v))
+ {
+ msg (SW, _("%s is not a numeric variable."), var_get_name (v));
+ goto error;
+ }
+
+ if (*n_vars >= allocated_vars)
+ *vars = x2nrealloc (*vars, &allocated_vars, sizeof **vars);
+ (*vars)[(*n_vars)++] = v;
+ }
+ }
+
+ return true;
+
+error:
+ free (*vars);
+ *vars = NULL;
+ *n_vars = 0;
+ return false;
+}