68239b85b9685f7495ca8a8c39f2038e82066126
[pspp] / src / language / stats / ctables.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2021 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <math.h>
20 #include <errno.h>
21
22 #include "data/casereader.h"
23 #include "data/casewriter.h"
24 #include "data/data-out.h"
25 #include "data/dataset.h"
26 #include "data/dictionary.h"
27 #include "data/mrset.h"
28 #include "data/subcase.h"
29 #include "data/value-labels.h"
30 #include "language/command.h"
31 #include "language/lexer/format-parser.h"
32 #include "language/lexer/lexer.h"
33 #include "language/lexer/variable-parser.h"
34 #include "libpspp/array.h"
35 #include "libpspp/assertion.h"
36 #include "libpspp/hash-functions.h"
37 #include "libpspp/hmap.h"
38 #include "libpspp/i18n.h"
39 #include "libpspp/message.h"
40 #include "libpspp/string-array.h"
41 #include "math/mode.h"
42 #include "math/moments.h"
43 #include "math/percentiles.h"
44 #include "math/sort.h"
45 #include "output/pivot-table.h"
46
47 #include "gl/minmax.h"
48 #include "gl/xalloc.h"
49
50 #include "gettext.h"
51 #define _(msgid) gettext (msgid)
52 #define N_(msgid) (msgid)
53
54 enum ctables_vlabel
55   {
56     CTVL_NONE = SETTINGS_VALUE_SHOW_DEFAULT,
57     CTVL_NAME = SETTINGS_VALUE_SHOW_VALUE,
58     CTVL_LABEL = SETTINGS_VALUE_SHOW_LABEL,
59     CTVL_BOTH = SETTINGS_VALUE_SHOW_BOTH,
60   };
61
62 /* XXX:
63    - unweighted summaries (U*)
64    - lower confidence limits (*.LCL)
65    - upper confidence limits (*.UCL)
66    - standard error (*.SE)
67  */
68 #define SUMMARIES                                                       \
69     /* All variables. */                                                \
70     S(CTSF_COUNT, "COUNT", N_("Count"), CTF_COUNT, CTFA_ALL)            \
71     S(CTSF_ECOUNT, "ECOUNT", N_("Adjusted Count"), CTF_COUNT, CTFA_ALL) \
72     S(CTSF_ROWPCT_COUNT, "ROWPCT.COUNT", N_("Row %"), CTF_PERCENT, CTFA_ALL) \
73     S(CTSF_COLPCT_COUNT, "COLPCT.COUNT", N_("Column %"), CTF_PERCENT, CTFA_ALL) \
74     S(CTSF_TABLEPCT_COUNT, "TABLEPCT.COUNT", N_("Table %"), CTF_PERCENT, CTFA_ALL) \
75     S(CTSF_SUBTABLEPCT_COUNT, "SUBTABLEPCT.COUNT", N_("Subtable %"), CTF_PERCENT, CTFA_ALL) \
76     S(CTSF_LAYERPCT_COUNT, "LAYERPCT.COUNT", N_("Layer %"), CTF_PERCENT, CTFA_ALL) \
77     S(CTSF_LAYERROWPCT_COUNT, "LAYERROWPCT.COUNT", N_("Layer Row %"), CTF_PERCENT, CTFA_ALL) \
78     S(CTSF_LAYERCOLPCT_COUNT, "LAYERCOLPCT.COUNT", N_("Layer Column %"), CTF_PERCENT, CTFA_ALL) \
79     S(CTSF_ROWPCT_VALIDN, "ROWPCT.VALIDN", N_("Row Valid N %"), CTF_PERCENT, CTFA_ALL) \
80     S(CTSF_COLPCT_VALIDN, "COLPCT.VALIDN", N_("Column Valid N %"), CTF_PERCENT, CTFA_ALL) \
81     S(CTSF_TABLEPCT_VALIDN, "TABLEPCT.VALIDN", N_("Table Valid N %"), CTF_PERCENT, CTFA_ALL) \
82     S(CTSF_SUBTABLEPCT_VALIDN, "SUBTABLEPCT.VALIDN", N_("Subtable Valid N %"), CTF_PERCENT, CTFA_ALL) \
83     S(CTSF_LAYERPCT_VALIDN, "LAYERPCT.VALIDN", N_("Layer Valid N %"), CTF_PERCENT, CTFA_ALL) \
84     S(CTSF_LAYERROWPCT_VALIDN, "LAYERROWPCT.VALIDN", N_("Layer Row Valid N %"), CTF_PERCENT, CTFA_ALL) \
85     S(CTSF_LAYERCOLPCT_VALIDN, "LAYERCOLPCT.VALIDN", N_("Layer Column Valid N %"), CTF_PERCENT, CTFA_ALL) \
86     S(CTSF_ROWPCT_TOTALN, "ROWPCT.TOTALN", N_("Row Total N %"), CTF_PERCENT, CTFA_ALL) \
87     S(CTSF_COLPCT_TOTALN, "COLPCT.TOTALN", N_("Column Total N %"), CTF_PERCENT, CTFA_ALL) \
88     S(CTSF_TABLEPCT_TOTALN, "TABLEPCT.TOTALN", N_("Table Total N %"), CTF_PERCENT, CTFA_ALL) \
89     S(CTSF_SUBTABLEPCT_TOTALN, "SUBTABLEPCT.TOTALN", N_("Subtable Total N %"), CTF_PERCENT, CTFA_ALL) \
90     S(CTSF_LAYERPCT_TOTALN, "LAYERPCT.TOTALN", N_("Layer Total N %"), CTF_PERCENT, CTFA_ALL) \
91     S(CTSF_LAYERROWPCT_TOTALN, "LAYERROWPCT.TOTALN", N_("Layer Row Total N %"), CTF_PERCENT, CTFA_ALL) \
92     S(CTSF_LAYERCOLPCT_TOTALN, "LAYERCOLPCT.TOTALN", N_("Layer Column Total N %"), CTF_PERCENT, CTFA_ALL) \
93                                                                         \
94     /* Scale variables, totals, and subtotals. */                       \
95     S(CTSF_MAXIMUM, "MAXIMUM", N_("Maximum"), CTF_GENERAL, CTFA_SCALE)  \
96     S(CTSF_MEAN, "MEAN", N_("Mean"), CTF_GENERAL, CTFA_SCALE)           \
97     S(CTSF_MEDIAN, "MEDIAN", N_("Median"), CTF_GENERAL, CTFA_SCALE)     \
98     S(CTSF_MINIMUM, "MINIMUM", N_("Minimum"), CTF_GENERAL, CTFA_SCALE)  \
99     S(CTSF_MISSING, "MISSING", N_("Missing"), CTF_GENERAL, CTFA_SCALE)  \
100     S(CTSF_MODE, "MODE", N_("Mode"), CTF_GENERAL, CTFA_SCALE)           \
101     S(CTSF_PTILE, "PTILE", N_("Percentile"), CTF_GENERAL, CTFA_SCALE)   \
102     S(CTSF_RANGE, "RANGE", N_("Range"), CTF_GENERAL, CTFA_SCALE)        \
103     S(CTSF_SEMEAN, "SEMEAN", N_("Std Error of Mean"), CTF_GENERAL, CTFA_SCALE) \
104     S(CTSF_STDDEV, "STDDEV", N_("Std Deviation"), CTF_GENERAL, CTFA_SCALE) \
105     S(CTSF_SUM, "SUM", N_("Sum"), CTF_GENERAL, CTFA_SCALE)              \
106     S(CSTF_TOTALN, "TOTALN", N_("Total N"), CTF_COUNT, CTFA_SCALE)      \
107     S(CTSF_ETOTALN, "ETOTALN", N_("Adjusted Total N"), CTF_COUNT, CTFA_SCALE) \
108     S(CTSF_VALIDN, "VALIDN", N_("Valid N"), CTF_COUNT, CTFA_SCALE)      \
109     S(CTSF_EVALIDN, "EVALIDN", N_("Adjusted Valid N"), CTF_COUNT, CTFA_SCALE) \
110     S(CTSF_VARIANCE, "VARIANCE", N_("Variance"), CTF_GENERAL, CTFA_SCALE) \
111     S(CTSF_ROWPCT_SUM, "ROWPCT.SUM", N_("Row Sum %"), CTF_PERCENT, CTFA_SCALE) \
112     S(CTSF_COLPCT_SUM, "COLPCT.SUM", N_("Column Sum %"), CTF_PERCENT, CTFA_SCALE) \
113     S(CTSF_TABLEPCT_SUM, "TABLEPCT.SUM", N_("Table Sum %"), CTF_PERCENT, CTFA_SCALE) \
114     S(CTSF_SUBTABLEPCT_SUM, "SUBTABLEPCT.SUM", N_("Subtable Sum %"), CTF_PERCENT, CTFA_SCALE) \
115     S(CTSF_LAYERPCT_SUM, "LAYERPCT.SUM", N_("Layer Sum %"), CTF_PERCENT, CTFA_SCALE) \
116     S(CTSF_LAYERROWPCT_SUM, "LAYERROWPCT.SUM", N_("Layer Row Sum %"), CTF_PERCENT, CTFA_SCALE) \
117     S(CTSF_LAYERCOLPCT_SUM, "LAYERCOLPCT.SUM", N_("Layer Column Sum %"), CTF_PERCENT, CTFA_SCALE) \
118
119 #if 0         /* Multiple response sets not yet implemented. */
120   S(CTSF_RESPONSES, "RESPONSES", N_("Responses"), CTF_COUNT, CTFA_MRSETS) \
121     S(CTSF_ROWPCT_RESPONSES, "ROWPCT.RESPONSES", N_("Row Responses %"), CTF_PERCENT, CTFA_MRSETS) \
122     S(CTSF_COLPCT_RESPONSES, "COLPCT.RESPONSES", N_("Column Responses %"), CTF_PERCENT, CTFA_MRSETS) \
123     S(CTSF_TABLEPCT_RESPONSES, "TABLEPCT.RESPONSES", N_("Table Responses %"), CTF_PERCENT, CTFA_MRSETS) \
124     S(CTSF_SUBTABLEPCT_RESPONSES, "SUBTABLEPCT.RESPONSES", N_("Subtable Responses %"), CTF_PERCENT, CTFA_MRSETS) \
125     S(CTSF_LAYERPCT_RESPONSES, "LAYERPCT.RESPONSES", N_("Layer Responses %"), CTF_PERCENT, CTFA_MRSETS) \
126     S(CTSF_LAYERROWPCT_RESPONSES, "LAYERROWPCT.RESPONSES", N_("Layer Row Responses %"), CTF_PERCENT, CTFA_MRSETS) \
127     S(CTSF_LAYERCOLPCT_RESPONSES, "LAYERCOLPCT.RESPONSES", N_("Layer Column Responses %"), CTF_PERCENT, CTFA_MRSETS) \
128     S(CTSF_ROWPCT_RESPONSES_COUNT, "ROWPCT.RESPONSES.COUNT", N_("Row Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) \
129     S(CTSF_COLPCT_RESPONSES_COUNT, "COLPCT.RESPONSES.COUNT", N_("Column Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) \
130     S(CTSF_TABLEPCT_RESPONSES_COUNT, "TABLEPCT.RESPONSES.COUNT", N_("Table Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) \
131     S(CTSF_SUBTABLEPCT_RESPONSES_COUNT, "SUBTABLEPCT.RESPONSES.COUNT", N_("Subtable Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) \
132     S(CTSF_LAYERPCT_RESPONSES_COUNT, "LAYERPCT.RESPONSES.COUNT", N_("Layer Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) \
133     S(CTSF_LAYERROWPCT_RESPONSES_COUNT, "LAYERROWPCT.RESPONSES.COUNT", N_("Layer Row Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) \
134     S(CTSF_LAYERCOLPCT_RESPONSES_COUNT, "LAYERCOLPCT.RESPONSES.COUNT", N_("Layer Column Responses % (Base: Count)"), CTF_PERCENT, CTFA_MRSETS) \
135     S(CTSF_ROWPCT_COUNT_RESPONSES, "ROWPCT.COUNT.RESPONSES", N_("Row Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) \
136     S(CTSF_COLPCT_COUNT_RESPONSES, "COLPCT.COUNT.RESPONSES", N_("Column Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) \
137     S(CTSF_TABLEPCT_COUNT_RESPONSES, "TABLEPCT.COUNT.RESPONSES", N_("Table Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) \
138     S(CTSF_SUBTABLEPCT_COUNT_RESPONSES, "SUBTABLEPCT.COUNT.RESPONSES", N_("Subtable Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) \
139     S(CTSF_LAYERPCT_COUNT_RESPONSES, "LAYERPCT.COUNT.RESPONSES", N_("Layer Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) \
140     S(CTSF_LAYERROWPCT_COUNT_RESPONSES, "LAYERROWPCT.COUNT.RESPONSES", N_("Layer Row Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS) \
141     S(CTSF_LAYERCOLPCT_COUNT_RESPONSES, "LAYERCOLPCT.RESPONSES.COUNT", N_("Layer Column Count % (Base: Responses)"), CTF_PERCENT, CTFA_MRSETS)
142 #endif
143
144 enum ctables_summary_function
145   {
146 #define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) ENUM,
147     SUMMARIES
148 #undef S
149   };
150
151 enum {
152 #define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) +1
153   N_CTSF_FUNCTIONS = SUMMARIES
154 #undef S
155 };
156
157 static bool ctables_summary_function_is_count (enum ctables_summary_function);
158
159 enum ctables_domain_type
160   {
161     /* Within a section, where stacked variables divide one section from
162        another. */
163     CTDT_TABLE,                  /* All layers of a whole section. */
164     CTDT_LAYER,                  /* One layer within a section. */
165     CTDT_LAYERROW,               /* Row in one layer within a section. */
166     CTDT_LAYERCOL,               /* Column in one layer within a section. */
167
168     /* Within a subtable, where a subtable pairs an innermost row variable with
169        an innermost column variable within a single layer.  */
170     CTDT_SUBTABLE,               /* Whole subtable. */
171     CTDT_ROW,                    /* Row within a subtable. */
172     CTDT_COL,                    /* Column within a subtable. */
173 #define N_CTDTS 7
174   };
175
176 struct ctables_domain
177   {
178     struct hmap_node node;
179
180     const struct ctables_cell *example;
181
182     double d_valid;             /* Dictionary weight. */
183     double d_count;
184     double d_total;
185     double e_valid;             /* Effective weight */
186     double e_count;
187     double e_total;
188   };
189
190 enum ctables_summary_variant
191   {
192     CSV_CELL,
193     CSV_TOTAL
194 #define N_CSVS 2
195   };
196
197 struct ctables_cell
198   {
199     /* In struct ctables_section's 'cells' hmap.  Indexed by all the values in
200        all the axes (except the scalar variable, if any). */
201     struct hmap_node node;
202
203     /* The domains that contain this cell. */
204     uint32_t omit_domains;
205     struct ctables_domain *domains[N_CTDTS];
206
207     bool hide;
208
209     bool postcompute;
210     enum ctables_summary_variant sv;
211
212     struct ctables_cell_axis
213       {
214         struct ctables_cell_value
215           {
216             const struct ctables_category *category;
217             union value value;
218           }
219         *cvs;
220         int leaf;
221       }
222     axes[PIVOT_N_AXES];
223
224     union ctables_summary *summaries;
225
226     //char *name;
227   };
228
229 struct ctables
230   {
231     const struct dictionary *dict;
232     struct pivot_table_look *look;
233
234     /* CTABLES has a number of extra formats that we implement via custom
235        currency specifications on an alternate fmt_settings. */
236 #define CTEF_NEGPAREN FMT_CCA
237 #define CTEF_NEQUAL   FMT_CCB
238 #define CTEF_PAREN    FMT_CCC
239 #define CTEF_PCTPAREN FMT_CCD
240     struct fmt_settings ctables_formats;
241
242     /* If this is NULL, zeros are displayed using the normal print format.
243        Otherwise, this string is displayed. */
244     char *zero;
245
246     /* If this is NULL, missing values are displayed using the normal print
247        format.  Otherwise, this string is displayed. */
248     char *missing;
249
250     /* Indexed by variable dictionary index. */
251     enum ctables_vlabel *vlabels;
252
253     struct hmap postcomputes;   /* Contains "struct ctables_postcompute"s. */
254
255     bool mrsets_count_duplicates; /* MRSETS. */
256     bool smissing_listwise;       /* SMISSING. */
257     struct variable *e_weight;    /* WEIGHT. */
258     int hide_threshold;           /* HIDESMALLCOUNTS. */
259
260     struct ctables_table **tables;
261     size_t n_tables;
262   };
263
264 static struct ctables_postcompute *ctables_find_postcompute (struct ctables *,
265                                                              const char *name);
266
267 struct ctables_postcompute
268   {
269     struct hmap_node hmap_node; /* In struct ctables's 'pcompute' hmap. */
270     char *name;                 /* Name, without leading &. */
271
272     struct msg_location *location; /* Location of definition. */
273     struct ctables_pcexpr *expr;
274     char *label;
275     struct ctables_summary_spec_set *specs;
276     bool hide_source_cats;
277   };
278
279 struct ctables_pcexpr
280   {
281     /* Precedence table:
282
283        ()
284        **
285        -
286        * /
287        - +
288     */
289     enum ctables_postcompute_op
290       {
291         /* Terminals. */
292         CTPO_CONSTANT,          /* 5 */
293         CTPO_CAT_NUMBER,        /* [5] */
294         CTPO_CAT_STRING,        /* ["STRING"] */
295         CTPO_CAT_RANGE,         /* [LO THRU 5] */
296         CTPO_CAT_MISSING,       /* MISSING */
297         CTPO_CAT_OTHERNM,       /* OTHERNM */
298         CTPO_CAT_SUBTOTAL,      /* SUBTOTAL */
299         CTPO_CAT_TOTAL,         /* TOTAL */
300
301         /* Nonterminals. */
302         CTPO_ADD,
303         CTPO_SUB,
304         CTPO_MUL,
305         CTPO_DIV,
306         CTPO_POW,
307         CTPO_NEG,
308       }
309     op;
310
311     union
312       {
313         /* CTPO_CAT_NUMBER. */
314         double number;
315
316         /* CTPO_CAT_STRING. */
317         char *string;
318
319         /* CTPO_CAT_RANGE. */
320         double range[2];
321
322         /* CTPO_CAT_SUBTOTAL. */
323         size_t subtotal_index;
324
325         /* Two elements: CTPO_ADD, CTPO_SUB, CTPO_MUL, CTPO_DIV, CTPO_POW.
326            One element: CTPO_NEG. */
327         struct ctables_pcexpr *subs[2];
328       };
329
330     /* Source location. */
331     struct msg_location *location;
332   };
333
334 static void ctables_pcexpr_destroy (struct ctables_pcexpr *);
335 static struct ctables_pcexpr *ctables_pcexpr_allocate_binary (
336   enum ctables_postcompute_op, struct ctables_pcexpr *sub0,
337   struct ctables_pcexpr *sub1);
338
339 struct ctables_summary_spec_set
340   {
341     struct ctables_summary_spec *specs;
342     size_t n;
343     size_t allocated;
344
345     /* The variable to which the summary specs are applied. */
346     struct variable *var;
347
348     /* Whether the variable to which the summary specs are applied is a scale
349        variable for the purpose of summarization.
350
351        (VALIDN and TOTALN act differently for summarizing scale and categorical
352        variables.) */
353     bool is_scale;
354
355     /* If any of these optional additional scale variables are missing, then
356        treat 'var' as if it's missing too.  This is for implementing
357        SMISSING=LISTWISE. */
358     struct variable **listwise_vars;
359     size_t n_listwise_vars;
360   };
361
362 static void ctables_summary_spec_set_clone (struct ctables_summary_spec_set *,
363                                             const struct ctables_summary_spec_set *);
364 static void ctables_summary_spec_set_uninit (struct ctables_summary_spec_set *);
365
366 /* A nested sequence of variables, e.g. a > b > c. */
367 struct ctables_nest
368   {
369     struct variable **vars;
370     size_t n;
371     size_t scale_idx;
372     size_t *domains[N_CTDTS];
373     size_t n_domains[N_CTDTS];
374     size_t group_head;
375
376     struct ctables_summary_spec_set specs[N_CSVS];
377   };
378
379 /* A stack of nestings, e.g. nest1 + nest2 + ... + nestN. */
380 struct ctables_stack
381   {
382     struct ctables_nest *nests;
383     size_t n;
384   };
385
386 struct ctables_value
387   {
388     struct hmap_node node;
389     union value value;
390     int leaf;
391   };
392
393 struct ctables_occurrence
394   {
395     struct hmap_node node;
396     union value value;
397   };
398
399 struct ctables_section
400   {
401     struct ctables_table *table;
402     struct ctables_nest *nests[PIVOT_N_AXES];
403     struct hmap *occurrences[PIVOT_N_AXES];
404     struct hmap cells;            /* Contains "struct ctable_cell"s. */
405     struct hmap domains[N_CTDTS]; /* Contains "struct ctable_domain"s. */
406   };
407
408 struct ctables_table
409   {
410     struct ctables *ctables;
411     struct ctables_axis *axes[PIVOT_N_AXES];
412     struct ctables_stack stacks[PIVOT_N_AXES];
413     struct ctables_section *sections;
414     size_t n_sections;
415     enum pivot_axis_type summary_axis;
416     struct ctables_summary_spec_set summary_specs;
417
418     const struct variable *clabels_example;
419     struct hmap clabels_values_map;
420     struct ctables_value **clabels_values;
421     size_t n_clabels_values;
422
423     enum pivot_axis_type slabels_axis;
424     bool slabels_visible;
425
426     /* The innermost category labels for axis 'a' appear on axis label_axis[a].
427
428        Most commonly, label_axis[a] == a, and in particular we always have
429        label_axis{PIVOT_AXIS_LAYER] == PIVOT_AXIS_LAYER.
430
431        If ROWLABELS or COLLABELS is specified, then one of
432        label_axis[PIVOT_AXIS_ROW] or label_axis[PIVOT_AXIS_COLUMN] can be the
433        opposite axis or PIVOT_AXIS_LAYER.  Only one of them will differ.
434     */
435     enum pivot_axis_type label_axis[PIVOT_N_AXES];
436     enum pivot_axis_type clabels_from_axis;
437
438     /* Indexed by variable dictionary index. */
439     struct ctables_categories **categories;
440     size_t n_categories;
441
442     double cilevel;
443
444     char *caption;
445     char *corner;
446     char *title;
447
448     struct ctables_chisq *chisq;
449     struct ctables_pairwise *pairwise;
450   };
451
452 struct ctables_categories
453   {
454     size_t n_refs;
455     struct ctables_category *cats;
456     size_t n_cats;
457     bool show_empty;
458   };
459
460 struct ctables_category
461   {
462     enum ctables_category_type
463       {
464         /* Explicit category lists. */
465         CCT_NUMBER,
466         CCT_STRING,
467         CCT_RANGE,
468         CCT_MISSING,
469         CCT_OTHERNM,
470         CCT_POSTCOMPUTE,
471
472         /* Totals and subtotals. */
473         CCT_SUBTOTAL,
474         CCT_TOTAL,
475
476         /* Implicit category lists. */
477         CCT_VALUE,
478         CCT_LABEL,
479         CCT_FUNCTION,
480
481         /* For contributing to TOTALN. */
482         CCT_EXCLUDED_MISSING,
483       }
484     type;
485
486     struct ctables_category *subtotal;
487
488     bool hide;
489
490     union
491       {
492         double number;          /* CCT_NUMBER. */
493         char *string;           /* CCT_STRING.  In dictionary encoding. */
494         double range[2];        /* CCT_RANGE. */
495
496         struct
497           {
498             char *total_label;      /* CCT_SUBTOTAL, CCT_TOTAL. */
499             bool hide_subcategories; /* CCT_SUBTOTAL. */
500           };
501
502         const struct ctables_postcompute *pc; /* CCT_POSTCOMPUTE. */
503
504         /* CCT_VALUE, CCT_LABEL, CCT_FUNCTION. */
505         struct
506           {
507             bool include_missing;
508             bool sort_ascending;
509
510             /* CCT_FUNCTION. */
511             enum ctables_summary_function sort_function;
512             struct variable *sort_var;
513             double percentile;
514           };
515       };
516
517     /* Source location.  This is null for CCT_TOTAL, CCT_VALUE, CCT_LABEL,
518        CCT_FUNCTION, CCT_EXCLUDED_MISSING. */
519     struct msg_location *location;
520   };
521
522 static void
523 ctables_category_uninit (struct ctables_category *cat)
524 {
525   if (!cat)
526     return;
527
528   switch (cat->type)
529     {
530     case CCT_NUMBER:
531     case CCT_RANGE:
532     case CCT_MISSING:
533     case CCT_OTHERNM:
534     case CCT_POSTCOMPUTE:
535       break;
536
537     case CCT_STRING:
538       free (cat->string);
539       break;
540
541     case CCT_SUBTOTAL:
542     case CCT_TOTAL:
543       free (cat->total_label);
544       break;
545
546     case CCT_VALUE:
547     case CCT_LABEL:
548     case CCT_FUNCTION:
549       break;
550
551     case CCT_EXCLUDED_MISSING:
552       break;
553     }
554 }
555
556 static bool
557 ctables_category_equal (const struct ctables_category *a,
558                         const struct ctables_category *b)
559 {
560   if (a->type != b->type)
561     return false;
562
563   switch (a->type)
564     {
565     case CCT_NUMBER:
566       return a->number == b->number;
567
568     case CCT_STRING:
569       return strcmp (a->string, b->string);
570
571     case CCT_RANGE:
572       return a->range[0] == b->range[0] && a->range[1] == b->range[1];
573
574     case CCT_MISSING:
575     case CCT_OTHERNM:
576       return true;
577
578     case CCT_POSTCOMPUTE:
579       return a->pc == b->pc;
580
581     case CCT_SUBTOTAL:
582     case CCT_TOTAL:
583       return !strcmp (a->total_label, b->total_label);
584
585     case CCT_VALUE:
586     case CCT_LABEL:
587     case CCT_FUNCTION:
588       return (a->include_missing == b->include_missing
589               && a->sort_ascending == b->sort_ascending
590               && a->sort_function == b->sort_function
591               && a->sort_var == b->sort_var
592               && a->percentile == b->percentile);
593
594     case CCT_EXCLUDED_MISSING:
595       return true;
596     }
597
598   NOT_REACHED ();
599 }
600
601 static void
602 ctables_categories_unref (struct ctables_categories *c)
603 {
604   if (!c)
605     return;
606
607   assert (c->n_refs > 0);
608   if (--c->n_refs)
609     return;
610
611   for (size_t i = 0; i < c->n_cats; i++)
612     ctables_category_uninit (&c->cats[i]);
613   free (c->cats);
614   free (c);
615 }
616
617 static bool
618 ctables_categories_equal (const struct ctables_categories *a,
619                           const struct ctables_categories *b)
620 {
621   if (a->n_cats != b->n_cats || a->show_empty != b->show_empty)
622     return false;
623
624   for (size_t i = 0; i < a->n_cats; i++)
625     if (!ctables_category_equal (&a->cats[i], &b->cats[i]))
626       return false;
627
628   return true;
629 }
630
631 /* Chi-square test (SIGTEST). */
632 struct ctables_chisq
633   {
634     double alpha;
635     bool include_mrsets;
636     bool all_visible;
637   };
638
639 /* Pairwise comparison test (COMPARETEST). */
640 struct ctables_pairwise
641   {
642     enum { PROP, MEAN } type;
643     double alpha[2];
644     bool include_mrsets;
645     bool meansvariance_allcats;
646     bool all_visible;
647     enum { BONFERRONI = 1, BH } adjust;
648     bool merge;
649     bool apa_style;
650     bool show_sig;
651   };
652
653 struct ctables_axis
654   {
655     enum ctables_axis_op
656       {
657         /* Terminals. */
658         CTAO_VAR,
659
660         /* Nonterminals. */
661         CTAO_STACK,             /* + */
662         CTAO_NEST,              /* > */
663       }
664     op;
665
666     union
667       {
668         /* Terminals. */
669         struct
670           {
671             struct variable *var;
672             bool scale;
673             struct ctables_summary_spec_set specs[N_CSVS];
674           };
675
676         /* Nonterminals. */
677         struct ctables_axis *subs[2];
678       };
679
680     struct msg_location *loc;
681   };
682
683 static void ctables_axis_destroy (struct ctables_axis *);
684
685 enum ctables_format
686   {
687     CTF_COUNT,
688     CTF_PERCENT,
689     CTF_GENERAL
690   };
691
692 enum ctables_function_availability
693   {
694     CTFA_ALL,                /* Any variables. */
695     CTFA_SCALE,              /* Only scale variables, totals, and subtotals. */
696     CTFA_MRSETS,             /* Only multiple-response sets */
697   };
698
699 struct ctables_summary_spec
700   {
701     enum ctables_summary_function function;
702     double percentile;          /* CTSF_PTILE only. */
703     char *label;
704
705     struct fmt_spec format;
706     bool is_ctables_format;       /* Is 'format' one of CTEF_*? */
707
708     size_t axis_idx;
709   };
710
711 static void
712 ctables_summary_spec_clone (struct ctables_summary_spec *dst,
713                             const struct ctables_summary_spec *src)
714 {
715   *dst = *src;
716   dst->label = xstrdup (src->label);
717 }
718
719 static void
720 ctables_summary_spec_uninit (struct ctables_summary_spec *s)
721 {
722   if (s)
723     free (s->label);
724 }
725
726 static void
727 ctables_summary_spec_set_clone (struct ctables_summary_spec_set *dst,
728                                 const struct ctables_summary_spec_set *src)
729 {
730   struct ctables_summary_spec *specs = xnmalloc (src->n, sizeof *specs);
731   for (size_t i = 0; i < src->n; i++)
732     ctables_summary_spec_clone (&specs[i], &src->specs[i]);
733
734   *dst = (struct ctables_summary_spec_set) {
735     .specs = specs,
736     .n = src->n,
737     .allocated = src->n,
738     .var = src->var,
739     .is_scale = src->is_scale,
740   };
741 }
742
743 static void
744 ctables_summary_spec_set_uninit (struct ctables_summary_spec_set *set)
745 {
746   for (size_t i = 0; i < set->n; i++)
747     ctables_summary_spec_uninit (&set->specs[i]);
748   free (set->specs);
749 }
750
751 static bool
752 parse_col_width (struct lexer *lexer, const char *name, double *width)
753 {
754   lex_match (lexer, T_EQUALS);
755   if (lex_match_id (lexer, "DEFAULT"))
756     *width = SYSMIS;
757   else if (lex_force_num_range_closed (lexer, name, 0, DBL_MAX))
758     {
759       *width = lex_number (lexer);
760       lex_get (lexer);
761     }
762   else
763     return false;
764
765   return true;
766 }
767
768 static bool
769 parse_bool (struct lexer *lexer, bool *b)
770 {
771   if (lex_match_id (lexer, "NO"))
772     *b = false;
773   else if (lex_match_id (lexer, "YES"))
774     *b = true;
775   else
776     {
777       lex_error_expecting (lexer, "YES", "NO");
778       return false;
779     }
780   return true;
781 }
782
783 static enum ctables_function_availability
784 ctables_function_availability (enum ctables_summary_function f)
785 {
786   static enum ctables_function_availability availability[] = {
787 #define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = AVAILABILITY,
788     SUMMARIES
789 #undef S
790   };
791
792   return availability[f];
793 }
794
795 static bool
796 ctables_summary_function_is_count (enum ctables_summary_function f)
797 {
798   switch (f)
799     {
800     case CTSF_COUNT:
801     case CTSF_ECOUNT:
802     case CTSF_ROWPCT_COUNT:
803     case CTSF_COLPCT_COUNT:
804     case CTSF_TABLEPCT_COUNT:
805     case CTSF_SUBTABLEPCT_COUNT:
806     case CTSF_LAYERPCT_COUNT:
807     case CTSF_LAYERROWPCT_COUNT:
808     case CTSF_LAYERCOLPCT_COUNT:
809       return true;
810
811     case CTSF_ROWPCT_VALIDN:
812     case CTSF_COLPCT_VALIDN:
813     case CTSF_TABLEPCT_VALIDN:
814     case CTSF_SUBTABLEPCT_VALIDN:
815     case CTSF_LAYERPCT_VALIDN:
816     case CTSF_LAYERROWPCT_VALIDN:
817     case CTSF_LAYERCOLPCT_VALIDN:
818     case CTSF_ROWPCT_TOTALN:
819     case CTSF_COLPCT_TOTALN:
820     case CTSF_TABLEPCT_TOTALN:
821     case CTSF_SUBTABLEPCT_TOTALN:
822     case CTSF_LAYERPCT_TOTALN:
823     case CTSF_LAYERROWPCT_TOTALN:
824     case CTSF_LAYERCOLPCT_TOTALN:
825     case CTSF_MAXIMUM:
826     case CTSF_MEAN:
827     case CTSF_MEDIAN:
828     case CTSF_MINIMUM:
829     case CTSF_MISSING:
830     case CTSF_MODE:
831     case CTSF_PTILE:
832     case CTSF_RANGE:
833     case CTSF_SEMEAN:
834     case CTSF_STDDEV:
835     case CTSF_SUM:
836     case CSTF_TOTALN:
837     case CTSF_ETOTALN:
838     case CTSF_VALIDN:
839     case CTSF_EVALIDN:
840     case CTSF_VARIANCE:
841     case CTSF_ROWPCT_SUM:
842     case CTSF_COLPCT_SUM:
843     case CTSF_TABLEPCT_SUM:
844     case CTSF_SUBTABLEPCT_SUM:
845     case CTSF_LAYERPCT_SUM:
846     case CTSF_LAYERROWPCT_SUM:
847     case CTSF_LAYERCOLPCT_SUM:
848       return false;
849   }
850   NOT_REACHED ();
851 }
852
853
854 static bool
855 parse_ctables_summary_function (struct lexer *lexer,
856                                 enum ctables_summary_function *f)
857 {
858   struct pair
859     {
860       enum ctables_summary_function function;
861       struct substring name;
862     };
863   static struct pair names[] = {
864 #define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) \
865     { ENUM, SS_LITERAL_INITIALIZER (NAME) },
866     SUMMARIES
867
868     /* The .COUNT suffix may be omitted. */
869     S(CTSF_ROWPCT_COUNT, "ROWPCT", _, _, _)
870     S(CTSF_COLPCT_COUNT, "COLPCT", _, _, _)
871     S(CTSF_TABLEPCT_COUNT, "TABLEPCT", _, _, _)
872     S(CTSF_SUBTABLEPCT_COUNT, "SUBTABLEPCT", _, _, _)
873     S(CTSF_LAYERPCT_COUNT, "LAYERPCT", _, _, _)
874     S(CTSF_LAYERROWPCT_COUNT, "LAYERROWPCT", _, _, _)
875     S(CTSF_LAYERCOLPCT_COUNT, "LAYERCOLPCT", _, _, _)
876 #undef S
877   };
878
879   if (!lex_force_id (lexer))
880     return false;
881
882   for (size_t i = 0; i < sizeof names / sizeof *names; i++)
883     if (ss_equals_case (names[i].name, lex_tokss (lexer)))
884       {
885         *f = names[i].function;
886         lex_get (lexer);
887         return true;
888       }
889
890   lex_error (lexer, _("Expecting summary function name."));
891   return false;
892 }
893
894 static void
895 ctables_axis_destroy (struct ctables_axis *axis)
896 {
897   if (!axis)
898     return;
899
900   switch (axis->op)
901     {
902     case CTAO_VAR:
903       for (size_t i = 0; i < N_CSVS; i++)
904         ctables_summary_spec_set_uninit (&axis->specs[i]);
905       break;
906
907     case CTAO_STACK:
908     case CTAO_NEST:
909       ctables_axis_destroy (axis->subs[0]);
910       ctables_axis_destroy (axis->subs[1]);
911       break;
912     }
913   msg_location_destroy (axis->loc);
914   free (axis);
915 }
916
917 static struct ctables_axis *
918 ctables_axis_new_nonterminal (enum ctables_axis_op op,
919                               struct ctables_axis *sub0,
920                               struct ctables_axis *sub1,
921                               struct lexer *lexer, int start_ofs)
922 {
923   struct ctables_axis *axis = xmalloc (sizeof *axis);
924   *axis = (struct ctables_axis) {
925     .op = op,
926     .subs = { sub0, sub1 },
927     .loc = lex_ofs_location (lexer, start_ofs, lex_ofs (lexer) - 1),
928   };
929   return axis;
930 }
931
932 struct ctables_axis_parse_ctx
933   {
934     struct lexer *lexer;
935     struct dictionary *dict;
936     struct ctables *ct;
937     struct ctables_table *t;
938   };
939
940 static struct fmt_spec
941 ctables_summary_default_format (enum ctables_summary_function function,
942                                 const struct variable *var)
943 {
944   static const enum ctables_format default_formats[] = {
945 #define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = FORMAT,
946     SUMMARIES
947 #undef S
948   };
949   switch (default_formats[function])
950     {
951     case CTF_COUNT:
952       return (struct fmt_spec) { .type = FMT_F, .w = 40 };
953
954     case CTF_PERCENT:
955       return (struct fmt_spec) { .type = FMT_PCT, .w = 40, .d = 1 };
956
957     case CTF_GENERAL:
958       return *var_get_print_format (var);
959
960     default:
961       NOT_REACHED ();
962     }
963 }
964
965 static char *
966 ctables_summary_default_label (enum ctables_summary_function function,
967                                double percentile)
968 {
969   static const char *default_labels[] = {
970 #define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = LABEL,
971     SUMMARIES
972 #undef S
973   };
974
975   return (function == CTSF_PTILE
976           ? xasprintf (_("Percentile %.2f"), percentile)
977           : xstrdup (gettext (default_labels[function])));
978 }
979
980 static const char *
981 ctables_summary_function_name (enum ctables_summary_function function)
982 {
983   static const char *names[] = {
984 #define S(ENUM, NAME, LABEL, FORMAT, AVAILABILITY) [ENUM] = NAME,
985     SUMMARIES
986 #undef S
987   };
988   return names[function];
989 }
990
991 static bool
992 add_summary_spec (struct ctables_axis *axis,
993                   enum ctables_summary_function function, double percentile,
994                   const char *label, const struct fmt_spec *format,
995                   bool is_ctables_format, const struct msg_location *loc,
996                   enum ctables_summary_variant sv)
997 {
998   if (axis->op == CTAO_VAR)
999     {
1000       const char *function_name = ctables_summary_function_name (function);
1001       const char *var_name = var_get_name (axis->var);
1002       switch (ctables_function_availability (function))
1003         {
1004         case CTFA_MRSETS:
1005           msg_at (SE, loc, _("Summary function %s applies only to multiple "
1006                              "response sets."), function_name);
1007           msg_at (SN, axis->loc, _("'%s' is not a multiple response set."),
1008                   var_name);
1009           return false;
1010
1011         case CTFA_SCALE:
1012 #if 0
1013           if (!axis->scale)
1014             {
1015               msg_at (SE, loc,
1016                       _("Summary function %s applies only to scale variables."),
1017                       function_name);
1018               msg_at (SN, axis->loc, _("'%s' is not a scale variable."),
1019                       var_name);
1020               return false;
1021             }
1022 #endif
1023           break;
1024
1025         case CTFA_ALL:
1026           break;
1027         }
1028
1029       struct ctables_summary_spec_set *set = &axis->specs[sv];
1030       if (set->n >= set->allocated)
1031         set->specs = x2nrealloc (set->specs, &set->allocated,
1032                                  sizeof *set->specs);
1033
1034       struct ctables_summary_spec *dst = &set->specs[set->n++];
1035       *dst = (struct ctables_summary_spec) {
1036         .function = function,
1037         .percentile = percentile,
1038         .label = xstrdup (label),
1039         .format = (format ? *format
1040                    : ctables_summary_default_format (function, axis->var)),
1041         .is_ctables_format = is_ctables_format,
1042       };
1043       return true;
1044     }
1045   else
1046     {
1047       for (size_t i = 0; i < 2; i++)
1048         if (!add_summary_spec (axis->subs[i], function, percentile, label,
1049                                format, is_ctables_format, loc, sv))
1050           return false;
1051       return true;
1052     }
1053 }
1054
1055 static struct ctables_axis *ctables_axis_parse_stack (
1056   struct ctables_axis_parse_ctx *);
1057
1058
1059 static struct ctables_axis *
1060 ctables_axis_parse_primary (struct ctables_axis_parse_ctx *ctx)
1061 {
1062   if (lex_match (ctx->lexer, T_LPAREN))
1063     {
1064       struct ctables_axis *sub = ctables_axis_parse_stack (ctx);
1065       if (!sub || !lex_force_match (ctx->lexer, T_RPAREN))
1066         {
1067           ctables_axis_destroy (sub);
1068           return NULL;
1069         }
1070       return sub;
1071     }
1072
1073   if (!lex_force_id (ctx->lexer))
1074     return NULL;
1075
1076   int start_ofs = lex_ofs (ctx->lexer);
1077   struct variable *var = parse_variable (ctx->lexer, ctx->dict);
1078   if (!var)
1079     return NULL;
1080
1081   struct ctables_axis *axis = xmalloc (sizeof *axis);
1082   *axis = (struct ctables_axis) { .op = CTAO_VAR, .var = var };
1083
1084   /* XXX should figure out default measures by reading data */
1085   axis->scale = (lex_match_phrase (ctx->lexer, "[S]") ? true
1086                  : lex_match_phrase (ctx->lexer, "[C]") ? false
1087                  : var_get_measure (var) == MEASURE_SCALE);
1088   axis->loc = lex_ofs_location (ctx->lexer, start_ofs,
1089                                 lex_ofs (ctx->lexer) - 1);
1090   if (axis->scale && var_is_alpha (var))
1091     {
1092       msg_at (SE, axis->loc, _("Cannot use string variable %s as a scale "
1093                                "variable."),
1094               var_get_name (var));
1095       ctables_axis_destroy (axis);
1096       return NULL;
1097     }
1098
1099   return axis;
1100 }
1101
1102 static bool
1103 has_digit (const char *s)
1104 {
1105   return s[strcspn (s, "0123456789")] != '\0';
1106 }
1107
1108 static bool
1109 parse_ctables_format_specifier (struct lexer *lexer, struct fmt_spec *format,
1110                                 bool *is_ctables_format)
1111 {
1112   char type[FMT_TYPE_LEN_MAX + 1];
1113   if (!parse_abstract_format_specifier__ (lexer, type, &format->w, &format->d))
1114     return false;
1115
1116   if (!strcasecmp (type, "NEGPAREN"))
1117     format->type = CTEF_NEGPAREN;
1118   else if (!strcasecmp (type, "NEQUAL"))
1119     format->type = CTEF_NEQUAL;
1120   else if (!strcasecmp (type, "PAREN"))
1121     format->type = CTEF_PAREN;
1122   else if (!strcasecmp (type, "PCTPAREN"))
1123     format->type = CTEF_PCTPAREN;
1124   else
1125     {
1126       *is_ctables_format = false;
1127       return (parse_format_specifier (lexer, format)
1128               && fmt_check_output (format)
1129               && fmt_check_type_compat (format, VAL_NUMERIC));
1130     }
1131
1132   if (format->w < 2)
1133     {
1134       msg (SE, _("Output format %s requires width 2 or greater."), type);
1135       return false;
1136     }
1137   else if (format->d > format->w - 1)
1138     {
1139       msg (SE, _("Output format %s requires width greater than decimals."),
1140            type);
1141       return false;
1142     }
1143   else
1144     {
1145       *is_ctables_format = true;
1146       return true;
1147     }
1148 }
1149
1150 static struct ctables_axis *
1151 ctables_axis_parse_postfix (struct ctables_axis_parse_ctx *ctx)
1152 {
1153   struct ctables_axis *sub = ctables_axis_parse_primary (ctx);
1154   if (!sub || !lex_match (ctx->lexer, T_LBRACK))
1155     return sub;
1156
1157   enum ctables_summary_variant sv = CSV_CELL;
1158   for (;;)
1159     {
1160       int start_ofs = lex_ofs (ctx->lexer);
1161
1162       /* Parse function. */
1163       enum ctables_summary_function function;
1164       if (!parse_ctables_summary_function (ctx->lexer, &function))
1165         goto error;
1166
1167       /* Parse percentile. */
1168       double percentile = 0;
1169       if (function == CTSF_PTILE)
1170         {
1171           if (!lex_force_num_range_closed (ctx->lexer, "PTILE", 0, 100))
1172             goto error;
1173           percentile = lex_number (ctx->lexer);
1174           lex_get (ctx->lexer);
1175         }
1176
1177       /* Parse label. */
1178       char *label;
1179       if (lex_is_string (ctx->lexer))
1180         {
1181           label = ss_xstrdup (lex_tokss (ctx->lexer));
1182           lex_get (ctx->lexer);
1183         }
1184       else
1185         label = ctables_summary_default_label (function, percentile);
1186
1187       /* Parse format. */
1188       struct fmt_spec format;
1189       const struct fmt_spec *formatp;
1190       bool is_ctables_format = false;
1191       if (lex_token (ctx->lexer) == T_ID
1192           && has_digit (lex_tokcstr (ctx->lexer)))
1193         {
1194           if (!parse_ctables_format_specifier (ctx->lexer, &format,
1195                                                &is_ctables_format))
1196             {
1197               free (label);
1198               goto error;
1199             }
1200           formatp = &format;
1201         }
1202       else
1203         formatp = NULL;
1204
1205       struct msg_location *loc = lex_ofs_location (ctx->lexer, start_ofs,
1206                                                    lex_ofs (ctx->lexer) - 1);
1207       add_summary_spec (sub, function, percentile, label, formatp,
1208                         is_ctables_format, loc, sv);
1209       free (label);
1210       msg_location_destroy (loc);
1211
1212       lex_match (ctx->lexer, T_COMMA);
1213       if (sv == CSV_CELL && lex_match_id (ctx->lexer, "TOTALS"))
1214         {
1215           if (!lex_force_match (ctx->lexer, T_LBRACK))
1216             goto error;
1217           sv = CSV_TOTAL;
1218         }
1219       else if (lex_match (ctx->lexer, T_RBRACK))
1220         {
1221           if (sv == CSV_TOTAL && !lex_force_match (ctx->lexer, T_RBRACK))
1222             goto error;
1223           return sub;
1224         }
1225     }
1226
1227 error:
1228   ctables_axis_destroy (sub);
1229   return NULL;
1230 }
1231
1232 static const struct ctables_axis *
1233 find_scale (const struct ctables_axis *axis)
1234 {
1235   if (!axis)
1236     return NULL;
1237   else if (axis->op == CTAO_VAR)
1238     return axis->scale ? axis : NULL;
1239   else
1240     {
1241       for (size_t i = 0; i < 2; i++)
1242         {
1243           const struct ctables_axis *scale = find_scale (axis->subs[i]);
1244           if (scale)
1245             return scale;
1246         }
1247       return NULL;
1248     }
1249 }
1250
1251 static const struct ctables_axis *
1252 find_categorical_summary_spec (const struct ctables_axis *axis)
1253 {
1254   if (!axis)
1255     return NULL;
1256   else if (axis->op == CTAO_VAR)
1257     return !axis->scale && axis->specs[CSV_CELL].n ? axis : NULL;
1258   else
1259     {
1260       for (size_t i = 0; i < 2; i++)
1261         {
1262           const struct ctables_axis *sum
1263             = find_categorical_summary_spec (axis->subs[i]);
1264           if (sum)
1265             return sum;
1266         }
1267       return NULL;
1268     }
1269 }
1270
1271 static struct ctables_axis *
1272 ctables_axis_parse_nest (struct ctables_axis_parse_ctx *ctx)
1273 {
1274   int start_ofs = lex_ofs (ctx->lexer);
1275   struct ctables_axis *lhs = ctables_axis_parse_postfix (ctx);
1276   if (!lhs)
1277     return NULL;
1278
1279   while (lex_match (ctx->lexer, T_GT))
1280     {
1281       struct ctables_axis *rhs = ctables_axis_parse_postfix (ctx);
1282       if (!rhs)
1283         return NULL;
1284
1285       struct ctables_axis *nest = ctables_axis_new_nonterminal (
1286         CTAO_NEST, lhs, rhs, ctx->lexer, start_ofs);
1287
1288       const struct ctables_axis *outer_scale = find_scale (lhs);
1289       const struct ctables_axis *inner_scale = find_scale (rhs);
1290       if (outer_scale && inner_scale)
1291         {
1292           msg_at (SE, nest->loc, _("Cannot nest scale variables."));
1293           msg_at (SN, outer_scale->loc, _("This is an outer scale variable."));
1294           msg_at (SN, inner_scale->loc, _("This is an inner scale variable."));
1295           ctables_axis_destroy (nest);
1296           return NULL;
1297         }
1298
1299       const struct ctables_axis *outer_sum = find_categorical_summary_spec (lhs);
1300       if (outer_sum)
1301         {
1302           msg_at (SE, nest->loc,
1303                   _("Summaries may only be requested for categorical variables "
1304                     "at the innermost nesting level."));
1305           msg_at (SN, outer_sum->loc,
1306                   _("This outer categorical variable has a summary."));
1307           ctables_axis_destroy (nest);
1308           return NULL;
1309         }
1310
1311       lhs = nest;
1312     }
1313
1314   return lhs;
1315 }
1316
1317 static struct ctables_axis *
1318 ctables_axis_parse_stack (struct ctables_axis_parse_ctx *ctx)
1319 {
1320   int start_ofs = lex_ofs (ctx->lexer);
1321   struct ctables_axis *lhs = ctables_axis_parse_nest (ctx);
1322   if (!lhs)
1323     return NULL;
1324
1325   while (lex_match (ctx->lexer, T_PLUS))
1326     {
1327       struct ctables_axis *rhs = ctables_axis_parse_nest (ctx);
1328       if (!rhs)
1329         return NULL;
1330
1331       lhs = ctables_axis_new_nonterminal (CTAO_STACK, lhs, rhs,
1332                                           ctx->lexer, start_ofs);
1333     }
1334
1335   return lhs;
1336 }
1337
1338 static bool
1339 ctables_axis_parse (struct lexer *lexer, struct dictionary *dict,
1340                     struct ctables *ct, struct ctables_table *t,
1341                     enum pivot_axis_type a)
1342 {
1343   if (lex_token (lexer) == T_BY
1344       || lex_token (lexer) == T_SLASH
1345       || lex_token (lexer) == T_ENDCMD)
1346     return true;
1347
1348   struct ctables_axis_parse_ctx ctx = {
1349     .lexer = lexer,
1350     .dict = dict,
1351     .ct = ct,
1352     .t = t
1353   };
1354   t->axes[a] = ctables_axis_parse_stack (&ctx);
1355   return t->axes[a] != NULL;
1356 }
1357
1358 static void
1359 ctables_chisq_destroy (struct ctables_chisq *chisq)
1360 {
1361   free (chisq);
1362 }
1363
1364 static void
1365 ctables_pairwise_destroy (struct ctables_pairwise *pairwise)
1366 {
1367   free (pairwise);
1368 }
1369
1370 static void
1371 ctables_table_destroy (struct ctables_table *t)
1372 {
1373   if (!t)
1374     return;
1375
1376   for (size_t i = 0; i < t->n_categories; i++)
1377     ctables_categories_unref (t->categories[i]);
1378   free (t->categories);
1379
1380   ctables_axis_destroy (t->axes[PIVOT_AXIS_COLUMN]);
1381   ctables_axis_destroy (t->axes[PIVOT_AXIS_ROW]);
1382   ctables_axis_destroy (t->axes[PIVOT_AXIS_LAYER]);
1383   free (t->caption);
1384   free (t->corner);
1385   free (t->title);
1386   ctables_chisq_destroy (t->chisq);
1387   ctables_pairwise_destroy (t->pairwise);
1388   free (t);
1389 }
1390
1391 static void
1392 ctables_destroy (struct ctables *ct)
1393 {
1394   if (!ct)
1395     return;
1396
1397   pivot_table_look_unref (ct->look);
1398   free (ct->zero);
1399   free (ct->missing);
1400   free (ct->vlabels);
1401   for (size_t i = 0; i < ct->n_tables; i++)
1402     ctables_table_destroy (ct->tables[i]);
1403   free (ct->tables);
1404   free (ct);
1405 }
1406
1407 static struct ctables_category
1408 cct_range (double low, double high)
1409 {
1410   return (struct ctables_category) {
1411     .type = CCT_RANGE,
1412     .range = { low, high }
1413   };
1414 }
1415
1416 static bool
1417 ctables_table_parse_subtotal (struct lexer *lexer, bool hide_subcategories,
1418                               struct ctables_category *cat)
1419 {
1420   char *total_label;
1421   if (lex_match (lexer, T_EQUALS))
1422     {
1423       if (!lex_force_string (lexer))
1424         return false;
1425
1426       total_label = ss_xstrdup (lex_tokss (lexer));
1427       lex_get (lexer);
1428     }
1429   else
1430     total_label = xstrdup (_("Subtotal"));
1431
1432   *cat = (struct ctables_category) {
1433     .type = CCT_SUBTOTAL,
1434     .hide_subcategories = hide_subcategories,
1435     .total_label = total_label
1436   };
1437   return true;
1438 }
1439
1440 static bool
1441 ctables_table_parse_explicit_category (struct lexer *lexer, struct ctables *ct,
1442                                        struct ctables_category *cat)
1443 {
1444   if (lex_match_id (lexer, "OTHERNM"))
1445     *cat = (struct ctables_category) { .type = CCT_OTHERNM };
1446   else if (lex_match_id (lexer, "MISSING"))
1447     *cat = (struct ctables_category) { .type = CCT_MISSING };
1448   else if (lex_match_id (lexer, "SUBTOTAL"))
1449     return ctables_table_parse_subtotal (lexer, false, cat);
1450   else if (lex_match_id (lexer, "HSUBTOTAL"))
1451     return ctables_table_parse_subtotal (lexer, true, cat);
1452   else if (lex_match_id (lexer, "LO"))
1453     {
1454       if (!lex_force_match_id (lexer, "THRU") || lex_force_num (lexer))
1455         return false;
1456       *cat = cct_range (-DBL_MAX, lex_number (lexer));
1457       lex_get (lexer);
1458     }
1459   else if (lex_is_number (lexer))
1460     {
1461       double number = lex_number (lexer);
1462       lex_get (lexer);
1463       if (lex_match_id (lexer, "THRU"))
1464         {
1465           if (lex_match_id (lexer, "HI"))
1466             *cat = cct_range (number, DBL_MAX);
1467           else
1468             {
1469               if (!lex_force_num (lexer))
1470                 return false;
1471               *cat = cct_range (number, lex_number (lexer));
1472               lex_get (lexer);
1473             }
1474         }
1475       else
1476         *cat = (struct ctables_category) {
1477           .type = CCT_NUMBER,
1478           .number = number
1479         };
1480     }
1481   else if (lex_is_string (lexer))
1482     {
1483       *cat = (struct ctables_category) {
1484         .type = CCT_STRING,
1485         .string = ss_xstrdup (lex_tokss (lexer)),
1486       };
1487       lex_get (lexer);
1488     }
1489   else if (lex_match (lexer, T_AND))
1490     {
1491       if (!lex_force_id (lexer))
1492         return false;
1493       struct ctables_postcompute *pc = ctables_find_postcompute (
1494         ct, lex_tokcstr (lexer));
1495       if (!pc)
1496         {
1497           struct msg_location *loc = lex_get_location (lexer, -1, 0);
1498           msg_at (SE, loc, _("Unknown postcompute &%s."),
1499                   lex_tokcstr (lexer));
1500           msg_location_destroy (loc);
1501           return false;
1502         }
1503       lex_get (lexer);
1504
1505       *cat = (struct ctables_category) { .type = CCT_POSTCOMPUTE, .pc = pc };
1506     }
1507   else
1508     {
1509       lex_error (lexer, NULL);
1510       return false;
1511     }
1512
1513   return true;
1514 }
1515
1516 static struct ctables_category *
1517 ctables_find_category_for_postcompute (const struct ctables_categories *cats,
1518                                        const struct ctables_pcexpr *e)
1519 {
1520   struct ctables_category *best = NULL;
1521   size_t n_subtotals = 0;
1522   for (size_t i = 0; i < cats->n_cats; i++)
1523     {
1524       struct ctables_category *cat = &cats->cats[i];
1525       switch (e->op)
1526         {
1527         case CTPO_CAT_NUMBER:
1528           if (cat->type == CCT_NUMBER && cat->number == e->number)
1529             best = cat;
1530           break;
1531
1532         case CTPO_CAT_STRING:
1533           if (cat->type == CCT_STRING && !strcmp (cat->string, e->string))
1534             best = cat;
1535           break;
1536
1537         case CTPO_CAT_RANGE:
1538           if (cat->type == CCT_RANGE
1539               && cat->range[0] == e->range[0]
1540               && cat->range[1] == e->range[1])
1541             best = cat;
1542           break;
1543
1544         case CTPO_CAT_MISSING:
1545           if (cat->type == CCT_MISSING)
1546             best = cat;
1547           break;
1548
1549         case CTPO_CAT_OTHERNM:
1550           if (cat->type == CCT_OTHERNM)
1551             best = cat;
1552           break;
1553
1554         case CTPO_CAT_SUBTOTAL:
1555           if (cat->type == CCT_SUBTOTAL)
1556             {
1557               n_subtotals++;
1558               if (e->subtotal_index == n_subtotals)
1559                 return cat;
1560               else if (e->subtotal_index == 0)
1561                 best = cat;
1562             }
1563           break;
1564
1565         case CTPO_CAT_TOTAL:
1566           if (cat->type == CCT_TOTAL)
1567             return cat;
1568           break;
1569
1570         case CTPO_CONSTANT:
1571         case CTPO_ADD:
1572         case CTPO_SUB:
1573         case CTPO_MUL:
1574         case CTPO_DIV:
1575         case CTPO_POW:
1576         case CTPO_NEG:
1577           NOT_REACHED ();
1578         }
1579     }
1580   if (e->op == CTPO_CAT_SUBTOTAL && e->subtotal_index == 0 && n_subtotals > 1)
1581     return NULL;
1582   return best;
1583 }
1584
1585 static bool
1586 ctables_recursive_check_postcompute (const struct ctables_pcexpr *e,
1587                                      struct ctables_category *pc_cat,
1588                                      const struct ctables_categories *cats,
1589                                      const struct msg_location *cats_location)
1590 {
1591   switch (e->op)
1592     {
1593     case CTPO_CAT_NUMBER:
1594     case CTPO_CAT_STRING:
1595     case CTPO_CAT_RANGE:
1596     case CTPO_CAT_MISSING:
1597     case CTPO_CAT_OTHERNM:
1598     case CTPO_CAT_SUBTOTAL:
1599     case CTPO_CAT_TOTAL:
1600       {
1601         struct ctables_category *cat = ctables_find_category_for_postcompute (
1602           cats, e);
1603         if (!cat)
1604           {
1605             if (e->op == CTPO_CAT_SUBTOTAL && e->subtotal_index == 0)
1606               {
1607                 size_t n_subtotals = 0;
1608                 for (size_t i = 0; i < cats->n_cats; i++)
1609                   n_subtotals += cats->cats[i].type == CCT_SUBTOTAL;
1610                 if (n_subtotals > 1)
1611                   {
1612                     msg_at (SE, cats_location,
1613                             ngettext ("These categories include %zu instance "
1614                                       "of SUBTOTAL or HSUBTOTAL, so references "
1615                                       "from computed categories must refer to "
1616                                       "subtotals by position.",
1617                                       "These categories include %zu instances "
1618                                       "of SUBTOTAL or HSUBTOTAL, so references "
1619                                       "from computed categories must refer to "
1620                                       "subtotals by position.",
1621                                       n_subtotals),
1622                             n_subtotals);
1623                     msg_at (SN, e->location,
1624                             _("This is the reference that lacks a position."));
1625                     return NULL;
1626                   }
1627               }
1628
1629             msg_at (SE, pc_cat->location,
1630                     _("Computed category &%s references a category not included "
1631                       "in the category list."),
1632                     pc_cat->pc->name);
1633             msg_at (SN, e->location, _("This is the missing category."));
1634             msg_at (SN, cats_location,
1635                     _("To fix the problem, add the missing category to the "
1636                       "list of categories here."));
1637             return false;
1638           }
1639         if (pc_cat->pc->hide_source_cats)
1640           cat->hide = true;
1641         return true;
1642       }
1643
1644     case CTPO_CONSTANT:
1645       return true;
1646
1647     case CTPO_ADD:
1648     case CTPO_SUB:
1649     case CTPO_MUL:
1650     case CTPO_DIV:
1651     case CTPO_POW:
1652     case CTPO_NEG:
1653       for (size_t i = 0; i < 2; i++)
1654         if (e->subs[i] && !ctables_recursive_check_postcompute (
1655               e->subs[i], pc_cat, cats, cats_location))
1656           return false;
1657       return true;
1658
1659     default:
1660       NOT_REACHED ();
1661     }
1662 }
1663
1664 static bool
1665 ctables_table_parse_categories (struct lexer *lexer, struct dictionary *dict,
1666                                 struct ctables *ct, struct ctables_table *t)
1667 {
1668   if (!lex_match_id (lexer, "VARIABLES"))
1669     return false;
1670   lex_match (lexer, T_EQUALS);
1671
1672   struct variable **vars;
1673   size_t n_vars;
1674   if (!parse_variables (lexer, dict, &vars, &n_vars, PV_NO_SCRATCH))
1675     return false;
1676
1677   struct ctables_categories *c = xmalloc (sizeof *c);
1678   *c = (struct ctables_categories) { .n_refs = n_vars, .show_empty = true };
1679   for (size_t i = 0; i < n_vars; i++)
1680     {
1681       struct ctables_categories **cp
1682         = &t->categories[var_get_dict_index (vars[i])];
1683       ctables_categories_unref (*cp);
1684       *cp = c;
1685     }
1686   free (vars);
1687
1688   size_t allocated_cats = 0;
1689   if (lex_match (lexer, T_LBRACK))
1690     {
1691       int cats_start_ofs = lex_ofs (lexer);
1692       do
1693         {
1694           if (c->n_cats >= allocated_cats)
1695             c->cats = x2nrealloc (c->cats, &allocated_cats, sizeof *c->cats);
1696
1697           int start_ofs = lex_ofs (lexer);
1698           struct ctables_category *cat = &c->cats[c->n_cats];
1699           if (!ctables_table_parse_explicit_category (lexer, ct, cat))
1700             return false;
1701           cat->location = lex_ofs_location (lexer, start_ofs, lex_ofs (lexer) - 1);
1702           c->n_cats++;
1703
1704           lex_match (lexer, T_COMMA);
1705         }
1706       while (!lex_match (lexer, T_RBRACK));
1707
1708       struct msg_location *cats_location
1709         = lex_ofs_location (lexer, cats_start_ofs, lex_ofs (lexer) - 1);
1710       for (size_t i = 0; i < c->n_cats; i++)
1711         {
1712           struct ctables_category *cat = &c->cats[i];
1713           if (cat->type == CCT_POSTCOMPUTE
1714               && !ctables_recursive_check_postcompute (cat->pc->expr, cat,
1715                                                        c, cats_location))
1716             return false;
1717         }
1718     }
1719
1720   struct ctables_category cat = {
1721     .type = CCT_VALUE,
1722     .include_missing = false,
1723     .sort_ascending = true,
1724   };
1725   bool show_totals = false;
1726   char *total_label = NULL;
1727   bool totals_before = false;
1728   while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
1729     {
1730       if (!c->n_cats && lex_match_id (lexer, "ORDER"))
1731         {
1732           lex_match (lexer, T_EQUALS);
1733           if (lex_match_id (lexer, "A"))
1734             cat.sort_ascending = true;
1735           else if (lex_match_id (lexer, "D"))
1736             cat.sort_ascending = false;
1737           else
1738             {
1739               lex_error_expecting (lexer, "A", "D");
1740               return false;
1741             }
1742         }
1743       else if (!c->n_cats && lex_match_id (lexer, "KEY"))
1744         {
1745           lex_match (lexer, T_EQUALS);
1746           if (lex_match_id (lexer, "VALUE"))
1747             cat.type = CCT_VALUE;
1748           else if (lex_match_id (lexer, "LABEL"))
1749             cat.type = CCT_LABEL;
1750           else
1751             {
1752               cat.type = CCT_FUNCTION;
1753               if (!parse_ctables_summary_function (lexer, &cat.sort_function))
1754                 return false;
1755
1756               if (lex_match (lexer, T_LPAREN))
1757                 {
1758                   cat.sort_var = parse_variable (lexer, dict);
1759                   if (!cat.sort_var)
1760                     return false;
1761
1762                   if (cat.sort_function == CTSF_PTILE)
1763                     {
1764                       lex_match (lexer, T_COMMA);
1765                       if (!lex_force_num_range_closed (lexer, "PTILE", 0, 100))
1766                         return false;
1767                       cat.percentile = lex_number (lexer);
1768                       lex_get (lexer);
1769                     }
1770
1771                   if (!lex_force_match (lexer, T_RPAREN))
1772                     return false;
1773                 }
1774               else if (ctables_function_availability (cat.sort_function)
1775                        == CTFA_SCALE)
1776                 {
1777                   bool UNUSED b = lex_force_match (lexer, T_LPAREN);
1778                   return false;
1779                 }
1780             }
1781         }
1782       else if (!c->n_cats && lex_match_id (lexer, "MISSING"))
1783         {
1784           lex_match (lexer, T_EQUALS);
1785           if (lex_match_id (lexer, "INCLUDE"))
1786             cat.include_missing = true;
1787           else if (lex_match_id (lexer, "EXCLUDE"))
1788             cat.include_missing = false;
1789           else
1790             {
1791               lex_error_expecting (lexer, "INCLUDE", "EXCLUDE");
1792               return false;
1793             }
1794         }
1795       else if (lex_match_id (lexer, "TOTAL"))
1796         {
1797           lex_match (lexer, T_EQUALS);
1798           if (!parse_bool (lexer, &show_totals))
1799             return false;
1800         }
1801       else if (lex_match_id (lexer, "LABEL"))
1802         {
1803           lex_match (lexer, T_EQUALS);
1804           if (!lex_force_string (lexer))
1805             return false;
1806           free (total_label);
1807           total_label = ss_xstrdup (lex_tokss (lexer));
1808           lex_get (lexer);
1809         }
1810       else if (lex_match_id (lexer, "POSITION"))
1811         {
1812           lex_match (lexer, T_EQUALS);
1813           if (lex_match_id (lexer, "BEFORE"))
1814             totals_before = true;
1815           else if (lex_match_id (lexer, "AFTER"))
1816             totals_before = false;
1817           else
1818             {
1819               lex_error_expecting (lexer, "BEFORE", "AFTER");
1820               return false;
1821             }
1822         }
1823       else if (lex_match_id (lexer, "EMPTY"))
1824         {
1825           lex_match (lexer, T_EQUALS);
1826           if (lex_match_id (lexer, "INCLUDE"))
1827             c->show_empty = true;
1828           else if (lex_match_id (lexer, "EXCLUDE"))
1829             c->show_empty = false;
1830           else
1831             {
1832               lex_error_expecting (lexer, "INCLUDE", "EXCLUDE");
1833               return false;
1834             }
1835         }
1836       else
1837         {
1838           if (!c->n_cats)
1839             lex_error_expecting (lexer, "ORDER", "KEY", "MISSING",
1840                                  "TOTAL", "LABEL", "POSITION", "EMPTY");
1841           else
1842             lex_error_expecting (lexer, "TOTAL", "LABEL", "POSITION", "EMPTY");
1843           return false;
1844         }
1845     }
1846
1847   if (!c->n_cats)
1848     {
1849       if (c->n_cats >= allocated_cats)
1850         c->cats = x2nrealloc (c->cats, &allocated_cats, sizeof *c->cats);
1851       c->cats[c->n_cats++] = cat;
1852     }
1853
1854   if (show_totals)
1855     {
1856       if (c->n_cats >= allocated_cats)
1857         c->cats = x2nrealloc (c->cats, &allocated_cats, sizeof *c->cats);
1858
1859       struct ctables_category *totals;
1860       if (totals_before)
1861         {
1862           insert_element (c->cats, c->n_cats, sizeof *c->cats, 0);
1863           totals = &c->cats[0];
1864         }
1865       else
1866         totals = &c->cats[c->n_cats];
1867       c->n_cats++;
1868
1869       *totals = (struct ctables_category) {
1870         .type = CCT_TOTAL,
1871         .total_label = total_label ? total_label : xstrdup (_("Total")),
1872       };
1873     }
1874
1875   struct ctables_category *subtotal = NULL;
1876   for (size_t i = totals_before ? 0 : c->n_cats;
1877        totals_before ? i < c->n_cats : i-- > 0;
1878        totals_before ? i++ : 0)
1879     {
1880       struct ctables_category *cat = &c->cats[i];
1881       switch (cat->type)
1882         {
1883         case CCT_NUMBER:
1884         case CCT_STRING:
1885         case CCT_RANGE:
1886         case CCT_MISSING:
1887         case CCT_OTHERNM:
1888           cat->subtotal = subtotal;
1889           break;
1890
1891         case CCT_POSTCOMPUTE:
1892           break;
1893
1894         case CCT_SUBTOTAL:
1895           subtotal = cat;
1896           break;
1897
1898         case CCT_TOTAL:
1899         case CCT_VALUE:
1900         case CCT_LABEL:
1901         case CCT_FUNCTION:
1902         case CCT_EXCLUDED_MISSING:
1903           break;
1904         }
1905     }
1906
1907   return true;
1908 }
1909
1910 static void
1911 ctables_nest_uninit (struct ctables_nest *nest)
1912 {
1913   if (nest)
1914     free (nest->vars);
1915 }
1916
1917 static void
1918 ctables_stack_uninit (struct ctables_stack *stack)
1919 {
1920   if (stack)
1921     {
1922       for (size_t i = 0; i < stack->n; i++)
1923         ctables_nest_uninit (&stack->nests[i]);
1924       free (stack->nests);
1925     }
1926 }
1927
1928 static struct ctables_stack
1929 nest_fts (struct ctables_stack s0, struct ctables_stack s1)
1930 {
1931   if (!s0.n)
1932     return s1;
1933   else if (!s1.n)
1934     return s0;
1935
1936   struct ctables_stack stack = { .nests = xnmalloc (s0.n, s1.n * sizeof *stack.nests) };
1937   for (size_t i = 0; i < s0.n; i++)
1938     for (size_t j = 0; j < s1.n; j++)
1939       {
1940         const struct ctables_nest *a = &s0.nests[i];
1941         const struct ctables_nest *b = &s1.nests[j];
1942
1943         size_t allocate = a->n + b->n;
1944         struct variable **vars = xnmalloc (allocate, sizeof *vars);
1945         enum pivot_axis_type *axes = xnmalloc (allocate, sizeof *axes);
1946         size_t n = 0;
1947         for (size_t k = 0; k < a->n; k++)
1948           vars[n++] = a->vars[k];
1949         for (size_t k = 0; k < b->n; k++)
1950           vars[n++] = b->vars[k];
1951         assert (n == allocate);
1952
1953         const struct ctables_nest *summary_src;
1954         if (!a->specs[CSV_CELL].var)
1955           summary_src = b;
1956         else if (!b->specs[CSV_CELL].var)
1957           summary_src = a;
1958         else
1959           NOT_REACHED ();
1960
1961         struct ctables_nest *new = &stack.nests[stack.n++];
1962         *new = (struct ctables_nest) {
1963           .vars = vars,
1964           .scale_idx = (a->scale_idx != SIZE_MAX ? a->scale_idx
1965                         : b->scale_idx != SIZE_MAX ? a->n + b->scale_idx
1966                         : SIZE_MAX),
1967           .n = n,
1968         };
1969         for (enum ctables_summary_variant sv = 0; sv < N_CSVS; sv++)
1970           ctables_summary_spec_set_clone (&new->specs[sv], &summary_src->specs[sv]);
1971       }
1972   ctables_stack_uninit (&s0);
1973   ctables_stack_uninit (&s1);
1974   return stack;
1975 }
1976
1977 static struct ctables_stack
1978 stack_fts (struct ctables_stack s0, struct ctables_stack s1)
1979 {
1980   struct ctables_stack stack = { .nests = xnmalloc (s0.n + s1.n, sizeof *stack.nests) };
1981   for (size_t i = 0; i < s0.n; i++)
1982     stack.nests[stack.n++] = s0.nests[i];
1983   for (size_t i = 0; i < s1.n; i++)
1984     {
1985       stack.nests[stack.n] = s1.nests[i];
1986       stack.nests[stack.n].group_head += s0.n;
1987       stack.n++;
1988     }
1989   assert (stack.n == s0.n + s1.n);
1990   free (s0.nests);
1991   free (s1.nests);
1992   return stack;
1993 }
1994
1995 static struct ctables_stack
1996 var_fts (const struct ctables_axis *a)
1997 {
1998   struct variable **vars = xmalloc (sizeof *vars);
1999   *vars = a->var;
2000
2001   struct ctables_nest *nest = xmalloc (sizeof *nest);
2002   *nest = (struct ctables_nest) {
2003     .vars = vars,
2004     .n = 1,
2005     .scale_idx = a->scale ? 0 : SIZE_MAX,
2006   };
2007   if (a->specs[CSV_CELL].n || a->scale)
2008     for (enum ctables_summary_variant sv = 0; sv < N_CSVS; sv++)
2009       {
2010         ctables_summary_spec_set_clone (&nest->specs[sv], &a->specs[sv]);
2011         nest->specs[sv].var = a->var;
2012         nest->specs[sv].is_scale = a->scale;
2013       }
2014   return (struct ctables_stack) { .nests = nest, .n = 1 };
2015 }
2016
2017 static struct ctables_stack
2018 enumerate_fts (enum pivot_axis_type axis_type, const struct ctables_axis *a)
2019 {
2020   if (!a)
2021     return (struct ctables_stack) { .n = 0 };
2022
2023   switch (a->op)
2024     {
2025     case CTAO_VAR:
2026       return var_fts (a);
2027
2028     case CTAO_STACK:
2029       return stack_fts (enumerate_fts (axis_type, a->subs[0]),
2030                         enumerate_fts (axis_type, a->subs[1]));
2031
2032     case CTAO_NEST:
2033       /* This should consider any of the scale variables found in the result to
2034          be linked to each other listwise for SMISSING=LISTWISE. */
2035       return nest_fts (enumerate_fts (axis_type, a->subs[0]),
2036                        enumerate_fts (axis_type, a->subs[1]));
2037     }
2038
2039   NOT_REACHED ();
2040 }
2041
2042 union ctables_summary
2043   {
2044     /* COUNT, VALIDN, TOTALN. */
2045     double count;
2046
2047     /* MINIMUM, MAXIMUM, RANGE. */
2048     struct
2049       {
2050         double min;
2051         double max;
2052       };
2053
2054     /* MEAN, SEMEAN, STDDEV, SUM, VARIANCE, *.SUM. */
2055     struct moments1 *moments;
2056
2057     /* MEDIAN, MODE, PTILE. */
2058     struct
2059       {
2060         struct casewriter *writer;
2061         double ovalid;
2062         double ovalue;
2063       };
2064
2065     /* XXX multiple response */
2066   };
2067
2068 static void
2069 ctables_summary_init (union ctables_summary *s,
2070                       const struct ctables_summary_spec *ss)
2071 {
2072   switch (ss->function)
2073     {
2074     case CTSF_COUNT:
2075     case CTSF_ECOUNT:
2076     case CTSF_ROWPCT_COUNT:
2077     case CTSF_COLPCT_COUNT:
2078     case CTSF_TABLEPCT_COUNT:
2079     case CTSF_SUBTABLEPCT_COUNT:
2080     case CTSF_LAYERPCT_COUNT:
2081     case CTSF_LAYERROWPCT_COUNT:
2082     case CTSF_LAYERCOLPCT_COUNT:
2083     case CTSF_ROWPCT_VALIDN:
2084     case CTSF_COLPCT_VALIDN:
2085     case CTSF_TABLEPCT_VALIDN:
2086     case CTSF_SUBTABLEPCT_VALIDN:
2087     case CTSF_LAYERPCT_VALIDN:
2088     case CTSF_LAYERROWPCT_VALIDN:
2089     case CTSF_LAYERCOLPCT_VALIDN:
2090     case CTSF_ROWPCT_TOTALN:
2091     case CTSF_COLPCT_TOTALN:
2092     case CTSF_TABLEPCT_TOTALN:
2093     case CTSF_SUBTABLEPCT_TOTALN:
2094     case CTSF_LAYERPCT_TOTALN:
2095     case CTSF_LAYERROWPCT_TOTALN:
2096     case CTSF_LAYERCOLPCT_TOTALN:
2097     case CTSF_MISSING:
2098     case CSTF_TOTALN:
2099     case CTSF_ETOTALN:
2100     case CTSF_VALIDN:
2101     case CTSF_EVALIDN:
2102       s->count = 0;
2103       break;
2104
2105     case CTSF_MAXIMUM:
2106     case CTSF_MINIMUM:
2107     case CTSF_RANGE:
2108       s->min = s->max = SYSMIS;
2109       break;
2110
2111     case CTSF_MEAN:
2112     case CTSF_SEMEAN:
2113     case CTSF_STDDEV:
2114     case CTSF_SUM:
2115     case CTSF_VARIANCE:
2116     case CTSF_ROWPCT_SUM:
2117     case CTSF_COLPCT_SUM:
2118     case CTSF_TABLEPCT_SUM:
2119     case CTSF_SUBTABLEPCT_SUM:
2120     case CTSF_LAYERPCT_SUM:
2121     case CTSF_LAYERROWPCT_SUM:
2122     case CTSF_LAYERCOLPCT_SUM:
2123       s->moments = moments1_create (MOMENT_VARIANCE);
2124       break;
2125
2126     case CTSF_MEDIAN:
2127     case CTSF_MODE:
2128     case CTSF_PTILE:
2129       {
2130         struct caseproto *proto = caseproto_create ();
2131         proto = caseproto_add_width (proto, 0);
2132         proto = caseproto_add_width (proto, 0);
2133
2134         struct subcase ordering;
2135         subcase_init (&ordering, 0, 0, SC_ASCEND);
2136         s->writer = sort_create_writer (&ordering, proto);
2137         subcase_uninit (&ordering);
2138         caseproto_unref (proto);
2139
2140         s->ovalid = 0;
2141         s->ovalue = SYSMIS;
2142       }
2143       break;
2144     }
2145 }
2146
2147 static void UNUSED
2148 ctables_summary_uninit (union ctables_summary *s,
2149                         const struct ctables_summary_spec *ss)
2150 {
2151   switch (ss->function)
2152     {
2153     case CTSF_COUNT:
2154     case CTSF_ECOUNT:
2155     case CTSF_ROWPCT_COUNT:
2156     case CTSF_COLPCT_COUNT:
2157     case CTSF_TABLEPCT_COUNT:
2158     case CTSF_SUBTABLEPCT_COUNT:
2159     case CTSF_LAYERPCT_COUNT:
2160     case CTSF_LAYERROWPCT_COUNT:
2161     case CTSF_LAYERCOLPCT_COUNT:
2162     case CTSF_ROWPCT_VALIDN:
2163     case CTSF_COLPCT_VALIDN:
2164     case CTSF_TABLEPCT_VALIDN:
2165     case CTSF_SUBTABLEPCT_VALIDN:
2166     case CTSF_LAYERPCT_VALIDN:
2167     case CTSF_LAYERROWPCT_VALIDN:
2168     case CTSF_LAYERCOLPCT_VALIDN:
2169     case CTSF_ROWPCT_TOTALN:
2170     case CTSF_COLPCT_TOTALN:
2171     case CTSF_TABLEPCT_TOTALN:
2172     case CTSF_SUBTABLEPCT_TOTALN:
2173     case CTSF_LAYERPCT_TOTALN:
2174     case CTSF_LAYERROWPCT_TOTALN:
2175     case CTSF_LAYERCOLPCT_TOTALN:
2176     case CTSF_MISSING:
2177     case CSTF_TOTALN:
2178     case CTSF_ETOTALN:
2179     case CTSF_VALIDN:
2180     case CTSF_EVALIDN:
2181       break;
2182
2183     case CTSF_MAXIMUM:
2184     case CTSF_MINIMUM:
2185     case CTSF_RANGE:
2186       break;
2187
2188     case CTSF_MEAN:
2189     case CTSF_SEMEAN:
2190     case CTSF_STDDEV:
2191     case CTSF_SUM:
2192     case CTSF_VARIANCE:
2193     case CTSF_ROWPCT_SUM:
2194     case CTSF_COLPCT_SUM:
2195     case CTSF_TABLEPCT_SUM:
2196     case CTSF_SUBTABLEPCT_SUM:
2197     case CTSF_LAYERPCT_SUM:
2198     case CTSF_LAYERROWPCT_SUM:
2199     case CTSF_LAYERCOLPCT_SUM:
2200       moments1_destroy (s->moments);
2201       break;
2202
2203     case CTSF_MEDIAN:
2204     case CTSF_MODE:
2205     case CTSF_PTILE:
2206       casewriter_destroy (s->writer);
2207       break;
2208     }
2209 }
2210
2211 static void
2212 ctables_summary_add (union ctables_summary *s,
2213                      const struct ctables_summary_spec *ss,
2214                      const struct variable *var, const union value *value,
2215                      bool is_scale, bool is_scale_missing,
2216                      bool is_missing, bool excluded_missing,
2217                      double d_weight, double e_weight)
2218 {
2219   /* To determine whether a case is included in a given table for a particular
2220      kind of summary, consider the following charts for each variable in the
2221      table.  Only if "yes" appears for every variable for the summary is the
2222      case counted.
2223
2224      Categorical variables:                    VALIDN   COUNT   TOTALN
2225        Valid values in included categories       yes     yes      yes
2226        Missing values in included categories     ---     yes      yes
2227        Missing values in excluded categories     ---     ---      yes
2228        Valid values in excluded categories       ---     ---      ---
2229
2230      Scale variables:                          VALIDN   COUNT   TOTALN
2231        Valid value                               yes     yes      yes
2232        Missing value                             ---     yes      yes
2233
2234      Missing values include both user- and system-missing.  (The system-missing
2235      value is always in an excluded category.)
2236   */
2237   switch (ss->function)
2238     {
2239     case CSTF_TOTALN:
2240     case CTSF_ROWPCT_TOTALN:
2241     case CTSF_COLPCT_TOTALN:
2242     case CTSF_TABLEPCT_TOTALN:
2243     case CTSF_SUBTABLEPCT_TOTALN:
2244     case CTSF_LAYERPCT_TOTALN:
2245     case CTSF_LAYERROWPCT_TOTALN:
2246     case CTSF_LAYERCOLPCT_TOTALN:
2247       s->count += d_weight;
2248       break;
2249
2250     case CTSF_COUNT:
2251     case CTSF_ROWPCT_COUNT:
2252     case CTSF_COLPCT_COUNT:
2253     case CTSF_TABLEPCT_COUNT:
2254     case CTSF_SUBTABLEPCT_COUNT:
2255     case CTSF_LAYERPCT_COUNT:
2256     case CTSF_LAYERROWPCT_COUNT:
2257     case CTSF_LAYERCOLPCT_COUNT:
2258       if (is_scale || !excluded_missing)
2259         s->count += d_weight;
2260       break;
2261
2262     case CTSF_VALIDN:
2263     case CTSF_ROWPCT_VALIDN:
2264     case CTSF_COLPCT_VALIDN:
2265     case CTSF_TABLEPCT_VALIDN:
2266     case CTSF_SUBTABLEPCT_VALIDN:
2267     case CTSF_LAYERPCT_VALIDN:
2268     case CTSF_LAYERROWPCT_VALIDN:
2269     case CTSF_LAYERCOLPCT_VALIDN:
2270       if (is_scale
2271           ? !is_scale_missing
2272           : !is_missing)
2273         s->count += d_weight;
2274       break;
2275
2276     case CTSF_MISSING:
2277       if (is_missing)
2278         s->count += d_weight;
2279       break;
2280
2281     case CTSF_ECOUNT:
2282       if (is_scale || !excluded_missing)
2283         s->count += e_weight;
2284       break;
2285
2286     case CTSF_EVALIDN:
2287       if (is_scale
2288           ? !is_scale_missing
2289           : !is_missing)
2290         s->count += e_weight;
2291       break;
2292
2293     case CTSF_ETOTALN:
2294       s->count += e_weight;
2295       break;
2296
2297     case CTSF_MAXIMUM:
2298     case CTSF_MINIMUM:
2299     case CTSF_RANGE:
2300       if (!is_scale_missing)
2301         {
2302           assert (!var_is_alpha (var)); /* XXX? */
2303           if (s->min == SYSMIS || value->f < s->min)
2304             s->min = value->f;
2305           if (s->max == SYSMIS || value->f > s->max)
2306             s->max = value->f;
2307         }
2308       break;
2309
2310     case CTSF_MEAN:
2311     case CTSF_SEMEAN:
2312     case CTSF_STDDEV:
2313     case CTSF_SUM:
2314     case CTSF_VARIANCE:
2315     case CTSF_ROWPCT_SUM:
2316     case CTSF_COLPCT_SUM:
2317     case CTSF_TABLEPCT_SUM:
2318     case CTSF_SUBTABLEPCT_SUM:
2319     case CTSF_LAYERPCT_SUM:
2320     case CTSF_LAYERROWPCT_SUM:
2321     case CTSF_LAYERCOLPCT_SUM:
2322       if (!is_scale_missing)
2323         moments1_add (s->moments, value->f, e_weight);
2324       break;
2325
2326     case CTSF_MEDIAN:
2327     case CTSF_MODE:
2328     case CTSF_PTILE:
2329       if (!is_scale_missing)
2330         {
2331           s->ovalid += e_weight;
2332
2333           struct ccase *c = case_create (casewriter_get_proto (s->writer));
2334           *case_num_rw_idx (c, 0) = value->f;
2335           *case_num_rw_idx (c, 1) = e_weight;
2336           casewriter_write (s->writer, c);
2337         }
2338       break;
2339     }
2340 }
2341
2342 static enum ctables_domain_type
2343 ctables_function_domain (enum ctables_summary_function function)
2344 {
2345   switch (function)
2346     {
2347     case CTSF_COUNT:
2348     case CTSF_ECOUNT:
2349     case CTSF_MISSING:
2350     case CSTF_TOTALN:
2351     case CTSF_ETOTALN:
2352     case CTSF_VALIDN:
2353     case CTSF_EVALIDN:
2354     case CTSF_MAXIMUM:
2355     case CTSF_MINIMUM:
2356     case CTSF_RANGE:
2357     case CTSF_MEAN:
2358     case CTSF_SEMEAN:
2359     case CTSF_STDDEV:
2360     case CTSF_SUM:
2361     case CTSF_VARIANCE:
2362     case CTSF_MEDIAN:
2363     case CTSF_PTILE:
2364     case CTSF_MODE:
2365       NOT_REACHED ();
2366
2367     case CTSF_COLPCT_COUNT:
2368     case CTSF_COLPCT_SUM:
2369     case CTSF_COLPCT_TOTALN:
2370     case CTSF_COLPCT_VALIDN:
2371       return CTDT_COL;
2372
2373     case CTSF_LAYERCOLPCT_COUNT:
2374     case CTSF_LAYERCOLPCT_SUM:
2375     case CTSF_LAYERCOLPCT_TOTALN:
2376     case CTSF_LAYERCOLPCT_VALIDN:
2377       return CTDT_LAYERCOL;
2378
2379     case CTSF_LAYERPCT_COUNT:
2380     case CTSF_LAYERPCT_SUM:
2381     case CTSF_LAYERPCT_TOTALN:
2382     case CTSF_LAYERPCT_VALIDN:
2383       return CTDT_LAYER;
2384
2385     case CTSF_LAYERROWPCT_COUNT:
2386     case CTSF_LAYERROWPCT_SUM:
2387     case CTSF_LAYERROWPCT_TOTALN:
2388     case CTSF_LAYERROWPCT_VALIDN:
2389       return CTDT_LAYERROW;
2390
2391     case CTSF_ROWPCT_COUNT:
2392     case CTSF_ROWPCT_SUM:
2393     case CTSF_ROWPCT_TOTALN:
2394     case CTSF_ROWPCT_VALIDN:
2395       return CTDT_ROW;
2396
2397     case CTSF_SUBTABLEPCT_COUNT:
2398     case CTSF_SUBTABLEPCT_SUM:
2399     case CTSF_SUBTABLEPCT_TOTALN:
2400     case CTSF_SUBTABLEPCT_VALIDN:
2401       return CTDT_SUBTABLE;
2402
2403     case CTSF_TABLEPCT_COUNT:
2404     case CTSF_TABLEPCT_SUM:
2405     case CTSF_TABLEPCT_TOTALN:
2406     case CTSF_TABLEPCT_VALIDN:
2407       return CTDT_TABLE;
2408     }
2409
2410   NOT_REACHED ();
2411 }
2412
2413 static double
2414 ctables_summary_value (const struct ctables_cell *cell,
2415                        union ctables_summary *s,
2416                        const struct ctables_summary_spec *ss)
2417 {
2418   switch (ss->function)
2419     {
2420     case CTSF_COUNT:
2421     case CTSF_ECOUNT:
2422       return s->count;
2423
2424     case CTSF_ROWPCT_COUNT:
2425     case CTSF_COLPCT_COUNT:
2426     case CTSF_TABLEPCT_COUNT:
2427     case CTSF_SUBTABLEPCT_COUNT:
2428     case CTSF_LAYERPCT_COUNT:
2429     case CTSF_LAYERROWPCT_COUNT:
2430     case CTSF_LAYERCOLPCT_COUNT:
2431       {
2432         enum ctables_domain_type d = ctables_function_domain (ss->function);
2433         return (cell->domains[d]->e_count
2434                 ? s->count / cell->domains[d]->e_count * 100
2435                 : SYSMIS);
2436       }
2437
2438     case CTSF_ROWPCT_VALIDN:
2439     case CTSF_COLPCT_VALIDN:
2440     case CTSF_TABLEPCT_VALIDN:
2441     case CTSF_SUBTABLEPCT_VALIDN:
2442     case CTSF_LAYERPCT_VALIDN:
2443     case CTSF_LAYERROWPCT_VALIDN:
2444     case CTSF_LAYERCOLPCT_VALIDN:
2445       {
2446         enum ctables_domain_type d = ctables_function_domain (ss->function);
2447         return (cell->domains[d]->e_valid
2448                 ? s->count / cell->domains[d]->e_valid * 100
2449                 : SYSMIS);
2450       }
2451
2452     case CTSF_ROWPCT_TOTALN:
2453     case CTSF_COLPCT_TOTALN:
2454     case CTSF_TABLEPCT_TOTALN:
2455     case CTSF_SUBTABLEPCT_TOTALN:
2456     case CTSF_LAYERPCT_TOTALN:
2457     case CTSF_LAYERROWPCT_TOTALN:
2458     case CTSF_LAYERCOLPCT_TOTALN:
2459       {
2460         enum ctables_domain_type d = ctables_function_domain (ss->function);
2461         return (cell->domains[d]->e_total
2462                 ? s->count / cell->domains[d]->e_total * 100
2463                 : SYSMIS);
2464       }
2465
2466     case CTSF_MISSING:
2467       return s->count;
2468
2469     case CSTF_TOTALN:
2470     case CTSF_ETOTALN:
2471       return s->count;
2472
2473     case CTSF_VALIDN:
2474       return s->count;
2475
2476     case CTSF_EVALIDN:
2477       return s->count;
2478
2479     case CTSF_MAXIMUM:
2480       return s->max;
2481
2482     case CTSF_MINIMUM:
2483       return s->min;
2484
2485     case CTSF_RANGE:
2486       return s->max != SYSMIS && s->min != SYSMIS ? s->max - s->min : SYSMIS;
2487
2488     case CTSF_MEAN:
2489       {
2490         double mean;
2491         moments1_calculate (s->moments, NULL, &mean, NULL, NULL, NULL);
2492         return mean;
2493       }
2494
2495     case CTSF_SEMEAN:
2496       {
2497         double weight, variance;
2498         moments1_calculate (s->moments, &weight, NULL, &variance, NULL, NULL);
2499         return calc_semean (variance, weight);
2500       }
2501
2502     case CTSF_STDDEV:
2503       {
2504         double variance;
2505         moments1_calculate (s->moments, NULL, NULL, &variance, NULL, NULL);
2506         return variance != SYSMIS ? sqrt (variance) : SYSMIS;
2507       }
2508
2509     case CTSF_SUM:
2510       {
2511         double weight, mean;
2512         moments1_calculate (s->moments, &weight, &mean, NULL, NULL, NULL);
2513         return weight != SYSMIS && mean != SYSMIS ? weight * mean : SYSMIS;
2514       }
2515
2516     case CTSF_VARIANCE:
2517       {
2518         double variance;
2519         moments1_calculate (s->moments, NULL, NULL, &variance, NULL, NULL);
2520         return variance;
2521       }
2522
2523     case CTSF_ROWPCT_SUM:
2524     case CTSF_COLPCT_SUM:
2525     case CTSF_TABLEPCT_SUM:
2526     case CTSF_SUBTABLEPCT_SUM:
2527     case CTSF_LAYERPCT_SUM:
2528     case CTSF_LAYERROWPCT_SUM:
2529     case CTSF_LAYERCOLPCT_SUM:
2530       NOT_REACHED ();
2531
2532     case CTSF_MEDIAN:
2533     case CTSF_PTILE:
2534       if (s->writer)
2535         {
2536           struct casereader *reader = casewriter_make_reader (s->writer);
2537           s->writer = NULL;
2538
2539           struct percentile *ptile = percentile_create (
2540             ss->function == CTSF_PTILE ? ss->percentile : 0.5, s->ovalid);
2541           struct order_stats *os = &ptile->parent;
2542           order_stats_accumulate_idx (&os, 1, reader, 1, 0);
2543           s->ovalue = percentile_calculate (ptile, PC_HAVERAGE);
2544           statistic_destroy (&ptile->parent.parent);
2545         }
2546       return s->ovalue;
2547
2548     case CTSF_MODE:
2549       if (s->writer)
2550         {
2551           struct casereader *reader = casewriter_make_reader (s->writer);
2552           s->writer = NULL;
2553
2554           struct mode *mode = mode_create ();
2555           struct order_stats *os = &mode->parent;
2556           order_stats_accumulate_idx (&os, 1, reader, 1, 0);
2557           s->ovalue = mode->mode;
2558           statistic_destroy (&mode->parent.parent);
2559         }
2560       return s->ovalue;
2561     }
2562
2563   NOT_REACHED ();
2564 }
2565
2566 struct ctables_cell_sort_aux
2567   {
2568     const struct ctables_nest *nest;
2569     enum pivot_axis_type a;
2570   };
2571
2572 static int
2573 ctables_cell_compare_3way (const void *a_, const void *b_, const void *aux_)
2574 {
2575   const struct ctables_cell_sort_aux *aux = aux_;
2576   struct ctables_cell *const *ap = a_;
2577   struct ctables_cell *const *bp = b_;
2578   const struct ctables_cell *a = *ap;
2579   const struct ctables_cell *b = *bp;
2580
2581   const struct ctables_nest *nest = aux->nest;
2582   for (size_t i = 0; i < nest->n; i++)
2583     if (i != nest->scale_idx)
2584       {
2585         const struct variable *var = nest->vars[i];
2586         const struct ctables_cell_value *a_cv = &a->axes[aux->a].cvs[i];
2587         const struct ctables_cell_value *b_cv = &b->axes[aux->a].cvs[i];
2588         if (a_cv->category != b_cv->category)
2589           return a_cv->category > b_cv->category ? 1 : -1;
2590
2591         const union value *a_val = &a_cv->value;
2592         const union value *b_val = &b_cv->value;
2593         switch (a_cv->category->type)
2594           {
2595           case CCT_NUMBER:
2596           case CCT_STRING:
2597           case CCT_SUBTOTAL:
2598           case CCT_TOTAL:
2599           case CCT_POSTCOMPUTE:
2600           case CCT_EXCLUDED_MISSING:
2601             /* Must be equal. */
2602             continue;
2603
2604           case CCT_RANGE:
2605           case CCT_MISSING:
2606           case CCT_OTHERNM:
2607             {
2608               int cmp = value_compare_3way (a_val, b_val, var_get_width (var));
2609               if (cmp)
2610                 return cmp;
2611             }
2612             break;
2613
2614           case CCT_VALUE:
2615             {
2616               int cmp = value_compare_3way (a_val, b_val, var_get_width (var));
2617               if (cmp)
2618                 return a_cv->category->sort_ascending ? cmp : -cmp;
2619             }
2620             break;
2621
2622           case CCT_LABEL:
2623             {
2624               const char *a_label = var_lookup_value_label (var, a_val);
2625               const char *b_label = var_lookup_value_label (var, b_val);
2626               int cmp = (a_label
2627                          ? (b_label ? strcmp (a_label, b_label) : 1)
2628                          : (b_label ? -1 : value_compare_3way (
2629                               a_val, b_val, var_get_width (var))));
2630               if (cmp)
2631                 return a_cv->category->sort_ascending ? cmp : -cmp;
2632             }
2633             break;
2634
2635           case CCT_FUNCTION:
2636             NOT_REACHED ();
2637           }
2638       }
2639   return 0;
2640 }
2641
2642 /* Algorithm:
2643
2644    For each row:
2645        For each ctables_table:
2646            For each combination of row vars:
2647                For each combination of column vars:
2648                    For each combination of layer vars:
2649                        Add entry
2650    Make a table of row values:
2651        Sort entries by row values
2652        Assign a 0-based index to each actual value
2653        Construct a dimension
2654    Make a table of column values
2655    Make a table of layer values
2656    For each entry:
2657        Fill the table entry using the indexes from before.
2658  */
2659
2660 static struct ctables_domain *
2661 ctables_domain_insert (struct ctables_section *s, struct ctables_cell *cell,
2662                        enum ctables_domain_type domain)
2663 {
2664   size_t hash = 0;
2665   for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
2666     {
2667       const struct ctables_nest *nest = s->nests[a];
2668       for (size_t i = 0; i < nest->n_domains[domain]; i++)
2669         {
2670           size_t v_idx = nest->domains[domain][i];
2671           struct ctables_cell_value *cv = &cell->axes[a].cvs[v_idx];
2672           hash = hash_pointer (cv->category, hash);
2673           if (cv->category->type != CCT_TOTAL
2674               && cv->category->type != CCT_SUBTOTAL
2675               && cv->category->type != CCT_POSTCOMPUTE)
2676             hash = value_hash (&cv->value,
2677                                var_get_width (nest->vars[v_idx]), hash);
2678         }
2679     }
2680
2681   struct ctables_domain *d;
2682   HMAP_FOR_EACH_WITH_HASH (d, struct ctables_domain, node, hash, &s->domains[domain])
2683     {
2684       const struct ctables_cell *df = d->example;
2685       for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
2686         {
2687           const struct ctables_nest *nest = s->nests[a];
2688           for (size_t i = 0; i < nest->n_domains[domain]; i++)
2689             {
2690               size_t v_idx = nest->domains[domain][i];
2691               struct ctables_cell_value *cv1 = &df->axes[a].cvs[v_idx];
2692               struct ctables_cell_value *cv2 = &cell->axes[a].cvs[v_idx];
2693               if (cv1->category != cv2->category
2694                   || (cv1->category->type != CCT_TOTAL
2695                       && cv1->category->type != CCT_SUBTOTAL
2696                       && cv1->category->type != CCT_POSTCOMPUTE
2697                       && !value_equal (&cv1->value, &cv2->value,
2698                                        var_get_width (nest->vars[v_idx]))))
2699                 goto not_equal;
2700             }
2701         }
2702       return d;
2703
2704     not_equal: ;
2705     }
2706
2707   d = xmalloc (sizeof *d);
2708   *d = (struct ctables_domain) { .example = cell };
2709   hmap_insert (&s->domains[domain], &d->node, hash);
2710   return d;
2711 }
2712
2713 static const struct ctables_category *
2714 ctables_categories_match (const struct ctables_categories *c,
2715                           const union value *v, const struct variable *var)
2716 {
2717   if (var_is_numeric (var) && v->f == SYSMIS)
2718     return NULL;
2719
2720   const struct ctables_category *othernm = NULL;
2721   for (size_t i = c->n_cats; i-- > 0; )
2722     {
2723       const struct ctables_category *cat = &c->cats[i];
2724       switch (cat->type)
2725         {
2726         case CCT_NUMBER:
2727           if (cat->number == v->f)
2728             return cat;
2729           break;
2730
2731         case CCT_STRING:
2732           NOT_REACHED ();
2733
2734         case CCT_RANGE:
2735           if ((cat->range[0] == -DBL_MAX || v->f >= cat->range[0])
2736               && (cat->range[1] == DBL_MAX || v->f <= cat->range[1]))
2737             return cat;
2738           break;
2739
2740         case CCT_MISSING:
2741           if (var_is_value_missing (var, v))
2742             return cat;
2743           break;
2744
2745         case CCT_POSTCOMPUTE:
2746           break;
2747
2748         case CCT_OTHERNM:
2749           if (!othernm)
2750             othernm = cat;
2751           break;
2752
2753         case CCT_SUBTOTAL:
2754         case CCT_TOTAL:
2755           break;
2756
2757         case CCT_VALUE:
2758         case CCT_LABEL:
2759         case CCT_FUNCTION:
2760           return (cat->include_missing || !var_is_value_missing (var, v) ? cat
2761                   : NULL);
2762
2763         case CCT_EXCLUDED_MISSING:
2764           break;
2765         }
2766     }
2767
2768   return var_is_value_missing (var, v) ? NULL : othernm;
2769 }
2770
2771 static const struct ctables_category *
2772 ctables_categories_total (const struct ctables_categories *c)
2773 {
2774   const struct ctables_category *first = &c->cats[0];
2775   const struct ctables_category *last = &c->cats[c->n_cats - 1];
2776   return (first->type == CCT_TOTAL ? first
2777           : last->type == CCT_TOTAL ? last
2778           : NULL);
2779 }
2780
2781 static struct ctables_cell *
2782 ctables_cell_insert__ (struct ctables_section *s, const struct ccase *c,
2783                        const struct ctables_category *cats[PIVOT_N_AXES][10])
2784 {
2785   size_t hash = 0;
2786   enum ctables_summary_variant sv = CSV_CELL;
2787   for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
2788     {
2789       const struct ctables_nest *nest = s->nests[a];
2790       for (size_t i = 0; i < nest->n; i++)
2791         if (i != nest->scale_idx)
2792           {
2793             hash = hash_pointer (cats[a][i], hash);
2794             if (cats[a][i]->type != CCT_TOTAL
2795                 && cats[a][i]->type != CCT_SUBTOTAL
2796                 && cats[a][i]->type != CCT_POSTCOMPUTE)
2797               hash = value_hash (case_data (c, nest->vars[i]),
2798                                  var_get_width (nest->vars[i]), hash);
2799             else
2800               sv = CSV_TOTAL;
2801           }
2802     }
2803
2804   struct ctables_cell *cell;
2805   HMAP_FOR_EACH_WITH_HASH (cell, struct ctables_cell, node, hash, &s->cells)
2806     {
2807       for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
2808         {
2809           const struct ctables_nest *nest = s->nests[a];
2810           for (size_t i = 0; i < nest->n; i++)
2811             if (i != nest->scale_idx
2812                 && (cats[a][i] != cell->axes[a].cvs[i].category
2813                     || (cats[a][i]->type != CCT_TOTAL
2814                         && cats[a][i]->type != CCT_SUBTOTAL
2815                         && cats[a][i]->type != CCT_POSTCOMPUTE
2816                         && !value_equal (case_data (c, nest->vars[i]),
2817                                          &cell->axes[a].cvs[i].value,
2818                                          var_get_width (nest->vars[i])))))
2819                 goto not_equal;
2820         }
2821
2822       return cell;
2823
2824     not_equal: ;
2825     }
2826
2827   cell = xmalloc (sizeof *cell);
2828   cell->hide = false;
2829   cell->sv = sv;
2830   cell->omit_domains = 0;
2831   cell->postcompute = false;
2832   //struct string name = DS_EMPTY_INITIALIZER;
2833   for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
2834     {
2835       const struct ctables_nest *nest = s->nests[a];
2836       cell->axes[a].cvs = (nest->n
2837                            ? xnmalloc (nest->n, sizeof *cell->axes[a].cvs)
2838                            : NULL);
2839       for (size_t i = 0; i < nest->n; i++)
2840         {
2841           const struct ctables_category *cat = cats[a][i];
2842           const struct variable *var = nest->vars[i];
2843           const union value *value = case_data (c, var);
2844           if (i != nest->scale_idx)
2845             {
2846               const struct ctables_category *subtotal = cat->subtotal;
2847               if (cat->hide || (subtotal && subtotal->hide_subcategories))
2848                 cell->hide = true;
2849
2850               if (cat->type == CCT_TOTAL
2851                   || cat->type == CCT_SUBTOTAL
2852                   || cat->type == CCT_POSTCOMPUTE)
2853                 {
2854                   /* XXX these should be more encompassing I think.*/
2855
2856                   switch (a)
2857                     {
2858                     case PIVOT_AXIS_COLUMN:
2859                       cell->omit_domains |= ((1u << CTDT_TABLE) |
2860                                              (1u << CTDT_LAYER) |
2861                                              (1u << CTDT_LAYERCOL) |
2862                                              (1u << CTDT_SUBTABLE) |
2863                                              (1u << CTDT_COL));
2864                       break;
2865                     case PIVOT_AXIS_ROW:
2866                       cell->omit_domains |= ((1u << CTDT_TABLE) |
2867                                              (1u << CTDT_LAYER) |
2868                                              (1u << CTDT_LAYERROW) |
2869                                              (1u << CTDT_SUBTABLE) |
2870                                              (1u << CTDT_ROW));
2871                       break;
2872                     case PIVOT_AXIS_LAYER:
2873                       cell->omit_domains |= ((1u << CTDT_TABLE) |
2874                                              (1u << CTDT_LAYER));
2875                       break;
2876                     }
2877                 }
2878               if (cat->type == CCT_POSTCOMPUTE)
2879                 cell->postcompute = true;
2880             }
2881
2882           cell->axes[a].cvs[i].category = cat;
2883           value_clone (&cell->axes[a].cvs[i].value, value, var_get_width (var));
2884
2885 #if 0
2886           if (i != nest->scale_idx)
2887             {
2888               if (!ds_is_empty (&name))
2889                 ds_put_cstr (&name, ", ");
2890               char *value_s = data_out (value, var_get_encoding (var),
2891                                         var_get_print_format (var),
2892                                         settings_get_fmt_settings ());
2893               if (cat->type == CCT_TOTAL
2894                   || cat->type == CCT_SUBTOTAL
2895                   || cat->type == CCT_POSTCOMPUTE)
2896                 ds_put_format (&name, "%s=total", var_get_name (var));
2897               else
2898                 ds_put_format (&name, "%s=%s", var_get_name (var),
2899                                value_s + strspn (value_s, " "));
2900               free (value_s);
2901             }
2902 #endif
2903         }
2904     }
2905   //cell->name = ds_steal_cstr (&name);
2906
2907   const struct ctables_nest *ss = s->nests[s->table->summary_axis];
2908   const struct ctables_summary_spec_set *specs = &ss->specs[cell->sv];
2909   cell->summaries = xmalloc (specs->n * sizeof *cell->summaries);
2910   for (size_t i = 0; i < specs->n; i++)
2911     ctables_summary_init (&cell->summaries[i], &specs->specs[i]);
2912   for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
2913     cell->domains[dt] = ctables_domain_insert (s, cell, dt);
2914   hmap_insert (&s->cells, &cell->node, hash);
2915   return cell;
2916 }
2917
2918 static bool
2919 is_scale_missing (const struct ctables_summary_spec_set *specs,
2920                   const struct ccase *c)
2921 {
2922   if (!specs->is_scale)
2923     return false;
2924
2925   if (var_is_num_missing (specs->var, case_num (c, specs->var)))
2926     return true;
2927
2928   for (size_t i = 0; i < specs->n_listwise_vars; i++)
2929     {
2930       const struct variable *var = specs->listwise_vars[i];
2931       if (var_is_num_missing (var, case_num (c, var)))
2932         return true;
2933     }
2934
2935   return false;
2936 }
2937
2938 static void
2939 ctables_cell_add__ (struct ctables_section *s, const struct ccase *c,
2940                     const struct ctables_category *cats[PIVOT_N_AXES][10],
2941                     bool is_missing, bool excluded_missing,
2942                     double d_weight, double e_weight)
2943 {
2944   struct ctables_cell *cell = ctables_cell_insert__ (s, c, cats);
2945   const struct ctables_nest *ss = s->nests[s->table->summary_axis];
2946
2947   const struct ctables_summary_spec_set *specs = &ss->specs[cell->sv];
2948
2949   bool scale_missing = is_scale_missing (specs, c);
2950   for (size_t i = 0; i < specs->n; i++)
2951     ctables_summary_add (&cell->summaries[i], &specs->specs[i],
2952                          specs->var, case_data (c, specs->var), specs->is_scale,
2953                          scale_missing, is_missing, excluded_missing,
2954                          d_weight, e_weight);
2955   for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
2956     if (!(cell->omit_domains && (1u << dt)))
2957       {
2958         struct ctables_domain *d = cell->domains[dt];
2959         d->d_total += d_weight;
2960         d->e_total += e_weight;
2961         if (!excluded_missing)
2962           {
2963             d->d_count += d_weight;
2964             d->e_count += e_weight;
2965           }
2966         if (!is_missing)
2967           {
2968             d->d_valid += d_weight;
2969             d->e_valid += e_weight;
2970           }
2971       }
2972 }
2973
2974 static void
2975 recurse_totals (struct ctables_section *s, const struct ccase *c,
2976                 const struct ctables_category *cats[PIVOT_N_AXES][10],
2977                 bool is_missing, bool excluded_missing,
2978                 double d_weight, double e_weight,
2979                 enum pivot_axis_type start_axis, size_t start_nest)
2980 {
2981   for (enum pivot_axis_type a = start_axis; a < PIVOT_N_AXES; a++)
2982     {
2983       const struct ctables_nest *nest = s->nests[a];
2984       for (size_t i = start_nest; i < nest->n; i++)
2985         {
2986           if (i == nest->scale_idx)
2987             continue;
2988
2989           const struct variable *var = nest->vars[i];
2990
2991           const struct ctables_category *total = ctables_categories_total (
2992             s->table->categories[var_get_dict_index (var)]);
2993           if (total)
2994             {
2995               const struct ctables_category *save = cats[a][i];
2996               cats[a][i] = total;
2997               ctables_cell_add__ (s, c, cats, is_missing, excluded_missing,
2998                                   d_weight, e_weight);
2999               recurse_totals (s, c, cats, is_missing, excluded_missing,
3000                               d_weight, e_weight, a, i + 1);
3001               cats[a][i] = save;
3002             }
3003         }
3004       start_nest = 0;
3005     }
3006 }
3007
3008 static void
3009 recurse_subtotals (struct ctables_section *s, const struct ccase *c,
3010                    const struct ctables_category *cats[PIVOT_N_AXES][10],
3011                    bool is_missing, bool excluded_missing,
3012                    double d_weight, double e_weight,
3013                    enum pivot_axis_type start_axis, size_t start_nest)
3014 {
3015   for (enum pivot_axis_type a = start_axis; a < PIVOT_N_AXES; a++)
3016     {
3017       const struct ctables_nest *nest = s->nests[a];
3018       for (size_t i = start_nest; i < nest->n; i++)
3019         {
3020           if (i == nest->scale_idx)
3021             continue;
3022
3023           const struct ctables_category *save = cats[a][i];
3024           if (save->subtotal)
3025             {
3026               cats[a][i] = save->subtotal;
3027               ctables_cell_add__ (s, c, cats, is_missing, excluded_missing,
3028                                   d_weight, e_weight);
3029               recurse_subtotals (s, c, cats, is_missing, excluded_missing,
3030                                  d_weight, e_weight, a, i + 1);
3031               cats[a][i] = save;
3032             }
3033         }
3034       start_nest = 0;
3035     }
3036 }
3037
3038 static void
3039 ctables_add_occurrence (const struct variable *var,
3040                         const union value *value,
3041                         struct hmap *occurrences)
3042 {
3043   int width = var_get_width (var);
3044   unsigned int hash = value_hash (value, width, 0);
3045
3046   struct ctables_occurrence *o;
3047   HMAP_FOR_EACH_WITH_HASH (o, struct ctables_occurrence, node, hash,
3048                            occurrences)
3049     if (value_equal (value, &o->value, width))
3050       return;
3051
3052   o = xmalloc (sizeof *o);
3053   value_clone (&o->value, value, width);
3054   hmap_insert (occurrences, &o->node, hash);
3055 }
3056
3057 static void
3058 ctables_cell_insert (struct ctables_section *s,
3059                      const struct ccase *c,
3060                      double d_weight, double e_weight)
3061 {
3062   const struct ctables_category *cats[PIVOT_N_AXES][10]; /* XXX */
3063
3064   /* Does at least one categorical variable have a missing value in an included
3065      or excluded category? */
3066   bool is_missing = false;
3067
3068   /* Does at least one categorical variable have a missing value in an excluded
3069      category? */
3070   bool excluded_missing = false;
3071
3072   for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
3073     {
3074       const struct ctables_nest *nest = s->nests[a];
3075       for (size_t i = 0; i < nest->n; i++)
3076         {
3077           if (i == nest->scale_idx)
3078             continue;
3079
3080           const struct variable *var = nest->vars[i];
3081           const union value *value = case_data (c, var);
3082
3083           bool var_missing = var_is_value_missing (var, value) != 0;
3084           if (var_missing)
3085             is_missing = true;
3086
3087           cats[a][i] = ctables_categories_match (
3088             s->table->categories[var_get_dict_index (var)], value, var);
3089           if (!cats[a][i])
3090             {
3091               if (!var_missing)
3092                 return;
3093
3094               static const struct ctables_category cct_excluded_missing = {
3095                 .type = CCT_EXCLUDED_MISSING,
3096                 .hide = true,
3097               };
3098               cats[a][i] = &cct_excluded_missing;
3099               excluded_missing = true;
3100             }
3101         }
3102     }
3103
3104   if (!excluded_missing)
3105     for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
3106       {
3107         const struct ctables_nest *nest = s->nests[a];
3108         for (size_t i = 0; i < nest->n; i++)
3109           if (i != nest->scale_idx)
3110             {
3111               const struct variable *var = nest->vars[i];
3112               const union value *value = case_data (c, var);
3113               ctables_add_occurrence (var, value, &s->occurrences[a][i]);
3114             }
3115       }
3116
3117   ctables_cell_add__ (s, c, cats, is_missing, excluded_missing,
3118                       d_weight, e_weight);
3119
3120   //if (!excluded_missing)
3121     {
3122       recurse_totals (s, c, cats, is_missing, excluded_missing,
3123                       d_weight, e_weight, 0, 0);
3124       recurse_subtotals (s, c, cats, is_missing, excluded_missing,
3125                          d_weight, e_weight, 0, 0);
3126     }
3127 }
3128
3129 struct merge_item
3130   {
3131     const struct ctables_summary_spec_set *set;
3132     size_t ofs;
3133   };
3134
3135 static int
3136 merge_item_compare_3way (const struct merge_item *a, const struct merge_item *b)
3137 {
3138   const struct ctables_summary_spec *as = &a->set->specs[a->ofs];
3139   const struct ctables_summary_spec *bs = &b->set->specs[b->ofs];
3140   if (as->function != bs->function)
3141     return as->function > bs->function ? 1 : -1;
3142   else if (as->percentile != bs->percentile)
3143     return as->percentile < bs->percentile ? 1 : -1;
3144   return strcmp (as->label, bs->label);
3145 }
3146
3147 static struct pivot_value *
3148 ctables_category_create_label (const struct ctables_category *cat,
3149                                const struct variable *var,
3150                                const union value *value)
3151 {
3152   return (cat->type == CCT_TOTAL || cat->type == CCT_SUBTOTAL
3153           ? pivot_value_new_user_text (cat->total_label, SIZE_MAX)
3154           : cat->type == CCT_POSTCOMPUTE && cat->pc->label
3155           ? pivot_value_new_user_text (cat->pc->label, SIZE_MAX)
3156           : pivot_value_new_var_value (var, value));
3157 }
3158
3159 static struct ctables_value *
3160 ctables_value_find__ (struct ctables_table *t, const union value *value,
3161                       int width, unsigned int hash)
3162 {
3163   struct ctables_value *clv;
3164   HMAP_FOR_EACH_WITH_HASH (clv, struct ctables_value, node,
3165                            hash, &t->clabels_values_map)
3166     if (value_equal (value, &clv->value, width))
3167       return clv;
3168   return NULL;
3169 }
3170
3171 static void
3172 ctables_value_insert (struct ctables_table *t, const union value *value,
3173                       int width)
3174 {
3175   unsigned int hash = value_hash (value, width, 0);
3176   struct ctables_value *clv = ctables_value_find__ (t, value, width, hash);
3177   if (!clv)
3178     {
3179       clv = xmalloc (sizeof *clv);
3180       value_clone (&clv->value, value, width);
3181       hmap_insert (&t->clabels_values_map, &clv->node, hash);
3182     }
3183 }
3184
3185 static struct ctables_value *
3186 ctables_value_find (struct ctables_table *t,
3187                     const union value *value, int width)
3188 {
3189   return ctables_value_find__ (t, value, width,
3190                                value_hash (value, width, 0));
3191 }
3192
3193 static void
3194 ctables_table_add_section (struct ctables_table *t, enum pivot_axis_type a,
3195                            size_t ix[PIVOT_N_AXES])
3196 {
3197   if (a < PIVOT_N_AXES)
3198     {
3199       size_t limit = MAX (t->stacks[a].n, 1);
3200       for (ix[a] = 0; ix[a] < limit; ix[a]++)
3201         ctables_table_add_section (t, a + 1, ix);
3202     }
3203   else
3204     {
3205       struct ctables_section *s = &t->sections[t->n_sections++];
3206       *s = (struct ctables_section) {
3207         .table = t,
3208         .cells = HMAP_INITIALIZER (s->cells),
3209       };
3210       for (a = 0; a < PIVOT_N_AXES; a++)
3211         if (t->stacks[a].n)
3212           {
3213             struct ctables_nest *nest = &t->stacks[a].nests[ix[a]];
3214             s->nests[a] = nest;
3215             s->occurrences[a] = xnmalloc (nest->n, sizeof *s->occurrences[a]);
3216             for (size_t i = 0; i < nest->n; i++)
3217               hmap_init (&s->occurrences[a][i]);
3218         }
3219       for (size_t i = 0; i < N_CTDTS; i++)
3220         hmap_init (&s->domains[i]);
3221     }
3222 }
3223
3224 static double
3225 ctpo_add (double a, double b)
3226 {
3227   return a + b;
3228 }
3229
3230 static double
3231 ctpo_sub (double a, double b)
3232 {
3233   return a - b;
3234 }
3235
3236 static double
3237 ctpo_mul (double a, double b)
3238 {
3239   return a * b;
3240 }
3241
3242 static double
3243 ctpo_div (double a, double b)
3244 {
3245   return b ? a / b : SYSMIS;
3246 }
3247
3248 static double
3249 ctpo_pow (double a, double b)
3250 {
3251   int save_errno = errno;
3252   errno = 0;
3253   double result = pow (a, b);
3254   if (errno)
3255     result = SYSMIS;
3256   errno = save_errno;
3257   return result;
3258 }
3259
3260 static double
3261 ctpo_neg (double a, double b UNUSED)
3262 {
3263   return -a;
3264 }
3265
3266 struct ctables_pcexpr_evaluate_ctx
3267   {
3268     const struct ctables_cell *cell;
3269     const struct ctables_section *section;
3270     const struct ctables_categories *cats;
3271     enum pivot_axis_type pc_a;
3272     size_t pc_a_idx;
3273   };
3274
3275 static double ctables_pcexpr_evaluate (
3276   const struct ctables_pcexpr_evaluate_ctx *, const struct ctables_pcexpr *);
3277
3278 static double
3279 ctables_pcexpr_evaluate_nonterminal (
3280   const struct ctables_pcexpr_evaluate_ctx *ctx,
3281   const struct ctables_pcexpr *e, size_t n_args,
3282   double evaluate (double, double))
3283 {
3284   double args[2] = { 0, 0 };
3285   for (size_t i = 0; i < n_args; i++)
3286     {
3287       args[i] = ctables_pcexpr_evaluate (ctx, e->subs[i]);
3288       if (!isfinite (args[i]) || args[i] == SYSMIS)
3289         return SYSMIS;
3290     }
3291   return evaluate (args[0], args[1]);
3292 }
3293
3294 static double
3295 ctables_pcexpr_evaluate_category (const struct ctables_pcexpr_evaluate_ctx *ctx,
3296                                   const struct ctables_cell_value *pc_cv)
3297 {
3298   const struct ctables_section *s = ctx->section;
3299
3300   size_t hash = 0;
3301   for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
3302     {
3303       const struct ctables_nest *nest = s->nests[a];
3304       for (size_t i = 0; i < nest->n; i++)
3305         if (i != nest->scale_idx)
3306           {
3307             const struct ctables_cell_value *cv
3308               = (a == ctx->pc_a && i == ctx->pc_a_idx ? pc_cv
3309                  : &ctx->cell->axes[a].cvs[i]);
3310             hash = hash_pointer (cv->category, hash);
3311             if (cv->category->type != CCT_TOTAL
3312                 && cv->category->type != CCT_SUBTOTAL
3313                 && cv->category->type != CCT_POSTCOMPUTE)
3314               hash = value_hash (&cv->value,
3315                                  var_get_width (nest->vars[i]), hash);
3316           }
3317     }
3318
3319   struct ctables_cell *tc;
3320   HMAP_FOR_EACH_WITH_HASH (tc, struct ctables_cell, node, hash, &s->cells)
3321     {
3322       for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
3323         {
3324           const struct ctables_nest *nest = s->nests[a];
3325           for (size_t i = 0; i < nest->n; i++)
3326             if (i != nest->scale_idx)
3327               {
3328                 const struct ctables_cell_value *p_cv
3329                   = (a == ctx->pc_a && i == ctx->pc_a_idx ? pc_cv
3330                      : &ctx->cell->axes[a].cvs[i]);
3331                 const struct ctables_cell_value *t_cv = &tc->axes[a].cvs[i];
3332                 if (p_cv->category != t_cv->category
3333                     || (p_cv->category->type != CCT_TOTAL
3334                         && p_cv->category->type != CCT_SUBTOTAL
3335                         && p_cv->category->type != CCT_POSTCOMPUTE
3336                         && !value_equal (&p_cv->value,
3337                                          &t_cv->value,
3338                                          var_get_width (nest->vars[i]))))
3339                   goto not_equal;
3340               }
3341         }
3342
3343       goto found;
3344
3345     not_equal: ;
3346     }
3347   return 0;
3348
3349 found: ;
3350   const struct ctables_table *t = s->table;
3351   const struct ctables_nest *specs_nest = s->nests[t->summary_axis];
3352   const struct ctables_summary_spec_set *specs = &specs_nest->specs[tc->sv];
3353   size_t j = 0 /* XXX */;
3354   return ctables_summary_value (tc, &tc->summaries[j], &specs->specs[j]);
3355 }
3356
3357 static double
3358 ctables_pcexpr_evaluate (const struct ctables_pcexpr_evaluate_ctx *ctx,
3359                          const struct ctables_pcexpr *e)
3360 {
3361   switch (e->op)
3362     {
3363     case CTPO_CONSTANT:
3364       return e->number;
3365
3366     case CTPO_CAT_RANGE:
3367       {
3368         struct ctables_cell_value cv = {
3369           .category = ctables_find_category_for_postcompute (ctx->cats, e)
3370         };
3371         assert (cv.category != NULL);
3372
3373         struct hmap *occurrences = &ctx->section->occurrences[ctx->pc_a][ctx->pc_a_idx];
3374         const struct ctables_occurrence *o;
3375
3376         double sum = 0.0;
3377         const struct variable *var = ctx->section->nests[ctx->pc_a]->vars[ctx->pc_a_idx];
3378         HMAP_FOR_EACH (o, struct ctables_occurrence, node, occurrences)
3379           if (ctables_categories_match (ctx->cats, &o->value, var) == cv.category)
3380             {
3381               cv.value = o->value;
3382               sum += ctables_pcexpr_evaluate_category (ctx, &cv);
3383             }
3384         return sum;
3385       }
3386
3387     case CTPO_CAT_NUMBER:
3388     case CTPO_CAT_STRING:
3389     case CTPO_CAT_MISSING:
3390     case CTPO_CAT_OTHERNM:
3391     case CTPO_CAT_SUBTOTAL:
3392     case CTPO_CAT_TOTAL:
3393       {
3394         struct ctables_cell_value cv = {
3395           .category = ctables_find_category_for_postcompute (ctx->cats, e),
3396           .value = { .f = e->number },
3397         };
3398         assert (cv.category != NULL);
3399         return ctables_pcexpr_evaluate_category (ctx, &cv);
3400       }
3401
3402     case CTPO_ADD:
3403       return ctables_pcexpr_evaluate_nonterminal (ctx, e, 2, ctpo_add);
3404
3405     case CTPO_SUB:
3406       return ctables_pcexpr_evaluate_nonterminal (ctx, e, 2, ctpo_sub);
3407
3408     case CTPO_MUL:
3409       return ctables_pcexpr_evaluate_nonterminal (ctx, e, 2, ctpo_mul);
3410
3411     case CTPO_DIV:
3412       return ctables_pcexpr_evaluate_nonterminal (ctx, e, 2, ctpo_div);
3413
3414     case CTPO_POW:
3415       return ctables_pcexpr_evaluate_nonterminal (ctx, e, 2, ctpo_pow);
3416
3417     case CTPO_NEG:
3418       return ctables_pcexpr_evaluate_nonterminal (ctx, e, 1, ctpo_neg);
3419     }
3420
3421   NOT_REACHED ();
3422 }
3423
3424 static double
3425 ctables_cell_calculate_postcompute (const struct ctables_section *s,
3426                                     const struct ctables_cell *cell)
3427 {
3428   enum pivot_axis_type pc_a;
3429   size_t pc_a_idx;
3430   const struct ctables_postcompute *pc;
3431   for (pc_a = 0; ; pc_a++)
3432     {
3433       assert (pc_a < PIVOT_N_AXES);
3434       for (pc_a_idx = 0; pc_a_idx < s->nests[pc_a]->n; pc_a_idx++)
3435         {
3436           const struct ctables_cell_value *cv = &cell->axes[pc_a].cvs[pc_a_idx];
3437           if (cv->category->type == CCT_POSTCOMPUTE)
3438             {
3439               pc = cv->category->pc;
3440               goto found;
3441             }
3442         }
3443     }
3444 found: ;
3445
3446   const struct variable *var = s->nests[pc_a]->vars[pc_a_idx];
3447   const struct ctables_categories *cats = s->table->categories[
3448     var_get_dict_index (var)];
3449   struct ctables_pcexpr_evaluate_ctx ctx = {
3450     .cell = cell,
3451     .section = s,
3452     .cats = cats,
3453     .pc_a = pc_a,
3454     .pc_a_idx = pc_a_idx,
3455   };
3456   return ctables_pcexpr_evaluate (&ctx, pc->expr);
3457 }
3458
3459 static void
3460 ctables_table_output (struct ctables *ct, struct ctables_table *t)
3461 {
3462   struct pivot_table *pt = pivot_table_create__ (
3463     (t->title
3464      ? pivot_value_new_user_text (t->title, SIZE_MAX)
3465      : pivot_value_new_text (N_("Custom Tables"))),
3466     "Custom Tables");
3467   if (t->caption)
3468     pivot_table_set_caption (
3469       pt, pivot_value_new_user_text (t->caption, SIZE_MAX));
3470   if (t->corner)
3471     pivot_table_set_caption (
3472       pt, pivot_value_new_user_text (t->corner, SIZE_MAX));
3473
3474   bool summary_dimension = (t->summary_axis != t->slabels_axis
3475                             || (!t->slabels_visible
3476                                 && t->summary_specs.n > 1));
3477   if (summary_dimension)
3478     {
3479       struct pivot_dimension *d = pivot_dimension_create (
3480         pt, t->slabels_axis, N_("Statistics"));
3481       const struct ctables_summary_spec_set *specs = &t->summary_specs;
3482       if (!t->slabels_visible)
3483         d->hide_all_labels = true;
3484       for (size_t i = 0; i < specs->n; i++)
3485         pivot_category_create_leaf (
3486           d->root, pivot_value_new_text (specs->specs[i].label));
3487     }
3488
3489   bool categories_dimension = t->clabels_example != NULL;
3490   if (categories_dimension)
3491     {
3492       struct pivot_dimension *d = pivot_dimension_create (
3493         pt, t->label_axis[t->clabels_from_axis],
3494         t->clabels_from_axis == PIVOT_AXIS_ROW
3495         ? N_("Row Categories")
3496         : N_("Column Categories"));
3497       const struct variable *var = t->clabels_example;
3498       const struct ctables_categories *c = t->categories[var_get_dict_index (var)];
3499       for (size_t i = 0; i < t->n_clabels_values; i++)
3500         {
3501           const struct ctables_value *value = t->clabels_values[i];
3502           const struct ctables_category *cat = ctables_categories_match (c, &value->value, var);
3503           assert (cat != NULL);
3504           pivot_category_create_leaf (d->root, ctables_category_create_label (
3505                                         cat, t->clabels_example, &value->value));
3506         }
3507     }
3508
3509   pivot_table_set_look (pt, ct->look);
3510   struct pivot_dimension *d[PIVOT_N_AXES];
3511   for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
3512     {
3513       static const char *names[] = {
3514         [PIVOT_AXIS_ROW] = N_("Rows"),
3515         [PIVOT_AXIS_COLUMN] = N_("Columns"),
3516         [PIVOT_AXIS_LAYER] = N_("Layers"),
3517       };
3518       d[a] = (t->axes[a] || a == t->summary_axis
3519               ? pivot_dimension_create (pt, a, names[a])
3520               : NULL);
3521       if (!d[a])
3522         continue;
3523
3524       assert (t->axes[a]);
3525
3526       for (size_t i = 0; i < t->stacks[a].n; i++)
3527         {
3528           struct ctables_nest *nest = &t->stacks[a].nests[i];
3529           struct ctables_section **sections = xnmalloc (t->n_sections,
3530                                                         sizeof *sections);
3531           size_t n_sections = 0;
3532
3533           size_t n_total_cells = 0;
3534           size_t max_depth = 0;
3535           for (size_t j = 0; j < t->n_sections; j++)
3536             if (t->sections[j].nests[a] == nest)
3537               {
3538                 struct ctables_section *s = &t->sections[j];
3539                 sections[n_sections++] = s;
3540                 n_total_cells += s->cells.count;
3541
3542                 size_t depth = s->nests[a]->n;
3543                 max_depth = MAX (depth, max_depth);
3544               }
3545
3546           struct ctables_cell **sorted = xnmalloc (n_total_cells,
3547                                                    sizeof *sorted);
3548           size_t n_sorted = 0;
3549
3550           for (size_t j = 0; j < n_sections; j++)
3551             {
3552               struct ctables_section *s = sections[j];
3553
3554               struct ctables_cell *cell;
3555               HMAP_FOR_EACH (cell, struct ctables_cell, node, &s->cells)
3556                 if (!cell->hide)
3557                   sorted[n_sorted++] = cell;
3558               assert (n_sorted <= n_total_cells);
3559             }
3560
3561           struct ctables_cell_sort_aux aux = { .nest = nest, .a = a };
3562           sort (sorted, n_sorted, sizeof *sorted, ctables_cell_compare_3way, &aux);
3563
3564 #if 0
3565           for (size_t j = 0; j < n_sorted; j++)
3566             {
3567               printf ("%s (%s): %f/%f = %.1f%%\n", sorted[j]->name, sorted[j]->contributes_to_domains ? "y" : "n", sorted[j]->summaries[0].count, sorted[j]->domains[CTDT_COL]->e_count, sorted[j]->summaries[0].count / sorted[j]->domains[CTDT_COL]->e_count * 100.0);
3568             }
3569           printf ("\n");
3570 #endif
3571           
3572           struct ctables_level
3573             {
3574               enum ctables_level_type
3575                 {
3576                   CTL_VAR,          /* Variable label for nest->vars[var_idx]. */
3577                   CTL_CATEGORY,     /* Category for nest->vars[var_idx]. */
3578                   CTL_SUMMARY,      /* Summary functions. */
3579                 }
3580                 type;
3581
3582               enum settings_value_show vlabel; /* CTL_VAR only. */
3583               size_t var_idx;
3584             };
3585           struct ctables_level *levels = xnmalloc (1 + 2 * max_depth, sizeof *levels);
3586           size_t n_levels = 0;
3587           for (size_t k = 0; k < nest->n; k++)
3588             {
3589               enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (nest->vars[k])];
3590               if (vlabel != CTVL_NONE)
3591                 {
3592                   levels[n_levels++] = (struct ctables_level) {
3593                     .type = CTL_VAR,
3594                     .vlabel = (enum settings_value_show) vlabel,
3595                     .var_idx = k,
3596                   };
3597                 }
3598
3599               if (nest->scale_idx != k
3600                   && (k != nest->n - 1 || t->label_axis[a] == a))
3601                 {
3602                   levels[n_levels++] = (struct ctables_level) {
3603                     .type = CTL_CATEGORY,
3604                     .var_idx = k,
3605                   };
3606                 }
3607             }
3608
3609           if (!summary_dimension && a == t->slabels_axis)
3610             {
3611               levels[n_levels++] = (struct ctables_level) {
3612                 .type = CTL_SUMMARY,
3613                 .var_idx = SIZE_MAX,
3614               };
3615             }
3616
3617           /* Pivot categories:
3618
3619              - variable label for nest->vars[0], if vlabel != CTVL_NONE
3620              - category for nest->vars[0], if nest->scale_idx != 0
3621              - variable label for nest->vars[1], if vlabel != CTVL_NONE
3622              - category for nest->vars[1], if nest->scale_idx != 1
3623              ...
3624              - variable label for nest->vars[n - 1], if vlabel != CTVL_NONE
3625              - category for nest->vars[n - 1], if t->label_axis[a] == a && nest->scale_idx != n - 1.
3626              - summary function, if 'a == t->slabels_axis && a ==
3627              t->summary_axis'.
3628
3629              Additional dimensions:
3630
3631              - If 'a == t->slabels_axis && a != t->summary_axis', add a summary
3632              dimension.
3633              - If 't->label_axis[b] == a' for some 'b != a', add a category
3634              dimension to 'a'.
3635           */
3636
3637
3638           struct pivot_category **groups = xnmalloc (1 + 2 * max_depth, sizeof *groups);
3639           int prev_leaf = 0;
3640           for (size_t j = 0; j < n_sorted; j++)
3641             {
3642               struct ctables_cell *cell = sorted[j];
3643               struct ctables_cell *prev = j > 0 ? sorted[j - 1] : NULL;
3644
3645               size_t n_common = 0;
3646               if (j > 0)
3647                 {
3648                   for (; n_common < n_levels; n_common++)
3649                     {
3650                       const struct ctables_level *level = &levels[n_common];
3651                       if (level->type == CTL_CATEGORY)
3652                         {
3653                           size_t var_idx = level->var_idx;
3654                           const struct ctables_category *c = cell->axes[a].cvs[var_idx].category;
3655                           if (prev->axes[a].cvs[var_idx].category != c)
3656                             break;
3657                           else if (c->type != CCT_SUBTOTAL
3658                                    && c->type != CCT_TOTAL
3659                                    && c->type != CCT_POSTCOMPUTE
3660                                    && !value_equal (&prev->axes[a].cvs[var_idx].value,
3661                                                     &cell->axes[a].cvs[var_idx].value,
3662                                                     var_get_type (nest->vars[var_idx])))
3663                             break;
3664                         }
3665                     }
3666                 }
3667
3668               for (size_t k = n_common; k < n_levels; k++)
3669                 {
3670                   const struct ctables_level *level = &levels[k];
3671                   struct pivot_category *parent = k ? groups[k - 1] : d[a]->root;
3672                   if (level->type == CTL_SUMMARY)
3673                     {
3674                       assert (k == n_levels - 1);
3675
3676                       const struct ctables_summary_spec_set *specs = &t->summary_specs;
3677                       for (size_t m = 0; m < specs->n; m++)
3678                         {
3679                           int leaf = pivot_category_create_leaf (
3680                             parent, pivot_value_new_text (specs->specs[m].label));
3681                           if (!m)
3682                             prev_leaf = leaf;
3683                         }
3684                     }
3685                   else
3686                     {
3687                       const struct variable *var = nest->vars[level->var_idx];
3688                       struct pivot_value *label;
3689                       if (level->type == CTL_VAR)
3690                         {
3691                           label = pivot_value_new_variable (var);
3692                           label->variable.show = level->vlabel;
3693                         }
3694                       else if (level->type == CTL_CATEGORY)
3695                         {
3696                           const struct ctables_cell_value *cv = &cell->axes[a].cvs[level->var_idx];
3697                           label = ctables_category_create_label (cv->category,
3698                                                                  var, &cv->value);
3699                         }
3700                       else
3701                         NOT_REACHED ();
3702
3703                       if (k == n_levels - 1)
3704                         prev_leaf = pivot_category_create_leaf (parent, label);
3705                       else
3706                         groups[k] = pivot_category_create_group__ (parent, label);
3707                     }
3708                 }
3709
3710               cell->axes[a].leaf = prev_leaf;
3711             }
3712           free (sorted);
3713           free (groups);
3714         }
3715     }
3716
3717   for (size_t i = 0; i < t->n_sections; i++)
3718     {
3719       struct ctables_section *s = &t->sections[i];
3720
3721       struct ctables_cell *cell;
3722       HMAP_FOR_EACH (cell, struct ctables_cell, node, &s->cells)
3723         {
3724           if (cell->hide)
3725             continue;
3726
3727           const struct ctables_nest *specs_nest = s->nests[t->summary_axis];
3728           const struct ctables_summary_spec_set *specs = &specs_nest->specs[cell->sv];
3729           for (size_t j = 0; j < specs->n; j++)
3730             {
3731               size_t dindexes[5];
3732               size_t n_dindexes = 0;
3733
3734               if (summary_dimension)
3735                 dindexes[n_dindexes++] = specs->specs[j].axis_idx;
3736
3737               if (categories_dimension)
3738                 {
3739                   const struct ctables_nest *clabels_nest = s->nests[t->clabels_from_axis];
3740                   const struct variable *var = clabels_nest->vars[clabels_nest->n - 1];
3741                   const union value *value = &cell->axes[t->clabels_from_axis].cvs[clabels_nest->n - 1].value;
3742                   const struct ctables_value *ctv = ctables_value_find (t, value, var_get_width (var));
3743                   if (!ctv)
3744                     continue;
3745                   dindexes[n_dindexes++] = ctv->leaf;
3746                 }
3747
3748               for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
3749                 if (d[a])
3750                   {
3751                     int leaf = cell->axes[a].leaf;
3752                     if (a == t->summary_axis && !summary_dimension)
3753                       leaf += j;
3754                     dindexes[n_dindexes++] = leaf;
3755                   }
3756
3757               const struct ctables_summary_spec *ss = &specs->specs[j];
3758
3759               double d = (cell->postcompute
3760                           ? ctables_cell_calculate_postcompute (s, cell)
3761                           : ctables_summary_value (cell, &cell->summaries[j], ss));
3762               struct pivot_value *value;
3763               if (ct->hide_threshold != 0
3764                   && d < ct->hide_threshold
3765                   && (cell->postcompute
3766                       ? false /* XXX */
3767                       : ctables_summary_function_is_count (ss->function)))
3768                 {
3769                   value = pivot_value_new_user_text_nocopy (
3770                     xasprintf ("<%d", ct->hide_threshold));
3771                 }
3772               else if (d == 0 && ct->zero)
3773                 value = pivot_value_new_user_text (ct->zero, SIZE_MAX);
3774               else if (d == SYSMIS && ct->missing)
3775                 value = pivot_value_new_user_text (ct->missing, SIZE_MAX);
3776               else if (specs->specs[j].is_ctables_format)
3777                 {
3778                   char *s = data_out_stretchy (&(union value) { .f = d },
3779                                                "UTF-8",
3780                                                &specs->specs[j].format,
3781                                                &ct->ctables_formats, NULL);
3782                   value = pivot_value_new_user_text_nocopy (s);
3783                 }
3784               else
3785                 {
3786                   value = pivot_value_new_number (d);
3787                   value->numeric.format = specs->specs[j].format;
3788                 }
3789               pivot_table_put (pt, dindexes, n_dindexes, value);
3790             }
3791         }
3792     }
3793
3794   pivot_table_submit (pt);
3795 }
3796
3797 static bool
3798 ctables_check_label_position (struct ctables_table *t, enum pivot_axis_type a)
3799 {
3800   enum pivot_axis_type label_pos = t->label_axis[a];
3801   if (label_pos == a)
3802     return true;
3803
3804   t->clabels_from_axis = a;
3805
3806   const char *subcommand_name = a == PIVOT_AXIS_ROW ? "ROWLABELS" : "COLLABELS";
3807   const char *pos_name = label_pos == PIVOT_AXIS_LAYER ? "LAYER" : "OPPOSITE";
3808
3809   const struct ctables_stack *stack = &t->stacks[a];
3810   if (!stack->n)
3811     return true;
3812
3813   const struct ctables_nest *n0 = &stack->nests[0];
3814   assert (n0->n > 0);
3815   const struct variable *v0 = n0->vars[n0->n - 1];
3816   struct ctables_categories *c0 = t->categories[var_get_dict_index (v0)];
3817   t->clabels_example = v0;
3818
3819   for (size_t i = 0; i < c0->n_cats; i++)
3820     if (c0->cats[i].type == CCT_FUNCTION)
3821       {
3822         msg (SE, _("%s=%s is not allowed with sorting based "
3823                    "on a summary function."),
3824              subcommand_name, pos_name);
3825         return false;
3826       }
3827   if (n0->n - 1 == n0->scale_idx)
3828     {
3829       msg (SE, _("%s=%s requires the variables to be moved to be categorical, "
3830                  "but %s is a scale variable."),
3831            subcommand_name, pos_name, var_get_name (v0));
3832       return false;
3833     }
3834
3835   for (size_t i = 1; i < stack->n; i++)
3836     {
3837       const struct ctables_nest *ni = &stack->nests[i];
3838       assert (ni->n > 0);
3839       const struct variable *vi = ni->vars[ni->n - 1];
3840       struct ctables_categories *ci = t->categories[var_get_dict_index (vi)];
3841
3842       if (ni->n - 1 == ni->scale_idx)
3843         {
3844           msg (SE, _("%s=%s requires the variables to be moved to be "
3845                      "categorical, but %s is a scale variable."),
3846                subcommand_name, pos_name, var_get_name (vi));
3847           return false;
3848         }
3849       if (var_get_width (v0) != var_get_width (vi))
3850         {
3851           msg (SE, _("%s=%s requires the variables to be "
3852                      "moved to have the same width, but %s has "
3853                      "width %d and %s has width %d."),
3854                subcommand_name, pos_name,
3855                var_get_name (v0), var_get_width (v0),
3856                var_get_name (vi), var_get_width (vi));
3857           return false;
3858         }
3859       if (!val_labs_equal (var_get_value_labels (v0),
3860                            var_get_value_labels (vi)))
3861         {
3862           msg (SE, _("%s=%s requires the variables to be "
3863                      "moved to have the same value labels, but %s "
3864                      "and %s have different value labels."),
3865                subcommand_name, pos_name,
3866                var_get_name (v0), var_get_name (vi));
3867           return false;
3868         }
3869       if (!ctables_categories_equal (c0, ci))
3870         {
3871           msg (SE, _("%s=%s requires the variables to be "
3872                      "moved to have the same category "
3873                      "specifications, but %s and %s have different "
3874                      "category specifications."),
3875                subcommand_name, pos_name,
3876                var_get_name (v0), var_get_name (vi));
3877           return false;
3878         }
3879     }
3880
3881   return true;
3882 }
3883
3884 static bool
3885 ctables_prepare_table (struct ctables_table *t)
3886 {
3887   for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
3888     if (t->axes[a])
3889       {
3890         t->stacks[a] = enumerate_fts (a, t->axes[a]);
3891
3892         for (size_t j = 0; j < t->stacks[a].n; j++)
3893           {
3894             struct ctables_nest *nest = &t->stacks[a].nests[j];
3895             for (enum ctables_domain_type dt = 0; dt < N_CTDTS; dt++)
3896               {
3897                 nest->domains[dt] = xmalloc (nest->n * sizeof *nest->domains[dt]);
3898                 nest->n_domains[dt] = 0;
3899
3900                 for (size_t k = 0; k < nest->n; k++)
3901                   {
3902                     if (k == nest->scale_idx)
3903                       continue;
3904
3905                     switch (dt)
3906                       {
3907                       case CTDT_TABLE:
3908                         continue;
3909
3910                       case CTDT_LAYER:
3911                         if (a != PIVOT_AXIS_LAYER)
3912                           continue;
3913                         break;
3914
3915                       case CTDT_SUBTABLE:
3916                       case CTDT_ROW:
3917                       case CTDT_COL:
3918                         if (dt == CTDT_SUBTABLE ? a != PIVOT_AXIS_LAYER
3919                             : dt == CTDT_ROW ? a == PIVOT_AXIS_COLUMN
3920                             : a == PIVOT_AXIS_ROW)
3921                           {
3922                             if (k == nest->n - 1
3923                                 || (nest->scale_idx == nest->n - 1
3924                                     && k == nest->n - 2))
3925                               continue;
3926                           }
3927                         break;
3928
3929                       case CTDT_LAYERROW:
3930                         if (a == PIVOT_AXIS_COLUMN)
3931                           continue;
3932                         break;
3933
3934                       case CTDT_LAYERCOL:
3935                         if (a == PIVOT_AXIS_ROW)
3936                           continue;
3937                         break;
3938                       }
3939
3940                     nest->domains[dt][nest->n_domains[dt]++] = k;
3941                   }
3942               }
3943           }
3944       }
3945     else
3946       {
3947         struct ctables_nest *nest = xmalloc (sizeof *nest);
3948         *nest = (struct ctables_nest) { .n = 0 };
3949         t->stacks[a] = (struct ctables_stack) { .nests = nest, .n = 1 };
3950       }
3951
3952   struct ctables_stack *stack = &t->stacks[t->summary_axis];
3953   for (size_t i = 0; i < stack->n; i++)
3954     {
3955       struct ctables_nest *nest = &stack->nests[i];
3956       if (!nest->specs[CSV_CELL].n)
3957         {
3958           struct ctables_summary_spec_set *specs = &nest->specs[CSV_CELL];
3959           specs->specs = xmalloc (sizeof *specs->specs);
3960           specs->n = 1;
3961
3962           enum ctables_summary_function function
3963             = specs->is_scale ? CTSF_MEAN : CTSF_COUNT;
3964
3965           *specs->specs = (struct ctables_summary_spec) {
3966             .function = function,
3967             .format = ctables_summary_default_format (function, specs->var),
3968             .label = ctables_summary_default_label (function, 0),
3969           };
3970           if (!specs->var)
3971             specs->var = nest->vars[0];
3972
3973           ctables_summary_spec_set_clone (&nest->specs[CSV_TOTAL],
3974                                           &nest->specs[CSV_CELL]);
3975         }
3976       else if (!nest->specs[CSV_TOTAL].n)
3977         ctables_summary_spec_set_clone (&nest->specs[CSV_TOTAL],
3978                                         &nest->specs[CSV_CELL]);
3979
3980       if (t->ctables->smissing_listwise)
3981         {
3982           struct variable **listwise_vars = NULL;
3983           size_t n = 0;
3984           size_t allocated = 0;
3985
3986           for (size_t j = nest->group_head; j < stack->n; j++)
3987             {
3988               const struct ctables_nest *other_nest = &stack->nests[j];
3989               if (other_nest->group_head != nest->group_head)
3990                 break;
3991
3992               if (nest != other_nest && other_nest->scale_idx < other_nest->n)
3993                 {
3994                   if (n >= allocated)
3995                     listwise_vars = x2nrealloc (listwise_vars, &allocated,
3996                                                 sizeof *listwise_vars);
3997                   listwise_vars[n++] = other_nest->vars[other_nest->scale_idx];
3998                 }
3999             }
4000           for (size_t j = 0; j < N_CSVS; j++)
4001             {
4002               nest->specs[j].listwise_vars = listwise_vars;
4003               nest->specs[j].n_listwise_vars = n;
4004             }
4005         }
4006     }
4007
4008   struct ctables_summary_spec_set *merged = &t->summary_specs;
4009   struct merge_item *items = xnmalloc (2 * stack->n, sizeof *items);
4010   size_t n_left = 0;
4011   for (size_t j = 0; j < stack->n; j++)
4012     {
4013       const struct ctables_nest *nest = &stack->nests[j];
4014       if (nest->n)
4015         for (enum ctables_summary_variant sv = 0; sv < N_CSVS; sv++)
4016           items[n_left++] = (struct merge_item) { .set = &nest->specs[sv] };
4017     }
4018
4019   while (n_left > 0)
4020     {
4021       struct merge_item min = items[0];
4022       for (size_t j = 1; j < n_left; j++)
4023         if (merge_item_compare_3way (&items[j], &min) < 0)
4024           min = items[j];
4025
4026       if (merged->n >= merged->allocated)
4027         merged->specs = x2nrealloc (merged->specs, &merged->allocated,
4028                                     sizeof *merged->specs);
4029       merged->specs[merged->n++] = min.set->specs[min.ofs];
4030
4031       for (size_t j = 0; j < n_left; )
4032         {
4033           if (merge_item_compare_3way (&items[j], &min) == 0)
4034             {
4035               struct merge_item *item = &items[j];
4036               item->set->specs[item->ofs].axis_idx = merged->n - 1;
4037               if (++item->ofs >= item->set->n)
4038                 {
4039                   items[j] = items[--n_left];
4040                   continue;
4041                 }
4042             }
4043           j++;
4044         }
4045     }
4046
4047 #if 0
4048   for (size_t j = 0; j < merged->n; j++)
4049     printf ("%s\n", ctables_summary_function_name (merged->specs[j].function));
4050
4051   for (size_t j = 0; j < stack->n; j++)
4052     {
4053       const struct ctables_nest *nest = &stack->nests[j];
4054       for (enum ctables_summary_variant sv = 0; sv < N_CSVS; sv++)
4055         {
4056           const struct ctables_summary_spec_set *specs = &nest->specs[sv];
4057           for (size_t k = 0; k < specs->n; k++)
4058             printf ("(%s, %zu) ", ctables_summary_function_name (specs->specs[k].function),
4059                     specs->specs[k].axis_idx);
4060           printf ("\n");
4061         }
4062     }
4063 #endif
4064
4065   return (ctables_check_label_position (t, PIVOT_AXIS_ROW)
4066           && ctables_check_label_position (t, PIVOT_AXIS_COLUMN));
4067 }
4068
4069 static void
4070 ctables_insert_clabels_values (struct ctables_table *t, const struct ccase *c,
4071                                enum pivot_axis_type a)
4072 {
4073   struct ctables_stack *stack = &t->stacks[a];
4074   for (size_t i = 0; i < stack->n; i++)
4075     {
4076       const struct ctables_nest *nest = &stack->nests[i];
4077       const struct variable *var = nest->vars[nest->n - 1];
4078       const union value *value = case_data (c, var);
4079
4080       if (var_is_numeric (var) && value->f == SYSMIS)
4081         continue;
4082
4083       if (ctables_categories_match (t->categories [var_get_dict_index (var)],
4084                                     value, var))
4085         ctables_value_insert (t, value, var_get_width (var));
4086     }
4087 }
4088
4089 static int
4090 compare_clabels_values_3way (const void *a_, const void *b_, const void *width_)
4091 {
4092   const struct ctables_value *const *ap = a_;
4093   const struct ctables_value *const *bp = b_;
4094   const struct ctables_value *a = *ap;
4095   const struct ctables_value *b = *bp;
4096   const int *width = width_;
4097   return value_compare_3way (&a->value, &b->value, *width);
4098 }
4099
4100 static void
4101 ctables_sort_clabels_values (struct ctables_table *t)
4102 {
4103   const struct variable *v0 = t->clabels_example;
4104   int width = var_get_width (v0);
4105
4106   struct ctables_categories *c0 = t->categories[var_get_dict_index (v0)];
4107   if (c0->show_empty)
4108     {
4109       const struct val_labs *val_labs = var_get_value_labels (v0);
4110       for (const struct val_lab *vl = val_labs_first (val_labs); vl;
4111            vl = val_labs_next (val_labs, vl))
4112         if (ctables_categories_match (c0, &vl->value, v0))
4113           ctables_value_insert (t, &vl->value, width);
4114     }
4115
4116   size_t n = hmap_count (&t->clabels_values_map);
4117   t->clabels_values = xnmalloc (n, sizeof *t->clabels_values);
4118
4119   struct ctables_value *clv;
4120   size_t i = 0;
4121   HMAP_FOR_EACH (clv, struct ctables_value, node, &t->clabels_values_map)
4122     t->clabels_values[i++] = clv;
4123   t->n_clabels_values = n;
4124   assert (i == n);
4125
4126   sort (t->clabels_values, n, sizeof *t->clabels_values,
4127         compare_clabels_values_3way, &width);
4128
4129   for (size_t i = 0; i < n; i++)
4130     t->clabels_values[i]->leaf = i;
4131 }
4132
4133 static void
4134 ctables_add_category_occurrences (const struct variable *var,
4135                                   struct hmap *occurrences,
4136                                   const struct ctables_categories *cats)
4137 {
4138   const struct val_labs *val_labs = var_get_value_labels (var);
4139
4140   for (size_t i = 0; i < cats->n_cats; i++)
4141     {
4142       const struct ctables_category *c = &cats->cats[i];
4143       switch (c->type)
4144         {
4145         case CCT_NUMBER:
4146           ctables_add_occurrence (var, &(const union value) { .f = c->number },
4147                                   occurrences);
4148           break;
4149
4150         case CCT_STRING:
4151           abort ();             /* XXX */
4152
4153         case CCT_RANGE:
4154           assert (var_is_numeric (var));
4155           for (const struct val_lab *vl = val_labs_first (val_labs); vl;
4156                vl = val_labs_next (val_labs, vl))
4157             if (vl->value.f >= c->range[0] && vl->value.f <= c->range[1])
4158               ctables_add_occurrence (var, &vl->value, occurrences);
4159           break;
4160
4161         case CCT_MISSING:
4162           for (const struct val_lab *vl = val_labs_first (val_labs); vl;
4163                vl = val_labs_next (val_labs, vl))
4164             if (var_is_value_missing (var, &vl->value))
4165               ctables_add_occurrence (var, &vl->value, occurrences);
4166           break;
4167
4168         case CCT_OTHERNM:
4169           for (const struct val_lab *vl = val_labs_first (val_labs); vl;
4170                vl = val_labs_next (val_labs, vl))
4171             ctables_add_occurrence (var, &vl->value, occurrences);
4172           break;
4173
4174         case CCT_POSTCOMPUTE:
4175           break;
4176
4177         case CCT_SUBTOTAL:
4178         case CCT_TOTAL:
4179           break;
4180
4181         case CCT_VALUE:
4182         case CCT_LABEL:
4183         case CCT_FUNCTION:
4184           for (const struct val_lab *vl = val_labs_first (val_labs); vl;
4185                vl = val_labs_next (val_labs, vl))
4186             if (c->include_missing || !var_is_value_missing (var, &vl->value))
4187               ctables_add_occurrence (var, &vl->value, occurrences);
4188           break;
4189
4190         case CCT_EXCLUDED_MISSING:
4191           break;
4192         }
4193     }
4194 }
4195
4196 static void
4197 ctables_section_recurse_add_empty_categories (
4198   struct ctables_section *s,
4199   const struct ctables_category *cats[PIVOT_N_AXES][10], struct ccase *c,
4200   enum pivot_axis_type a, size_t a_idx)
4201 {
4202   if (a >= PIVOT_N_AXES)
4203     ctables_cell_insert__ (s, c, cats);
4204   else if (!s->nests[a] || a_idx >= s->nests[a]->n)
4205     ctables_section_recurse_add_empty_categories (s, cats, c, a + 1, 0);
4206   else
4207     {
4208       const struct variable *var = s->nests[a]->vars[a_idx];
4209       const struct ctables_categories *categories = s->table->categories[
4210         var_get_dict_index (var)];
4211       int width = var_get_width (var);
4212       const struct hmap *occurrences = &s->occurrences[a][a_idx];
4213       const struct ctables_occurrence *o;
4214       HMAP_FOR_EACH (o, struct ctables_occurrence, node, occurrences)
4215         {
4216           union value *value = case_data_rw (c, var);
4217           value_destroy (value, width);
4218           value_clone (value, &o->value, width);
4219           cats[a][a_idx] = ctables_categories_match (categories, value, var);
4220           assert (cats[a][a_idx] != NULL);
4221           ctables_section_recurse_add_empty_categories (s, cats, c, a, a_idx + 1);
4222         }
4223
4224       for (size_t i = 0; i < categories->n_cats; i++)
4225         {
4226           const struct ctables_category *cat = &categories->cats[i];
4227           if (cat->type == CCT_POSTCOMPUTE)
4228             {
4229               cats[a][a_idx] = cat;
4230               ctables_section_recurse_add_empty_categories (s, cats, c, a, a_idx + 1);
4231             }
4232         }
4233     }
4234 }
4235
4236 static void
4237 ctables_section_add_empty_categories (struct ctables_section *s)
4238 {
4239   bool show_empty = false;
4240   for (size_t a = 0; a < PIVOT_N_AXES; a++)
4241     if (s->nests[a])
4242       for (size_t k = 0; k < s->nests[a]->n; k++)
4243         if (k != s->nests[a]->scale_idx)
4244           {
4245             const struct variable *var = s->nests[a]->vars[k];
4246             const struct ctables_categories *cats = s->table->categories[
4247               var_get_dict_index (var)];
4248             if (cats->show_empty)
4249               {
4250                 show_empty = true;
4251                 ctables_add_category_occurrences (var, &s->occurrences[a][k], cats);
4252               }
4253           }
4254   if (!show_empty)
4255     return;
4256
4257   const struct ctables_category *cats[PIVOT_N_AXES][10]; /* XXX */
4258   struct ccase *c = case_create (dict_get_proto (s->table->ctables->dict));
4259   ctables_section_recurse_add_empty_categories (s, cats, c, 0, 0);
4260   case_unref (c);
4261 }
4262
4263 static bool
4264 ctables_execute (struct dataset *ds, struct ctables *ct)
4265 {
4266   for (size_t i = 0; i < ct->n_tables; i++)
4267     {
4268       struct ctables_table *t = ct->tables[i];
4269       t->sections = xnmalloc (MAX (1, t->stacks[PIVOT_AXIS_ROW].n) *
4270                               MAX (1, t->stacks[PIVOT_AXIS_COLUMN].n) *
4271                               MAX (1, t->stacks[PIVOT_AXIS_LAYER].n),
4272                               sizeof *t->sections);
4273       size_t ix[PIVOT_N_AXES];
4274       ctables_table_add_section (t, 0, ix);
4275     }
4276
4277   struct casereader *input = proc_open (ds);
4278   bool warn_on_invalid = true;
4279   for (struct ccase *c = casereader_read (input); c;
4280        case_unref (c), c = casereader_read (input))
4281     {
4282       double d_weight = dict_get_case_weight (dataset_dict (ds), c,
4283                                               &warn_on_invalid);
4284       double e_weight = (ct->e_weight
4285                          ? var_force_valid_weight (ct->e_weight,
4286                                                    case_num (c, ct->e_weight),
4287                                                    &warn_on_invalid)
4288                          : d_weight);
4289
4290       for (size_t i = 0; i < ct->n_tables; i++)
4291         {
4292           struct ctables_table *t = ct->tables[i];
4293
4294           for (size_t j = 0; j < t->n_sections; j++)
4295             ctables_cell_insert (&t->sections[j], c, d_weight, e_weight);
4296
4297           for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
4298             if (t->label_axis[a] != a)
4299               ctables_insert_clabels_values (t, c, a);
4300         }
4301     }
4302   casereader_destroy (input);
4303
4304   for (size_t i = 0; i < ct->n_tables; i++)
4305     {
4306       struct ctables_table *t = ct->tables[i];
4307
4308       if (t->clabels_example)
4309         ctables_sort_clabels_values (t);
4310
4311       for (size_t j = 0; j < t->n_sections; j++)
4312         ctables_section_add_empty_categories (&t->sections[j]);
4313
4314       ctables_table_output (ct, ct->tables[i]);
4315     }
4316   return proc_commit (ds);
4317 }
4318 \f
4319 /* Postcomputes. */
4320
4321 typedef struct ctables_pcexpr *parse_recursively_func (struct lexer *);
4322
4323 static void
4324 ctables_pcexpr_destroy (struct ctables_pcexpr *e)
4325 {
4326   if (e)
4327     {
4328       switch (e->op)
4329         {
4330         case CTPO_CAT_STRING:
4331           free (e->string);
4332           break;
4333
4334         case CTPO_ADD:
4335         case CTPO_SUB:
4336         case CTPO_MUL:
4337         case CTPO_DIV:
4338         case CTPO_POW:
4339         case CTPO_NEG:
4340           for (size_t i = 0; i < 2; i++)
4341             ctables_pcexpr_destroy (e->subs[i]);
4342           break;
4343
4344         case CTPO_CONSTANT:
4345         case CTPO_CAT_NUMBER:
4346         case CTPO_CAT_RANGE:
4347         case CTPO_CAT_MISSING:
4348         case CTPO_CAT_OTHERNM:
4349         case CTPO_CAT_SUBTOTAL:
4350         case CTPO_CAT_TOTAL:
4351           break;
4352         }
4353
4354       msg_location_destroy (e->location);
4355       free (e);
4356     }
4357 }
4358
4359 static struct ctables_pcexpr *
4360 ctables_pcexpr_allocate_binary (enum ctables_postcompute_op op,
4361                                 struct ctables_pcexpr *sub0,
4362                                 struct ctables_pcexpr *sub1)
4363 {
4364   struct ctables_pcexpr *e = xmalloc (sizeof *e);
4365   *e = (struct ctables_pcexpr) {
4366     .op = op,
4367     .subs = { sub0, sub1 },
4368     .location = msg_location_merged (sub0->location, sub1->location),
4369   };
4370   return e;
4371 }
4372
4373 /* How to parse an operator. */
4374 struct operator
4375   {
4376     enum token_type token;
4377     enum ctables_postcompute_op op;
4378   };
4379
4380 static const struct operator *
4381 match_operator (struct lexer *lexer, const struct operator ops[], size_t n_ops)
4382 {
4383   for (const struct operator *op = ops; op < ops + n_ops; op++)
4384     if (lex_token (lexer) == op->token)
4385       {
4386         if (op->token != T_NEG_NUM)
4387           lex_get (lexer);
4388
4389         return op;
4390       }
4391
4392   return NULL;
4393 }
4394
4395 static struct ctables_pcexpr *
4396 parse_binary_operators__ (struct lexer *lexer,
4397                           const struct operator ops[], size_t n_ops,
4398                           parse_recursively_func *parse_next_level,
4399                           const char *chain_warning,
4400                           struct ctables_pcexpr *lhs)
4401 {
4402   for (int op_count = 0; ; op_count++)
4403     {
4404       const struct operator *op = match_operator (lexer, ops, n_ops);
4405       if (!op)
4406         {
4407           if (op_count > 1 && chain_warning)
4408             msg_at (SW, lhs->location, "%s", chain_warning);
4409
4410           return lhs;
4411         }
4412
4413       struct ctables_pcexpr *rhs = parse_next_level (lexer);
4414       if (!rhs)
4415         {
4416           ctables_pcexpr_destroy (lhs);
4417           return NULL;
4418         }
4419
4420       lhs = ctables_pcexpr_allocate_binary (op->op, lhs, rhs);
4421     }
4422 }
4423
4424 static struct ctables_pcexpr *
4425 parse_binary_operators (struct lexer *lexer,
4426                         const struct operator ops[], size_t n_ops,
4427                         parse_recursively_func *parse_next_level,
4428                         const char *chain_warning)
4429 {
4430   struct ctables_pcexpr *lhs = parse_next_level (lexer);
4431   if (!lhs)
4432     return NULL;
4433
4434   return parse_binary_operators__ (lexer, ops, n_ops, parse_next_level,
4435                                    chain_warning, lhs);
4436 }
4437
4438 static struct ctables_pcexpr *parse_add (struct lexer *);
4439
4440 static struct ctables_pcexpr
4441 ctpo_cat_range (double low, double high)
4442 {
4443   return (struct ctables_pcexpr) {
4444     .op = CTPO_CAT_RANGE,
4445     .range = { low, high },
4446   };
4447 }
4448
4449 static struct ctables_pcexpr *
4450 parse_primary (struct lexer *lexer)
4451 {
4452   int start_ofs = lex_ofs (lexer);
4453   struct ctables_pcexpr e;
4454   if (lex_is_number (lexer))
4455     {
4456       e = (struct ctables_pcexpr) { .op = CTPO_CONSTANT,
4457                                     .number = lex_number (lexer) };
4458       lex_get (lexer);
4459     }
4460   else if (lex_match_id (lexer, "MISSING"))
4461     e = (struct ctables_pcexpr) { .op = CTPO_CAT_MISSING };
4462   else if (lex_match_id (lexer, "OTHERNM"))
4463     e = (struct ctables_pcexpr) { .op = CTPO_CAT_OTHERNM };
4464   else if (lex_match_id (lexer, "TOTAL"))
4465     e = (struct ctables_pcexpr) { .op = CTPO_CAT_TOTAL };
4466   else if (lex_match_id (lexer, "SUBTOTAL"))
4467     {
4468       size_t subtotal_index = 0;
4469       if (lex_match (lexer, T_LBRACK))
4470         {
4471           if (!lex_force_int_range (lexer, "SUBTOTAL", 1, LONG_MAX))
4472             return NULL;
4473           subtotal_index = lex_integer (lexer);
4474           lex_get (lexer);
4475           if (!lex_force_match (lexer, T_RBRACK))
4476             return NULL;
4477         }
4478       e = (struct ctables_pcexpr) { .op = CTPO_CAT_SUBTOTAL,
4479                                     .subtotal_index = subtotal_index };
4480     }
4481   else if (lex_match (lexer, T_LBRACK))
4482     {
4483       if (lex_match_id (lexer, "LO"))
4484         {
4485           if (!lex_force_match_id (lexer, "THRU") || lex_force_num (lexer))
4486             return false;
4487           e = ctpo_cat_range (-DBL_MAX, lex_number (lexer));
4488           lex_get (lexer);
4489         }
4490       else if (lex_is_number (lexer))
4491         {
4492           double number = lex_number (lexer);
4493           lex_get (lexer);
4494           if (lex_match_id (lexer, "THRU"))
4495             {
4496               if (lex_match_id (lexer, "HI"))
4497                 e = ctpo_cat_range (number, DBL_MAX);
4498               else
4499                 {
4500                   if (!lex_force_num (lexer))
4501                     return false;
4502                   e = ctpo_cat_range (number, lex_number (lexer));
4503                   lex_get (lexer);
4504                 }
4505             }
4506           else
4507             e = (struct ctables_pcexpr) { .op = CTPO_CAT_NUMBER,
4508                                           .number = number };
4509         }
4510       else if (lex_is_string (lexer))
4511         {
4512           e = (struct ctables_pcexpr) {
4513             .op = CTPO_CAT_STRING,
4514             .string = ss_xstrdup (lex_tokss (lexer)),
4515           };
4516           lex_get (lexer);
4517         }
4518       else
4519         {
4520           lex_error (lexer, NULL);
4521           return NULL;
4522         }
4523
4524       if (!lex_force_match (lexer, T_RBRACK))
4525         {
4526           if (e.op == CTPO_CAT_STRING)
4527             free (e.string);
4528           return NULL;
4529         }
4530     }
4531   else if (lex_match (lexer, T_LPAREN))
4532     {
4533       struct ctables_pcexpr *ep = parse_add (lexer);
4534       if (!ep)
4535         return NULL;
4536       if (!lex_force_match (lexer, T_RPAREN))
4537         {
4538           ctables_pcexpr_destroy (ep);
4539           return NULL;
4540         }
4541       return ep;
4542     }
4543   else
4544     {
4545       lex_error (lexer, NULL);
4546       return NULL;
4547     }
4548
4549   e.location = lex_ofs_location (lexer, start_ofs, lex_ofs (lexer) - 1);
4550   return xmemdup (&e, sizeof e);
4551 }
4552
4553 static struct ctables_pcexpr *
4554 ctables_pcexpr_allocate_neg (struct ctables_pcexpr *sub,
4555                              struct lexer *lexer, int start_ofs)
4556 {
4557   struct ctables_pcexpr *e = xmalloc (sizeof *e);
4558   *e = (struct ctables_pcexpr) {
4559     .op = CTPO_NEG,
4560     .subs = { sub },
4561     .location = lex_ofs_location (lexer, start_ofs, lex_ofs (lexer) - 1),
4562   };
4563   return e;
4564 }
4565
4566 static struct ctables_pcexpr *
4567 parse_exp (struct lexer *lexer)
4568 {
4569   static const struct operator op = { T_EXP, CTPO_POW };
4570
4571   const char *chain_warning =
4572     _("The exponentiation operator (`**') is left-associative: "
4573       "`a**b**c' equals `(a**b)**c', not `a**(b**c)'.  "
4574       "To disable this warning, insert parentheses.");
4575
4576   if (lex_token (lexer) != T_NEG_NUM || lex_next_token (lexer, 1) != T_EXP)
4577     return parse_binary_operators (lexer, &op, 1,
4578                                    parse_primary, chain_warning);
4579
4580   /* Special case for situations like "-5**6", which must be parsed as
4581      -(5**6). */
4582
4583   int start_ofs = lex_ofs (lexer);
4584   struct ctables_pcexpr *lhs = xmalloc (sizeof *lhs);
4585   *lhs = (struct ctables_pcexpr) {
4586     .op = CTPO_CONSTANT,
4587     .number = -lex_tokval (lexer),
4588     .location = lex_ofs_location (lexer, start_ofs, lex_ofs (lexer)),
4589   };
4590   lex_get (lexer);
4591
4592   struct ctables_pcexpr *node = parse_binary_operators__ (
4593     lexer, &op, 1, parse_primary, chain_warning, lhs);
4594   if (!node)
4595     return NULL;
4596
4597   return ctables_pcexpr_allocate_neg (node, lexer, start_ofs);
4598 }
4599
4600 /* Parses the unary minus level. */
4601 static struct ctables_pcexpr *
4602 parse_neg (struct lexer *lexer)
4603 {
4604   int start_ofs = lex_ofs (lexer);
4605   if (!lex_match (lexer, T_DASH))
4606     return parse_exp (lexer);
4607
4608   struct ctables_pcexpr *inner = parse_neg (lexer);
4609   if (!inner)
4610     return NULL;
4611
4612   return ctables_pcexpr_allocate_neg (inner, lexer, start_ofs);
4613 }
4614
4615 /* Parses the multiplication and division level. */
4616 static struct ctables_pcexpr *
4617 parse_mul (struct lexer *lexer)
4618 {
4619   static const struct operator ops[] =
4620     {
4621       { T_ASTERISK, CTPO_MUL },
4622       { T_SLASH, CTPO_DIV },
4623     };
4624
4625   return parse_binary_operators (lexer, ops, sizeof ops / sizeof *ops,
4626                                  parse_neg, NULL);
4627 }
4628
4629 /* Parses the addition and subtraction level. */
4630 static struct ctables_pcexpr *
4631 parse_add (struct lexer *lexer)
4632 {
4633   static const struct operator ops[] =
4634     {
4635       { T_PLUS, CTPO_ADD },
4636       { T_DASH, CTPO_SUB },
4637       { T_NEG_NUM, CTPO_ADD },
4638     };
4639
4640   return parse_binary_operators (lexer, ops, sizeof ops / sizeof *ops,
4641                                  parse_mul, NULL);
4642 }
4643
4644 static struct ctables_postcompute *
4645 ctables_find_postcompute (struct ctables *ct, const char *name)
4646 {
4647   struct ctables_postcompute *pc;
4648   HMAP_FOR_EACH_WITH_HASH (pc, struct ctables_postcompute, hmap_node,
4649                            utf8_hash_case_string (name, 0), &ct->postcomputes)
4650     if (!utf8_strcasecmp (pc->name, name))
4651       return pc;
4652   return NULL;
4653 }
4654
4655 static bool
4656 ctables_parse_pcompute (struct lexer *lexer, struct ctables *ct)
4657 {
4658   int pcompute_start = lex_ofs (lexer) - 1;
4659
4660   if (!lex_force_match (lexer, T_AND) || !lex_force_id (lexer))
4661     return false;
4662
4663   char *name = ss_xstrdup (lex_tokss (lexer));
4664
4665   lex_get (lexer);
4666   if (!lex_force_match (lexer, T_EQUALS)
4667       || !lex_force_match_id (lexer, "EXPR")
4668       || !lex_force_match (lexer, T_LPAREN))
4669     {
4670       free (name);
4671       return false;
4672     }
4673
4674   int expr_start = lex_ofs (lexer);
4675   struct ctables_pcexpr *expr = parse_add (lexer);
4676   int expr_end = lex_ofs (lexer) - 1;
4677   if (!expr || !lex_force_match (lexer, T_RPAREN))
4678     {
4679       free (name);
4680       return false;
4681     }
4682   int pcompute_end = lex_ofs (lexer) - 1;
4683
4684   struct msg_location *location = lex_ofs_location (lexer, pcompute_start,
4685                                                     pcompute_end);
4686
4687   struct ctables_postcompute *pc = ctables_find_postcompute (ct, name);
4688   if (pc)
4689     {
4690       msg_at (SW, location, _("New definition of &%s will override the "
4691                               "previous definition."),
4692               pc->name);
4693       msg_at (SN, pc->location, _("This is the previous definition."));
4694
4695       ctables_pcexpr_destroy (pc->expr);
4696       msg_location_destroy (pc->location);
4697       free (name);
4698     }
4699   else
4700     {
4701       pc = xmalloc (sizeof *pc);
4702       *pc = (struct ctables_postcompute) { .name = name };
4703       hmap_insert (&ct->postcomputes, &pc->hmap_node,
4704                    utf8_hash_case_string (pc->name, 0));
4705     }
4706   pc->expr = expr;
4707   pc->location = location;
4708   if (!pc->label)
4709     pc->label = lex_ofs_representation (lexer, expr_start, expr_end);
4710   return true;
4711 }
4712
4713 static bool
4714 ctables_parse_pproperties_format (struct lexer *lexer,
4715                                   struct ctables_summary_spec_set *sss)
4716 {
4717   *sss = (struct ctables_summary_spec_set) { .n = 0 };
4718
4719   while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH
4720          && !(lex_token (lexer) == T_ID
4721               && (lex_id_match (ss_cstr ("LABEL"), lex_tokss (lexer))
4722                   || lex_id_match (ss_cstr ("HIDESOURCECATS"),
4723                                    lex_tokss (lexer)))))
4724     {
4725       /* Parse function. */
4726       enum ctables_summary_function function;
4727       if (!parse_ctables_summary_function (lexer, &function))
4728         goto error;
4729
4730       /* Parse percentile. */
4731       double percentile = 0;
4732       if (function == CTSF_PTILE)
4733         {
4734           if (!lex_force_num_range_closed (lexer, "PTILE", 0, 100))
4735             goto error;
4736           percentile = lex_number (lexer);
4737           lex_get (lexer);
4738         }
4739
4740       /* Parse format. */
4741       struct fmt_spec format;
4742       if (!parse_format_specifier (lexer, &format)
4743           || !fmt_check_output (&format)
4744           || !fmt_check_type_compat (&format, VAL_NUMERIC))
4745         goto error;
4746
4747       if (sss->n >= sss->allocated)
4748         sss->specs = x2nrealloc (sss->specs, &sss->allocated,
4749                                  sizeof *sss->specs);
4750       sss->specs[sss->n++] = (struct ctables_summary_spec) {
4751         .function = function,
4752         .percentile = percentile,
4753         .format = format,
4754       };
4755     }
4756   return true;
4757
4758 error:
4759   ctables_summary_spec_set_uninit (sss);
4760   return false;
4761 }
4762
4763 static bool
4764 ctables_parse_pproperties (struct lexer *lexer, struct ctables *ct)
4765 {
4766   struct ctables_postcompute **pcs = NULL;
4767   size_t n_pcs = 0;
4768   size_t allocated_pcs = 0;
4769
4770   while (lex_match (lexer, T_AND))
4771     {
4772       if (!lex_force_id (lexer))
4773         goto error;
4774       struct ctables_postcompute *pc
4775         = ctables_find_postcompute (ct, lex_tokcstr (lexer));
4776       if (!pc)
4777         {
4778           msg (SE, _("Unknown computed category &%s."), lex_tokcstr (lexer));
4779           goto error;
4780         }
4781       lex_get (lexer);
4782
4783       if (n_pcs >= allocated_pcs)
4784         pcs = x2nrealloc (pcs, &allocated_pcs, sizeof *pcs);
4785       pcs[n_pcs++] = pc;
4786     }
4787
4788   while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
4789     {
4790       if (lex_match_id (lexer, "LABEL"))
4791         {
4792           lex_match (lexer, T_EQUALS);
4793           if (!lex_force_string (lexer))
4794             goto error;
4795
4796           for (size_t i = 0; i < n_pcs; i++)
4797             {
4798               free (pcs[i]->label);
4799               pcs[i]->label = ss_xstrdup (lex_tokss (lexer));
4800             }
4801
4802           lex_get (lexer);
4803         }
4804       else if (lex_match_id (lexer, "FORMAT"))
4805         {
4806           lex_match (lexer, T_EQUALS);
4807
4808           struct ctables_summary_spec_set sss;
4809           if (!ctables_parse_pproperties_format (lexer, &sss))
4810             goto error;
4811
4812           for (size_t i = 0; i < n_pcs; i++)
4813             {
4814               if (pcs[i]->specs)
4815                 ctables_summary_spec_set_uninit (pcs[i]->specs);
4816               else
4817                 pcs[i]->specs = xmalloc (sizeof *pcs[i]->specs);
4818               ctables_summary_spec_set_clone (pcs[i]->specs, &sss);
4819             }
4820           ctables_summary_spec_set_uninit (&sss);
4821         }
4822       else if (lex_match_id (lexer, "HIDESOURCECATS"))
4823         {
4824           lex_match (lexer, T_EQUALS);
4825           bool hide_source_cats;
4826           if (!parse_bool (lexer, &hide_source_cats))
4827             goto error;
4828           for (size_t i = 0; i < n_pcs; i++)
4829             pcs[i]->hide_source_cats = hide_source_cats;
4830         }
4831       else
4832         {
4833           lex_error_expecting (lexer, "LABEL", "FORMAT", "HIDESOURCECATS");
4834           goto error;
4835         }
4836     }
4837   free (pcs);
4838   return true;
4839
4840 error:
4841   free (pcs);
4842   return false;
4843 }
4844
4845 int
4846 cmd_ctables (struct lexer *lexer, struct dataset *ds)
4847 {
4848   size_t n_vars = dict_get_n_vars (dataset_dict (ds));
4849   enum ctables_vlabel *vlabels = xnmalloc (n_vars, sizeof *vlabels);
4850   enum settings_value_show tvars = settings_get_show_variables ();
4851   for (size_t i = 0; i < n_vars; i++)
4852     vlabels[i] = (enum ctables_vlabel) tvars;
4853
4854   struct pivot_table_look *look = pivot_table_look_unshare (
4855     pivot_table_look_ref (pivot_table_look_get_default ()));
4856   look->omit_empty = false;
4857
4858   struct ctables *ct = xmalloc (sizeof *ct);
4859   *ct = (struct ctables) {
4860     .dict = dataset_dict (ds),
4861     .look = look,
4862     .ctables_formats = FMT_SETTINGS_INIT,
4863     .vlabels = vlabels,
4864     .postcomputes = HMAP_INITIALIZER (ct->postcomputes),
4865   };
4866
4867   struct ctf
4868     {
4869       enum fmt_type type;
4870       const char *dot_string;
4871       const char *comma_string;
4872     };
4873   static const struct ctf ctfs[4] = {
4874     { CTEF_NEGPAREN, "(,,,)",   "(...)" },
4875     { CTEF_NEQUAL,   "-,N=,,",  "-.N=.." },
4876     { CTEF_PAREN,    "-,(,),",  "-.(.)." },
4877     { CTEF_PCTPAREN, "-,(,%),", "-.(.%)." },
4878   };
4879   bool is_dot = settings_get_fmt_settings ()->decimal == '.';
4880   for (size_t i = 0; i < 4; i++)
4881     {
4882       const char *s = is_dot ? ctfs[i].dot_string : ctfs[i].comma_string;
4883       fmt_settings_set_cc (&ct->ctables_formats, ctfs[i].type,
4884                            fmt_number_style_from_string (s));
4885     }
4886
4887   if (!lex_force_match (lexer, T_SLASH))
4888     goto error;
4889
4890   while (!lex_match_id (lexer, "TABLE"))
4891     {
4892       if (lex_match_id (lexer, "FORMAT"))
4893         {
4894           double widths[2] = { SYSMIS, SYSMIS };
4895           double units_per_inch = 72.0;
4896
4897           while (lex_token (lexer) != T_SLASH)
4898             {
4899               if (lex_match_id (lexer, "MINCOLWIDTH"))
4900                 {
4901                   if (!parse_col_width (lexer, "MINCOLWIDTH", &widths[0]))
4902                     goto error;
4903                 }
4904               else if (lex_match_id (lexer, "MAXCOLWIDTH"))
4905                 {
4906                   if (!parse_col_width (lexer, "MAXCOLWIDTH", &widths[1]))
4907                     goto error;
4908                 }
4909               else if (lex_match_id (lexer, "UNITS"))
4910                 {
4911                   lex_match (lexer, T_EQUALS);
4912                   if (lex_match_id (lexer, "POINTS"))
4913                     units_per_inch = 72.0;
4914                   else if (lex_match_id (lexer, "INCHES"))
4915                     units_per_inch = 1.0;
4916                   else if (lex_match_id (lexer, "CM"))
4917                     units_per_inch = 2.54;
4918                   else
4919                     {
4920                       lex_error_expecting (lexer, "POINTS", "INCHES", "CM");
4921                       goto error;
4922                     }
4923                 }
4924               else if (lex_match_id (lexer, "EMPTY"))
4925                 {
4926                   free (ct->zero);
4927                   ct->zero = NULL;
4928
4929                   lex_match (lexer, T_EQUALS);
4930                   if (lex_match_id (lexer, "ZERO"))
4931                     {
4932                       /* Nothing to do. */
4933                     }
4934                   else if (lex_match_id (lexer, "BLANK"))
4935                     ct->zero = xstrdup ("");
4936                   else if (lex_force_string (lexer))
4937                     {
4938                       ct->zero = ss_xstrdup (lex_tokss (lexer));
4939                       lex_get (lexer);
4940                     }
4941                   else
4942                     goto error;
4943                 }
4944               else if (lex_match_id (lexer, "MISSING"))
4945                 {
4946                   lex_match (lexer, T_EQUALS);
4947                   if (!lex_force_string (lexer))
4948                     goto error;
4949
4950                   free (ct->missing);
4951                   ct->missing = (strcmp (lex_tokcstr (lexer), ".")
4952                                  ? ss_xstrdup (lex_tokss (lexer))
4953                                  : NULL);
4954                   lex_get (lexer);
4955                 }
4956               else
4957                 {
4958                   lex_error_expecting (lexer, "MINCOLWIDTH", "MAXCOLWIDTH",
4959                                        "UNITS", "EMPTY", "MISSING");
4960                   goto error;
4961                 }
4962             }
4963
4964           if (widths[0] != SYSMIS && widths[1] != SYSMIS
4965               && widths[0] > widths[1])
4966             {
4967               msg (SE, _("MINCOLWIDTH must not be greater than MAXCOLWIDTH."));
4968               goto error;
4969             }
4970
4971           for (size_t i = 0; i < 2; i++)
4972             if (widths[i] != SYSMIS)
4973               {
4974                 int *wr = ct->look->width_ranges[TABLE_HORZ];
4975                 wr[i] = widths[i] / units_per_inch * 96.0;
4976                 if (wr[0] > wr[1])
4977                   wr[!i] = wr[i];
4978               }
4979         }
4980       else if (lex_match_id (lexer, "VLABELS"))
4981         {
4982           if (!lex_force_match_id (lexer, "VARIABLES"))
4983             goto error;
4984           lex_match (lexer, T_EQUALS);
4985
4986           struct variable **vars;
4987           size_t n_vars;
4988           if (!parse_variables (lexer, dataset_dict (ds), &vars, &n_vars,
4989                                 PV_NO_SCRATCH))
4990             goto error;
4991
4992           if (!lex_force_match_id (lexer, "DISPLAY"))
4993             {
4994               free (vars);
4995               goto error;
4996             }
4997           lex_match (lexer, T_EQUALS);
4998
4999           enum ctables_vlabel vlabel;
5000           if (lex_match_id (lexer, "DEFAULT"))
5001             vlabel = (enum ctables_vlabel) settings_get_show_variables ();
5002           else if (lex_match_id (lexer, "NAME"))
5003             vlabel = CTVL_NAME;
5004           else if (lex_match_id (lexer, "LABEL"))
5005             vlabel = CTVL_LABEL;
5006           else if (lex_match_id (lexer, "BOTH"))
5007             vlabel = CTVL_BOTH;
5008           else if (lex_match_id (lexer, "NONE"))
5009             vlabel = CTVL_NONE;
5010           else
5011             {
5012               lex_error_expecting (lexer, "DEFAULT", "NAME", "LABEL",
5013                                    "BOTH", "NONE");
5014               free (vars);
5015               goto error;
5016             }
5017
5018           for (size_t i = 0; i < n_vars; i++)
5019             ct->vlabels[var_get_dict_index (vars[i])] = vlabel;
5020           free (vars);
5021         }
5022       else if (lex_match_id (lexer, "MRSETS"))
5023         {
5024           if (!lex_force_match_id (lexer, "COUNTDUPLICATES"))
5025             goto error;
5026           lex_match (lexer, T_EQUALS);
5027           if (!parse_bool (lexer, &ct->mrsets_count_duplicates))
5028             goto error;
5029         }
5030       else if (lex_match_id (lexer, "SMISSING"))
5031         {
5032           if (lex_match_id (lexer, "VARIABLE"))
5033             ct->smissing_listwise = false;
5034           else if (lex_match_id (lexer, "LISTWISE"))
5035             ct->smissing_listwise = true;
5036           else
5037             {
5038               lex_error_expecting (lexer, "VARIABLE", "LISTWISE");
5039               goto error;
5040             }
5041         }
5042       else if (lex_match_id (lexer, "PCOMPUTE"))
5043         {
5044           if (!ctables_parse_pcompute (lexer, ct))
5045             goto error;
5046         }
5047       else if (lex_match_id (lexer, "PPROPERTIES"))
5048         {
5049           if (!ctables_parse_pproperties (lexer, ct))
5050             goto error;
5051         }
5052       else if (lex_match_id (lexer, "WEIGHT"))
5053         {
5054           if (!lex_force_match_id (lexer, "VARIABLE"))
5055             goto error;
5056           lex_match (lexer, T_EQUALS);
5057           ct->e_weight = parse_variable (lexer, dataset_dict (ds));
5058           if (!ct->e_weight)
5059             goto error;
5060         }
5061       else if (lex_match_id (lexer, " HIDESMALLCOUNTS"))
5062         {
5063           if (lex_match_id (lexer, "COUNT"))
5064             {
5065               lex_match (lexer, T_EQUALS);
5066               if (!lex_force_int_range (lexer, "HIDESMALLCOUNTS COUNT",
5067                                         2, INT_MAX))
5068                 goto error;
5069               ct->hide_threshold = lex_integer (lexer);
5070               lex_get (lexer);
5071             }
5072           else if (ct->hide_threshold == 0)
5073             ct->hide_threshold = 5;
5074         }
5075       else
5076         {
5077           lex_error_expecting (lexer, "FORMAT", "VLABELS", "MRSETS",
5078                                "SMISSING", "PCOMPUTE", "PPROPERTIES",
5079                                "WEIGHT", "HIDESMALLCOUNTS", "TABLE");
5080           goto error;
5081         }
5082
5083       if (!lex_force_match (lexer, T_SLASH))
5084         goto error;
5085     }
5086
5087   size_t allocated_tables = 0;
5088   do
5089     {
5090       if (ct->n_tables >= allocated_tables)
5091         ct->tables = x2nrealloc (ct->tables, &allocated_tables,
5092                                  sizeof *ct->tables);
5093
5094       struct ctables_category *cat = xmalloc (sizeof *cat);
5095       *cat = (struct ctables_category) {
5096         .type = CCT_VALUE,
5097         .include_missing = false,
5098         .sort_ascending = true,
5099       };
5100
5101       struct ctables_categories *c = xmalloc (sizeof *c);
5102       size_t n_vars = dict_get_n_vars (dataset_dict (ds));
5103       *c = (struct ctables_categories) {
5104         .n_refs = n_vars,
5105         .cats = cat,
5106         .n_cats = 1,
5107         .show_empty = true,
5108       };
5109
5110       struct ctables_categories **categories = xnmalloc (n_vars,
5111                                                          sizeof *categories);
5112       for (size_t i = 0; i < n_vars; i++)
5113         categories[i] = c;
5114
5115       struct ctables_table *t = xmalloc (sizeof *t);
5116       *t = (struct ctables_table) {
5117         .ctables = ct,
5118         .slabels_axis = PIVOT_AXIS_COLUMN,
5119         .slabels_visible = true,
5120         .clabels_values_map = HMAP_INITIALIZER (t->clabels_values_map),
5121         .label_axis = {
5122           [PIVOT_AXIS_ROW] = PIVOT_AXIS_ROW,
5123           [PIVOT_AXIS_COLUMN] = PIVOT_AXIS_COLUMN,
5124           [PIVOT_AXIS_LAYER] = PIVOT_AXIS_LAYER,
5125         },
5126         .clabels_from_axis = PIVOT_AXIS_LAYER,
5127         .categories = categories,
5128         .n_categories = n_vars,
5129         .cilevel = 95,
5130       };
5131       ct->tables[ct->n_tables++] = t;
5132
5133       lex_match (lexer, T_EQUALS);
5134       if (!ctables_axis_parse (lexer, dataset_dict (ds), ct, t, PIVOT_AXIS_ROW))
5135         goto error;
5136       if (lex_match (lexer, T_BY))
5137         {
5138           if (!ctables_axis_parse (lexer, dataset_dict (ds),
5139                                    ct, t, PIVOT_AXIS_COLUMN))
5140             goto error;
5141
5142           if (lex_match (lexer, T_BY))
5143             {
5144               if (!ctables_axis_parse (lexer, dataset_dict (ds),
5145                                        ct, t, PIVOT_AXIS_LAYER))
5146                 goto error;
5147             }
5148         }
5149
5150       if (!t->axes[PIVOT_AXIS_ROW] && !t->axes[PIVOT_AXIS_COLUMN]
5151           && !t->axes[PIVOT_AXIS_LAYER])
5152         {
5153           lex_error (lexer, _("At least one variable must be specified."));
5154           goto error;
5155         }
5156
5157       const struct ctables_axis *scales[PIVOT_N_AXES];
5158       size_t n_scales = 0;
5159       for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
5160         {
5161           scales[a] = find_scale (t->axes[a]);
5162           if (scales[a])
5163             n_scales++;
5164         }
5165       if (n_scales > 1)
5166         {
5167           msg (SE, _("Scale variables may appear only on one axis."));
5168           if (scales[PIVOT_AXIS_ROW])
5169             msg_at (SN, scales[PIVOT_AXIS_ROW]->loc,
5170                     _("This scale variable appears on the rows axis."));
5171           if (scales[PIVOT_AXIS_COLUMN])
5172             msg_at (SN, scales[PIVOT_AXIS_COLUMN]->loc,
5173                     _("This scale variable appears on the columns axis."));
5174           if (scales[PIVOT_AXIS_LAYER])
5175             msg_at (SN, scales[PIVOT_AXIS_LAYER]->loc,
5176                     _("This scale variable appears on the layer axis."));
5177           goto error;
5178         }
5179
5180       const struct ctables_axis *summaries[PIVOT_N_AXES];
5181       size_t n_summaries = 0;
5182       for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
5183         {
5184           summaries[a] = (scales[a]
5185                           ? scales[a]
5186                           : find_categorical_summary_spec (t->axes[a]));
5187           if (summaries[a])
5188             n_summaries++;
5189         }
5190       if (n_summaries > 1)
5191         {
5192           msg (SE, _("Summaries may appear only on one axis."));
5193           if (summaries[PIVOT_AXIS_ROW])
5194             msg_at (SN, summaries[PIVOT_AXIS_ROW]->loc,
5195                     _("This variable on the rows axis has a summary."));
5196           if (summaries[PIVOT_AXIS_COLUMN])
5197             msg_at (SN, summaries[PIVOT_AXIS_COLUMN]->loc,
5198                     _("This variable on the columns axis has a summary."));
5199           if (summaries[PIVOT_AXIS_LAYER])
5200             msg_at (SN, summaries[PIVOT_AXIS_LAYER]->loc,
5201                     _("This variable on the layers axis has a summary."));
5202           goto error;
5203         }
5204       for (enum pivot_axis_type a = 0; a < PIVOT_N_AXES; a++)
5205         if (n_summaries ? summaries[a] : t->axes[a])
5206           {
5207             t->summary_axis = a;
5208             break;
5209           }
5210
5211       if (lex_token (lexer) == T_ENDCMD)
5212         {
5213           if (!ctables_prepare_table (t))
5214             goto error;
5215           break;
5216         }
5217       if (!lex_force_match (lexer, T_SLASH))
5218         break;
5219
5220       while (!lex_match_id (lexer, "TABLE") && lex_token (lexer) != T_ENDCMD)
5221         {
5222           if (lex_match_id (lexer, "SLABELS"))
5223             {
5224               while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
5225                 {
5226                   if (lex_match_id (lexer, "POSITION"))
5227                     {
5228                       lex_match (lexer, T_EQUALS);
5229                       if (lex_match_id (lexer, "COLUMN"))
5230                         t->slabels_axis = PIVOT_AXIS_COLUMN;
5231                       else if (lex_match_id (lexer, "ROW"))
5232                         t->slabels_axis = PIVOT_AXIS_ROW;
5233                       else if (lex_match_id (lexer, "LAYER"))
5234                         t->slabels_axis = PIVOT_AXIS_LAYER;
5235                       else
5236                         {
5237                           lex_error_expecting (lexer, "COLUMN", "ROW", "LAYER");
5238                           goto error;
5239                         }
5240                     }
5241                   else if (lex_match_id (lexer, "VISIBLE"))
5242                     {
5243                       lex_match (lexer, T_EQUALS);
5244                       if (!parse_bool (lexer, &t->slabels_visible))
5245                         goto error;
5246                     }
5247                   else
5248                     {
5249                       lex_error_expecting (lexer, "POSITION", "VISIBLE");
5250                       goto error;
5251                     }
5252                 }
5253             }
5254           else if (lex_match_id (lexer, "CLABELS"))
5255             {
5256               while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
5257                 {
5258                   if (lex_match_id (lexer, "AUTO"))
5259                     {
5260                       t->label_axis[PIVOT_AXIS_ROW] = PIVOT_AXIS_ROW;
5261                       t->label_axis[PIVOT_AXIS_COLUMN] = PIVOT_AXIS_COLUMN;
5262                     }
5263                   else if (lex_match_id (lexer, "ROWLABELS"))
5264                     {
5265                       lex_match (lexer, T_EQUALS);
5266                       if (lex_match_id (lexer, "OPPOSITE"))
5267                         t->label_axis[PIVOT_AXIS_ROW] = PIVOT_AXIS_COLUMN;
5268                       else if (lex_match_id (lexer, "LAYER"))
5269                         t->label_axis[PIVOT_AXIS_ROW] = PIVOT_AXIS_LAYER;
5270                       else
5271                         {
5272                           lex_error_expecting (lexer, "OPPOSITE", "LAYER");
5273                           goto error;
5274                         }
5275                     }
5276                   else if (lex_match_id (lexer, "COLLABELS"))
5277                     {
5278                       lex_match (lexer, T_EQUALS);
5279                       if (lex_match_id (lexer, "OPPOSITE"))
5280                         t->label_axis[PIVOT_AXIS_COLUMN] = PIVOT_AXIS_ROW;
5281                       else if (lex_match_id (lexer, "LAYER"))
5282                         t->label_axis[PIVOT_AXIS_COLUMN] = PIVOT_AXIS_LAYER;
5283                       else
5284                         {
5285                           lex_error_expecting (lexer, "OPPOSITE", "LAYER");
5286                           goto error;
5287                         }
5288                     }
5289                   else
5290                     {
5291                       lex_error_expecting (lexer, "AUTO", "ROWLABELS",
5292                                            "COLLABELS");
5293                       goto error;
5294                     }
5295                 }
5296             }
5297           else if (lex_match_id (lexer, "CRITERIA"))
5298             {
5299               if (!lex_force_match_id (lexer, "CILEVEL"))
5300                 goto error;
5301               lex_match (lexer, T_EQUALS);
5302
5303               if (!lex_force_num_range_halfopen (lexer, "CILEVEL", 0, 100))
5304                 goto error;
5305               t->cilevel = lex_number (lexer);
5306               lex_get (lexer);
5307             }
5308           else if (lex_match_id (lexer, "CATEGORIES"))
5309             {
5310               if (!ctables_table_parse_categories (lexer, dataset_dict (ds),
5311                                                    ct, t))
5312                 goto error;
5313             }
5314           else if (lex_match_id (lexer, "TITLES"))
5315             {
5316               do
5317                 {
5318                   char **textp;
5319                   if (lex_match_id (lexer, "CAPTION"))
5320                     textp = &t->caption;
5321                   else if (lex_match_id (lexer, "CORNER"))
5322                     textp = &t->corner;
5323                   else if (lex_match_id (lexer, "TITLE"))
5324                     textp = &t->title;
5325                   else
5326                     {
5327                       lex_error_expecting (lexer, "CAPTION", "CORNER", "TITLE");
5328                       goto error;
5329                     }
5330                   lex_match (lexer, T_EQUALS);
5331
5332                   struct string s = DS_EMPTY_INITIALIZER;
5333                   while (lex_is_string (lexer))
5334                     {
5335                       if (!ds_is_empty (&s))
5336                         ds_put_byte (&s, ' ');
5337                       ds_put_substring (&s, lex_tokss (lexer));
5338                       lex_get (lexer);
5339                     }
5340                   free (*textp);
5341                   *textp = ds_steal_cstr (&s);
5342                 }
5343               while (lex_token (lexer) != T_SLASH
5344                      && lex_token (lexer) != T_ENDCMD);
5345             }
5346           else if (lex_match_id (lexer, "SIGTEST"))
5347             {
5348               if (!t->chisq)
5349                 {
5350                   t->chisq = xmalloc (sizeof *t->chisq);
5351                   *t->chisq = (struct ctables_chisq) {
5352                     .alpha = .05,
5353                     .include_mrsets = true,
5354                     .all_visible = true,
5355                   };
5356                 }
5357
5358               do
5359                 {
5360                   if (lex_match_id (lexer, "TYPE"))
5361                     {
5362                       lex_match (lexer, T_EQUALS);
5363                       if (!lex_force_match_id (lexer, "CHISQUARE"))
5364                         goto error;
5365                     }
5366                   else if (lex_match_id (lexer, "ALPHA"))
5367                     {
5368                       lex_match (lexer, T_EQUALS);
5369                       if (!lex_force_num_range_halfopen (lexer, "ALPHA", 0, 1))
5370                         goto error;
5371                       t->chisq->alpha = lex_number (lexer);
5372                       lex_get (lexer);
5373                     }
5374                   else if (lex_match_id (lexer, "INCLUDEMRSETS"))
5375                     {
5376                       lex_match (lexer, T_EQUALS);
5377                       if (parse_bool (lexer, &t->chisq->include_mrsets))
5378                         goto error;
5379                     }
5380                   else if (lex_match_id (lexer, "CATEGORIES"))
5381                     {
5382                       lex_match (lexer, T_EQUALS);
5383                       if (lex_match_id (lexer, "ALLVISIBLE"))
5384                         t->chisq->all_visible = true;
5385                       else if (lex_match_id (lexer, "SUBTOTALS"))
5386                         t->chisq->all_visible = false;
5387                       else
5388                         {
5389                           lex_error_expecting (lexer,
5390                                                "ALLVISIBLE", "SUBTOTALS");
5391                           goto error;
5392                         }
5393                     }
5394                   else
5395                     {
5396                       lex_error_expecting (lexer, "TYPE", "ALPHA",
5397                                            "INCLUDEMRSETS", "CATEGORIES");
5398                       goto error;
5399                     }
5400                 }
5401               while (lex_token (lexer) != T_SLASH
5402                      && lex_token (lexer) != T_ENDCMD);
5403             }
5404           else if (lex_match_id (lexer, "COMPARETEST"))
5405             {
5406               if (!t->pairwise)
5407                 {
5408                   t->pairwise = xmalloc (sizeof *t->pairwise);
5409                   *t->pairwise = (struct ctables_pairwise) {
5410                     .type = PROP,
5411                     .alpha = { .05, .05 },
5412                     .adjust = BONFERRONI,
5413                     .include_mrsets = true,
5414                     .meansvariance_allcats = true,
5415                     .all_visible = true,
5416                     .merge = false,
5417                     .apa_style = true,
5418                     .show_sig = false,
5419                   };
5420                 }
5421
5422               do
5423                 {
5424                   if (lex_match_id (lexer, "TYPE"))
5425                     {
5426                       lex_match (lexer, T_EQUALS);
5427                       if (lex_match_id (lexer, "PROP"))
5428                         t->pairwise->type = PROP;
5429                       else if (lex_match_id (lexer, "MEAN"))
5430                         t->pairwise->type = MEAN;
5431                       else
5432                         {
5433                           lex_error_expecting (lexer, "PROP", "MEAN");
5434                           goto error;
5435                         }
5436                     }
5437                   else if (lex_match_id (lexer, "ALPHA"))
5438                     {
5439                       lex_match (lexer, T_EQUALS);
5440
5441                       if (!lex_force_num_range_open (lexer, "ALPHA", 0, 1))
5442                         goto error;
5443                       double a0 = lex_number (lexer);
5444                       lex_get (lexer);
5445
5446                       lex_match (lexer, T_COMMA);
5447                       if (lex_is_number (lexer))
5448                         {
5449                           if (!lex_force_num_range_open (lexer, "ALPHA", 0, 1))
5450                             goto error;
5451                           double a1 = lex_number (lexer);
5452                           lex_get (lexer);
5453
5454                           t->pairwise->alpha[0] = MIN (a0, a1);
5455                           t->pairwise->alpha[1] = MAX (a0, a1);
5456                         }
5457                       else
5458                         t->pairwise->alpha[0] = t->pairwise->alpha[1] = a0;
5459                     }
5460                   else if (lex_match_id (lexer, "ADJUST"))
5461                     {
5462                       lex_match (lexer, T_EQUALS);
5463                       if (lex_match_id (lexer, "BONFERRONI"))
5464                         t->pairwise->adjust = BONFERRONI;
5465                       else if (lex_match_id (lexer, "BH"))
5466                         t->pairwise->adjust = BH;
5467                       else if (lex_match_id (lexer, "NONE"))
5468                         t->pairwise->adjust = 0;
5469                       else
5470                         {
5471                           lex_error_expecting (lexer, "BONFERRONI", "BH",
5472                                                "NONE");
5473                           goto error;
5474                         }
5475                     }
5476                   else if (lex_match_id (lexer, "INCLUDEMRSETS"))
5477                     {
5478                       lex_match (lexer, T_EQUALS);
5479                       if (!parse_bool (lexer, &t->pairwise->include_mrsets))
5480                         goto error;
5481                     }
5482                   else if (lex_match_id (lexer, "MEANSVARIANCE"))
5483                     {
5484                       lex_match (lexer, T_EQUALS);
5485                       if (lex_match_id (lexer, "ALLCATS"))
5486                         t->pairwise->meansvariance_allcats = true;
5487                       else if (lex_match_id (lexer, "TESTEDCATS"))
5488                         t->pairwise->meansvariance_allcats = false;
5489                       else
5490                         {
5491                           lex_error_expecting (lexer, "ALLCATS", "TESTEDCATS");
5492                           goto error;
5493                         }
5494                     }
5495                   else if (lex_match_id (lexer, "CATEGORIES"))
5496                     {
5497                       lex_match (lexer, T_EQUALS);
5498                       if (lex_match_id (lexer, "ALLVISIBLE"))
5499                         t->pairwise->all_visible = true;
5500                       else if (lex_match_id (lexer, "SUBTOTALS"))
5501                         t->pairwise->all_visible = false;
5502                       else
5503                         {
5504                           lex_error_expecting (lexer, "ALLVISIBLE",
5505                                                "SUBTOTALS");
5506                           goto error;
5507                         }
5508                     }
5509                   else if (lex_match_id (lexer, "MERGE"))
5510                     {
5511                       lex_match (lexer, T_EQUALS);
5512                       if (!parse_bool (lexer, &t->pairwise->merge))
5513                         goto error;
5514                     }
5515                   else if (lex_match_id (lexer, "STYLE"))
5516                     {
5517                       lex_match (lexer, T_EQUALS);
5518                       if (lex_match_id (lexer, "APA"))
5519                         t->pairwise->apa_style = true;
5520                       else if (lex_match_id (lexer, "SIMPLE"))
5521                         t->pairwise->apa_style = false;
5522                       else
5523                         {
5524                           lex_error_expecting (lexer, "APA", "SIMPLE");
5525                           goto error;
5526                         }
5527                     }
5528                   else if (lex_match_id (lexer, "SHOWSIG"))
5529                     {
5530                       lex_match (lexer, T_EQUALS);
5531                       if (!parse_bool (lexer, &t->pairwise->show_sig))
5532                         goto error;
5533                     }
5534                   else
5535                     {
5536                       lex_error_expecting (lexer, "TYPE", "ALPHA", "ADJUST",
5537                                            "INCLUDEMRSETS", "MEANSVARIANCE",
5538                                            "CATEGORIES", "MERGE", "STYLE",
5539                                            "SHOWSIG");
5540                       goto error;
5541                     }
5542                 }
5543               while (lex_token (lexer) != T_SLASH
5544                      && lex_token (lexer) != T_ENDCMD);
5545             }
5546           else
5547             {
5548               lex_error_expecting (lexer, "TABLE", "SLABELS", "CLABELS",
5549                                    "CRITERIA", "CATEGORIES", "TITLES",
5550                                    "SIGTEST", "COMPARETEST");
5551               goto error;
5552             }
5553
5554           if (!lex_match (lexer, T_SLASH))
5555             break;
5556         }
5557
5558       if (t->label_axis[PIVOT_AXIS_ROW] != PIVOT_AXIS_ROW
5559           && t->label_axis[PIVOT_AXIS_COLUMN] != PIVOT_AXIS_COLUMN)
5560         {
5561           msg (SE, _("ROWLABELS and COLLABELS may not both be specified."));
5562           goto error;
5563         }
5564
5565       if (!ctables_prepare_table (t))
5566         goto error;
5567     }
5568   while (lex_token (lexer) != T_ENDCMD);
5569
5570   bool ok = ctables_execute (ds, ct);
5571   ctables_destroy (ct);
5572   return ok ? CMD_SUCCESS : CMD_FAILURE;
5573
5574 error:
5575   ctables_destroy (ct);
5576   return CMD_FAILURE;
5577 }
5578