Change how checking for missing values works.
[pspp] / src / language / stats / autorecode.c
index dcd0a14d76fc1a0330774032cf35b3d3aaab8226..499f149d22a14c4003f2d2ae1a9a42d368202798 100644 (file)
@@ -1,5 +1,6 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2009, 2010, 2012, 2013, 2014 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2009, 2010, 2012, 2013, 2014
+   2021,  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
@@ -95,8 +96,7 @@ struct autorecode_pgm
   bool blank_valid;
 };
 
-static trns_proc_func autorecode_trns_proc;
-static trns_free_func autorecode_trns_free;
+static const struct trns_class autorecode_trns_class;
 
 static int compare_arc_items (const void *, const void *, const void *aux);
 static void arc_free (struct autorecode_pgm *);
@@ -131,7 +131,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
   bool print = false;
 
   /* Create procedure. */
-  struct autorecode_pgm *arc = xzalloc (sizeof *arc);
+  struct autorecode_pgm *arc = XZALLOC (struct autorecode_pgm);
   arc->blank_valid = true;
 
   /* Parse variable lists. */
@@ -245,7 +245,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
       spec->format = *var_get_print_format (src_vars[i]);
 
       const char *label = var_get_label (src_vars[i]);
-      spec->label = label ? xstrdup (label) : NULL;
+      spec->label = xstrdup_if_nonnull (label);
 
       if (group && i > 0)
         spec->items = arc->specs[0].items;
@@ -311,8 +311,8 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
         struct arc_item *item = xmalloc (sizeof *item);
         item->width = width;
         value_clone (&item->from, value, width);
-        item->missing = mv_is_value_missing_varwidth (&spec->mv, value, spec->width,
-                                                      MV_ANY);
+        item->missing = mv_is_value_missing_varwidth (&spec->mv, value,
+                                                      spec->width);
         item->value_label = ds_steal_cstr (&value_label);
         hmap_insert (&spec->items->ht, &item->hmap_node, hash);
 
@@ -369,7 +369,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
                : pivot_value_new_text_format (N_("Recoding %s into %s."),
                                               spec->src_name,
                                               var_get_name (spec->dst)));
-          struct pivot_table *table = pivot_table_create__ (title);
+          struct pivot_table *table = pivot_table_create__ (title, "Recoding");
 
           pivot_dimension_create (
             table, PIVOT_AXIS_COLUMN, N_("Attributes"),
@@ -386,7 +386,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
                 old_values->root, pivot_value_new_value (
                   &item->from, item->width,
                   (item->width
-                   ? &(struct fmt_spec) { FMT_F, item->width, 0 }
+                   ? &(struct fmt_spec) { .type = FMT_F, .w = item->width }
                    : &spec->format),
                   dict_get_encoding (dict)));
               pivot_table_put2 (table, 0, old_value_idx,
@@ -428,7 +428,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
           mv_init (&mv, 0);
           if (n_missing > 3)
             mv_add_range (&mv, lo, hi);
-          else if (n_missing > 0)
+          else
             for (size_t k = 0; k < n_missing; k++)
               mv_add_num (&mv, lo + k);
           var_set_missing_values (spec->dst, &mv);
@@ -449,7 +449,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds)
       /* Free array. */
       free (items);
     }
-  add_transformation (ds, autorecode_trns_proc, autorecode_trns_free, arc);
+  add_transformation (ds, &autorecode_trns_class, arc);
 
   for (size_t i = 0; i < n_dsts; i++)
     free (dst_names[i]);
@@ -491,9 +491,10 @@ arc_free (struct autorecode_pgm *arc)
         }
 
       size_t n_rec_items =
-        (arc->n_specs == 1 || arc->specs[0].items == arc->specs[1].items
+        (arc->n_specs >= 2 && arc->specs[0].items == arc->specs[1].items
          ? 1
          : arc->n_specs);
+
       for (size_t i = 0; i < n_rec_items; i++)
         {
           struct arc_spec *spec = &arc->specs[i];
@@ -551,7 +552,7 @@ compare_arc_items (const void *a_, const void *b_, const void *direction_)
   return direction == ASCENDING ? cmp : -cmp;
 }
 
-static int
+static enum trns_result
 autorecode_trns_proc (void *arc_, struct ccase **c,
                       casenumber case_idx UNUSED)
 {
@@ -566,7 +567,7 @@ autorecode_trns_proc (void *arc_, struct ccase **c,
       size_t hash = value_hash (value, width, 0);
       const struct arc_item *item = find_arc_item (spec->items, value, width,
                                                    hash);
-      case_data_rw (*c, spec->dst)->f = item ? item->to : SYSMIS;
+      *case_num_rw (*c, spec->dst) = item ? item->to : SYSMIS;
     }
 
   return TRNS_CONTINUE;
@@ -580,3 +581,9 @@ autorecode_trns_free (void *arc_)
   arc_free (arc);
   return true;
 }
+
+static const struct trns_class autorecode_trns_class = {
+  .name = "AUTORECODE",
+  .execute = autorecode_trns_proc,
+  .destroy = autorecode_trns_free,
+};