X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fdata-io%2Fget.c;h=be5614166ad08716692237118ddc059ad70e610b;hb=5f7f751a47c68946a0fcbc9898f43f5499c5c6c5;hp=78e91c3dde7269f2450265f7c4b1c47fa528d663;hpb=77e551d23575da6b89f866612ab39c2b0497c9be;p=pspp diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index 78e91c3dde..be5614166a 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -18,27 +18,37 @@ 02110-1301, USA. */ #include -#include + #include -#include + #include #include +#include +#include #include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include #include +#include #include +#include #include -#include +#include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "gettext.h" #define _(msgid) gettext (msgid) @@ -50,7 +60,7 @@ static void map_case (const struct case_map *, const struct ccase *, struct ccase *); static void destroy_case_map (struct case_map *); -static bool parse_dict_trim (struct dictionary *); +static bool parse_dict_trim (struct lexer *, struct dictionary *); /* Reading system and portable files. */ @@ -75,7 +85,7 @@ static void case_reader_pgm_free (struct case_reader_pgm *); /* Parses a GET or IMPORT command. */ static int -parse_read_command (enum reader_command type) +parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command type) { struct case_reader_pgm *pgm = NULL; struct file_handle *fh = NULL; @@ -83,27 +93,27 @@ parse_read_command (enum reader_command type) for (;;) { - lex_match ('/'); + lex_match (lexer, '/'); - if (lex_match_id ("FILE") || token == T_STRING) + if (lex_match_id (lexer, "FILE") || lex_token (lexer) == T_STRING) { - lex_match ('='); + lex_match (lexer, '='); - fh = fh_parse (FH_REF_FILE | FH_REF_SCRATCH); + fh = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH); if (fh == NULL) goto error; } - else if (type == IMPORT_CMD && lex_match_id ("TYPE")) + else if (type == IMPORT_CMD && lex_match_id (lexer, "TYPE")) { - lex_match ('='); + lex_match (lexer, '='); - if (lex_match_id ("COMM")) + if (lex_match_id (lexer, "COMM")) type = PFM_COMM; - else if (lex_match_id ("TAPE")) + else if (lex_match_id (lexer, "TAPE")) type = PFM_TAPE; else { - lex_error (_("expecting COMM or TAPE")); + lex_error (lexer, _("expecting COMM or TAPE")); goto error; } } @@ -113,11 +123,11 @@ parse_read_command (enum reader_command type) if (fh == NULL) { - lex_sbc_missing ("FILE"); + lex_sbc_missing (lexer, "FILE"); goto error; } - discard_variables (); + discard_variables (ds); pgm = xmalloc (sizeof *pgm); pgm->reader = any_reader_open (fh, &dict); @@ -130,19 +140,20 @@ parse_read_command (enum reader_command type) start_case_map (dict); - while (token != '.') + while (lex_token (lexer) != '.') { - lex_match ('/'); - if (!parse_dict_trim (dict)) + lex_match (lexer, '/'); + if (!parse_dict_trim (lexer, dict)) goto error; } pgm->map = finish_case_map (dict); - dict_destroy (default_dict); - default_dict = dict; + dict_destroy (dataset_dict (ds)); + dataset_set_dict (ds, dict); - vfm_source = create_case_source (&case_reader_source_class, pgm); + proc_set_source (ds, + create_case_source (&case_reader_source_class, pgm)); return CMD_SUCCESS; @@ -216,16 +227,16 @@ static const struct case_source_class case_reader_source_class = /* GET. */ int -cmd_get (void) +cmd_get (struct lexer *lexer, struct dataset *ds) { - return parse_read_command (GET_CMD); + return parse_read_command (lexer, ds, GET_CMD); } /* IMPORT. */ int -cmd_import (void) +cmd_import (struct lexer *lexer, struct dataset *ds) { - return parse_read_command (IMPORT_CMD); + return parse_read_command (lexer, ds, IMPORT_CMD); } /* Writing system and portable files. */ @@ -279,7 +290,8 @@ case_writer_destroy (struct case_writer *aw) On failure, returns a null pointer. */ static struct case_writer * -parse_write_command (enum writer_type writer_type, +parse_write_command (struct lexer *lexer, struct dataset *ds, + enum writer_type writer_type, enum command_type command_type, bool *retain_unselected) { @@ -302,7 +314,7 @@ parse_write_command (enum writer_type writer_type, *retain_unselected = true; handle = NULL; - dict = dict_clone (default_dict); + dict = dict_clone (dataset_dict (ds)); aw = xmalloc (sizeof *aw); aw->writer = NULL; aw->map = NULL; @@ -315,10 +327,10 @@ parse_write_command (enum writer_type writer_type, start_case_map (dict); dict_delete_scratch_vars (dict); - lex_match ('/'); + lex_match (lexer, '/'); for (;;) { - if (lex_match_id ("OUTFILE")) + if (lex_match_id (lexer, "OUTFILE")) { if (handle != NULL) { @@ -326,88 +338,88 @@ parse_write_command (enum writer_type writer_type, goto error; } - lex_match ('='); + lex_match (lexer, '='); - handle = fh_parse (FH_REF_FILE | FH_REF_SCRATCH); + handle = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH); if (handle == NULL) goto error; } - else if (lex_match_id ("NAMES")) + else if (lex_match_id (lexer, "NAMES")) print_short_names = true; - else if (lex_match_id ("PERMISSIONS")) + else if (lex_match_id (lexer, "PERMISSIONS")) { bool cw; - lex_match ('='); - if (lex_match_id ("READONLY")) + lex_match (lexer, '='); + if (lex_match_id (lexer, "READONLY")) cw = false; - else if (lex_match_id ("WRITEABLE")) + else if (lex_match_id (lexer, "WRITEABLE")) cw = true; else { - lex_error (_("expecting %s or %s"), "READONLY", "WRITEABLE"); + lex_error (lexer, _("expecting %s or %s"), "READONLY", "WRITEABLE"); goto error; } sysfile_opts.create_writeable = porfile_opts.create_writeable = cw; } - else if (command_type == PROC_CMD && lex_match_id ("UNSELECTED")) + else if (command_type == PROC_CMD && lex_match_id (lexer, "UNSELECTED")) { - lex_match ('='); - if (lex_match_id ("RETAIN")) + lex_match (lexer, '='); + if (lex_match_id (lexer, "RETAIN")) *retain_unselected = true; - else if (lex_match_id ("DELETE")) + else if (lex_match_id (lexer, "DELETE")) *retain_unselected = false; else { - lex_error (_("expecting %s or %s"), "RETAIN", "DELETE"); + lex_error (lexer, _("expecting %s or %s"), "RETAIN", "DELETE"); goto error; } } - else if (writer_type == SYSFILE_WRITER && lex_match_id ("COMPRESSED")) + else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "COMPRESSED")) sysfile_opts.compress = true; - else if (writer_type == SYSFILE_WRITER && lex_match_id ("UNCOMPRESSED")) + else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "UNCOMPRESSED")) sysfile_opts.compress = false; - else if (writer_type == SYSFILE_WRITER && lex_match_id ("VERSION")) + else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "VERSION")) { - lex_match ('='); - if (!lex_force_int ()) + lex_match (lexer, '='); + if (!lex_force_int (lexer)) goto error; - sysfile_opts.version = lex_integer (); - lex_get (); + sysfile_opts.version = lex_integer (lexer); + lex_get (lexer); } - else if (writer_type == PORFILE_WRITER && lex_match_id ("TYPE")) + else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "TYPE")) { - lex_match ('='); - if (lex_match_id ("COMMUNICATIONS")) + lex_match (lexer, '='); + if (lex_match_id (lexer, "COMMUNICATIONS")) porfile_opts.type = PFM_COMM; - else if (lex_match_id ("TAPE")) + else if (lex_match_id (lexer, "TAPE")) porfile_opts.type = PFM_TAPE; else { - lex_error (_("expecting %s or %s"), "COMM", "TAPE"); + lex_error (lexer, _("expecting %s or %s"), "COMM", "TAPE"); goto error; } } - else if (writer_type == PORFILE_WRITER && lex_match_id ("DIGITS")) + else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS")) { - lex_match ('='); - if (!lex_force_int ()) + lex_match (lexer, '='); + if (!lex_force_int (lexer)) goto error; - porfile_opts.digits = lex_integer (); - lex_get (); + porfile_opts.digits = lex_integer (lexer); + lex_get (lexer); } - else if (!parse_dict_trim (dict)) + else if (!parse_dict_trim (lexer, dict)) goto error; - if (!lex_match ('/')) + if (!lex_match (lexer, '/')) break; } - if (lex_end_of_command () != CMD_SUCCESS) + if (lex_end_of_command (lexer) != CMD_SUCCESS) goto error; if (handle == NULL) { - lex_sbc_missing ("OUTFILE"); + lex_sbc_missing (lexer, "OUTFILE"); goto error; } @@ -432,6 +444,8 @@ parse_write_command (enum writer_type writer_type, } else aw->writer = any_writer_open (handle, dict); + if (aw->writer == NULL) + goto error; dict_destroy (dict); return aw; @@ -444,7 +458,7 @@ parse_write_command (enum writer_type writer_type, /* Writes case C to writer AW. */ static bool -case_writer_write_case (struct case_writer *aw, struct ccase *c) +case_writer_write_case (struct case_writer *aw, const struct ccase *c) { if (aw->map != NULL) { @@ -456,26 +470,26 @@ case_writer_write_case (struct case_writer *aw, struct ccase *c) /* SAVE and EXPORT. */ -static bool output_proc (struct ccase *, void *); +static bool output_proc (const struct ccase *, void *, const struct dataset *); /* Parses and performs the SAVE or EXPORT procedure. */ static int -parse_output_proc (enum writer_type writer_type) +parse_output_proc (struct lexer *lexer, struct dataset *ds, enum writer_type writer_type) { bool retain_unselected; struct variable *saved_filter_variable; struct case_writer *aw; bool ok; - aw = parse_write_command (writer_type, PROC_CMD, &retain_unselected); + aw = parse_write_command (lexer, ds, writer_type, PROC_CMD, &retain_unselected); if (aw == NULL) return CMD_CASCADING_FAILURE; - saved_filter_variable = dict_get_filter (default_dict); + saved_filter_variable = dict_get_filter (dataset_dict (ds)); if (retain_unselected) - dict_set_filter (default_dict, NULL); - ok = procedure (output_proc, aw); - dict_set_filter (default_dict, saved_filter_variable); + dict_set_filter (dataset_dict (ds), NULL); + ok = procedure (ds, output_proc, aw); + dict_set_filter (dataset_dict (ds), saved_filter_variable); case_writer_destroy (aw); return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE; @@ -483,22 +497,22 @@ parse_output_proc (enum writer_type writer_type) /* Writes case C to file. */ static bool -output_proc (struct ccase *c, void *aw_) +output_proc (const struct ccase *c, void *aw_, const struct dataset *ds UNUSED) { struct case_writer *aw = aw_; return case_writer_write_case (aw, c); } int -cmd_save (void) +cmd_save (struct lexer *lexer, struct dataset *ds) { - return parse_output_proc (SYSFILE_WRITER); + return parse_output_proc (lexer, ds, SYSFILE_WRITER); } int -cmd_export (void) +cmd_export (struct lexer *lexer, struct dataset *ds) { - return parse_output_proc (PORFILE_WRITER); + return parse_output_proc (lexer, ds, PORFILE_WRITER); } /* XSAVE and XEXPORT. */ @@ -514,23 +528,23 @@ static trns_free_func output_trns_free; /* Parses the XSAVE or XEXPORT transformation command. */ static int -parse_output_trns (enum writer_type writer_type) +parse_output_trns (struct lexer *lexer, struct dataset *ds, enum writer_type writer_type) { struct output_trns *t = xmalloc (sizeof *t); - t->aw = parse_write_command (writer_type, XFORM_CMD, NULL); + t->aw = parse_write_command (lexer, ds, writer_type, XFORM_CMD, NULL); if (t->aw == NULL) { free (t); return CMD_CASCADING_FAILURE; } - add_transformation (output_trns_proc, output_trns_free, t); + add_transformation (ds, output_trns_proc, output_trns_free, t); return CMD_SUCCESS; } /* Writes case C to the system file specified on XSAVE or XEXPORT. */ static int -output_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED) +output_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED) { struct output_trns *t = trns_; case_writer_write_case (t->aw, c); @@ -555,50 +569,50 @@ output_trns_free (void *trns_) /* XSAVE command. */ int -cmd_xsave (void) +cmd_xsave (struct lexer *lexer, struct dataset *ds) { - return parse_output_trns (SYSFILE_WRITER); + return parse_output_trns (lexer, ds, SYSFILE_WRITER); } /* XEXPORT command. */ int -cmd_xexport (void) +cmd_xexport (struct lexer *lexer, struct dataset *ds) { - return parse_output_trns (PORFILE_WRITER); + return parse_output_trns (lexer, ds, PORFILE_WRITER); } -static bool rename_variables (struct dictionary *dict); -static bool drop_variables (struct dictionary *dict); -static bool keep_variables (struct dictionary *dict); +static bool rename_variables (struct lexer *lexer, struct dictionary *dict); +static bool drop_variables (struct lexer *, struct dictionary *dict); +static bool keep_variables (struct lexer *, struct dictionary *dict); /* Commands that read and write system files share a great deal of common syntactic structure for rearranging and dropping variables. This function parses this syntax and modifies DICT appropriately. Returns true on success, false on failure. */ static bool -parse_dict_trim (struct dictionary *dict) +parse_dict_trim (struct lexer *lexer, struct dictionary *dict) { - if (lex_match_id ("MAP")) + if (lex_match_id (lexer, "MAP")) { /* FIXME. */ return true; } - else if (lex_match_id ("DROP")) - return drop_variables (dict); - else if (lex_match_id ("KEEP")) - return keep_variables (dict); - else if (lex_match_id ("RENAME")) - return rename_variables (dict); + else if (lex_match_id (lexer, "DROP")) + return drop_variables (lexer, dict); + else if (lex_match_id (lexer, "KEEP")) + return keep_variables (lexer, dict); + else if (lex_match_id (lexer, "RENAME")) + return rename_variables (lexer, dict); else { - lex_error (_("expecting a valid subcommand")); + lex_error (lexer, _("expecting a valid subcommand")); return false; } } /* Parses and performs the RENAME subcommand of GET and SAVE. */ static bool -rename_variables (struct dictionary *dict) +rename_variables (struct lexer *lexer, struct dictionary *dict) { size_t i; @@ -611,29 +625,29 @@ rename_variables (struct dictionary *dict) int group; - lex_match ('='); - if (token != '(') + lex_match (lexer, '='); + if (lex_token (lexer) != '(') { struct variable *v; - v = parse_dict_variable (dict); + v = parse_variable (lexer, dict); if (v == NULL) return 0; - if (!lex_force_match ('=') - || !lex_force_id ()) + if (!lex_force_match (lexer, '=') + || !lex_force_id (lexer)) return 0; - if (dict_lookup_var (dict, tokid) != NULL) + if (dict_lookup_var (dict, lex_tokid (lexer)) != NULL) { msg (SE, _("Cannot rename %s as %s because there already exists " "a variable named %s. To rename variables with " "overlapping names, use a single RENAME subcommand " "such as \"/RENAME (A=B)(B=C)(C=A)\", or equivalently, " - "\"/RENAME (A B C=B C A)\"."), v->name, tokid, tokid); + "\"/RENAME (A B C=B C A)\"."), v->name, lex_tokid (lexer), lex_tokid (lexer)); return 0; } - dict_rename_var (dict, v, tokid); - lex_get (); + dict_rename_var (dict, v, lex_tokid (lexer)); + lex_get (lexer); return 1; } @@ -641,18 +655,18 @@ rename_variables (struct dictionary *dict) v = NULL; new_names = 0; group = 1; - while (lex_match ('(')) + while (lex_match (lexer, '(')) { size_t old_nv = nv; - if (!parse_variables (dict, &v, &nv, PV_NO_DUPLICATE | PV_APPEND)) + if (!parse_variables (lexer, dict, &v, &nv, PV_NO_DUPLICATE | PV_APPEND)) goto done; - if (!lex_match ('=')) + if (!lex_match (lexer, '=')) { msg (SE, _("`=' expected after variable list.")); goto done; } - if (!parse_DATA_LIST_vars (&new_names, &nn, PV_APPEND | PV_NO_SCRATCH)) + if (!parse_DATA_LIST_vars (lexer, &new_names, &nn, PV_APPEND | PV_NO_SCRATCH)) goto done; if (nn != nv) { @@ -662,7 +676,7 @@ rename_variables (struct dictionary *dict) (unsigned) (nv - old_nv), (unsigned) (nn - old_nv), group); goto done; } - if (!lex_force_match (')')) + if (!lex_force_match (lexer, ')')) goto done; group++; } @@ -686,13 +700,13 @@ rename_variables (struct dictionary *dict) /* Parses and performs the DROP subcommand of GET and SAVE. Returns true if successful, false on failure.*/ static bool -drop_variables (struct dictionary *dict) +drop_variables (struct lexer *lexer, struct dictionary *dict) { struct variable **v; size_t nv; - lex_match ('='); - if (!parse_variables (dict, &v, &nv, PV_NONE)) + lex_match (lexer, '='); + if (!parse_variables (lexer, dict, &v, &nv, PV_NONE)) return false; dict_delete_vars (dict, v, nv); free (v); @@ -708,14 +722,14 @@ drop_variables (struct dictionary *dict) /* Parses and performs the KEEP subcommand of GET and SAVE. Returns true if successful, false on failure.*/ static bool -keep_variables (struct dictionary *dict) +keep_variables (struct lexer *lexer, struct dictionary *dict) { struct variable **v; size_t nv; size_t i; - lex_match ('='); - if (!parse_variables (dict, &v, &nv, PV_NONE)) + lex_match (lexer, '='); + if (!parse_variables (lexer, dict, &v, &nv, PV_NONE)) return false; /* Move the specified variables to the beginning. */ @@ -773,7 +787,7 @@ struct mtf_proc char first[LONG_NAME_LEN + 1], last[LONG_NAME_LEN + 1]; struct dictionary *dict; /* Dictionary of output file. */ - struct case_sink *sink; /* Sink to receive output. */ + struct casefile *output; /* MATCH FILES output. */ struct ccase mtf_case; /* Case used for output. */ unsigned seq_num; /* Have we initialized this variable? */ @@ -786,8 +800,8 @@ static int mtf_merge_dictionary (struct dictionary *const, struct mtf_file *); static bool mtf_delete_file_in_place (struct mtf_proc *, struct mtf_file **); static bool mtf_read_nonactive_records (void *); -static bool mtf_processing_finish (void *); -static bool mtf_processing (struct ccase *, void *); +static bool mtf_processing_finish (void *, const struct dataset *); +static bool mtf_processing (const struct ccase *, void *, const struct dataset *); static char *var_type_description (struct variable *); @@ -796,7 +810,7 @@ static struct variable *get_master (struct variable *); /* Parse and execute the MATCH FILES command. */ int -cmd_match_files (void) +cmd_match_files (struct lexer *lexer, struct dataset *ds) { struct mtf_proc mtf; struct mtf_file *first_table = NULL; @@ -813,28 +827,28 @@ cmd_match_files (void) mtf.first[0] = '\0'; mtf.last[0] = '\0'; mtf.dict = dict_create (); - mtf.sink = NULL; + mtf.output = NULL; case_nullify (&mtf.mtf_case); mtf.seq_num = 0; mtf.seq_nums = NULL; - dict_set_case_limit (mtf.dict, dict_get_case_limit (default_dict)); + dict_set_case_limit (mtf.dict, dict_get_case_limit (dataset_dict (ds))); - lex_match ('/'); - while (token == T_ID - && (lex_id_match ("FILE", tokid) || lex_id_match ("TABLE", tokid))) + lex_match (lexer, '/'); + while (lex_token (lexer) == T_ID + && (lex_id_match ("FILE", lex_tokid (lexer)) || lex_id_match ("TABLE", lex_tokid (lexer)))) { struct mtf_file *file = xmalloc (sizeof *file); - if (lex_match_id ("FILE")) + if (lex_match_id (lexer, "FILE")) file->type = MTF_FILE; - else if (lex_match_id ("TABLE")) + else if (lex_match_id (lexer, "TABLE")) { file->type = MTF_TABLE; saw_table = true; } else - assert (0); - lex_match ('='); + NOT_REACHED (); + lex_match (lexer, '='); file->by = NULL; file->handle = NULL; @@ -869,7 +883,7 @@ cmd_match_files (void) first_table->prev = file; } - if (lex_match ('*')) + if (lex_match (lexer, '*')) { file->handle = NULL; file->reader = NULL; @@ -882,28 +896,24 @@ cmd_match_files (void) } used_active_file = true; - assert (pgm_state != STATE_INPUT); - if (pgm_state == STATE_INIT) + if (!proc_has_source (ds)) { msg (SE, _("Cannot specify the active file since no active " "file has been defined.")); goto error; } - if (temporary != 0) - { - msg (SE, - _("MATCH FILES may not be used after TEMPORARY when " - "the active file is an input source. " - "Temporary transformations will be made permanent.")); - cancel_temporary (); - } + if (proc_make_temporary_transformations_permanent (ds)) + msg (SE, + _("MATCH FILES may not be used after TEMPORARY when " + "the active file is an input source. " + "Temporary transformations will be made permanent.")); - file->dict = default_dict; + file->dict = dataset_dict (ds); } else { - file->handle = fh_parse (FH_REF_FILE | FH_REF_SCRATCH); + file->handle = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH); if (file->handle == NULL) goto error; @@ -914,18 +924,18 @@ cmd_match_files (void) case_create (&file->input, dict_get_next_value_idx (file->dict)); } - while (lex_match ('/')) - if (lex_match_id ("RENAME")) + while (lex_match (lexer, '/')) + if (lex_match_id (lexer, "RENAME")) { - if (!rename_variables (file->dict)) + if (!rename_variables (lexer, file->dict)) goto error; } - else if (lex_match_id ("IN")) + else if (lex_match_id (lexer, "IN")) { - lex_match ('='); - if (token != T_ID) + lex_match (lexer, '='); + if (lex_token (lexer) != T_ID) { - lex_error (NULL); + lex_error (lexer, NULL); goto error; } @@ -935,17 +945,17 @@ cmd_match_files (void) "TABLE.")); goto error; } - file->in_name = xstrdup (tokid); - lex_get (); + file->in_name = xstrdup (lex_tokid (lexer)); + lex_get (lexer); saw_in = true; } mtf_merge_dictionary (mtf.dict, file); } - while (token != '.') + while (lex_token (lexer) != '.') { - if (lex_match (T_BY)) + if (lex_match (lexer, T_BY)) { struct variable **by; @@ -955,8 +965,8 @@ cmd_match_files (void) goto error; } - lex_match ('='); - if (!parse_variables (mtf.dict, &by, &mtf.by_cnt, + lex_match (lexer, '='); + if (!parse_variables (lexer, mtf.dict, &by, &mtf.by_cnt, PV_NO_DUPLICATE | PV_NO_SCRATCH)) goto error; @@ -981,7 +991,7 @@ cmd_match_files (void) } free (by); } - else if (lex_match_id ("FIRST")) + else if (lex_match_id (lexer, "FIRST")) { if (mtf.first[0] != '\0') { @@ -989,13 +999,13 @@ cmd_match_files (void) goto error; } - lex_match ('='); - if (!lex_force_id ()) + lex_match (lexer, '='); + if (!lex_force_id (lexer)) goto error; - strcpy (mtf.first, tokid); - lex_get (); + strcpy (mtf.first, lex_tokid (lexer)); + lex_get (lexer); } - else if (lex_match_id ("LAST")) + else if (lex_match_id (lexer, "LAST")) { if (mtf.last[0] != '\0') { @@ -1003,35 +1013,35 @@ cmd_match_files (void) goto error; } - lex_match ('='); - if (!lex_force_id ()) + lex_match (lexer, '='); + if (!lex_force_id (lexer)) goto error; - strcpy (mtf.last, tokid); - lex_get (); + strcpy (mtf.last, lex_tokid (lexer)); + lex_get (lexer); } - else if (lex_match_id ("MAP")) + else if (lex_match_id (lexer, "MAP")) { /* FIXME. */ } - else if (lex_match_id ("DROP")) + else if (lex_match_id (lexer, "DROP")) { - if (!drop_variables (mtf.dict)) + if (!drop_variables (lexer, mtf.dict)) goto error; } - else if (lex_match_id ("KEEP")) + else if (lex_match_id (lexer, "KEEP")) { - if (!keep_variables (mtf.dict)) + if (!keep_variables (lexer, mtf.dict)) goto error; } else { - lex_error (NULL); + lex_error (lexer, NULL); goto error; } - if (!lex_match ('/') && token != '.') + if (!lex_match (lexer, '/') && lex_token (lexer) != '.') { - lex_end_of_command (); + lex_end_of_command (lexer); goto error; } } @@ -1079,7 +1089,7 @@ cmd_match_files (void) goto error; } iter->in_var->print = iter->in_var->write - = make_output_format (FMT_F, 1, 0); + = fmt_for_output (FMT_F, 1, 0); } /* MATCH FILES performs an n-way merge on all its input files. @@ -1116,13 +1126,10 @@ cmd_match_files (void) values. */ if (!used_active_file) - discard_variables (); + discard_variables (ds); dict_compact_values (mtf.dict); - mtf.sink = create_case_sink (&storage_sink_class, mtf.dict, NULL); - if (mtf.sink->class->open != NULL) - mtf.sink->class->open (mtf.sink); - + mtf.output = fastfile_create (dict_get_next_value_idx (mtf.dict)); mtf.seq_nums = xcalloc (dict_get_var_cnt (mtf.dict), sizeof *mtf.seq_nums); case_create (&mtf.mtf_case, dict_get_next_value_idx (mtf.dict)); @@ -1130,18 +1137,24 @@ cmd_match_files (void) goto error; if (used_active_file) - ok = procedure (mtf_processing, &mtf) && mtf_processing_finish (&mtf); + { + proc_set_sink (ds, + create_case_sink (&null_sink_class, + dataset_dict (ds), NULL)); + ok = + ( procedure (ds, mtf_processing, &mtf) && + mtf_processing_finish (&mtf, ds) ); + } else - ok = mtf_processing_finish (&mtf); + ok = mtf_processing_finish (&mtf, ds); - free_case_source (vfm_source); - vfm_source = NULL; + discard_variables (ds); - dict_destroy (default_dict); - default_dict = mtf.dict; + dict_destroy (dataset_dict (ds)); + dataset_set_dict (ds, mtf.dict); mtf.dict = NULL; - vfm_source = mtf.sink->class->make_source (mtf.sink); - free_case_sink (mtf.sink); + proc_set_source (ds, storage_source_create (mtf.output)); + mtf.output = NULL; if (!mtf_free (&mtf)) ok = false; @@ -1154,7 +1167,7 @@ cmd_match_files (void) /* Repeats 2...7 an arbitrary number of times. */ static bool -mtf_processing_finish (void *mtf_) +mtf_processing_finish (void *mtf_, const struct dataset *ds) { struct mtf_proc *mtf = mtf_; struct mtf_file *iter; @@ -1164,12 +1177,12 @@ mtf_processing_finish (void *mtf_) if (iter->handle == NULL) { if (!mtf_delete_file_in_place (mtf, &iter)) - abort (); + NOT_REACHED (); break; } while (mtf->head && mtf->head->type == MTF_FILE) - if (!mtf_processing (NULL, mtf)) + if (!mtf_processing (NULL, mtf, ds)) return false; return true; @@ -1302,10 +1315,10 @@ mtf_read_nonactive_records (void *mtf_) static inline int mtf_compare_BY_values (struct mtf_proc *mtf, struct mtf_file *a, struct mtf_file *b, - struct ccase *c) + const struct ccase *c) { - struct ccase *ca = case_is_null (&a->input) ? c : &a->input; - struct ccase *cb = case_is_null (&b->input) ? c : &b->input; + const struct ccase *ca = case_is_null (&a->input) ? c : &a->input; + const struct ccase *cb = case_is_null (&b->input) ? c : &b->input; assert ((a == NULL) + (b == NULL) + (c == NULL) <= 1); return case_compare_2dict (ca, cb, a->by, b->by, mtf->by_cnt); } @@ -1313,7 +1326,7 @@ mtf_compare_BY_values (struct mtf_proc *mtf, /* Perform one iteration of steps 3...7 above. Returns true if successful, false if an I/O error occurred. */ static bool -mtf_processing (struct ccase *c, void *mtf_) +mtf_processing (const struct ccase *c, void *mtf_, const struct dataset *ds UNUSED) { struct mtf_proc *mtf = mtf_; @@ -1417,7 +1430,7 @@ mtf_processing (struct ccase *c, void *mtf_) if (mv != NULL && mtf->seq_nums[mv->index] != mtf->seq_num) { - struct ccase *record + const struct ccase *record = case_is_null (&iter->input) ? c : &iter->input; union value *out = case_data_rw (&mtf->mtf_case, mv->fv); @@ -1464,7 +1477,7 @@ mtf_processing (struct ccase *c, void *mtf_) } /* 5. Write the output record. */ - mtf->sink->class->write (mtf->sink, &mtf->mtf_case); + casefile_append (mtf->output, &mtf->mtf_case); /* 6. Read another record from each input file FILE and TABLE that we stored values from above. If we come to the end of @@ -1539,8 +1552,11 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) if (dv->width == mv->width) { if (val_labs_count (dv->val_labs) - && !val_labs_count (mv->val_labs)) - mv->val_labs = val_labs_copy (dv->val_labs); + && !val_labs_count (mv->val_labs)) + { + val_labs_destroy (mv->val_labs); + mv->val_labs = val_labs_copy (dv->val_labs); + } if (!mv_is_empty (&dv->miss) && mv_is_empty (&mv->miss)) mv_copy (&mv->miss, &dv->miss); }