From 65620ac48c2b146a580a80af120590e4e3d4a6d4 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Mon, 24 Oct 2005 05:41:44 +0000 Subject: [PATCH] Refactored to make it easier to abstract a dictionary from the rest of PSPP. --- src/Makefile.am | 4 +- src/algorithm.c | 26 -------- src/dictionary.c | 5 +- src/format-prs.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++ src/format.c | 122 ------------------------------------ src/lex-def.c | 98 +++++++++++++++++++++++++++++ src/lex-def.h | 83 +++++++++++++++++++++++++ src/lexer.c | 66 +------------------- src/lexer.h | 55 +---------------- src/vars-atr.c | 64 +++++++++++-------- src/vars-prs.c | 35 ----------- src/vfm.c | 30 +++++++++ 12 files changed, 414 insertions(+), 331 deletions(-) create mode 100644 src/format-prs.c create mode 100644 src/lex-def.c create mode 100644 src/lex-def.h diff --git a/src/Makefile.am b/src/Makefile.am index 7c77ccc926..87ecce90ce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,10 +50,10 @@ data-list.c data-list.h data-out.c date.c debug-print.h descript.c \ devind.c devind.h dfm-read.c dfm-read.h dfm-write.c dfm-write.h \ dictionary.c dictionary.h do-if.c do-ifP.h echo.c error.c error.h \ factor_stats.c factor_stats.h file-handle.h file-type.c filename.c \ -filename.h flip.c font.h format.c format.def format.h formats.c get.c \ +filename.h flip.c font.h format.c format-prs.c format.def format.h formats.c get.c \ getl.c getl.h glob.c glob.h groff-font.c group.c group.h group_proc.h \ hash.c hash.h histogram.c histogram.h html.c htmlP.h include.c \ -inpt-pgm.c lexer.c lexer.h levene.c levene.h linked-list.c \ +inpt-pgm.c lexer.c lexer.h lex-def.h lex-def.c levene.c levene.h linked-list.c \ linked-list.h log.h loop.c magic.c magic.h main.c main.h matrix-data.c \ mis-val.c misc.c misc.h missing-values.c missing-values.h \ modify-vars.c moments.c moments.h numeric.c output.c output.h \ diff --git a/src/algorithm.c b/src/algorithm.c index 54103b36d6..74f2be4004 100644 --- a/src/algorithm.c +++ b/src/algorithm.c @@ -307,32 +307,6 @@ is_partitioned (const void *array, size_t count, size_t size, return 1; } -/* A algo_random_func that uses random.h. */ -unsigned -algo_default_random (unsigned max, void *aux UNUSED) -{ - unsigned long r_min = gsl_rng_min (get_rng ()); - return (gsl_rng_get (get_rng ()) - r_min) % max; -} - -/* Randomly reorders ARRAY, which contains COUNT elements of SIZE - bytes each. Uses RANDOM as a source of random data, passing - AUX as the auxiliary data. RANDOM may be null to use a - default random source. */ -void -random_shuffle (void *array_, size_t count, size_t size, - algo_random_func *random, void *aux) -{ - unsigned char *array = array_; - int i; - - if (random == NULL) - random = algo_default_random; - - for (i = 1; i < count; i++) - SWAP (array + i * size, array + random (i + 1, aux) * size, size); -} - /* Copies the COUNT elements of SIZE bytes each from ARRAY to RESULT, except that elements for which PREDICATE is false are not copied. Returns the number of elements copied. AUX is diff --git a/src/dictionary.c b/src/dictionary.c index c63b2e1bcf..0bfa02cdd2 100644 --- a/src/dictionary.c +++ b/src/dictionary.c @@ -260,10 +260,9 @@ dict_create_var (struct dictionary *d, const char *name, int width) assert (d != NULL); assert (name != NULL); - assert (strlen (name) >= 1); - assert (strlen (name) <= LONG_NAME_LEN); - assert (width >= 0 && width < 256); + + assert (var_is_valid_name(name,0)); /* Make sure there's not already a variable by that name. */ if (dict_lookup_var (d, name) != NULL) diff --git a/src/format-prs.c b/src/format-prs.c new file mode 100644 index 0000000000..988c05b520 --- /dev/null +++ b/src/format-prs.c @@ -0,0 +1,157 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include "format.h" +#include +#include "error.h" +#include +#include "error.h" +#include "lexer.h" +#include "misc.h" +#include "str.h" +#include "var.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + + +/* Parses the alphabetic prefix of the current token as a format + specifier name. Returns the corresponding format specifier + type if successful, or -1 on failure. If ALLOW_XT is zero, + then X and T format specifiers are not allowed. If CP is + nonzero, then *CP is set to the first non-alphabetic character + in the current token on success or to a null pointer on + failure. */ +int +parse_format_specifier_name (const char **cp, enum fmt_parse_flags flags) +{ + char *sp, *ep; + int idx; + + sp = ep = ds_c_str (&tokstr); + while (isalpha ((unsigned char) *ep)) + ep++; + + if (sp != ep) + { + /* Find format. */ + for (idx = 0; idx < FMT_NUMBER_OF_FORMATS; idx++) + if (strlen (formats[idx].name) == ep - sp + && !buf_compare_case (formats[idx].name, sp, ep - sp)) + break; + + /* Check format. */ + if (idx < FMT_NUMBER_OF_FORMATS) + { + if (!(flags & FMTP_ALLOW_XT) && (idx == FMT_T || idx == FMT_X)) + { + if (!(flags & FMTP_SUPPRESS_ERRORS)) + msg (SE, _("X and T format specifiers not allowed here.")); + idx = -1; + } + } + else + { + /* No match. */ + if (!(flags & FMTP_SUPPRESS_ERRORS)) + msg (SE, _("%.*s is not a valid data format."), + (int) (ep - sp), ds_c_str (&tokstr)); + idx = -1; + } + } + else + { + lex_error ("expecting data format"); + idx = -1; + } + + if (cp != NULL) + { + if (idx != -1) + *cp = ep; + else + *cp = NULL; + } + + return idx; +} + + +/* Parses a format specifier from the token stream and returns + nonzero only if successful. Emits an error message on + failure. Allows X and T format specifiers only if ALLOW_XT is + nonzero. The caller should call check_input_specifier() or + check_output_specifier() on the parsed format as + necessary. */ +int +parse_format_specifier (struct fmt_spec *input, enum fmt_parse_flags flags) +{ + struct fmt_spec spec; + struct fmt_desc *f; + const char *cp; + char *cp2; + int type, w, d; + + if (token != T_ID) + { + if (!(flags & FMTP_SUPPRESS_ERRORS)) + msg (SE, _("Format specifier expected.")); + return 0; + } + type = parse_format_specifier_name (&cp, flags); + if (type == -1) + return 0; + f = &formats[type]; + + w = strtol (cp, &cp2, 10); + if (cp2 == cp && type != FMT_X) + { + if (!(flags & FMTP_SUPPRESS_ERRORS)) + msg (SE, _("Data format %s does not specify a width."), + ds_c_str (&tokstr)); + return 0; + } + + cp = cp2; + if (f->n_args > 1 && *cp == '.') + { + cp++; + d = strtol (cp, &cp2, 10); + cp = cp2; + } + else + d = 0; + + if (*cp) + { + if (!(flags & FMTP_SUPPRESS_ERRORS)) + msg (SE, _("Data format %s is not valid."), ds_c_str (&tokstr)); + return 0; + } + lex_get (); + + spec.type = type; + spec.w = w; + spec.d = d; + *input = spec; + + return 1; +} + diff --git a/src/format.c b/src/format.c index a37f71e814..5ee7ace500 100644 --- a/src/format.c +++ b/src/format.c @@ -43,67 +43,6 @@ struct fmt_desc formats[FMT_NUMBER_OF_FORMATS + 1] = /* Common formats. */ const struct fmt_spec f8_2 = {FMT_F, 8, 2}; -/* Parses the alphabetic prefix of the current token as a format - specifier name. Returns the corresponding format specifier - type if successful, or -1 on failure. If ALLOW_XT is zero, - then X and T format specifiers are not allowed. If CP is - nonzero, then *CP is set to the first non-alphabetic character - in the current token on success or to a null pointer on - failure. */ -int -parse_format_specifier_name (const char **cp, enum fmt_parse_flags flags) -{ - char *sp, *ep; - int idx; - - sp = ep = ds_c_str (&tokstr); - while (isalpha ((unsigned char) *ep)) - ep++; - - if (sp != ep) - { - /* Find format. */ - for (idx = 0; idx < FMT_NUMBER_OF_FORMATS; idx++) - if (strlen (formats[idx].name) == ep - sp - && !buf_compare_case (formats[idx].name, sp, ep - sp)) - break; - - /* Check format. */ - if (idx < FMT_NUMBER_OF_FORMATS) - { - if (!(flags & FMTP_ALLOW_XT) && (idx == FMT_T || idx == FMT_X)) - { - if (!(flags & FMTP_SUPPRESS_ERRORS)) - msg (SE, _("X and T format specifiers not allowed here.")); - idx = -1; - } - } - else - { - /* No match. */ - if (!(flags & FMTP_SUPPRESS_ERRORS)) - msg (SE, _("%.*s is not a valid data format."), - (int) (ep - sp), ds_c_str (&tokstr)); - idx = -1; - } - } - else - { - lex_error ("expecting data format"); - idx = -1; - } - - if (cp != NULL) - { - if (idx != -1) - *cp = ep; - else - *cp = NULL; - } - - return idx; -} - /* Converts F to its string representation (for instance, "F8.2") and returns a pointer to a static buffer containing that string. */ char * @@ -361,67 +300,6 @@ convert_fmt_ItoO (const struct fmt_spec *input, struct fmt_spec *output) assert (check_output_specifier (output, 0)); } -/* Parses a format specifier from the token stream and returns - nonzero only if successful. Emits an error message on - failure. Allows X and T format specifiers only if ALLOW_XT is - nonzero. The caller should call check_input_specifier() or - check_output_specifier() on the parsed format as - necessary. */ -int -parse_format_specifier (struct fmt_spec *input, enum fmt_parse_flags flags) -{ - struct fmt_spec spec; - struct fmt_desc *f; - const char *cp; - char *cp2; - int type, w, d; - - if (token != T_ID) - { - if (!(flags & FMTP_SUPPRESS_ERRORS)) - msg (SE, _("Format specifier expected.")); - return 0; - } - type = parse_format_specifier_name (&cp, flags); - if (type == -1) - return 0; - f = &formats[type]; - - w = strtol (cp, &cp2, 10); - if (cp2 == cp && type != FMT_X) - { - if (!(flags & FMTP_SUPPRESS_ERRORS)) - msg (SE, _("Data format %s does not specify a width."), - ds_c_str (&tokstr)); - return 0; - } - - cp = cp2; - if (f->n_args > 1 && *cp == '.') - { - cp++; - d = strtol (cp, &cp2, 10); - cp = cp2; - } - else - d = 0; - - if (*cp) - { - if (!(flags & FMTP_SUPPRESS_ERRORS)) - msg (SE, _("Data format %s is not valid."), ds_c_str (&tokstr)); - return 0; - } - lex_get (); - - spec.type = type; - spec.w = w; - spec.d = d; - *input = spec; - - return 1; -} - /* Returns the width corresponding to the format specifier. The return value is the value of the `width' member of a `struct variable' for such an input format. */ diff --git a/src/lex-def.c b/src/lex-def.c new file mode 100644 index 0000000000..15f06b1af8 --- /dev/null +++ b/src/lex-def.c @@ -0,0 +1,98 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000, 2005 Free Software Foundation, Inc. + Written by John Darrington + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* + This file is concerned with the definition of the PSPP syntax, NOT the + action of scanning/parsing code . +*/ + +#include +#include "lex-def.h" + + +#include +#include + + +/* Table of keywords. */ +const char *keywords[T_N_KEYWORDS + 1] = + { + "AND", "OR", "NOT", + "EQ", "GE", "GT", "LE", "LT", "NE", + "ALL", "BY", "TO", "WITH", + NULL, + }; + + + +/* Comparing identifiers. */ + +/* Keywords match if one of the following is true: KW and TOK are + identical (except for differences in case), or TOK is at least 3 + characters long and those characters are identical to KW. KW_LEN + is the length of KW, TOK_LEN is the length of TOK. */ +int +lex_id_match_len (const char *kw, size_t kw_len, + const char *tok, size_t tok_len) +{ + size_t i = 0; + + assert (kw && tok); + for (;;) + { + if (i == kw_len && i == tok_len) + return 1; + else if (i == tok_len) + return i >= 3; + else if (i == kw_len) + return 0; + else if (toupper ((unsigned char) kw[i]) + != toupper ((unsigned char) tok[i])) + return 0; + + i++; + } +} + +/* Same as lex_id_match_len() minus the need to pass in the lengths. */ +int +lex_id_match (const char *kw, const char *tok) +{ + return lex_id_match_len (kw, strlen (kw), tok, strlen (tok)); +} + + + +/* Returns the proper token type, either T_ID or a reserved keyword + enum, for ID[], which must contain LEN characters. */ +int +lex_id_to_token (const char *id, size_t len) +{ + const char **kwp; + + if (len < 2 || len > 4) + return T_ID; + + for (kwp = keywords; *kwp; kwp++) + if (!strcasecmp (*kwp, id)) + return T_FIRST_KEYWORD + (kwp - keywords); + + return T_ID; +} + diff --git a/src/lex-def.h b/src/lex-def.h new file mode 100644 index 0000000000..6146efc227 --- /dev/null +++ b/src/lex-def.h @@ -0,0 +1,83 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#if !lex_def_h +#define lex_def_h 1 + +#include +#include +#include + +/* Returns nonzero if character CH may be the first character in an + identifier. */ +#define CHAR_IS_ID1(CH) \ + (isalpha ((unsigned char) (CH)) \ + || (CH) == '@' \ + || (CH) == '#' \ + || (CH) == '$') + +/* Returns nonzero if character CH may be a character in an + identifier other than the first. */ +#define CHAR_IS_IDN(CH) \ + (CHAR_IS_ID1 (CH) \ + || isdigit ((unsigned char) (CH)) \ + || (CH) == '.' \ + || (CH) == '_') + +/* Token types. */ +/* The order of the enumerals below is important. Do not change it. */ +enum + { + T_ID = 256, /* Identifier. */ + T_POS_NUM, /* Positive number. */ + T_NEG_NUM, /* Negative number. */ + T_STRING, /* Quoted string. */ + T_STOP, /* End of input. */ + + T_AND, /* AND */ + T_OR, /* OR */ + T_NOT, /* NOT */ + + T_EQ, /* EQ */ + T_GE, /* GE or >= */ + T_GT, /* GT or > */ + T_LE, /* LE or <= */ + T_LT, /* LT or < */ + T_NE, /* NE or ~= */ + + T_ALL, /* ALL */ + T_BY, /* BY */ + T_TO, /* TO */ + T_WITH, /* WITH */ + + T_EXP, /* ** */ + + T_FIRST_KEYWORD = T_AND, + T_LAST_KEYWORD = T_WITH, + T_N_KEYWORDS = T_LAST_KEYWORD - T_FIRST_KEYWORD + 1 + }; + + +/* Comparing identifiers. */ +int lex_id_match_len (const char *keyword_string, size_t keyword_len, + const char *token_string, size_t token_len); +int lex_id_match (const char *keyword_string, const char *token_string); +int lex_id_to_token (const char *id, size_t len); + +#endif /* !lex_def_h */ diff --git a/src/lexer.c b/src/lexer.c index 8a3ccc2188..77d40cfbb0 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -45,6 +45,9 @@ /* Global variables. */ +extern const char *keywords[T_N_KEYWORDS + 1]; + + /* Current token. */ int token; @@ -60,15 +63,6 @@ struct string tokstr; /* Static variables. */ -/* Table of keywords. */ -static const char *keywords[T_N_KEYWORDS + 1] = - { - "AND", "OR", "NOT", - "EQ", "GE", "GT", "LE", "LT", "NE", - "ALL", "BY", "TO", "WITH", - NULL, - }; - /* Pointer to next token in getl_buf. */ static char *prog; @@ -624,60 +618,6 @@ lex_force_id (void) return 0; } } - -/* Comparing identifiers. */ - -/* Keywords match if one of the following is true: KW and TOK are - identical (except for differences in case), or TOK is at least 3 - characters long and those characters are identical to KW. KW_LEN - is the length of KW, TOK_LEN is the length of TOK. */ -int -lex_id_match_len (const char *kw, size_t kw_len, - const char *tok, size_t tok_len) -{ - size_t i = 0; - - assert (kw && tok); - for (;;) - { - if (i == kw_len && i == tok_len) - return 1; - else if (i == tok_len) - return i >= 3; - else if (i == kw_len) - return 0; - else if (toupper ((unsigned char) kw[i]) - != toupper ((unsigned char) tok[i])) - return 0; - - i++; - } -} - -/* Same as lex_id_match_len() minus the need to pass in the lengths. */ -int -lex_id_match (const char *kw, const char *tok) -{ - return lex_id_match_len (kw, strlen (kw), tok, strlen (tok)); -} - -/* Returns the proper token type, either T_ID or a reserved keyword - enum, for ID[], which must contain LEN characters. */ -int -lex_id_to_token (const char *id, size_t len) -{ - const char **kwp; - - if (len < 2 || len > 4) - return T_ID; - - for (kwp = keywords; *kwp; kwp++) - if (!strcasecmp (*kwp, id)) - return T_FIRST_KEYWORD + (kwp - keywords); - - return T_ID; -} - /* Weird token functions. */ /* Returns the first character of the next token, except that if the diff --git a/src/lexer.h b/src/lexer.h index 816b4317f9..6e8dd48f7e 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -24,54 +24,8 @@ #include #include -/* Returns nonzero if character CH may be the first character in an - identifier. */ -#define CHAR_IS_ID1(CH) \ - (isalpha ((unsigned char) (CH)) \ - || (CH) == '@' \ - || (CH) == '#' \ - || (CH) == '$') - -/* Returns nonzero if character CH may be a character in an - identifier other than the first. */ -#define CHAR_IS_IDN(CH) \ - (CHAR_IS_ID1 (CH) \ - || isdigit ((unsigned char) (CH)) \ - || (CH) == '.' \ - || (CH) == '_') - -/* Token types. */ -/* The order of the enumerals below is important. Do not change it. */ -enum - { - T_ID = 256, /* Identifier. */ - T_POS_NUM, /* Positive number. */ - T_NEG_NUM, /* Negative number. */ - T_STRING, /* Quoted string. */ - T_STOP, /* End of input. */ - - T_AND, /* AND */ - T_OR, /* OR */ - T_NOT, /* NOT */ - - T_EQ, /* EQ */ - T_GE, /* GE or >= */ - T_GT, /* GT or > */ - T_LE, /* LE or <= */ - T_LT, /* LT or < */ - T_NE, /* NE or ~= */ - - T_ALL, /* ALL */ - T_BY, /* BY */ - T_TO, /* TO */ - T_WITH, /* WITH */ - - T_EXP, /* ** */ - - T_FIRST_KEYWORD = T_AND, - T_LAST_KEYWORD = T_WITH, - T_N_KEYWORDS = T_LAST_KEYWORD - T_FIRST_KEYWORD + 1 - }; +#include "lex-def.h" + extern int token; extern double tokval; @@ -110,11 +64,6 @@ int lex_force_num (void); int lex_force_id (void); int lex_force_string (void); -/* Comparing identifiers. */ -int lex_id_match_len (const char *keyword_string, size_t keyword_len, - const char *token_string, size_t token_len); -int lex_id_match (const char *keyword_string, const char *token_string); -int lex_id_to_token (const char *id, size_t len); /* Weird token functions. */ int lex_look_ahead (void); diff --git a/src/vars-atr.c b/src/vars-atr.c index 5e34cb5946..adaa6a4cc2 100644 --- a/src/vars-atr.c +++ b/src/vars-atr.c @@ -114,33 +114,6 @@ hash_value(const union value *v, int width) -/* Discards all the current state in preparation for a data-input - command like DATA LIST or GET. */ -void -discard_variables (void) -{ - dict_clear (default_dict); - default_handle = NULL; - - n_lag = 0; - - if (vfm_source != NULL) - { - free_case_source (vfm_source); - vfm_source = NULL; - } - - cancel_transformations (); - - ctl_stack = NULL; - - expr_free (process_if_expr); - process_if_expr = NULL; - - cancel_temporary (); - - pgm_state = STATE_INIT; -} /* Returns true if NAME is an acceptable name for a variable, false otherwise. If ISSUE_ERROR is true, issues an @@ -298,3 +271,40 @@ var_set_short_name_suffix (struct variable *v, const char *base, int suffix) ofs = strlen (v->short_name); strcpy (v->short_name + ofs, start); } + + +/* 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]) + { + default: + return DC_ORDINARY; + case '$': + return DC_SYSTEM; + case '#': + return DC_SCRATCH; + } +} + +/* Returns the name of dictionary class DICT_CLASS. */ +const char * +dict_class_to_name (enum dict_class dict_class) +{ + switch (dict_class) + { + case DC_ORDINARY: + return _("ordinary"); + case DC_SYSTEM: + return _("system"); + case DC_SCRATCH: + return _("scratch"); + default: + assert (0); + abort (); + } +} diff --git a/src/vars-prs.c b/src/vars-prs.c index 37629604d8..bed6031d94 100644 --- a/src/vars-prs.c +++ b/src/vars-prs.c @@ -91,41 +91,6 @@ parse_variable (void) return parse_dict_variable (default_dict); } -/* 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]) - { - default: - return DC_ORDINARY; - case '$': - return DC_SYSTEM; - case '#': - return DC_SCRATCH; - } -} - -/* Returns the name of dictionary class DICT_CLASS. */ -const char * -dict_class_to_name (enum dict_class dict_class) -{ - switch (dict_class) - { - case DC_ORDINARY: - return _("ordinary"); - case DC_SYSTEM: - return _("system"); - case DC_SCRATCH: - return _("scratch"); - default: - assert (0); - abort (); - } -} /* Parses a set of variables from dictionary D given options OPTS. Resulting list of variables stored in *VAR and the diff --git a/src/vfm.c b/src/vfm.c index 6d7e526bf1..b88d3eb138 100644 --- a/src/vfm.c +++ b/src/vfm.c @@ -30,6 +30,7 @@ #include "alloc.h" #include "case.h" #include "casefile.h" +#include "command.h" #include "dictionary.h" #include "do-ifP.h" #include "error.h" @@ -907,3 +908,32 @@ multipass_split_output (struct multipass_split_aux_data *aux) casefile_destroy (aux->casefile); aux->casefile = NULL; } + + +/* Discards all the current state in preparation for a data-input + command like DATA LIST or GET. */ +void +discard_variables (void) +{ + dict_clear (default_dict); + default_handle = NULL; + + n_lag = 0; + + if (vfm_source != NULL) + { + free_case_source (vfm_source); + vfm_source = NULL; + } + + cancel_transformations (); + + ctl_stack = NULL; + + expr_free (process_if_expr); + process_if_expr = NULL; + + cancel_temporary (); + + pgm_state = STATE_INIT; +} -- 2.30.2