/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 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
This must be the final step; otherwise we'd have to
delete destination variables on failure. */
if (trns->src_vars != trns->dst_vars)
- create_dst_vars (trns, dataset_dict (ds));
+ create_dst_vars (trns, dataset_dict (ds));
/* Done. */
add_transformation (ds,
do
{
struct map_in in;
+
if (!parse_map_in (lexer, &in, trns->pool,
trns->src_type, max_src_width))
return false;
if (!parse_map_out (lexer, trns->pool, &out))
return false;
- dst_type = val_type_from_width (out.width);
+
+ if (out.copy_input)
+ dst_type = trns->src_type;
+ else
+ dst_type = val_type_from_width (out.width);
if (have_dst_type && dst_type != trns->dst_type)
{
msg (SE, _("Inconsistent target variable types. "
parse_map_in (struct lexer *lexer, struct map_in *in, struct pool *pool,
enum val_type src_type, size_t max_src_width)
{
+
if (lex_match_id (lexer, "ELSE"))
+ {
set_map_in_generic (in, MAP_ELSE);
+ }
else if (src_type == VAL_NUMERIC)
{
if (lex_match_id (lexer, "MISSING"))
}
else
{
- if (!lex_force_string (lexer))
+ if (lex_match_id (lexer, "MISSING"))
+ set_map_in_generic (in, MAP_MISSING);
+ else if (!lex_force_string (lexer))
return false;
- set_map_in_str (in, pool, lex_tokstr (lexer), max_src_width);
- lex_get (lexer);
- if (lex_token (lexer) == T_ID
- && lex_id_match (ss_cstr ("THRU"), ss_cstr (lex_tokid (lexer))))
- {
- msg (SE, _("THRU is not allowed with string variables."));
- return false;
- }
+ else
+ {
+ set_map_in_str (in, pool, lex_tokstr (lexer), max_src_width);
+ lex_get (lexer);
+ if (lex_token (lexer) == T_ID
+ && lex_id_match (ss_cstr ("THRU"), ss_cstr (lex_tokid (lexer))))
+ {
+ msg (SE, _("THRU is not allowed with string variables."));
+ return false;
+ }
+ }
}
return true;
set_map_out_str (out, pool, lex_tokstr (lexer));
lex_get (lexer);
}
- else if (lex_match_id (lexer, "COPY"))
- out->copy_input = true;
+ else if (lex_match_id (lexer, "COPY"))
+ {
+ out->copy_input = true;
+ out->width = 0;
+ }
else
{
lex_error (lexer, _("expecting output value"));
return false;
}
}
+
}
else
{
/* Returns the output mapping in TRNS for an input of VALUE with
the given WIDTH, or a null pointer if there is no mapping. */
static const struct map_out *
-find_src_string (struct recode_trns *trns, const char *value, int width)
+find_src_string (struct recode_trns *trns, const char *value, const struct variable *src_var)
{
struct mapping *m;
+ int width = var_get_width (src_var);
for (m = trns->mappings; m < trns->mappings + trns->map_cnt; m++)
{
msg_disable ();
match = data_in (ss_buffer (value, width), LEGACY_NATIVE,
- FMT_F, 0, 0, &uv, 0);
+ FMT_F, 0, 0, 0, &uv, 0);
msg_enable ();
out->value.f = uv.f;
break;
}
+ case MAP_MISSING:
+ match = var_is_str_missing (src_var, value, MV_ANY);
+ break;
default:
NOT_REACHED ();
}
/* Performs RECODE transformation. */
static int
-recode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
+recode_trns_proc (void *trns_, struct ccase **c, casenumber case_idx UNUSED)
{
struct recode_trns *trns = trns_;
size_t i;
+ *c = case_unshare (*c);
for (i = 0; i < trns->var_cnt; i++)
{
const struct variable *src_var = trns->src_vars[i];
const struct variable *dst_var = trns->dst_vars[i];
- const union value *src_data = case_data (c, src_var);
- union value *dst_data = case_data_rw (c, dst_var);
+ const union value *src_data = case_data (*c, src_var);
+ union value *dst_data = case_data_rw (*c, dst_var);
const struct map_out *out;
if (trns->src_type == VAL_NUMERIC)
out = find_src_numeric (trns, src_data->f, src_var);
else
- out = find_src_string (trns, src_data->s, var_get_width (src_var));
+ out = find_src_string (trns, src_data->s, src_var);
if (trns->dst_type == VAL_NUMERIC)
{