X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fdata-io%2Fget.c;h=f8a84b142919d59d43f31222bf42c45fdb747b8d;hb=ebad3a92846289fb77c7e0fb8bb48ac7c02de68c;hp=383513e632f0aadb5640d17e4cb81411fd312711;hpb=130ced32165dc409b1be560d3d7a581a7ba3c5ee;p=pspp diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index 383513e632..f8a84b1429 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -45,17 +45,11 @@ #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 size_t case_map_get_value_cnt (const struct case_map *); - static bool parse_dict_trim (struct lexer *, struct dictionary *); /* Reading system and portable files. */ @@ -67,8 +61,7 @@ enum reader_command 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. */ @@ -88,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; @@ -120,7 +114,7 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command if (reader == NULL) goto error; - start_case_map (dict); + case_map_prepare_dict (dict); while (lex_token (lexer) != '.') { @@ -128,8 +122,9 @@ 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), @@ -139,9 +134,11 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command 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); @@ -149,18 +146,19 @@ parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command } static void -get_translate_case (const struct ccase *input, struct ccase *output, +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_) { struct case_map *map = map_; - destroy_case_map (map); + case_map_destroy (map); return true; } @@ -238,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, '/'); @@ -337,6 +335,7 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, goto error; } + dict_delete_scratch_vars (dict); dict_compact_values (dict); if (fh_get_referent (handle) == FH_REF_FILE) @@ -356,7 +355,7 @@ 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), @@ -365,12 +364,14 @@ parse_write_command (struct lexer *lexer, struct dataset *ds, 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; } @@ -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, ')')) @@ -727,8 +728,8 @@ cmd_match_files (struct lexer *lexer, struct dataset *ds) 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; @@ -983,6 +984,7 @@ 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)); @@ -1085,6 +1087,7 @@ mtf_close_all_files (struct mtf_proc *mtf) 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); @@ -1324,131 +1327,3 @@ mtf_merge_dictionary (struct dictionary *const m, struct mtf_file *f) 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; - - case_create (dst, map->value_cnt); - 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); - } -} - -/* Returns the number of `union value's in cases created by - MAP. */ -static size_t -case_map_get_value_cnt (const struct case_map *map) -{ - return map->value_cnt; -}