X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Flexer%2Fvariable-parser.c;h=98b70ea2f7ac97001391135a9968ef2900164757;hb=8e018d25310cb53e5339b46e95f0abe02db83782;hp=64792aaaec56ced30eadc35077efd292c7bf41a7;hpb=81fff61a96bece351e381ad3fef8ab1248a952ba;p=pspp diff --git a/src/language/lexer/variable-parser.c b/src/language/lexer/variable-parser.c index 64792aaaec..98b70ea2f7 100644 --- a/src/language/lexer/variable-parser.c +++ b/src/language/lexer/variable-parser.c @@ -19,6 +19,8 @@ #include +#include + #include #include #include @@ -118,6 +120,29 @@ parse_variables (const struct dictionary *d, struct variable ***var, return success; } +/* Parses a set of variables from dictionary D given options + OPTS. Resulting list of variables stored in *VARS and the + number of variables into *VAR_CNT. Returns nonzero only if + successful. Same behavior as parse_variables, except that all + allocations are taken from the given POOL. */ +int +parse_variables_pool (struct pool *pool, const struct dictionary *dict, + struct variable ***vars, size_t *var_cnt, int opts) +{ + int retval; + + /* PV_APPEND is unsafe because parse_variables would free the + existing names on failure, but those names are presumably + already in the pool, which would attempt to re-free it + later. */ + assert (!(opts & PV_APPEND)); + + retval = parse_variables (dict, vars, var_cnt, opts); + if (retval) + pool_register (pool, free, *vars); + return retval; +} + /* 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 @@ -162,20 +187,16 @@ add_variable (struct variable ***v, size_t *nv, size_t *mv, (*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 + else if ((pv_opts & PV_DUPLICATE) || !included[idx]) { if (*nv >= *mv) { *mv = 2 * (*nv + 1); *v = xnrealloc (*v, *mv, sizeof **v); } - - if ((pv_opts & PV_DUPLICATE) || !included[idx]) - { - (*v)[(*nv)++] = add; - if (!(pv_opts & PV_DUPLICATE)) - included[idx] = 1; - } + (*v)[(*nv)++] = add; + if (included != NULL) + included[idx] = 1; } } @@ -241,16 +262,16 @@ parse_var_set_vars (const struct var_set *vs, else included = NULL; - if (lex_match (T_ALL)) - add_variables (v, nv, &mv, included, pv_opts, - vs, 0, var_set_get_cnt (vs) - 1, DC_ORDINARY); - else + do { - 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 { enum dict_class class; size_t first_idx; - + if (!parse_var_idx_class (vs, &first_idx, &class)) goto fail; @@ -291,13 +312,15 @@ parse_var_set_vars (const struct var_set *vs, 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); + + if (pv_opts & PV_SINGLE) + break; + lex_match (','); } + while (token == T_ALL + || (token == T_ID && var_set_lookup_var (vs, tokid) != NULL)); if (*nv == 0) goto fail; @@ -472,6 +495,40 @@ fail: return success; } +/* Registers each of the NAMES[0...NNAMES - 1] in POOL, as well + as NAMES itself. */ +static void +register_vars_pool (struct pool *pool, char **names, size_t nnames) +{ + size_t i; + + for (i = 0; i < nnames; i++) + pool_register (pool, free, names[i]); + pool_register (pool, free, names); +} + +/* Parses a list of variable names according to the DATA LIST + version of the TO convention. Same args as + parse_DATA_LIST_vars(), except that all allocations are taken + from the given POOL. */ +int +parse_DATA_LIST_vars_pool (struct pool *pool, + char ***names, size_t *nnames, int pv_opts) +{ + int retval; + + /* PV_APPEND is unsafe because parse_DATA_LIST_vars would free + the existing names on failure, but those names are + presumably already in the pool, which would attempt to + re-free it later. */ + assert (!(pv_opts & PV_APPEND)); + + retval = parse_DATA_LIST_vars (names, nnames, pv_opts); + if (retval) + register_vars_pool (pool, *names, *nnames); + return retval; +} + /* Parses a list of variables where some of the variables may be existing and the rest are to be created. Same args as parse_DATA_LIST_vars(). */ @@ -520,24 +577,25 @@ 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_DATA_LIST_vars(), except that all allocations are taken + parse_mixed_vars(), except that all allocations are taken from the given POOL. */ int parse_mixed_vars_pool (struct pool *pool, char ***names, size_t *nnames, int pv_opts) { - int retval = parse_mixed_vars (names, nnames, pv_opts); - if (retval) - { - size_t i; + int retval; - for (i = 0; i < *nnames; i++) - pool_register (pool, free, (*names)[i]); - pool_register (pool, free, *names); - } + /* PV_APPEND is unsafe because parse_mixed_vars_pool would free + the existing names on failure, but those names are + presumably already in the pool, which would attempt to + re-free it later. */ + assert (!(pv_opts & PV_APPEND)); + + retval = parse_mixed_vars (names, nnames, pv_opts); + if (retval) + register_vars_pool (pool, *names, *nnames); return retval; } - /* A set of variables. */ struct var_set