X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=inline;f=src%2Flanguage%2Flexer%2Fvariable-parser.c;h=a2068f02eaf2f3d568cc64fd77f33506c90a93f5;hb=c708736bdd0fea4b79f3ee4a10e00c3abb95d9e3;hp=7f25d8eb685f0be26818df389bb2fef07182db38;hpb=e9aa6e433b846849da90550f6800095d569fb549;p=pspp diff --git a/src/language/lexer/variable-parser.c b/src/language/lexer/variable-parser.c index 7f25d8eb68..a2068f02ea 100644 --- a/src/language/lexer/variable-parser.c +++ b/src/language/lexer/variable-parser.c @@ -99,9 +99,9 @@ parse_variable (void) /* 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 + number of variables into *CNT. Returns true only if successful. */ -int +bool parse_variables (const struct dictionary *d, struct variable ***var, size_t *cnt, int opts) { @@ -120,19 +120,42 @@ 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 true only if + successful. Same behavior as parse_variables, except that all + allocations are taken from the given POOL. */ +bool +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 + dictionary class, and returns true. Returns false on failure. */ -static int +static bool parse_var_idx_class (const struct var_set *vs, size_t *idx, enum dict_class *class) { if (!parse_vs_variable_idx (vs, idx)) - return 0; + return false; *class = dict_class_from_id (var_set_get_var (vs, *idx)->name); - return 1; + return true; } /* Add the variable from VS with index IDX to the list of @@ -164,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; } } @@ -199,10 +218,10 @@ add_variables (struct variable ***v, size_t *nv, size_t *mv, char *included, add_variable (v, nv, mv, included, pv_opts, vs, i); } -/* Note that if parse_variables() returns 0, *v is free()'d. - Conversely, if parse_variables() returns non-zero, then *nv is +/* Note that if parse_variables() returns false, *v is free()'d. + Conversely, if parse_variables() returns true, then *nv is nonzero and *v is non-NULL. */ -int +bool parse_var_set_vars (const struct var_set *vs, struct variable ***v, size_t *nv, int pv_opts) @@ -243,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; @@ -293,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; @@ -360,7 +381,7 @@ extract_num (char *s, char *r, int *n, int *d) /* Parses a list of variable names according to the DATA LIST version of the TO convention. */ -int +bool parse_DATA_LIST_vars (char ***names, size_t *nnames, int pv_opts) { int n1, n2; @@ -474,10 +495,44 @@ 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. */ +bool +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(). */ -int +bool parse_mixed_vars (char ***names, size_t *nnames, int pv_opts) { size_t i; @@ -522,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 +bool 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