Fixed a bug causing pspp to crash when computed variables had no format
[pspp-builds.git] / src / autorecode.c
index 5ae1e7f6ef79784695593bf689c22cc555ba98cd..8d15ce63ba3b55fe858cf10e593cd47c9c9f1486 100644 (file)
@@ -30,8 +30,6 @@
 #include "var.h"
 #include "vfm.h"
 
-#undef DEBUGGING
-/*#define DEBUGGING 1 */
 #include "debug-print.h"
 
 /* FIXME: This module is less than ideally efficient, both in space
@@ -78,11 +76,9 @@ static int print;
 
 static int autorecode_trns_proc (struct trns_header *, struct ccase *);
 static void autorecode_trns_free (struct trns_header *);
-static int autorecode_proc_func (struct ccase *);
-static int compare_alpha_value (const void *, const void *, void *);
-static unsigned hash_alpha_value (const void *, void *);
-static int compare_numeric_value (const void *, const void *, void *);
-static unsigned hash_numeric_value (const void *, void *);
+static int autorecode_proc_func (struct ccase *, void *);
+static hsh_compare_func compare_alpha_value, compare_numeric_value;
+static hsh_hash_func hash_alpha_value, hash_numeric_value;
 static void recode (void);
 
 /* Performs the AUTORECODE procedure. */
@@ -102,7 +98,7 @@ cmd_autorecode (void)
   lex_match_id ("AUTORECODE");
   lex_match_id ("VARIABLES");
   lex_match ('=');
-  if (!parse_variables (&default_dict, &v_src, &nv_src, PV_NO_DUPLICATE))
+  if (!parse_variables (default_dict, &v_src, &nv_src, PV_NO_DUPLICATE))
     return CMD_FAILURE;
   if (!lex_force_match_id ("INTO"))
     return CMD_FAILURE;
