Eliminated global variable current_dataset.
[pspp-builds.git] / src / language / xforms / recode.c
index c9cb203961071d556cbb2a279838fe42f36e8bb0..6af3e5d1cd3548f5490f8494714e4899839a59a3 100644 (file)
 #include <data/case.h>
 #include <data/data-in.h>
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
+#include <language/lexer/variable-parser.h>
 #include <language/lexer/range-parser.h>
 #include <libpspp/alloc.h>
+#include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
 #include <libpspp/magic.h>
 #include <libpspp/message.h>
@@ -56,18 +58,25 @@ enum map_in_type
     MAP_CONVERT                        /* "123" => 123. */
   };
 
+/* A value involved in a RECODE mapping. */
+union recode_value 
+  {
+    double f;                   /* Numeric. */
+    char *c;                    /* Short or long string. */
+  };
+
 /* Describes input values to be mapped. */
 struct map_in
   {
     enum map_in_type type;      /* One of MAP_*. */
-    union value x, y;           /* Source values. */
+    union recode_value x, y;    /* Source values. */
   };
 
 /* Describes the value used as output from a mapping. */
 struct map_out 
   {
     bool copy_input;            /* If true, copy input to output. */
-    union value value;          /* If copy_input false, recoded value. */
+    union recode_value value;   /* If copy_input false, recoded value. */
     int width;                  /* If copy_input false, output value width. */ 
   };
 
@@ -99,9 +108,9 @@ struct recode_trns
     size_t map_cnt;             /* Number of mappings. */
   };
 
-static bool parse_src_vars (struct recode_trns *);
+static bool parse_src_vars (struct recode_trns *, const struct dictionary *dict);
 static bool parse_mappings (struct recode_trns *);
-static bool parse_dst_vars (struct recode_trns *);
+static bool parse_dst_vars (struct recode_trns *, const struct dictionary *dict);
 
 static void add_mapping (struct recode_trns *,
                          size_t *map_allocated, const struct map_in *);
@@ -119,7 +128,7 @@ static void set_map_out_str (struct map_out *, struct pool *,
                              const struct string *);
 
 static void enlarge_dst_widths (struct recode_trns *);
-static void create_dst_vars (struct recode_trns *);
+static void create_dst_vars (struct recode_trns *, struct dictionary *);
 
 static trns_proc_func recode_trns_proc;
 static trns_free_func recode_trns_free;
@@ -128,7 +137,7 @@ static trns_free_func recode_trns_free;
 
 /* Parses the RECODE transformation. */
 int
-cmd_recode (void)
+cmd_recode (struct dataset *ds)
 {
   do
     {
@@ -138,9 +147,9 @@ cmd_recode (void)
       /* Parse source variable names,
          then input to output mappings,
          then destintation variable names. */
-      if (!parse_src_vars (trns)
+      if (!parse_src_vars (trns, dataset_dict (ds) )
           || !parse_mappings (trns)
-          || !parse_dst_vars (trns))
+          || !parse_dst_vars (trns, dataset_dict (ds)))
         {
           recode_trns_free (trns);
           return CMD_FAILURE;
@@ -155,10 +164,11 @@ cmd_recode (void)
          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);
+        create_dst_vars (trns, dataset_dict (ds));
 
       /* Done. */
-      add_transformation (recode_trns_proc, recode_trns_free, trns);
+      add_transformation (ds, 
+                         recode_trns_proc, recode_trns_free, trns);
     }
   while (lex_match ('/'));
   
@@ -169,9 +179,9 @@ cmd_recode (void)
    TRNS->var_cnt.  Sets TRNS->src_type.  Returns true if
    successful, false on parse error. */
 static bool
-parse_src_vars (struct recode_trns *trns) 
+parse_src_vars (struct recode_trns *trns, const struct dictionary *dict
 {
-  if (!parse_variables (default_dict, &trns->src_vars, &trns->var_cnt,
+  if (!parse_variables (dict, &trns->src_vars, &trns->var_cnt,
                         PV_SAME_TYPE))
     return false;
   pool_register (trns->pool, free, trns->src_vars);
@@ -405,7 +415,7 @@ set_map_out_str (struct map_out *out, struct pool *pool,
 /* Parses a set of target variables into TRNS->dst_vars and
    TRNS->dst_names. */
 static bool
-parse_dst_vars (struct recode_trns *trns) 
+parse_dst_vars (struct recode_trns *trns, const struct dictionary *dict
 {
   size_t i;
   
@@ -414,7 +424,8 @@ parse_dst_vars (struct recode_trns *trns)
       size_t name_cnt;
       size_t i;
 
-      if (!parse_mixed_vars_pool (trns->pool, &trns->dst_names, &name_cnt,
+      if (!parse_mixed_vars_pool (dict, trns->pool, 
+                                 &trns->dst_names, &name_cnt,
                                   PV_NONE))
         return false;
 
@@ -432,8 +443,7 @@ parse_dst_vars (struct recode_trns *trns)
       for (i = 0; i < trns->var_cnt; i++)
         {
           struct variable *v;
-          v = trns->dst_vars[i] = dict_lookup_var (default_dict,
-                                                  trns->dst_names[i]);
+          v = trns->dst_vars[i] = dict_lookup_var (dict, trns->dst_names[i]);
           if (v == NULL && trns->dst_type == ALPHA) 
             {
               msg (SE, _("There is no variable named "
@@ -506,7 +516,7 @@ enlarge_dst_widths (struct recode_trns *trns)
 
 /* Creates destination variables that don't already exist. */
 static void
-create_dst_vars (struct recode_trns *trns)
+create_dst_vars (struct recode_trns *trns, struct dictionary *dict)
 {
   size_t i;
 
@@ -515,9 +525,9 @@ create_dst_vars (struct recode_trns *trns)
       struct variable **var = &trns->dst_vars[i];
       const char *name = trns->dst_names[i];
           
-      *var = dict_lookup_var (default_dict, name);
+      *var = dict_lookup_var (dict, name);
       if (*var == NULL)
-        *var = dict_create_var_assert (default_dict, name, 0);
+        *var = dict_create_var_assert (dict, name, 0);
       assert ((*var)->type == trns->dst_type);
     }
 }
@@ -552,7 +562,7 @@ find_src_numeric (struct recode_trns *trns, double value, struct variable *v)
           match = true;
           break;
         default:
-          abort ();
+          NOT_REACHED ();
         }
 
       if (match)
@@ -585,21 +595,23 @@ find_src_string (struct recode_trns *trns, const char *value, int width)
           break;
         case MAP_CONVERT:
           {
+            union value uv;
             struct data_in di;
 
             di.s = value;
             di.e = value + width;
-            di.v = &out->value;
+            di.v = &uv;
             di.flags = DI_IGNORE_ERROR;
             di.f1 = di.f2 = 0;
             di.format.type = FMT_F;
             di.format.w = width;
             di.format.d = 0;
             match = data_in (&di);
+            out->value.f = uv.f;
             break;
           }
         default:
-          abort ();
+          NOT_REACHED ();
         }
 
       if (match)
@@ -611,7 +623,7 @@ find_src_string (struct recode_trns *trns, const char *value, int width)
 
 /* Performs RECODE transformation. */
 static int
-recode_trns_proc (void *trns_, struct ccase *c, int case_idx UNUSED)
+recode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
 {
   struct recode_trns *trns = trns_;
   size_t i;