dictionary: Fix invariant that no split file vars means SPLIT_NONE.
authorBen Pfaff <blp@cs.stanford.edu>
Thu, 16 Feb 2023 23:59:45 +0000 (15:59 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 17 Feb 2023 00:02:25 +0000 (16:02 -0800)
Add SHOW SPLIT to enable testing.

Fixes a crash bug reported by Frans Houweling
at https://lists.gnu.org/archive/html/bug-gnu-pspp/2023-01/msg00011.html

src/data/dictionary.c
src/language/commands/set.c
tests/language/commands/split-file.at

index 60349bce61ec4650b8287f2e28b9bcff5973ac66..1dffcb542f36faa457438a15e0ce1ab2094ab735 100644 (file)
@@ -416,19 +416,21 @@ dict_set_split_vars__ (struct dictionary *d,
   assert (n == 0 || split != NULL);
 
   d->n_splits = n;
-  d->split_type = type == SPLIT_NONE ? SPLIT_LAYERED : type;
+  d->split_type = (n == 0 ? SPLIT_NONE
+                   : type == SPLIT_NONE ? SPLIT_LAYERED
+                   : type);
   if (n > 0)
-   {
-    d->split = xnrealloc (d->split, n, sizeof *d->split) ;
-    memcpy (d->split, split, n * sizeof *d->split);
-   }
+    {
+      d->split = xnrealloc (d->split, n, sizeof *d->split) ;
+      memcpy (d->split, split, n * sizeof *d->split);
+    }
   else
-   {
-    free (d->split);
-    d->split = NULL;
-   }
+    {
+      free (d->split);
+      d->split = NULL;
+    }
 
- if (!skip_callbacks)
 if (!skip_callbacks)
     {
       if (d->changed) d->changed (d, d->changed_data);
       if (d->callbacks &&  d->callbacks->split_changed)
index eb74280fed8e4fa1087e9c0a0fe4b8e58775209d..75ba7b413edbd75a24f90730cc438749770cb310 100644 (file)
@@ -954,6 +954,43 @@ show_SMALL (const struct dataset *ds UNUSED)
   return xstrdup (buf);
 }
 
+static char *
+show_SPLIT (const struct dataset *ds)
+{
+  const struct dictionary *dict = dataset_dict (ds);
+
+  const char *type;
+  switch (dict_get_split_type (dict))
+    {
+    case SPLIT_NONE:
+      return xstrdup ("none");
+
+    case SPLIT_SEPARATE:
+      type = "SEPARATE";
+      break;
+
+    case SPLIT_LAYERED:
+      type = "LAYERED";
+      break;
+
+    default:
+      NOT_REACHED ();
+    }
+
+  struct string s = DS_EMPTY_INITIALIZER;
+
+  size_t n = dict_get_n_splits (dict);
+  const struct variable *const *vars = dict_get_split_vars (dict);
+  for (size_t i = 0; i < n; i++)
+    {
+      if (i > 0)
+        ds_put_cstr (&s, ", ");
+      ds_put_cstr (&s, var_get_name (vars[i]));
+    }
+  ds_put_format (&s, " (%s)", type);
+  return ds_steal_cstr (&s);
+}
+
 static char *
 show_SUBTITLE (const struct dataset *ds UNUSED)
 {
@@ -1271,6 +1308,7 @@ static const struct setting settings[] = {
   { "SCOMPRESSION", parse_SCOMPRESSION, show_SCOMPRESSION },
   { "SEED", parse_SEED, NULL },
   { "SMALL", parse_SMALL, show_SMALL },
+  { "SPLIT", NULL, show_SPLIT },
   { "TEMPDIR", NULL, show_TEMPDIR },
   { "TNUMBERS", parse_TNUMBERS, show_TNUMBERS },
   { "TVARS", parse_TVARS, show_TVARS },
index efdf3dcfd312056189498046084b8293b56c4e1c..a66671278b6ef2057d70d4337e7e87415beac750 100644 (file)
@@ -145,3 +145,76 @@ specified.
       |               ^~~~~~~~
 ])
 AT_CLEANUP
+
+AT_SETUP([SPLIT FILE - SHOW SPLIT and SPLIT FILE OFF])
+AT_DATA([show.sps], [dnl
+SET PRINTBACK=ON.
+
+SHOW SPLIT.
+
+DATA LIST LIST NOTABLE/x y z.
+SPLIT FILE BY x y.
+SHOW SPLIT.
+
+SPLIT FILE LAYERED BY y z.
+SHOW SPLIT.
+
+SPLIT FILE SEPARATE BY x z.
+SHOW SPLIT.
+
+SPLIT FILE OFF.
+SHOW SPLIT.
+])
+AT_CHECK([pspp show.sps -O box=unicode], [0], [dnl
+SET PRINTBACK=ON.
+
+SHOW SPLIT.
+
+  Settings
+╭─────┬────╮
+│SPLIT│none│
+╰─────┴────╯
+
+
+DATA LIST LIST NOTABLE/x y z.
+
+SPLIT FILE BY x y.
+
+SHOW SPLIT.
+
+       Settings
+╭─────┬──────────────╮
+│SPLIT│x, y (LAYERED)│
+╰─────┴──────────────╯
+
+
+SPLIT FILE LAYERED BY y z.
+
+SHOW SPLIT.
+
+       Settings
+╭─────┬──────────────╮
+│SPLIT│y, z (LAYERED)│
+╰─────┴──────────────╯
+
+
+SPLIT FILE SEPARATE BY x z.
+
+SHOW SPLIT.
+
+        Settings
+╭─────┬───────────────╮
+│SPLIT│x, z (SEPARATE)│
+╰─────┴───────────────╯
+
+
+SPLIT FILE OFF.
+
+SHOW SPLIT.
+
+  Settings
+╭─────┬────╮
+│SPLIT│none│
+╰─────┴────╯
+])
+AT_CLEANUP
\ No newline at end of file