X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=inline;f=src%2Flanguage%2Fdata-io%2Fget.c;h=f8a84b142919d59d43f31222bf42c45fdb747b8d;hb=47e6024280cbc95dbfa637009091cc8404c84fb0;hp=950afeb47e6fb285e63fe7285de4807829d9b915;hpb=aed0d6941f474ebd12224d8092bb0e6da64081c6;p=pspp
diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c
index 950afeb47e..f8a84b1429 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);
- }
-}