+
+ {
+ struct casegrouper *grouper;
+ struct casereader *group;
+ bool ok;
+
+ grouper = casegrouper_create_splits (proc_open (ds), means.dict);
+ while (casegrouper_get_next_group (grouper, &group))
+ {
+ /* Allocate the workspaces. */
+ for (int t = 0; t < means.n_tables; ++t)
+ {
+ struct mtable *mt = means.table + t;
+ mt->summ = xcalloc (mt->n_combinations * mt->n_dep_vars,
+ sizeof (*mt->summ));
+ mt->ws = xcalloc (mt->n_combinations, sizeof (*mt->ws));
+ }
+ run_means (&means, group, ds);
+ for (int t = 0; t < means.n_tables; ++t)
+ {
+ const struct mtable *mt = means.table + t;
+
+ means_case_processing_summary (mt);
+ means_shipout (mt, &means);
+
+ for (int i = 0; i < mt->n_combinations; ++i)
+ {
+ struct workspace *ws = mt->ws + i;
+ if (ws->root_cell == NULL)
+ continue;
+
+ means_destroy_cells (&means, ws->root_cell, mt);
+ }
+ }
+
+ /* Destroy the workspaces. */
+ for (int t = 0; t < means.n_tables; ++t)
+ {
+ struct mtable *mt = means.table + t;
+ free (mt->summ);
+ for (int i = 0; i < mt->n_combinations; ++i)
+ {
+ struct workspace *ws = mt->ws + i;
+ destroy_workspace (mt, ws);
+ }
+ free (mt->ws);
+ }
+ }
+ ok = casegrouper_destroy (grouper);
+ ok = proc_commit (ds) && ok;
+ }
+
+ pool_destroy (means.pool);
+ return CMD_SUCCESS;
+
+ error:
+
+ pool_destroy (means.pool);
+ return CMD_FAILURE;