X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fdata-io%2Fget.c;h=f8a84b142919d59d43f31222bf42c45fdb747b8d;hb=bd64b7f8def9cbbf882f31ae34ecec86cbfd6093;hp=950afeb47e6fb285e63fe7285de4807829d9b915;hpb=aed0d6941f474ebd12224d8092bb0e6da64081c6;p=pspp-builds.git diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index 950afeb4..f8a84b14 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -1,20 +1,18 @@ -/* PSPP - computes sample statistics. +/* PSPP - a program for statistical analysis. Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc. - 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 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 3 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. + 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. */ + along with this program. If not, see . */ #include @@ -23,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -47,29 +45,23 @@ #include #include +#include "xalloc.h" + #include "gettext.h" #define _(msgid) gettext (msgid) -/* Rearranging and reducing a dictionary. */ -static void start_case_map (struct dictionary *); -static struct case_map *finish_case_map (struct dictionary *); -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 lexer *, struct dictionary *); /* Reading system and portable files. */ /* Type of command. */ -enum reader_command +enum reader_command { GET_CMD, IMPORT_CMD }; -static void get_translate_case (const struct ccase *, struct ccase *, - void *map_); +static void get_translate_case (struct ccase *, struct ccase *, void *map_); static bool get_destroy_case_map (void *map_); /* Parses a GET or IMPORT command. */ @@ -89,6 +81,7 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command { lex_match (lexer, '='); + fh_unref (fh); fh = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH); if (fh == NULL) goto error; @@ -108,20 +101,20 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command } } else - break; + break; } - - if (fh == NULL) + + if (fh == NULL) { lex_sbc_missing (lexer, "FILE"); goto error; } - + reader = any_reader_open (fh, &dict); if (reader == NULL) goto error; - start_case_map (dict); + case_map_prepare_dict (dict); while (lex_token (lexer) != '.') { @@ -129,20 +122,23 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command if (!parse_dict_trim (lexer, dict)) goto error; } + dict_compact_values (dict); - map = finish_case_map (dict); + map = case_map_from_dict (dict); if (map != NULL) reader = casereader_create_translator (reader, dict_get_next_value_idx (dict), get_translate_case, get_destroy_case_map, map); - + proc_set_active_file (ds, reader, dict); + fh_unref (fh); return CMD_SUCCESS; error: + fh_unref (fh); casereader_destroy (reader); if (dict != NULL) dict_destroy (dict); @@ -150,36 +146,37 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command } static void -get_translate_case (const struct ccase *input, struct ccase *output, - void *map_) +get_translate_case (struct ccase *input, struct ccase *output, + void *map_) { struct case_map *map = map_; - map_case (map, input, output); + case_map_execute (map, input, output); + case_destroy (input); } static bool -get_destroy_case_map (void *map_) +get_destroy_case_map (void *map_) { struct case_map *map = map_; - destroy_case_map (map); + case_map_destroy (map); return true; } /* GET. */ int -cmd_get (struct lexer *lexer, struct dataset *ds) +cmd_get (struct lexer *lexer, struct dataset *ds) { return parse_read_command (lexer, ds, GET_CMD); } /* IMPORT. */ int -cmd_import (struct lexer *lexer, struct dataset *ds) +cmd_import (struct lexer *lexer, struct dataset *ds) { return parse_read_command (lexer, ds, IMPORT_CMD); } -/* Writing system and portable files. */ +/* Writing system and portable files. */ /* Type of output file. */ enum writer_type @@ -189,7 +186,7 @@ enum writer_type }; /* Type of a command. */ -enum command_type +enum command_type { XFORM_CMD, /* Transformation. */ PROC_CMD /* Procedure. */ @@ -206,7 +203,7 @@ enum command_type On failure, returns a null pointer. */ static struct casewriter * -parse_write_command (struct lexer *lexer, struct dataset *ds, +parse_write_command (struct lexer *lexer, struct dataset *ds, enum writer_type writer_type, enum command_type command_type, bool *retain_unselected) @@ -239,7 +236,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, sysfile_opts = sfm_writer_default_options (); porfile_opts = pfm_writer_default_options (); - start_case_map (dict); + case_map_prepare_dict (dict); dict_delete_scratch_vars (dict); lex_match (lexer, '/'); @@ -247,24 +244,24 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, { if (lex_match_id (lexer, "OUTFILE")) { - if (handle != NULL) + if (handle != NULL) { lex_sbc_only_once ("OUTFILE"); - goto error; + goto error; } - + lex_match (lexer, '='); - + handle = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH); if (handle == NULL) goto error; } else if (lex_match_id (lexer, "NAMES")) print_short_names = true; - else if (lex_match_id (lexer, "PERMISSIONS")) + else if (lex_match_id (lexer, "PERMISSIONS")) { bool cw; - + lex_match (lexer, '='); if (lex_match_id (lexer, "READONLY")) cw = false; @@ -277,7 +274,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, } sysfile_opts.create_writeable = porfile_opts.create_writeable = cw; } - else if (command_type == PROC_CMD && lex_match_id (lexer, "UNSELECTED")) + else if (command_type == PROC_CMD && lex_match_id (lexer, "UNSELECTED")) { lex_match (lexer, '='); if (lex_match_id (lexer, "RETAIN")) @@ -302,7 +299,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, sysfile_opts.version = lex_integer (lexer); lex_get (lexer); } - else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "TYPE")) + else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "TYPE")) { lex_match (lexer, '='); if (lex_match_id (lexer, "COMMUNICATIONS")) @@ -315,7 +312,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, goto error; } } - else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS")) + else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS")) { lex_match (lexer, '='); if (!lex_force_int (lexer)) @@ -325,24 +322,25 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, } else if (!parse_dict_trim (lexer, dict)) goto error; - + if (!lex_match (lexer, '/')) break; } if (lex_end_of_command (lexer) != CMD_SUCCESS) goto error; - if (handle == NULL) + if (handle == NULL) { lex_sbc_missing (lexer, "OUTFILE"); goto error; } + dict_delete_scratch_vars (dict); dict_compact_values (dict); - if (fh_get_referent (handle) == FH_REF_FILE) + if (fh_get_referent (handle) == FH_REF_FILE) { - switch (writer_type) + switch (writer_type) { case SYSFILE_WRITER: writer = sfm_open_writer (handle, dict, sysfile_opts); @@ -357,20 +355,23 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, if (writer == NULL) goto error; - map = finish_case_map (dict); + map = case_map_from_dict (dict); if (map != NULL) writer = casewriter_create_translator (writer, + case_map_get_value_cnt (map), get_translate_case, get_destroy_case_map, map); dict_destroy (dict); - + + fh_unref (handle); return writer; error: + fh_unref (handle); casewriter_destroy (writer); dict_destroy (dict); - destroy_case_map (map); + case_map_destroy (map); return NULL; } @@ -387,11 +388,11 @@ parse_output_proc (struct lexer *lexer, struct dataset *ds, enum writer_type wri output = parse_write_command (lexer, ds, writer_type, PROC_CMD, &retain_unselected); - if (output == NULL) + if (output == NULL) return CMD_CASCADING_FAILURE; saved_filter_variable = dict_get_filter (dataset_dict (ds)); - if (retain_unselected) + if (retain_unselected) dict_set_filter (dataset_dict (ds), NULL); casereader_transfer (proc_open (ds), output); @@ -404,13 +405,13 @@ parse_output_proc (struct lexer *lexer, struct dataset *ds, enum writer_type wri } int -cmd_save (struct lexer *lexer, struct dataset *ds) +cmd_save (struct lexer *lexer, struct dataset *ds) { return parse_output_proc (lexer, ds, SYSFILE_WRITER); } int -cmd_export (struct lexer *lexer, struct dataset *ds) +cmd_export (struct lexer *lexer, struct dataset *ds) { return parse_output_proc (lexer, ds, PORFILE_WRITER); } @@ -418,7 +419,7 @@ cmd_export (struct lexer *lexer, struct dataset *ds) /* XSAVE and XEXPORT. */ /* Transformation. */ -struct output_trns +struct output_trns { struct casewriter *writer; /* Writer. */ }; @@ -428,11 +429,11 @@ static trns_free_func output_trns_free; /* Parses the XSAVE or XEXPORT transformation command. */ static int -parse_output_trns (struct lexer *lexer, struct dataset *ds, 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->writer = parse_write_command (lexer, ds, writer_type, XFORM_CMD, NULL); - if (t->writer == NULL) + if (t->writer == NULL) { free (t); return CMD_CASCADING_FAILURE; @@ -466,14 +467,14 @@ output_trns_free (void *trns_) /* XSAVE command. */ int -cmd_xsave (struct lexer *lexer, struct dataset *ds) +cmd_xsave (struct lexer *lexer, struct dataset *ds) { return parse_output_trns (lexer, ds, SYSFILE_WRITER); } /* XEXPORT command. */ int -cmd_xexport (struct lexer *lexer, struct dataset *ds) +cmd_xexport (struct lexer *lexer, struct dataset *ds) { return parse_output_trns (lexer, ds, PORFILE_WRITER); } @@ -489,7 +490,7 @@ static bool keep_variables (struct lexer *, struct dictionary *dict); static bool parse_dict_trim (struct lexer *lexer, struct dictionary *dict) { - if (lex_match_id (lexer, "MAP")) + if (lex_match_id (lexer, "MAP")) { /* FIXME. */ return true; @@ -543,7 +544,7 @@ rename_variables (struct lexer *lexer, struct dictionary *dict) var_get_name (v), lex_tokid (lexer), lex_tokid (lexer)); return 0; } - + dict_rename_var (dict, v, lex_tokid (lexer)); lex_get (lexer); return 1; @@ -568,10 +569,10 @@ rename_variables (struct lexer *lexer, struct dictionary *dict) goto done; if (nn != nv) { - msg (SE, _("Number of variables on left side of `=' (%d) does not " - "match number of variables on right side (%d), in " + msg (SE, _("Number of variables on left side of `=' (%zu) does not " + "match number of variables on right side (%zu), in " "parenthesized group %d of RENAME subcommand."), - (unsigned) (nv - old_nv), (unsigned) (nn - old_nv), group); + nv - old_nv, nn - old_nv, group); goto done; } if (!lex_force_match (lexer, ')')) @@ -579,7 +580,7 @@ rename_variables (struct lexer *lexer, struct dictionary *dict) group++; } - if (!dict_rename_vars (dict, v, new_names, nv, &err_name)) + if (!dict_rename_vars (dict, v, new_names, nv, &err_name)) { msg (SE, _("Requested renaming duplicates variable name %s."), err_name); goto done; @@ -632,7 +633,7 @@ keep_variables (struct lexer *lexer, struct dictionary *dict) /* Move the specified variables to the beginning. */ dict_reorder_vars (dict, v, nv); - + /* Delete the remaining variables. */ v = xnrealloc (v, dict_get_var_cnt (dict) - nv, sizeof *v); for (i = nv; i < dict_get_var_cnt (dict); i++) @@ -660,7 +661,7 @@ struct mtf_file enum mtf_type type; int sequence; - struct variable **by; /* List of BY variables for this file. */ + const struct variable **by; /* List of BY variables for this file. */ struct mtf_variable *vars; /* Variables to copy to output. */ size_t var_cnt; /* Number of other variables. */ @@ -674,14 +675,14 @@ struct mtf_file struct variable *in_var; /* Variable (in master dictionary). */ }; -struct mtf_variable +struct mtf_variable { struct variable *in_var; struct variable *out_var; }; /* MATCH FILES procedure. */ -struct mtf_proc +struct mtf_proc { struct ll_list files; /* List of "struct mtf_file"s. */ int nonempty_files; /* FILEs that are not at end-of-file. */ @@ -701,7 +702,7 @@ struct mtf_proc struct ccase buffered_case; /* Case ready for output except that we don't know the value for the LAST variable yet. */ struct ccase prev_BY_case; /* Case with values of last set of BY vars. */ - struct variable **prev_BY; /* Last set of BY variables. */ + const struct variable **prev_BY; /* Last set of BY variables. */ }; static void mtf_free (struct mtf_proc *); @@ -723,12 +724,12 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) struct mtf_proc mtf; struct ll *first_table; struct mtf_file *file, *next; - + bool saw_in = false; struct casereader *active_file = NULL; - char first_name[LONG_NAME_LEN + 1] = ""; - char last_name[LONG_NAME_LEN + 1] = ""; + char first_name[VAR_NAME_LEN + 1] = ""; + char last_name[VAR_NAME_LEN + 1] = ""; struct taint *taint = NULL; @@ -763,18 +764,18 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) file->vars = NULL; case_nullify (&file->input); - if (lex_match_id (lexer, "FILE")) + if (lex_match_id (lexer, "FILE")) { file->type = MTF_FILE; ll_insert (first_table, &file->ll); mtf.nonempty_files++; } - else if (lex_match_id (lexer, "TABLE")) + else if (lex_match_id (lexer, "TABLE")) { file->type = MTF_TABLE; ll_push_tail (&mtf.files, &file->ll); if (first_table == ll_null (&mtf.files)) - first_table = &file->ll; + first_table = &file->ll; } else NOT_REACHED (); @@ -809,10 +810,10 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) } while (lex_match (lexer, '/')) - if (lex_match_id (lexer, "RENAME")) + if (lex_match_id (lexer, "RENAME")) { if (!rename_variables (lexer, file->dict)) - goto error; + goto error; } else if (lex_match_id (lexer, "IN")) { @@ -836,7 +837,7 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) mtf_merge_dictionary (mtf.dict, file); } - + while (lex_token (lexer) != '.') { if (lex_match (lexer, T_BY)) @@ -844,13 +845,13 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) struct mtf_file *file; struct variable **by; bool ok; - + if (mtf.by_cnt) { lex_sbc_only_once ("BY"); goto error; } - + lex_match (lexer, '='); if (!parse_variables (lexer, mtf.dict, &by, &mtf.by_cnt, PV_NO_DUPLICATE | PV_NO_SCRATCH)) @@ -860,7 +861,7 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) ll_for_each (file, struct mtf_file, ll, &mtf.files) { size_t i; - + file->by = xnmalloc (mtf.by_cnt, sizeof *file->by); for (i = 0; i < mtf.by_cnt; i++) { @@ -883,28 +884,28 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) if (!ok) goto error; } - else if (lex_match_id (lexer, "FIRST")) + else if (lex_match_id (lexer, "FIRST")) { if (first_name[0] != '\0') { lex_sbc_only_once ("FIRST"); goto error; } - + lex_match (lexer, '='); if (!lex_force_id (lexer)) goto error; strcpy (first_name, lex_tokid (lexer)); lex_get (lexer); } - else if (lex_match_id (lexer, "LAST")) + else if (lex_match_id (lexer, "LAST")) { if (last_name[0] != '\0') { lex_sbc_only_once ("LAST"); goto error; } - + lex_match (lexer, '='); if (!lex_force_id (lexer)) goto error; @@ -915,12 +916,12 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) { /* FIXME. */ } - else if (lex_match_id (lexer, "DROP")) + else if (lex_match_id (lexer, "DROP")) { if (!drop_variables (lexer, mtf.dict)) goto error; } - else if (lex_match_id (lexer, "KEEP")) + else if (lex_match_id (lexer, "KEEP")) { if (!keep_variables (lexer, mtf.dict)) goto error; @@ -931,7 +932,7 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) goto error; } - if (!lex_match (lexer, '/') && lex_token (lexer) != '.') + if (!lex_match (lexer, '/') && lex_token (lexer) != '.') { lex_end_of_command (lexer); goto error; @@ -954,24 +955,24 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) /* Set up mapping from each file's variables to master variables. */ - ll_for_each (file, struct mtf_file, ll, &mtf.files) + ll_for_each (file, struct mtf_file, ll, &mtf.files) { size_t in_var_cnt = dict_get_var_cnt (file->dict); file->vars = xnmalloc (in_var_cnt, sizeof *file->vars); file->var_cnt = 0; - for (i = 0; i < in_var_cnt; i++) + for (i = 0; i < in_var_cnt; i++) { struct variable *in_var = dict_get_var (file->dict, i); struct variable *out_var = dict_lookup_var (mtf.dict, var_get_name (in_var)); - if (out_var != NULL) + if (out_var != NULL) { struct mtf_variable *mv = &file->vars[file->var_cnt++]; mv->in_var = in_var; mv->out_var = out_var; - } + } } } @@ -983,15 +984,16 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) || !create_flag_var ("LAST", last_name, mtf.dict, &mtf.last)) goto error; + dict_delete_scratch_vars (mtf.dict); dict_compact_values (mtf.dict); mtf.output = autopaging_writer_create (dict_get_next_value_idx (mtf.dict)); taint = taint_clone (casewriter_get_taint (mtf.output)); - ll_for_each (file, struct mtf_file, ll, &mtf.files) + ll_for_each (file, struct mtf_file, ll, &mtf.files) { - if (file->reader == NULL) + if (file->reader == NULL) { - if (active_file == NULL) + if (active_file == NULL) { proc_discard_output (ds); file->reader = active_file = proc_open (ds); @@ -1001,12 +1003,12 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) } taint_propagate (casereader_get_taint (file->reader), taint); } - + ll_for_each_safe (file, next, struct mtf_file, ll, &mtf.files) mtf_read_record (&mtf, file); while (mtf.nonempty_files > 0) mtf_process_case (&mtf); - if ((mtf.first != NULL || mtf.last != NULL) && mtf.prev_BY != NULL) + if ((mtf.first != NULL || mtf.last != NULL) && mtf.prev_BY != NULL) { if (mtf.last != NULL) case_data_rw (&mtf.buffered_case, mtf.last)->f = 1.0; @@ -1045,7 +1047,7 @@ static bool create_flag_var (const char *subcommand, const char *var_name, struct dictionary *dict, struct variable **var) { - if (var_name != NULL && var_name[0] != '\0') + if (var_name != NULL && var_name[0] != '\0') { struct fmt_spec format = fmt_for_output (FMT_F, 1, 0); *var = dict_create_var (dict, var_name, 0); @@ -1058,7 +1060,7 @@ create_flag_var (const char *subcommand, const char *var_name, } var_set_both_formats (*var, &format); } - else + else *var = NULL; return true; } @@ -1078,13 +1080,14 @@ var_type_description (struct variable *v) Returns true if successful, false if an I/O error occurred on any of the files. */ static bool -mtf_close_all_files (struct mtf_proc *mtf) +mtf_close_all_files (struct mtf_proc *mtf) { struct mtf_file *file; bool ok = true; ll_for_each_preremove (file, struct mtf_file, ll, &mtf->files) { + fh_unref (file->handle); casereader_destroy (file->reader); free (file->by); dict_destroy (file->dict); @@ -1157,12 +1160,12 @@ mtf_process_case (struct mtf_proc *mtf) ll_for_each (file, struct mtf_file, ll, &mtf->files) if (case_is_null (&file->input)) file->sequence = -1; - else if (file->type == MTF_FILE) + else if (file->type == MTF_FILE) { int cmp = min != NULL ? mtf_compare_BY_values (mtf, min, file) : 1; if (cmp <= 0) file->sequence = cmp < 0 ? -1 : min_sequence; - else + else { file->sequence = ++min_sequence; min = file; @@ -1178,37 +1181,37 @@ mtf_process_case (struct mtf_proc *mtf) } while (cmp > 0 && mtf_read_record (mtf, file)); file->sequence = cmp == 0 ? min_sequence : -1; - } + } /* Form the output case from the input cases. */ case_create (&c, dict_get_next_value_idx (mtf->dict)); - for (i = 0; i < dict_get_var_cnt (mtf->dict); i++) + for (i = 0; i < dict_get_var_cnt (mtf->dict); i++) { struct variable *v = dict_get_var (mtf->dict, i); - value_set_missing (case_data_rw (&c, v), var_get_width (v)); + value_set_missing (case_data_rw (&c, v), var_get_width (v)); } ll_for_each_reverse (file, struct mtf_file, ll, &mtf->files) { bool include_file = file->sequence == min_sequence; - if (include_file) + if (include_file) for (i = 0; i < file->var_cnt; i++) { const struct mtf_variable *mv = &file->vars[i]; const union value *in = case_data (&file->input, mv->in_var); union value *out = case_data_rw (&c, mv->out_var); - value_copy (out, in, var_get_width (mv->in_var)); + value_copy (out, in, var_get_width (mv->in_var)); } - if (file->in_var != NULL) + if (file->in_var != NULL) case_data_rw (&c, file->in_var)->f = include_file; } - + /* Write the output case. */ - if (mtf->first == NULL && mtf->last == NULL) + if (mtf->first == NULL && mtf->last == NULL) { /* With no FIRST or LAST variables, it's trivial. */ casewriter_write (mtf->output, &c); } - else + else { /* It's harder with LAST, because we can't know whether this case is the last in a group until we've prepared @@ -1222,7 +1225,7 @@ mtf_process_case (struct mtf_proc *mtf) might not be in the output (the user is allowed to drop them). */ bool new_BY; - if (mtf->prev_BY != NULL) + if (mtf->prev_BY != NULL) { new_BY = case_compare_2dict (&min->input, &mtf->prev_BY_case, min->by, mtf->prev_BY, @@ -1231,28 +1234,28 @@ mtf_process_case (struct mtf_proc *mtf) case_data_rw (&mtf->buffered_case, mtf->last)->f = new_BY; casewriter_write (mtf->output, &mtf->buffered_case); } - else + else new_BY = true; case_move (&mtf->buffered_case, &c); if (mtf->first != NULL) case_data_rw (&mtf->buffered_case, mtf->first)->f = new_BY; - if (new_BY) + if (new_BY) { mtf->prev_BY = min->by; case_destroy (&mtf->prev_BY_case); - case_clone (&mtf->prev_BY_case, &min->input); + case_clone (&mtf->prev_BY_case, &min->input); } } /* Read another record from each input file FILE with minimum values. */ ll_for_each (file, struct mtf_file, ll, &mtf->files) - if (file->type == MTF_FILE) + if (file->type == MTF_FILE) { if (file->sequence == min_sequence) - mtf_read_record (mtf, file); + mtf_read_record (mtf, file); } else break; @@ -1271,7 +1274,7 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) d_docs = dict_get_documents (d); m_docs = dict_get_documents (m); - if (d_docs != NULL) + if (d_docs != NULL) { if (m_docs == NULL) dict_set_documents (m, d_docs); @@ -1282,7 +1285,7 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) free (new_docs); } } - + for (i = 0; i < dict_get_var_cnt (d); i++) { struct variable *dv = dict_get_var (d, i); @@ -1293,7 +1296,7 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) if (mv != NULL) { - if (var_get_width (mv) != var_get_width (dv)) + if (var_get_width (mv) != var_get_width (dv)) { char *dv_description = var_type_description (dv); char *mv_description = var_type_description (mv); @@ -1306,7 +1309,7 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) free (mv_description); return false; } - + if (var_get_width (dv) == var_get_width (mv)) { if (var_has_value_labels (dv) && !var_has_value_labels (mv)) @@ -1318,128 +1321,9 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) if (var_get_label (dv) && !var_get_label (mv)) var_set_label (mv, var_get_label (dv)); } - else + else mv = dict_clone_var_assert (m, dv, var_get_name (dv)); } return true; } - -/* Case map. - - A case map copies data from a case that corresponds for one - dictionary to a case that corresponds to a second dictionary - derived from the first by, optionally, deleting, reordering, - or renaming variables. (No new variables may be created.) - */ - -/* A case map. */ -struct case_map - { - size_t value_cnt; /* Number of values in map. */ - int *map; /* For each destination index, the - corresponding source index. */ - }; - -/* Prepares dictionary D for producing a case map. Afterward, - the caller may delete, reorder, or rename variables within D - at will before using finish_case_map() to produce the case - map. - - Uses D's aux members, which must otherwise not be in use. */ -static void -start_case_map (struct dictionary *d) -{ - size_t var_cnt = dict_get_var_cnt (d); - size_t i; - - for (i = 0; i < var_cnt; i++) - { - struct variable *v = dict_get_var (d, i); - int *src_fv = xmalloc (sizeof *src_fv); - *src_fv = var_get_case_index (v); - var_attach_aux (v, src_fv, var_dtor_free); - } -} - -/* Produces a case map from dictionary D, which must have been - previously prepared with start_case_map(). - - Does not retain any reference to D, and clears the aux members - set up by start_case_map(). - - Returns the new case map, or a null pointer if no mapping is - required (that is, no data has changed position). */ -static struct case_map * -finish_case_map (struct dictionary *d) -{ - struct case_map *map; - size_t var_cnt = dict_get_var_cnt (d); - size_t i; - int identity_map; - - map = xmalloc (sizeof *map); - map->value_cnt = dict_get_next_value_idx (d); - map->map = xnmalloc (map->value_cnt, sizeof *map->map); - for (i = 0; i < map->value_cnt; i++) - map->map[i] = -1; - - identity_map = 1; - for (i = 0; i < var_cnt; i++) - { - struct variable *v = dict_get_var (d, i); - size_t value_cnt = var_get_value_cnt (v); - int *src_fv = (int *) var_detach_aux (v); - size_t idx; - - if (var_get_case_index (v) != *src_fv) - identity_map = 0; - - for (idx = 0; idx < value_cnt; idx++) - { - int src_idx = *src_fv + idx; - int dst_idx = var_get_case_index (v) + idx; - - assert (map->map[dst_idx] == -1); - map->map[dst_idx] = src_idx; - } - free (src_fv); - } - - if (identity_map) - { - destroy_case_map (map); - return NULL; - } - - while (map->value_cnt > 0 && map->map[map->value_cnt - 1] == -1) - map->value_cnt--; - - return map; -} - -/* Maps from SRC to DST, applying case map MAP. */ -static void -map_case (const struct case_map *map, - const struct ccase *src, struct ccase *dst) -{ - size_t dst_idx; - - for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++) - { - int src_idx = map->map[dst_idx]; - if (src_idx != -1) - *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx); - } -} - -/* Destroys case map MAP. */ -static void -destroy_case_map (struct case_map *map) -{ - if (map != NULL) - { - free (map->map); - free (map); - } -}