+static bool
+ctables_check_label_position (struct ctables_table *t,
+ enum pivot_axis_type axis,
+ enum ctables_label_position label_pos,
+ const char *subcommand_name)
+{
+ if (label_pos == CTLP_NORMAL)
+ return true;
+
+ const struct ctables_stack *stack = &t->stacks[axis];
+ if (!stack->n)
+ return true;
+
+ const struct ctables_nest *n0 = &stack->nests[0];
+ const struct variable *v0 = n0->vars[n0->n - 1];
+ struct ctables_categories *c0 = t->categories[var_get_dict_index (v0)];
+
+ for (size_t i = 0; i < c0->n_cats; i++)
+ if (c0->cats[i].type == CCT_FUNCTION)
+ {
+ msg (SE, _("%s=%s is not allowed with sorting based "
+ "on a summary function."),
+ subcommand_name, ctables_label_position_to_string (label_pos));
+ return false;
+ }
+
+ for (size_t i = 1; i < stack->n; i++)
+ {
+ const struct ctables_nest *ni = &stack->nests[i];
+ const struct variable *vi = ni->vars[ni->n - 1];
+ struct ctables_categories *ci = t->categories[var_get_dict_index (vi)];
+
+ if (var_get_width (v0) != var_get_width (vi))
+ {
+ msg (SE, _("%s=%s requires the variables to be "
+ "moved to have the same width, but %s has "
+ "width %d and %s has width %d."),
+ subcommand_name, ctables_label_position_to_string (label_pos),
+ var_get_name (v0), var_get_width (v0),
+ var_get_name (vi), var_get_width (vi));
+ return false;
+ }
+ if (!val_labs_equal (var_get_value_labels (v0),
+ var_get_value_labels (vi)))
+ {
+ msg (SE, _("%s=%s requires the variables to be "
+ "moved to have the same value labels, but %s "
+ "and %s have different value labels."),
+ subcommand_name, ctables_label_position_to_string (label_pos),
+ var_get_name (v0), var_get_name (vi));
+ return false;
+ }
+ if (!ctables_categories_equal (c0, ci))
+ {
+ msg (SE, _("%s=%s requires the variables to be "
+ "moved to have the same category "
+ "specifications, but %s and %s have different "
+ "category specifications."),
+ subcommand_name, ctables_label_position_to_string (label_pos),
+ var_get_name (v0), var_get_name (vi));
+ return false;
+ }
+ }
+
+ return true;
+}
+