Fix bug in CLABELS when a missing category was moved, and add test.
[pspp] / src / language / stats / ctables.c
index 51493b0012a3c268310ea085c15fe150eb628d38..e34621e2fa4ad270ede00e0d80d39059e35edf58 100644 (file)
@@ -3002,6 +3002,20 @@ ctables_value_find__ (struct ctables_table *t, const union value *value,
   return NULL;
 }
 
+static void
+ctables_value_insert (struct ctables_table *t, const union value *value,
+                      int width)
+{
+  unsigned int hash = value_hash (value, width, 0);
+  struct ctables_value *clv = ctables_value_find__ (t, value, width, hash);
+  if (!clv)
+    {
+      clv = xmalloc (sizeof *clv);
+      value_clone (&clv->value, value, width);
+      hmap_insert (&t->clabels_values_map, &clv->node, hash);
+    }
+}
+
 static struct ctables_value *
 ctables_value_find (struct ctables_table *t,
                     const union value *value, int width)
@@ -3547,7 +3561,8 @@ ctables_table_output (struct ctables *ct, struct ctables_table *t)
                   const struct variable *var = clabels_nest->vars[clabels_nest->n - 1];
                   const union value *value = &cell->axes[t->clabels_from_axis].cvs[clabels_nest->n - 1].value;
                   const struct ctables_value *ctv = ctables_value_find (t, value, var_get_width (var));
-                  assert (ctv != NULL);
+                  if (!ctv)
+                    continue;
                   dindexes[n_dindexes++] = ctv->leaf;
                 }
 
@@ -3828,25 +3843,14 @@ ctables_insert_clabels_values (struct ctables_table *t, const struct ccase *c,
     {
       const struct ctables_nest *nest = &stack->nests[i];
       const struct variable *var = nest->vars[nest->n - 1];
-      int width = var_get_width (var);
       const union value *value = case_data (c, var);
 
       if (var_is_numeric (var) && value->f == SYSMIS)
         continue;
 
-      if (!ctables_categories_match (t->categories [var_get_dict_index (var)],
-                                     value, var))
-        continue;
-
-      unsigned int hash = value_hash (value, width, 0);
-
-      struct ctables_value *clv = ctables_value_find__ (t, value, width, hash);
-      if (!clv)
-        {
-          clv = xmalloc (sizeof *clv);
-          value_clone (&clv->value, value, width);
-          hmap_insert (&t->clabels_values_map, &clv->node, hash);
-        }
+      if (ctables_categories_match (t->categories [var_get_dict_index (var)],
+                                    value, var))
+        ctables_value_insert (t, value, var_get_width (var));
     }
 }
 
@@ -3864,7 +3868,18 @@ compare_clabels_values_3way (const void *a_, const void *b_, const void *width_)
 static void
 ctables_sort_clabels_values (struct ctables_table *t)
 {
-  int width = var_get_width (t->clabels_example);
+  const struct variable *v0 = t->clabels_example;
+  int width = var_get_width (v0);
+
+  struct ctables_categories *c0 = t->categories[var_get_dict_index (v0)];
+  if (c0->show_empty)
+    {
+      const struct val_labs *val_labs = var_get_value_labels (v0);
+      for (const struct val_lab *vl = val_labs_first (val_labs); vl;
+           vl = val_labs_next (val_labs, vl))
+        if (ctables_categories_match (c0, &vl->value, v0))
+          ctables_value_insert (t, &vl->value, width);
+    }
 
   size_t n = hmap_count (&t->clabels_values_map);
   t->clabels_values = xnmalloc (n, sizeof *t->clabels_values);
@@ -4847,7 +4862,7 @@ cmd_ctables (struct lexer *lexer, struct dataset *ds)
           [PIVOT_AXIS_COLUMN] = PIVOT_AXIS_COLUMN,
           [PIVOT_AXIS_LAYER] = PIVOT_AXIS_LAYER,
         },
-        .clabels_from_axis = PIVOT_AXIS_LAYER, 
+        .clabels_from_axis = PIVOT_AXIS_LAYER,
         .categories = categories,
         .n_categories = n_vars,
         .cilevel = 95,