CTABLES split file
[pspp] / src / language / stats / ctables.c
index eed3a8e3c8b57554403b20ea46d01cf1d61b3ca9..fd296a00216e5165bcbe9427fc79cd99ccf71128 100644 (file)
@@ -1395,6 +1395,7 @@ ctables_destroy (struct ctables *ct)
       hmap_delete (&ct->postcomputes, &pc->hmap_node);
       free (pc);
     }
+  hmap_destroy (&ct->postcomputes);
 
   fmt_settings_uninit (&ct->ctables_formats);
   pivot_table_look_unref (ct->look);
@@ -4239,6 +4240,8 @@ ctables_pcexpr_evaluate (const struct ctables_pcexpr_evaluate_ctx *ctx,
 
     case CTPO_CAT_NRANGE:
     case CTPO_CAT_SRANGE:
+    case CTPO_CAT_MISSING:
+    case CTPO_CAT_OTHERNM:
       {
         struct ctables_cell_value cv = {
           .category = ctables_find_category_for_postcompute (ctx->section->table->ctables->dict, ctx->cats, ctx->parse_format, e)
@@ -4260,8 +4263,6 @@ ctables_pcexpr_evaluate (const struct ctables_pcexpr_evaluate_ctx *ctx,
       }
 
     case CTPO_CAT_NUMBER:
-    case CTPO_CAT_MISSING:
-    case CTPO_CAT_OTHERNM:
     case CTPO_CAT_SUBTOTAL:
     case CTPO_CAT_TOTAL:
       {
@@ -4282,11 +4283,21 @@ ctables_pcexpr_evaluate (const struct ctables_pcexpr_evaluate_ctx *ctx,
             s = xmalloc (width);
             buf_copy_rpad (s, width, e->string.string, e->string.length, ' ');
           }
-        struct ctables_cell_value cv = {
-          .category = ctables_find_category_for_postcompute (ctx->section->table->ctables->dict, ctx->cats, ctx->parse_format, e),
-          .value = { .s = CHAR_CAST (uint8_t *, s ? s : e->string.string) },
-        };
-        assert (cv.category != NULL);
+
+        const struct ctables_category *category
+          = ctables_find_category_for_postcompute (
+            ctx->section->table->ctables->dict,
+            ctx->cats, ctx->parse_format, e);
+        assert (category != NULL);
+
+        struct ctables_cell_value cv = { .category = category };
+        if (category->type == CCT_NUMBER)
+          cv.value.f = category->number;
+        else if (category->type == CCT_STRING)
+          cv.value.s = CHAR_CAST (uint8_t *, s ? s : e->string.string);
+        else
+          NOT_REACHED ();
+
         double retval = ctables_pcexpr_evaluate_category (ctx, &cv);
         free (s);
         return retval;
@@ -5502,23 +5513,27 @@ ctables_execute (struct dataset *ds, struct casereader *input,
     }
 
   struct dictionary *dict = dataset_dict (ds);
+
+  bool splitting = dict_get_split_type (dict) == SPLIT_SEPARATE;
   struct casegrouper *grouper
-    = (dict_get_split_type (dict) == SPLIT_SEPARATE
+    = (splitting
        ? casegrouper_create_splits (input, dict)
        : casegrouper_create_vars (input, NULL, 0));
   struct casereader *group;
   while (casegrouper_get_next_group (grouper, &group))
     {
-      /* Output SPLIT FILE variables. */
-      struct ccase *c = casereader_peek (group, 0);
-      if (c != NULL)
+      if (splitting)
         {
-          output_split_file_values (ds, c);
-          case_unref (c);
+          struct ccase *c = casereader_peek (group, 0);
+          if (c != NULL)
+            {
+              output_split_file_values (ds, c);
+              case_unref (c);
+            }
         }
 
       bool warn_on_invalid = true;
-      for (c = casereader_read (group); c;
+      for (struct ccase *c = casereader_read (group); c;
            case_unref (c), c = casereader_read (group))
         {
           double d_weight = dict_get_case_weight (dict, c, &warn_on_invalid);