@@ -130,7 +126,7 @@ cmd_autorecode (void)
     {
       int j;
 
-      if (is_varname (n_dest[i]))
+      if (dict_lookup_var (default_dict, n_dest[i]) != NULL)
        {
          msg (SE, _("Target variable %s duplicates existing variable %s."),
               n_dest[i], n_dest[i]);
@@ -152,17 +148,17 @@ cmd_autorecode (void)
   for (i = 0; i < nv_dest; i++)
     if (v_src[i]->type == ALPHA)
       h_trans[i] = hsh_create (10, compare_alpha_value,
-                              hash_alpha_value, NULL,
-                              (void *) v_src[i]->width);
+                              hash_alpha_value, NULL, v_src[i]);
     else
       h_trans[i] = hsh_create (10, compare_numeric_value,
                               hash_numeric_value, NULL, NULL);
 
-  procedure (NULL, autorecode_proc_func, NULL);
+  procedure (NULL, autorecode_proc_func, NULL, NULL);
 
   for (i = 0; i < nv_dest; i++)
     {
-      v_dest[i] = force_create_variable (&default_dict, n_dest[i], NUMERIC, 0);
+      v_dest[i] = dict_create_var_assert (default_dict, n_dest[i], 0);
+      v_dest[i]->init = 0;
       free (n_dest[i]);
     }
   free (n_dest);
@@ -204,7 +200,7 @@ recode (void)
   for (i = 0; i < nv_src; i++)
     {
       struct arc_spec *spec = &t->arc[i];
-      void **p = hsh_sort (h_trans[i], NULL);
+      void **p = hsh_sort (h_trans[i]);
       int count = hsh_count (h_trans[i]);
       int j;
 
@@ -213,8 +209,7 @@ recode (void)
 
       if (v_src[i]->type == ALPHA)
        spec->items = hsh_create (2 * count, compare_alpha_value,
-                                 hash_alpha_value, NULL,
-                                 (void *) v_src[i]->width);
+                                 hash_alpha_value, NULL, v_src[i]);
       else
        spec->items = hsh_create (2 * count, compare_numeric_value,
                                  hash_numeric_value, NULL, NULL);
@@ -222,12 +217,14 @@ recode (void)
       for (j = 0; *p; p++, j++)
        {
          struct arc_item *item = pool_alloc (arc_pool, sizeof *item);
-
-         memcpy (&item->from, *p, sizeof (union value));
-         if (v_src[i]->type == ALPHA)
-           item->from.c = pool_strdup (arc_pool, item->from.c);
+          union value *vp = *p;
+          
+         if (v_src[i]->type == NUMERIC)
+            item->from.f = vp->f;
+          else
+           item->from.c = pool_strdup (arc_pool, vp->c);
          item->to = !descend ? j + 1 : count - j;
-         force_hsh_insert (spec->items, item);
+         hsh_force_insert (spec->items, item);
        }
       
       hsh_destroy (h_trans[i]);
@@ -249,12 +246,12 @@ autorecode_trns_proc (struct trns_header * trns, struct ccase * c)
       struct arc_item *item;
 
       if (spec->src->type == NUMERIC)
-       item = force_hsh_find (spec->items, &c->data[spec->src->fv].f);
+       item = hsh_force_find (spec->items, &c->data[spec->src->fv].f);
       else
        {
          union value v;
          v.c = c->data[spec->src->fv].s;
-         item = force_hsh_find (spec->items, &v);
+         item = hsh_force_find (spec->items, &v);
        }
 
       c->data[spec->dest->fv].f = item->to;
@@ -276,33 +273,43 @@ autorecode_trns_free (struct trns_header * trns)
 /* AUTORECODE procedure. */
 
 static int
-compare_alpha_value (const void *a, const void *b, void *len)
+compare_alpha_value (const void *a_, const void *b_, void *v_)
 {
-  return memcmp (((union value *) a)->c, ((union value *) b)->c, (int) len);
+  const union value *a = a_;
+  const union value *b = b_;
+  const struct variable *v = v_;
+
+  return memcmp (a->c, b->c, v->width);
 }
 
 static unsigned
-hash_alpha_value (const void *a, void *len)
+hash_alpha_value (const void *a_, void *v_)
 {
-  return hashpjw_d (((union value *) a)->c, &((union value *) a)->c[(int) len]);
+  const union value *a = a_;
+  const struct variable *v = v_;
+  
+  return hsh_hash_bytes (a->c, v->width);
 }
 
 static int
-compare_numeric_value (const void *pa, const void *pb, void *foobar unused)
+compare_numeric_value (const void *a_, const void *b_, void *foo UNUSED)
 {
-  double a = ((union value *) pa)->f, b = ((union value *) pb)->f;
-  return a > b ? 1 : (a < b ? -1 : 0);
+  const union value *a = a_;
+  const union value *b = b_;
+
+  return a->f < b->f ? -1 : a->f > b->f;
 }
 
 static unsigned
-hash_numeric_value (const void *a, void *len unused)
+hash_numeric_value (const void *a_, void *foo UNUSED)
 {
-  return hashpjw_d ((char *) &((union value *) a)->f,
-                   (char *) &(&((union value *) a)->f)[1]);
+  const union value *a = a_;
+
+  return hsh_hash_double (a->f);
 }
 
 static int
-autorecode_proc_func (struct ccase * c)
+autorecode_proc_func (struct ccase *c, void *aux UNUSED)
 {
   int i;
 
@@ -316,7 +323,7 @@ autorecode_proc_func (struct ccase * c)
        {
          v.f = c->data[v_src[i]->fv].f;
          vpp = (union value **) hsh_probe (h_trans[i], &v);
-         if (NULL == *vpp)
+         if (*vpp == NULL)
            {
              vp = pool_alloc (hash_pool, sizeof (union value));
              vp->f = v.f;
@@ -327,13 +334,10 @@ autorecode_proc_func (struct ccase * c)
        {
          v.c = c->data[v_src[i]->fv].s;
          vpp = (union value **) hsh_probe (h_trans[i], &v);
-         if (NULL == *vpp)
+         if (*vpp == NULL)
            {
              vp = pool_alloc (hash_pool, sizeof (union value));
-#if __CHECKER__
-             memset (vp, 0, sizeof (union value));
-#endif
-             vp->c = pool_strdup (hash_pool, v.c);
+             vp->c = pool_strndup (hash_pool, v.c, v_src[i]->width);
              *vpp = vp;
            }
        }