1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2017, 2018 Free Software Foundation, Inc.
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.
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.
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/>. */
19 #include "output/pivot-table.h"
23 #include "data/data-out.h"
24 #include "data/settings.h"
25 #include "data/value.h"
26 #include "data/variable.h"
27 #include "data/file-name.h"
28 #include "libpspp/hash-functions.h"
29 #include "libpspp/i18n.h"
30 #include "output/driver.h"
31 #include "output/spv/spv-table-look.h"
33 #include "gl/c-ctype.h"
34 #include "gl/configmake.h"
35 #include "gl/intprops.h"
36 #include "gl/minmax.h"
37 #include "gl/relocatable.h"
38 #include "gl/xalloc.h"
39 #include "gl/xmemdup0.h"
43 #define _(msgid) gettext (msgid)
44 #define N_(msgid) msgid
46 static const struct fmt_spec *pivot_table_get_format (
47 const struct pivot_table *, const char *s);
49 /* Pivot table display styling. */
51 /* Returns the name of AREA. */
53 pivot_area_to_string (enum pivot_area area)
57 case PIVOT_AREA_TITLE: return "title";
58 case PIVOT_AREA_CAPTION: return "caption";
59 case PIVOT_AREA_FOOTER: return "footer";
60 case PIVOT_AREA_CORNER: return "corner";
61 case PIVOT_AREA_COLUMN_LABELS: return "column labels";
62 case PIVOT_AREA_ROW_LABELS: return "row labels";
63 case PIVOT_AREA_DATA: return "data";
64 case PIVOT_AREA_LAYERS: return "layers";
65 case PIVOT_N_AREAS: default: return "**error**";
69 /* Returns the name of BORDER. */
71 pivot_border_to_string (enum pivot_border border)
75 case PIVOT_BORDER_TITLE:
78 case PIVOT_BORDER_OUTER_LEFT:
79 return "left outer frame";
80 case PIVOT_BORDER_OUTER_TOP:
81 return "top outer frame";
82 case PIVOT_BORDER_OUTER_RIGHT:
83 return "right outer frame";
84 case PIVOT_BORDER_OUTER_BOTTOM:
85 return "bottom outer frame";
87 case PIVOT_BORDER_INNER_LEFT:
88 return "left inner frame";
89 case PIVOT_BORDER_INNER_TOP:
90 return "top inner frame";
91 case PIVOT_BORDER_INNER_RIGHT:
92 return "right inner frame";
93 case PIVOT_BORDER_INNER_BOTTOM:
94 return "bottom inner frame";
96 case PIVOT_BORDER_DATA_LEFT:
97 return "data area left";
98 case PIVOT_BORDER_DATA_TOP:
99 return "data area top";
101 case PIVOT_BORDER_DIM_ROW_HORZ:
102 return "row label horizontal dimension border";
103 case PIVOT_BORDER_DIM_ROW_VERT:
104 return "row label vertical dimension border";
105 case PIVOT_BORDER_DIM_COL_HORZ:
106 return "column label horizontal dimension border";
107 case PIVOT_BORDER_DIM_COL_VERT:
108 return "column label vertical dimension border";
110 case PIVOT_BORDER_CAT_ROW_HORZ:
111 return "row label horizontal category border";
112 case PIVOT_BORDER_CAT_ROW_VERT:
113 return "row label vertical category border";
114 case PIVOT_BORDER_CAT_COL_HORZ:
115 return "column label horizontal category border";
116 case PIVOT_BORDER_CAT_COL_VERT:
117 return "column label vertical category border";
119 case PIVOT_N_BORDERS:
126 pivot_table_sizing_uninit (struct pivot_table_sizing *sizing)
130 free (sizing->widths);
131 free (sizing->breaks);
132 free (sizing->keeps);
136 /* Pivot table looks. */
138 static const struct pivot_table_look *
139 default_look (const struct pivot_table_look *new)
141 static struct pivot_table_look *look;
144 pivot_table_look_unref (look);
145 look = pivot_table_look_ref (new);
149 char *error = pivot_table_look_read ("default.stt", &look);
151 look = pivot_table_look_ref (pivot_table_look_builtin_default ());
156 const struct pivot_table_look *
157 pivot_table_look_get_default (void)
159 return default_look (NULL);
163 pivot_table_look_set_default (const struct pivot_table_look *look)
168 char * WARN_UNUSED_RESULT
169 pivot_table_look_read (const char *name, struct pivot_table_look **lookp)
173 /* Construct search path. */
177 const char *home = getenv ("HOME");
179 path[n++] = xasprintf ("%s/.pspp/looks", home);
181 path[n++] = relocate2 (PKGDATADIR "/looks", &allocated);
185 char *file = fn_search_path (name, (char **) path);
188 char *name2 = xasprintf ("%s.stt", name);
189 file = fn_search_path (name2, (char **) path);
194 return xasprintf ("%s: not found", name);
197 char *error = spv_table_look_read (file, lookp);
202 const struct pivot_table_look *
203 pivot_table_look_builtin_default (void)
205 static struct pivot_table_look look = {
209 .row_labels_in_corner = true,
211 [TABLE_HORZ] = { 36, 72 },
212 [TABLE_VERT] = { 36, 120 },
216 #define AREA(BOLD, H, V, L, R, T, B) { \
218 .halign = TABLE_HALIGN_##H, \
219 .valign = TABLE_VALIGN_##V, \
220 .margin = { [TABLE_HORZ][0] = L, [TABLE_HORZ][1] = R, \
221 [TABLE_VERT][0] = T, [TABLE_VERT][1] = B }, \
225 .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK}, \
226 .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE}, \
228 .typeface = (char *) "Sans Serif", \
231 [PIVOT_AREA_TITLE] = AREA(true, CENTER, CENTER, 8,11,1,8),
232 [PIVOT_AREA_CAPTION] = AREA(false, LEFT, TOP, 8,11,1,1),
233 [PIVOT_AREA_FOOTER] = AREA(false, LEFT, TOP, 11, 8,2,3),
234 [PIVOT_AREA_CORNER] = AREA(false, LEFT, BOTTOM, 8,11,1,1),
235 [PIVOT_AREA_COLUMN_LABELS] = AREA(false, CENTER, BOTTOM, 8,11,1,3),
236 [PIVOT_AREA_ROW_LABELS] = AREA(false, LEFT, TOP, 8,11,1,3),
237 [PIVOT_AREA_DATA] = AREA(false, MIXED, TOP, 8,11,1,1),
238 [PIVOT_AREA_LAYERS] = AREA(false, LEFT, BOTTOM, 8,11,1,3),
243 #define BORDER(STROKE) { .stroke = STROKE, .color = CELL_COLOR_BLACK }
244 [PIVOT_BORDER_TITLE] = BORDER(TABLE_STROKE_NONE),
245 [PIVOT_BORDER_OUTER_LEFT] = BORDER(TABLE_STROKE_NONE),
246 [PIVOT_BORDER_OUTER_TOP] = BORDER(TABLE_STROKE_NONE),
247 [PIVOT_BORDER_OUTER_RIGHT] = BORDER(TABLE_STROKE_NONE),
248 [PIVOT_BORDER_OUTER_BOTTOM] = BORDER(TABLE_STROKE_NONE),
249 [PIVOT_BORDER_INNER_LEFT] = BORDER(TABLE_STROKE_THICK),
250 [PIVOT_BORDER_INNER_TOP] = BORDER(TABLE_STROKE_THICK),
251 [PIVOT_BORDER_INNER_RIGHT] = BORDER(TABLE_STROKE_THICK),
252 [PIVOT_BORDER_INNER_BOTTOM] = BORDER(TABLE_STROKE_THICK),
253 [PIVOT_BORDER_DATA_LEFT] = BORDER(TABLE_STROKE_THICK),
254 [PIVOT_BORDER_DATA_TOP] = BORDER(TABLE_STROKE_THICK),
255 [PIVOT_BORDER_DIM_ROW_HORZ] = BORDER(TABLE_STROKE_SOLID),
256 [PIVOT_BORDER_DIM_ROW_VERT] = BORDER(TABLE_STROKE_NONE),
257 [PIVOT_BORDER_DIM_COL_HORZ] = BORDER(TABLE_STROKE_SOLID),
258 [PIVOT_BORDER_DIM_COL_VERT] = BORDER(TABLE_STROKE_SOLID),
259 [PIVOT_BORDER_CAT_ROW_HORZ] = BORDER(TABLE_STROKE_NONE),
260 [PIVOT_BORDER_CAT_ROW_VERT] = BORDER(TABLE_STROKE_NONE),
261 [PIVOT_BORDER_CAT_COL_HORZ] = BORDER(TABLE_STROKE_SOLID),
262 [PIVOT_BORDER_CAT_COL_VERT] = BORDER(TABLE_STROKE_SOLID),
269 struct pivot_table_look *
270 pivot_table_look_new_builtin_default (void)
272 return pivot_table_look_unshare (
273 pivot_table_look_ref (pivot_table_look_builtin_default ()));
276 struct pivot_table_look *
277 pivot_table_look_ref (const struct pivot_table_look *look_)
279 assert (look_->ref_cnt > 0);
281 struct pivot_table_look *look = CONST_CAST (struct pivot_table_look *, look_);
287 xstrdup_if_nonempty (const char *s)
289 return s && s[0] ? xstrdup (s) : NULL;
292 struct pivot_table_look *
293 pivot_table_look_unshare (struct pivot_table_look *old)
295 assert (old->ref_cnt > 0);
296 if (old->ref_cnt == 1)
299 pivot_table_look_unref (old);
301 struct pivot_table_look *new = xmemdup (old, sizeof *old);
303 new->name = xstrdup_if_nonempty (old->name);
304 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
305 table_area_style_copy (NULL, &new->areas[i], &old->areas[i]);
306 new->continuation = xstrdup_if_nonempty (old->continuation);
312 pivot_table_look_unref (struct pivot_table_look *look)
316 assert (look->ref_cnt > 0);
317 if (!--look->ref_cnt)
320 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
321 table_area_style_uninit (&look->areas[i]);
322 free (look->continuation);
330 /* Returns the name of AXIS_TYPE. */
332 pivot_axis_type_to_string (enum pivot_axis_type axis_type)
336 case PIVOT_AXIS_LAYER:
342 case PIVOT_AXIS_COLUMN:
350 static enum pivot_axis_type
351 pivot_axis_type_transpose (enum pivot_axis_type axis_type)
353 assert (axis_type == PIVOT_AXIS_ROW || axis_type == PIVOT_AXIS_COLUMN);
354 return (axis_type == PIVOT_AXIS_ROW ? PIVOT_AXIS_COLUMN : PIVOT_AXIS_ROW);
357 /* Implementation of PIVOT_AXIS_FOR_EACH. */
359 pivot_axis_iterator_next (size_t *indexes, const struct pivot_axis *axis)
363 if (axis->n_dimensions)
364 for (size_t i = 0; i < axis->n_dimensions; i++)
365 if (axis->dimensions[i]->n_leaves == 0)
368 return xcalloc (axis->n_dimensions, sizeof *indexes);
371 for (size_t i = 0; i < axis->n_dimensions; i++)
373 const struct pivot_dimension *d = axis->dimensions[i];
374 if (++indexes[i] < d->n_leaves)
387 pivot_category_set_rc (struct pivot_category *category, const char *s)
389 const struct fmt_spec *format = pivot_table_get_format (
390 category->dimension->table, s);
392 category->format = *format;
396 pivot_category_create_leaves_valist (struct pivot_category *parent,
400 while ((s = va_arg (args, const char *)))
402 if (!strncmp (s, "RC_", 3))
404 assert (parent->n_subs);
405 pivot_category_set_rc (parent->subs[parent->n_subs - 1], s);
408 pivot_category_create_leaf (parent, pivot_value_new_text (s));
412 /* Creates a new dimension with the given NAME in TABLE and returns it. The
413 dimension is added to axis AXIS_TYPE, becoming the outermost dimension on
416 NAME should be a translatable name, but not actually translated yet,
417 e.g. enclosed in N_(). To use a different kind of value for a name, use
418 pivot_dimension_create__() instead.
420 The optional varargs parameters may be used to add an initial set of
421 categories to the dimension. Each string should be a translatable category
422 name, but not actually translated yet, e.g. enclosed in N_(). Each string
423 may optionally be followod by a PIVOT_RC_* string that specifies the default
424 numeric format for cells in this category. */
425 struct pivot_dimension * SENTINEL (0)
426 (pivot_dimension_create) (struct pivot_table *table,
427 enum pivot_axis_type axis_type,
428 const char *name, ...)
430 struct pivot_dimension *d = pivot_dimension_create__ (
431 table, axis_type, pivot_value_new_text (name));
434 va_start (args, name);
435 pivot_category_create_leaves_valist (d->root, args);
441 /* Creates a new dimension with the given NAME in TABLE and returns it. The
442 dimension is added to axis AXIS_TYPE, becoming the outermost dimension on
444 struct pivot_dimension *
445 pivot_dimension_create__ (struct pivot_table *table,
446 enum pivot_axis_type axis_type,
447 struct pivot_value *name)
449 assert (pivot_table_is_empty (table));
451 struct pivot_dimension *d = xmalloc (sizeof *d);
452 *d = (struct pivot_dimension) {
454 .axis_type = axis_type,
455 .level = table->axes[axis_type].n_dimensions,
456 .top_index = table->n_dimensions,
457 .root = xmalloc (sizeof *d->root),
460 struct pivot_category *root = d->root;
461 *root = (struct pivot_category) {
466 .data_index = SIZE_MAX,
467 .presentation_index = SIZE_MAX,
470 table->dimensions = xrealloc (
471 table->dimensions, (table->n_dimensions + 1) * sizeof *table->dimensions);
472 table->dimensions[table->n_dimensions++] = d;
474 struct pivot_axis *axis = &table->axes[axis_type];
475 axis->dimensions = xrealloc (
476 axis->dimensions, (axis->n_dimensions + 1) * sizeof *axis->dimensions);
477 axis->dimensions[axis->n_dimensions++] = d;
479 if (axis_type == PIVOT_AXIS_LAYER)
481 free (table->current_layer);
482 table->current_layer = xcalloc (axis[PIVOT_AXIS_LAYER].n_dimensions,
483 sizeof *table->current_layer);
486 /* axis->extent and axis->label_depth will be calculated later. */
492 pivot_dimension_destroy (struct pivot_dimension *d)
497 pivot_category_destroy (d->root);
498 free (d->data_leaves);
499 free (d->presentation_leaves);
503 /* Returns the first leaf node in an in-order traversal that is a child of
505 static const struct pivot_category * UNUSED
506 pivot_category_first_leaf (const struct pivot_category *cat)
508 if (pivot_category_is_leaf (cat))
511 for (size_t i = 0; i < cat->n_subs; i++)
513 const struct pivot_category *first
514 = pivot_category_first_leaf (cat->subs[i]);
522 /* Returns the next leaf node in an in-order traversal starting at CAT, which
524 static const struct pivot_category * UNUSED
525 pivot_category_next_leaf (const struct pivot_category *cat)
527 assert (pivot_category_is_leaf (cat));
531 const struct pivot_category *parent = cat->parent;
534 for (size_t i = cat->group_index + 1; i < parent->n_subs; i++)
536 const struct pivot_category *next
537 = pivot_category_first_leaf (parent->subs[i]);
547 pivot_category_add_child (struct pivot_category *child)
549 struct pivot_category *parent = child->parent;
551 assert (pivot_category_is_group (parent));
552 if (parent->n_subs >= parent->allocated_subs)
553 parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
554 sizeof *parent->subs);
555 parent->subs[parent->n_subs++] = child;
558 /* Adds leaf categories as a child of PARENT. To create top-level categories
559 within dimension 'd', pass 'd->root' for PARENT.
561 Each of the varargs parameters should be a string, each of which should be a
562 translatable category name, but not actually translated yet, e.g. enclosed
563 in N_(). Each string may optionally be followod by a PIVOT_RC_* string that
564 specifies the default numeric format for cells in this category.
566 Returns the category index, which is just a 0-based array index, for the
569 Leaves have to be created in in-order, that is, don't create a group and add
570 some leaves, then add leaves outside the group and try to add more leaves
573 (pivot_category_create_leaves) (struct pivot_category *parent, ...)
575 int retval = parent->dimension->n_leaves;
578 va_start (args, parent);
579 pivot_category_create_leaves_valist (parent, args);
585 /* Creates a new leaf category with the given NAME as a child of PARENT. To
586 create a top-level category within dimension 'd', pass 'd->root' for PARENT.
587 Returns the category index, which is just a 0-based array index, for the new
590 Leaves have to be created in in-order, that is, don't create a group and add
591 some leaves, then add leaves outside the group and try to add more leaves
594 pivot_category_create_leaf (struct pivot_category *parent,
595 struct pivot_value *name)
597 return pivot_category_create_leaf_rc (parent, name, NULL);
600 /* Creates a new leaf category with the given NAME as a child of PARENT. To
601 create a top-level category within dimension 'd', pass 'd->root' for PARENT.
602 Returns the category index, which is just a 0-based array index, for the new
605 If RC is nonnull and the name of a result category, the category is assigned
606 that result category.
608 Leaves have to be created in in-order, that is, don't create a group and add
609 some leaves, then add leaves outside the group and try to add more leaves
612 pivot_category_create_leaf_rc (struct pivot_category *parent,
613 struct pivot_value *name, const char *rc)
615 struct pivot_dimension *d = parent->dimension;
617 struct pivot_category *leaf = xmalloc (sizeof *leaf);
618 *leaf = (struct pivot_category) {
622 .group_index = parent->n_subs,
623 .data_index = d->n_leaves,
624 .presentation_index = d->n_leaves,
627 if (d->n_leaves >= d->allocated_leaves)
629 d->data_leaves = x2nrealloc (d->data_leaves, &d->allocated_leaves,
630 sizeof *d->data_leaves);
631 d->presentation_leaves = xrealloc (
632 d->presentation_leaves,
633 d->allocated_leaves * sizeof *d->presentation_leaves);
636 d->data_leaves[d->n_leaves] = leaf;
637 d->presentation_leaves[d->n_leaves] = leaf;
640 pivot_category_add_child (leaf);
642 /* Make sure that the new child is the last in in-order. */
643 assert (!pivot_category_next_leaf (leaf));
645 pivot_category_set_rc (leaf, rc);
647 return leaf->data_index;
650 /* Adds a new category group named NAME as a child of PARENT. To create a
651 top-level group within dimension 'd', pass 'd->root' for PARENT.
653 NAME should be a translatable name, but not actually translated yet,
654 e.g. enclosed in N_(). To use a different kind of value for a name, use
655 pivot_category_create_group__() instead.
657 The optional varargs parameters may be used to add an initial set of
658 categories to the group. Each string should be a translatable category
659 name, but not actually translated yet, e.g. enclosed in N_(). Each string
660 may optionally be followod by a PIVOT_RC_* string that specifies the default
661 numeric format for cells in this category.
663 Returns the new group. */
664 struct pivot_category * SENTINEL (0)
665 (pivot_category_create_group) (struct pivot_category *parent,
666 const char *name, ...)
668 struct pivot_category *group = pivot_category_create_group__ (
669 parent, pivot_value_new_text (name));
672 va_start (args, name);
673 pivot_category_create_leaves_valist (group, args);
679 /* Adds a new category group named NAME as a child of PARENT. To create a
680 top-level group within dimension 'd', pass 'd->root' for PARENT. Returns
682 struct pivot_category *
683 pivot_category_create_group__ (struct pivot_category *parent,
684 struct pivot_value *name)
686 struct pivot_dimension *d = parent->dimension;
688 struct pivot_category *group = xmalloc (sizeof *group);
689 *group = (struct pivot_category) {
694 .group_index = parent->n_subs,
695 .data_index = SIZE_MAX,
696 .presentation_index = SIZE_MAX,
699 pivot_category_add_child (group);
705 pivot_category_destroy (struct pivot_category *c)
710 pivot_value_destroy (c->name);
711 for (size_t i = 0; i < c->n_subs; i++)
712 pivot_category_destroy (c->subs[i]);
719 These are usually the easiest way to control the formatting of numeric data
720 in a pivot table. See pivot_dimension_create() for an explanation of their
724 const char *name; /* "RC_*". */
725 struct fmt_spec format;
728 /* Formats for most of the result classes. */
729 static struct result_class result_classes[] =
731 { PIVOT_RC_INTEGER, { FMT_F, 40, 0 } },
732 { PIVOT_RC_PERCENT, { FMT_PCT, 40, 1 } },
733 { PIVOT_RC_CORRELATION, { FMT_F, 40, 3 } },
734 { PIVOT_RC_SIGNIFICANCE, { FMT_F, 40, 3 } },
735 { PIVOT_RC_RESIDUAL, { FMT_F, 40, 2 } },
736 { PIVOT_RC_COUNT, { 0, 0, 0 } },
737 { PIVOT_RC_OTHER, { 0, 0, 0 } },
740 /* Has PIVOT_RC_COUNT been overridden by the user? */
741 static bool overridden_count_format;
743 static struct result_class *
744 pivot_result_class_find (const char *s)
746 for (size_t i = 0; i < sizeof result_classes / sizeof *result_classes; i++)
747 if (!strcmp (s, result_classes[i].name))
748 return &result_classes[i];
752 static const struct fmt_spec *
753 pivot_table_get_format (const struct pivot_table *table, const char *s)
757 else if (!strcmp (s, PIVOT_RC_OTHER))
758 return settings_get_format ();
759 else if (!strcmp (s, PIVOT_RC_COUNT) && !overridden_count_format)
760 return &table->weight_format;
763 const struct result_class *rc = pivot_result_class_find (s);
764 return rc ? &rc->format : NULL;
768 /* Sets the format specification for the result class named S (which should not
769 include the RC_ prefix) to *FORMAT. Returns true if successful, false if S
770 does not name a known result class. */
772 pivot_result_class_change (const char *s_, const struct fmt_spec *format)
774 char *s = xasprintf ("RC_%s", s_);
775 struct result_class *rc = pivot_result_class_find (s);
778 rc->format = *format;
779 if (!strcmp (s, PIVOT_RC_COUNT))
780 overridden_count_format = true;
789 /* Creates and returns a new pivot table with the given TITLE. TITLE should be
790 a text string marked for translation but not actually translated yet,
791 e.g. N_("Descriptive Statistics"). The un-translated text string is used as
792 the pivot table's subtype.
794 Operations commonly performed on the new pivot_table:
796 - If empty rows or columns should not be displayed, set ->omit_empty to
799 - Set the format to use for "count" values with pivot_table_set_weight_var()
800 or pivot_table_set_weight_format().
802 This function is a shortcut for pivot_table_create__() for the most common
803 case. Use pivot_table_create__() directly if the title should be some kind
804 of value other than an ordinary text string, or if the subtype should be
805 different from the title.
807 See the large comment at the top of pivot-table.h for general advice on
808 creating pivot tables. */
810 pivot_table_create (const char *title)
812 return pivot_table_create__ (pivot_value_new_text (title), title);
815 /* Creates and returns a new pivot table with the given TITLE, and takes
816 ownership of TITLE. The new pivot table's subtype is SUBTYPE, which
817 should be an untranslated English string that describes the contents of
818 the table at a high level without being specific about the variables or
819 other context involved.
821 Operations commonly performed on the new pivot_table:
823 - If empty rows or columns should not be displayed, set ->omit_empty to
826 - Set the format to use for "count" values with pivot_table_set_weight_var()
827 or pivot_table_set_weight_format().
829 See the large comment at the top of pivot-table.h for general advice on
830 creating pivot tables. */
832 pivot_table_create__ (struct pivot_value *title, const char *subtype)
834 struct pivot_table *table = xzalloc (sizeof *table);
836 table->show_caption = true;
837 table->weight_format = (struct fmt_spec) { FMT_F, 40, 0 };
838 table->title = title;
839 table->subtype = subtype ? pivot_value_new_text (subtype) : NULL;
840 table->command_c = output_get_command_name ();
841 table->look = pivot_table_look_ref (pivot_table_look_get_default ());
843 hmap_init (&table->cells);
848 /* Creates and returns a new pivot table with the given TITLE and a single cell
849 with the given CONTENT.
851 This is really just for error handling. */
853 pivot_table_create_for_text (struct pivot_value *title,
854 struct pivot_value *content)
856 struct pivot_table *table = pivot_table_create__ (title, "Error");
858 struct pivot_dimension *d = pivot_dimension_create (
859 table, PIVOT_AXIS_ROW, N_("Error"));
860 d->hide_all_labels = true;
861 pivot_category_create_leaf (d->root, pivot_value_new_text ("null"));
863 pivot_table_put1 (table, 0, content);
868 /* Increases TABLE's reference count, indicating that it has an additional
869 owner. A pivot table that is shared among multiple owners must not be
872 pivot_table_ref (const struct pivot_table *table_)
874 struct pivot_table *table = CONST_CAST (struct pivot_table *, table_);
879 /* Decreases TABLE's reference count, indicating that it has one fewer owner.
880 If TABLE no longer has any owners, it is freed. */
882 pivot_table_unref (struct pivot_table *table)
886 assert (table->ref_cnt > 0);
887 if (--table->ref_cnt)
890 free (table->current_layer);
891 pivot_table_look_unref (table->look);
893 for (int i = 0; i < TABLE_N_AXES; i++)
894 pivot_table_sizing_uninit (&table->sizing[i]);
896 for (int i = 0; i < sizeof table->ccs / sizeof *table->ccs; i++)
897 free (table->ccs[i]);
899 free (table->command_local);
900 free (table->command_c);
901 free (table->language);
902 free (table->locale);
904 free (table->dataset);
905 free (table->datafile);
907 for (size_t i = 0; i < table->n_footnotes; i++)
908 pivot_footnote_destroy (table->footnotes[i]);
909 free (table->footnotes);
911 pivot_value_destroy (table->title);
912 pivot_value_destroy (table->subtype);
913 pivot_value_destroy (table->corner_text);
914 pivot_value_destroy (table->caption);
916 for (size_t i = 0; i < table->n_dimensions; i++)
917 pivot_dimension_destroy (table->dimensions[i]);
918 free (table->dimensions);
920 for (size_t i = 0; i < PIVOT_N_AXES; i++)
921 free (table->axes[i].dimensions);
923 struct pivot_cell *cell, *next_cell;
924 HMAP_FOR_EACH_SAFE (cell, next_cell, struct pivot_cell, hmap_node,
927 hmap_delete (&table->cells, &cell->hmap_node);
928 pivot_value_destroy (cell->value);
931 hmap_destroy (&table->cells);
936 /* Returns true if TABLE has more than one owner. A pivot table that is shared
937 among multiple owners must not be modified. */
939 pivot_table_is_shared (const struct pivot_table *table)
941 return table->ref_cnt > 1;
944 const struct pivot_table_look *
945 pivot_table_get_look (const struct pivot_table *table)
951 pivot_table_set_look (struct pivot_table *table,
952 const struct pivot_table_look *look)
954 pivot_table_look_unref (table->look);
955 table->look = pivot_table_look_ref (look);
958 /* Sets the format used for PIVOT_RC_COUNT cells to the one used for variable
959 WV, which should be the weight variable for the dictionary whose data or
960 statistics are being put into TABLE.
962 This has no effect if WV is NULL. */
964 pivot_table_set_weight_var (struct pivot_table *table,
965 const struct variable *wv)
968 pivot_table_set_weight_format (table, var_get_print_format (wv));
971 /* Sets the format used for PIVOT_RC_COUNT cells to WFMT, which should be the
972 format for the dictionary whose data or statistics are being put into TABLE.
974 This has no effect if WFMT is NULL. */
976 pivot_table_set_weight_format (struct pivot_table *table,
977 const struct fmt_spec *wfmt)
980 table->weight_format = *wfmt;
983 /* Returns true if TABLE has no cells, false otherwise. */
985 pivot_table_is_empty (const struct pivot_table *table)
987 return hmap_is_empty (&table->cells);
991 pivot_cell_hash_indexes (const size_t *indexes, size_t n_idx)
993 return hash_bytes (indexes, n_idx * sizeof *indexes, 0);
997 equal_indexes (const size_t *a, const unsigned int *b, size_t n)
999 for (size_t i = 0; i < n; i++)
1006 static struct pivot_cell *
1007 pivot_table_lookup_cell__ (const struct pivot_table *table,
1008 const size_t *dindexes, unsigned int hash)
1010 struct pivot_cell *cell;
1011 HMAP_FOR_EACH_WITH_HASH (cell, struct pivot_cell, hmap_node, hash,
1013 if (equal_indexes (dindexes, cell->idx, table->n_dimensions))
1018 static struct pivot_cell *
1019 pivot_cell_allocate (size_t n_idx)
1021 struct pivot_cell *cell UNUSED;
1022 return xmalloc (sizeof *cell + n_idx * sizeof *cell->idx);
1025 static struct pivot_cell *
1026 pivot_table_insert_cell (struct pivot_table *table, const size_t *dindexes)
1028 unsigned int hash = pivot_cell_hash_indexes (dindexes, table->n_dimensions);
1029 struct pivot_cell *cell = pivot_table_lookup_cell__ (table, dindexes, hash);
1032 cell = pivot_cell_allocate (table->n_dimensions);
1033 for (size_t i = 0; i < table->n_dimensions; i++)
1034 cell->idx[i] = dindexes[i];
1036 hmap_insert (&table->cells, &cell->hmap_node, hash);
1041 /* Puts VALUE in the cell in TABLE whose indexes are given by the N indexes in
1042 DINDEXES. N must be the number of dimensions in TABLE. Takes ownership of
1045 If VALUE is a numeric value without a specified format, this function checks
1046 each of the categories designated by DINDEXES[] and takes the format from
1047 the first category with a result class. If none has a result class, uses
1048 the overall default numeric format. */
1050 pivot_table_put (struct pivot_table *table, const size_t *dindexes, size_t n,
1051 struct pivot_value *value)
1053 assert (n == table->n_dimensions);
1055 if (value->type == PIVOT_VALUE_NUMERIC && !value->numeric.format.w)
1057 for (size_t i = 0; i < table->n_dimensions; i++)
1059 const struct pivot_dimension *d = table->dimensions[i];
1060 if (dindexes[i] < d->n_leaves)
1062 const struct pivot_category *c = d->data_leaves[dindexes[i]];
1065 value->numeric.format = c->format;
1070 value->numeric.format = *settings_get_format ();
1075 struct pivot_cell *cell = pivot_table_insert_cell (table, dindexes);
1076 pivot_value_destroy (cell->value);
1077 cell->value = value;
1080 /* Puts VALUE in the cell in TABLE with index IDX1. TABLE must have 1
1081 dimension. Takes ownership of VALUE. */
1083 pivot_table_put1 (struct pivot_table *table, size_t idx1,
1084 struct pivot_value *value)
1086 size_t dindexes[] = { idx1 };
1087 pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
1090 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2). TABLE must have 2
1091 dimensions. Takes ownership of VALUE. */
1093 pivot_table_put2 (struct pivot_table *table, size_t idx1, size_t idx2,
1094 struct pivot_value *value)
1096 size_t dindexes[] = { idx1, idx2 };
1097 pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
1100 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2, IDX3). TABLE must
1101 have 3 dimensions. Takes ownership of VALUE. */
1103 pivot_table_put3 (struct pivot_table *table, size_t idx1, size_t idx2,
1104 size_t idx3, struct pivot_value *value)
1106 size_t dindexes[] = { idx1, idx2, idx3 };
1107 pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
1110 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2, IDX3, IDX4). TABLE
1111 must have 4 dimensions. Takes ownership of VALUE. */
1113 pivot_table_put4 (struct pivot_table *table, size_t idx1, size_t idx2,
1114 size_t idx3, size_t idx4, struct pivot_value *value)
1116 size_t dindexes[] = { idx1, idx2, idx3, idx4 };
1117 pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
1120 /* Creates and returns a new footnote in TABLE with the given CONTENT and an
1121 automatically assigned marker.
1123 The footnote will only appear in output if it is referenced. Use
1124 pivot_value_add_footnote() to add a reference to the footnote. */
1125 struct pivot_footnote *
1126 pivot_table_create_footnote (struct pivot_table *table,
1127 struct pivot_value *content)
1129 return pivot_table_create_footnote__ (table, table->n_footnotes,
1133 static struct pivot_value *
1134 pivot_make_default_footnote_marker (int idx, bool show_numeric_markers)
1136 char text[INT_BUFSIZE_BOUND (size_t)];
1137 if (show_numeric_markers)
1138 snprintf (text, sizeof text, "%d", idx + 1);
1140 str_format_26adic (idx + 1, false, text, sizeof text);
1141 return pivot_value_new_user_text (text, -1);
1144 /* Creates or modifies a footnote in TABLE with 0-based number IDX (and creates
1145 all lower indexes as a side effect). If MARKER is nonnull, sets the
1146 footnote's marker; if CONTENT is nonnull, sets the footnote's content. */
1147 struct pivot_footnote *
1148 pivot_table_create_footnote__ (struct pivot_table *table, size_t idx,
1149 struct pivot_value *marker,
1150 struct pivot_value *content)
1152 if (idx >= table->n_footnotes)
1154 while (idx >= table->allocated_footnotes)
1155 table->footnotes = x2nrealloc (table->footnotes,
1156 &table->allocated_footnotes,
1157 sizeof *table->footnotes);
1158 while (idx >= table->n_footnotes)
1160 struct pivot_footnote *f = xmalloc (sizeof *f);
1161 f->idx = table->n_footnotes;
1162 f->marker = pivot_make_default_footnote_marker (
1163 f->idx, table->look->show_numeric_markers);
1167 table->footnotes[table->n_footnotes++] = f;
1171 struct pivot_footnote *f = table->footnotes[idx];
1174 pivot_value_destroy (f->marker);
1179 pivot_value_destroy (f->content);
1180 f->content = content;
1185 /* Frees the data owned by F. */
1187 pivot_footnote_destroy (struct pivot_footnote *f)
1191 pivot_value_destroy (f->content);
1192 pivot_value_destroy (f->marker);
1197 /* Converts per-axis presentation-order indexes, given in PINDEXES, into data
1198 indexes for each dimension in TABLE in DINDEXES[]. */
1200 pivot_table_convert_indexes_ptod (const struct pivot_table *table,
1201 const size_t *pindexes[PIVOT_N_AXES],
1202 size_t dindexes[/* table->n_dimensions */])
1204 for (size_t i = 0; i < PIVOT_N_AXES; i++)
1206 const struct pivot_axis *axis = &table->axes[i];
1208 for (size_t j = 0; j < axis->n_dimensions; j++)
1210 const struct pivot_dimension *d = axis->dimensions[j];
1211 dindexes[d->top_index]
1212 = d->presentation_leaves[pindexes[i][j]]->data_index;
1218 pivot_table_enumerate_axis (const struct pivot_table *table,
1219 enum pivot_axis_type axis_type,
1220 const size_t *layer_indexes, bool omit_empty,
1223 const struct pivot_axis *axis = &table->axes[axis_type];
1224 if (!axis->n_dimensions)
1226 size_t *enumeration = xnmalloc (2, sizeof *enumeration);
1228 enumeration[1] = SIZE_MAX;
1233 else if (!axis->extent)
1235 size_t *enumeration = xmalloc (sizeof *enumeration);
1236 *enumeration = SIZE_MAX;
1242 size_t *enumeration = xnmalloc (xsum (xtimes (axis->extent,
1243 axis->n_dimensions), 1),
1244 sizeof *enumeration);
1245 size_t *p = enumeration;
1246 size_t *dindexes = XCALLOC (table->n_dimensions, size_t);
1248 size_t *axis_indexes;
1249 PIVOT_AXIS_FOR_EACH (axis_indexes, axis)
1253 enum pivot_axis_type axis2_type
1254 = pivot_axis_type_transpose (axis_type);
1256 size_t *axis2_indexes;
1257 PIVOT_AXIS_FOR_EACH (axis2_indexes, &table->axes[axis2_type])
1259 const size_t *pindexes[PIVOT_N_AXES];
1260 pindexes[PIVOT_AXIS_LAYER] = layer_indexes;
1261 pindexes[axis_type] = axis_indexes;
1262 pindexes[axis2_type] = axis2_indexes;
1263 pivot_table_convert_indexes_ptod (table, pindexes, dindexes);
1264 if (pivot_table_get (table, dindexes))
1270 free (axis2_indexes);
1273 memcpy (p, axis_indexes, axis->n_dimensions * sizeof *p);
1274 p += axis->n_dimensions;
1276 if (omit_empty && p == enumeration)
1278 PIVOT_AXIS_FOR_EACH (axis_indexes, axis)
1280 memcpy (p, axis_indexes, axis->n_dimensions * sizeof *p);
1281 p += axis->n_dimensions;
1286 *n = (p - enumeration) / axis->n_dimensions;
1292 static const struct pivot_cell *
1293 pivot_table_lookup_cell (const struct pivot_table *table,
1294 const size_t *dindexes)
1296 unsigned int hash = pivot_cell_hash_indexes (dindexes, table->n_dimensions);
1297 return pivot_table_lookup_cell__ (table, dindexes, hash);
1300 const struct pivot_value *
1301 pivot_table_get (const struct pivot_table *table, const size_t *dindexes)
1303 const struct pivot_cell *cell = pivot_table_lookup_cell (table, dindexes);
1304 return cell ? cell->value : NULL;
1307 struct pivot_value *
1308 pivot_table_get_rw (struct pivot_table *table, const size_t *dindexes)
1310 struct pivot_cell *cell = pivot_table_insert_cell (table, dindexes);
1312 cell->value = pivot_value_new_user_text ("", -1);
1317 distribute_extra_depth (struct pivot_category *category, size_t extra_depth)
1319 if (pivot_category_is_group (category) && category->n_subs)
1320 for (size_t i = 0; i < category->n_subs; i++)
1321 distribute_extra_depth (category->subs[i], extra_depth);
1323 category->extra_depth += extra_depth;
1327 pivot_category_assign_label_depth (struct pivot_category *category,
1328 bool dimension_labels_in_corner)
1330 category->extra_depth = 0;
1332 if (pivot_category_is_group (category))
1335 for (size_t i = 0; i < category->n_subs; i++)
1337 pivot_category_assign_label_depth (category->subs[i], false);
1338 depth = MAX (depth, category->subs[i]->label_depth);
1341 for (size_t i = 0; i < category->n_subs; i++)
1343 struct pivot_category *sub = category->subs[i];
1345 size_t extra_depth = depth - sub->label_depth;
1347 distribute_extra_depth (sub, extra_depth);
1349 sub->label_depth = depth;
1352 category->show_label_in_corner = (category->show_label
1353 && dimension_labels_in_corner);
1354 category->label_depth
1355 = (category->show_label && !category->show_label_in_corner
1356 ? depth + 1 : depth);
1359 category->label_depth = 1;
1363 pivot_axis_assign_label_depth (struct pivot_table *table,
1364 enum pivot_axis_type axis_type,
1365 bool dimension_labels_in_corner)
1367 struct pivot_axis *axis = &table->axes[axis_type];
1368 bool any_label_shown_in_corner = false;
1369 axis->label_depth = 0;
1371 for (size_t i = 0; i < axis->n_dimensions; i++)
1373 struct pivot_dimension *d = axis->dimensions[i];
1374 pivot_category_assign_label_depth (d->root, dimension_labels_in_corner);
1375 d->label_depth = d->hide_all_labels ? 0 : d->root->label_depth;
1376 axis->label_depth += d->label_depth;
1377 axis->extent *= d->n_leaves;
1379 if (d->root->show_label_in_corner)
1380 any_label_shown_in_corner = true;
1382 return any_label_shown_in_corner;
1386 pivot_table_assign_label_depth (struct pivot_table *table)
1388 pivot_axis_assign_label_depth (table, PIVOT_AXIS_COLUMN, false);
1389 if (pivot_axis_assign_label_depth (
1390 table, PIVOT_AXIS_ROW, (table->look->row_labels_in_corner
1391 && !table->corner_text))
1392 && table->axes[PIVOT_AXIS_COLUMN].label_depth == 0)
1393 table->axes[PIVOT_AXIS_COLUMN].label_depth = 1;
1394 pivot_axis_assign_label_depth (table, PIVOT_AXIS_LAYER, false);
1402 indent (int indentation)
1404 for (int i = 0; i < indentation * 2; i++)
1409 pivot_value_dump (const struct pivot_value *value)
1411 char *s = pivot_value_to_string (value, SETTINGS_VALUE_SHOW_DEFAULT,
1412 SETTINGS_VALUE_SHOW_DEFAULT);
1418 pivot_table_dump_value (const struct pivot_value *value, const char *name,
1423 indent (indentation);
1424 printf ("%s: ", name);
1425 pivot_value_dump (value);
1431 pivot_table_dump_string (const char *string, const char *name, int indentation)
1435 indent (indentation);
1436 printf ("%s: %s\n", name, string);
1441 pivot_category_dump (const struct pivot_category *c, int indentation)
1443 indent (indentation);
1444 printf ("%s \"", pivot_category_is_leaf (c) ? "leaf" : "group");
1445 pivot_value_dump (c->name);
1448 if (pivot_category_is_leaf (c))
1449 printf ("data_index=%zu\n", c->data_index);
1452 printf (" (label %s)", c->show_label ? "shown" : "hidden");
1455 for (size_t i = 0; i < c->n_subs; i++)
1456 pivot_category_dump (c->subs[i], indentation + 1);
1461 pivot_dimension_dump (const struct pivot_dimension *d, int indentation)
1463 indent (indentation);
1464 printf ("%s dimension %zu (where 0=innermost), label_depth=%d:\n",
1465 pivot_axis_type_to_string (d->axis_type), d->level, d->label_depth);
1467 pivot_category_dump (d->root, indentation + 1);
1471 table_area_style_dump (enum pivot_area area, const struct table_area_style *a,
1474 indent (indentation);
1475 printf ("%s: ", pivot_area_to_string (area));
1476 font_style_dump (&a->font_style);
1478 cell_style_dump (&a->cell_style);
1483 table_border_style_dump (enum pivot_border border,
1484 const struct table_border_style *b, int indentation)
1486 indent (indentation);
1487 printf ("%s: %s ", pivot_border_to_string (border),
1488 table_stroke_to_string (b->stroke));
1489 cell_color_dump (&b->color);
1494 compose_headings (const struct pivot_axis *axis,
1495 const size_t *column_enumeration,
1496 enum settings_value_show show_values,
1497 enum settings_value_show show_variables)
1499 if (!axis->n_dimensions || !axis->extent || !axis->label_depth)
1502 char ***headings = xnmalloc (axis->label_depth, sizeof *headings);
1503 for (size_t i = 0; i < axis->label_depth; i++)
1504 headings[i] = xcalloc (axis->extent, sizeof **headings);
1506 const size_t *indexes;
1508 PIVOT_ENUMERATION_FOR_EACH (indexes, column_enumeration, axis)
1510 int row = axis->label_depth - 1;
1511 for (int dim_index = 0; dim_index < axis->n_dimensions; dim_index++)
1513 const struct pivot_dimension *d = axis->dimensions[dim_index];
1514 if (d->hide_all_labels)
1516 for (const struct pivot_category *c
1517 = d->presentation_leaves[indexes[dim_index]];
1521 if (pivot_category_is_leaf (c) || (c->show_label
1522 && !c->show_label_in_corner))
1524 headings[row][column] = pivot_value_to_string (
1525 c->name, show_values, show_variables);
1526 if (!*headings[row][column])
1527 headings[row][column] = xstrdup ("<blank>");
1539 free_headings (const struct pivot_axis *axis, char ***headings)
1541 for (size_t i = 0; i < axis->label_depth; i++)
1543 for (size_t j = 0; j < axis->extent; j++)
1544 free (headings[i][j]);
1551 pivot_table_sizing_dump (const char *name,
1552 const int width_ranges[2],
1553 const struct pivot_table_sizing *s,
1556 indent (indentation);
1557 printf ("%ss: min=%d, max=%d\n", name, width_ranges[0], width_ranges[1]);
1560 indent (indentation + 1);
1561 printf ("%s widths:", name);
1562 for (size_t i = 0; i < s->n_widths; i++)
1563 printf (" %d", s->widths[i]);
1568 indent (indentation + 1);
1569 printf ("break after %ss:", name);
1570 for (size_t i = 0; i < s->n_breaks; i++)
1571 printf (" %zu", s->breaks[i]);
1576 indent (indentation + 1);
1577 printf ("keep %ss together:", name);
1578 for (size_t i = 0; i < s->n_keeps; i++)
1579 printf (" [%zu,%zu]",
1581 s->keeps[i].ofs + s->keeps[i].n - 1);
1587 pivot_table_dump (const struct pivot_table *table, int indentation)
1592 int old_decimal = settings_get_decimal_char (FMT_COMMA);
1593 if (table->decimal == '.' || table->decimal == ',')
1594 settings_set_decimal_char (table->decimal);
1596 pivot_table_dump_value (table->title, "title", indentation);
1597 pivot_table_dump_string (table->command_c, "command", indentation);
1598 pivot_table_dump_string (table->dataset, "dataset", indentation);
1599 pivot_table_dump_string (table->datafile, "datafile", indentation);
1600 pivot_table_dump_string (table->notes, "notes", indentation);
1601 pivot_table_dump_string (table->look->name, "table-look", indentation);
1604 indent (indentation);
1606 struct tm *tm = localtime (&table->date);
1607 printf ("date: %d-%02d-%02d %d:%02d:%02d\n", tm->tm_year + 1900,
1608 tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
1612 indent (indentation);
1613 printf ("sizing:\n");
1614 pivot_table_sizing_dump ("column", table->look->width_ranges[TABLE_HORZ],
1615 &table->sizing[TABLE_HORZ], indentation + 1);
1616 pivot_table_sizing_dump ("row", table->look->width_ranges[TABLE_VERT],
1617 &table->sizing[TABLE_VERT], indentation + 1);
1619 indent (indentation);
1620 printf ("areas:\n");
1621 for (enum pivot_area area = 0; area < PIVOT_N_AREAS; area++)
1622 table_area_style_dump (area, &table->look->areas[area], indentation + 1);
1624 indent (indentation);
1625 printf ("borders:\n");
1626 for (enum pivot_border border = 0; border < PIVOT_N_BORDERS; border++)
1627 table_border_style_dump (border, &table->look->borders[border],
1630 for (size_t i = 0; i < table->n_dimensions; i++)
1631 pivot_dimension_dump (table->dimensions[i], indentation);
1633 /* Presentation and data indexes. */
1634 size_t *dindexes = XCALLOC (table->n_dimensions, size_t);
1636 const struct pivot_axis *layer_axis = &table->axes[PIVOT_AXIS_LAYER];
1637 if (layer_axis->n_dimensions)
1639 indent (indentation);
1640 printf ("current layer:");
1642 for (size_t i = 0; i < layer_axis->n_dimensions; i++)
1644 const struct pivot_dimension *d = layer_axis->dimensions[i];
1645 char *name = pivot_value_to_string (d->root->name,
1647 table->show_variables);
1648 char *value = pivot_value_to_string (
1649 d->data_leaves[table->current_layer[i]]->name,
1650 table->show_values, table->show_variables);
1651 printf (" %s=%s", name, value);
1659 size_t *layer_indexes;
1660 size_t layer_iteration = 0;
1661 PIVOT_AXIS_FOR_EACH (layer_indexes, &table->axes[PIVOT_AXIS_LAYER])
1663 indent (indentation);
1664 printf ("layer %zu:", layer_iteration++);
1666 const struct pivot_axis *layer_axis = &table->axes[PIVOT_AXIS_LAYER];
1667 for (size_t i = 0; i < layer_axis->n_dimensions; i++)
1669 const struct pivot_dimension *d = layer_axis->dimensions[i];
1671 fputs (i == 0 ? " " : ", ", stdout);
1672 pivot_value_dump (d->root->name);
1673 fputs (" =", stdout);
1675 struct pivot_value **names = xnmalloc (layer_axis->label_depth,
1678 for (const struct pivot_category *c
1679 = d->presentation_leaves[layer_indexes[i]];
1683 if (pivot_category_is_leaf (c) || c->show_label)
1684 names[n_names++] = c->name;
1687 for (size_t i = n_names; i-- > 0;)
1690 pivot_value_dump (names[i]);
1696 size_t *column_enumeration = pivot_table_enumerate_axis (
1697 table, PIVOT_AXIS_COLUMN, layer_indexes, table->look->omit_empty, NULL);
1698 size_t *row_enumeration = pivot_table_enumerate_axis (
1699 table, PIVOT_AXIS_ROW, layer_indexes, table->look->omit_empty, NULL);
1701 char ***column_headings = compose_headings (
1702 &table->axes[PIVOT_AXIS_COLUMN], column_enumeration,
1703 table->show_values, table->show_variables);
1704 for (size_t y = 0; y < table->axes[PIVOT_AXIS_COLUMN].label_depth; y++)
1706 indent (indentation + 1);
1707 for (size_t x = 0; x < table->axes[PIVOT_AXIS_COLUMN].extent; x++)
1710 fputs ("; ", stdout);
1711 if (column_headings[y][x])
1712 fputs (column_headings[y][x], stdout);
1716 free_headings (&table->axes[PIVOT_AXIS_COLUMN], column_headings);
1718 indent (indentation + 1);
1719 printf ("-----------------------------------------------\n");
1721 char ***row_headings = compose_headings (
1722 &table->axes[PIVOT_AXIS_ROW], row_enumeration,
1723 table->show_values, table->show_variables);
1726 const size_t *pindexes[PIVOT_N_AXES]
1727 = { [PIVOT_AXIS_LAYER] = layer_indexes };
1728 PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_ROW], row_enumeration,
1729 &table->axes[PIVOT_AXIS_ROW])
1731 indent (indentation + 1);
1734 for (size_t y = 0; y < table->axes[PIVOT_AXIS_ROW].label_depth; y++)
1737 fputs ("; ", stdout);
1738 if (row_headings[y][x])
1739 fputs (row_headings[y][x], stdout);
1745 PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_COLUMN],
1747 &table->axes[PIVOT_AXIS_COLUMN])
1752 pivot_table_convert_indexes_ptod (table, pindexes, dindexes);
1753 const struct pivot_value *value = pivot_table_get (
1756 pivot_value_dump (value);
1763 free (column_enumeration);
1764 free (row_enumeration);
1765 free_headings (&table->axes[PIVOT_AXIS_ROW], row_headings);
1768 pivot_table_dump_value (table->caption, "caption", indentation);
1770 for (size_t i = 0; i < table->n_footnotes; i++)
1772 const struct pivot_footnote *f = table->footnotes[i];
1773 indent (indentation);
1776 pivot_value_dump (f->marker);
1778 printf ("%zu", f->idx);
1780 pivot_value_dump (f->content);
1785 settings_set_decimal_char (old_decimal);
1789 consume_int (const char *p, size_t *n)
1792 while (c_isdigit (*p))
1793 *n = *n * 10 + (*p++ - '0');
1798 pivot_format_inner_template (struct string *out, const char *template,
1800 struct pivot_value **values, size_t n_values,
1801 enum settings_value_show show_values,
1802 enum settings_value_show show_variables)
1804 size_t args_consumed = 0;
1805 while (*template && *template != ':')
1807 if (*template == '\\' && template[1])
1809 ds_put_byte (out, template[1] == 'n' ? '\n' : template[1]);
1812 else if (*template == escape)
1815 template = consume_int (template + 1, &index);
1816 if (index >= 1 && index <= n_values)
1818 pivot_value_format (values[index - 1], show_values,
1819 show_variables, out);
1820 args_consumed = MAX (args_consumed, index);
1824 ds_put_byte (out, *template++);
1826 return args_consumed;
1830 pivot_extract_inner_template (const char *template, const char **p)
1836 if (*template == '\\' && template[1] != '\0')
1838 else if (*template == ':')
1839 return template + 1;
1840 else if (*template == '\0')
1848 pivot_format_template (struct string *out, const char *template,
1849 const struct pivot_argument *args, size_t n_args,
1850 enum settings_value_show show_values,
1851 enum settings_value_show show_variables)
1855 if (*template == '\\' && template[1] != '\0')
1857 ds_put_byte (out, template[1] == 'n' ? '\n' : template[1]);
1860 else if (*template == '^')
1863 template = consume_int (template + 1, &index);
1864 if (index >= 1 && index <= n_args && args[index - 1].n > 0)
1865 pivot_value_format (args[index - 1].values[0],
1866 show_values, show_variables, out);
1868 else if (*template == '[')
1870 const char *tmpl[2];
1871 template = pivot_extract_inner_template (template + 1, &tmpl[0]);
1872 template = pivot_extract_inner_template (template, &tmpl[1]);
1873 template += *template == ']';
1876 template = consume_int (template, &index);
1877 if (index < 1 || index > n_args)
1880 const struct pivot_argument *arg = &args[index - 1];
1881 size_t left = arg->n;
1884 struct pivot_value **values = arg->values + (arg->n - left);
1885 int tmpl_idx = left == arg->n && *tmpl[0] != ':' ? 0 : 1;
1886 char escape = "%^"[tmpl_idx];
1887 size_t used = pivot_format_inner_template (
1888 out, tmpl[tmpl_idx], escape, values, left,
1889 show_values, show_variables);
1890 if (!used || used > left)
1896 ds_put_byte (out, *template++);
1900 static enum settings_value_show
1901 interpret_show (enum settings_value_show global_show,
1902 enum settings_value_show table_show,
1903 enum settings_value_show value_show,
1906 return (!has_label ? SETTINGS_VALUE_SHOW_VALUE
1907 : value_show != SETTINGS_VALUE_SHOW_DEFAULT ? value_show
1908 : table_show != SETTINGS_VALUE_SHOW_DEFAULT ? table_show
1912 /* Appends a text representation of the body of VALUE to OUT. SHOW_VALUES and
1913 SHOW_VARIABLES control whether variable and value labels are included.
1915 The "body" omits subscripts and superscripts and footnotes. */
1917 pivot_value_format_body (const struct pivot_value *value,
1918 enum settings_value_show show_values,
1919 enum settings_value_show show_variables,
1922 enum settings_value_show show;
1923 bool numeric = false;
1925 switch (value->type)
1927 case PIVOT_VALUE_NUMERIC:
1928 show = interpret_show (settings_get_show_values (),
1930 value->numeric.show,
1931 value->numeric.value_label != NULL);
1932 if (show & SETTINGS_VALUE_SHOW_VALUE)
1934 char *s = data_out (&(union value) { .f = value->numeric.x },
1935 "UTF-8", &value->numeric.format);
1936 ds_put_cstr (out, s + strspn (s, " "));
1939 if (show & SETTINGS_VALUE_SHOW_LABEL)
1941 if (show & SETTINGS_VALUE_SHOW_VALUE)
1942 ds_put_byte (out, ' ');
1943 ds_put_cstr (out, value->numeric.value_label);
1945 numeric = !(show & SETTINGS_VALUE_SHOW_LABEL);
1948 case PIVOT_VALUE_STRING:
1949 show = interpret_show (settings_get_show_values (),
1952 value->string.value_label != NULL);
1953 if (show & SETTINGS_VALUE_SHOW_VALUE)
1955 if (value->string.hex)
1957 for (const uint8_t *p = CHAR_CAST (uint8_t *, value->string.s);
1959 ds_put_format (out, "%02X", *p);
1962 ds_put_cstr (out, value->string.s);
1964 if (show & SETTINGS_VALUE_SHOW_LABEL)
1966 if (show & SETTINGS_VALUE_SHOW_VALUE)
1967 ds_put_byte (out, ' ');
1968 ds_put_cstr (out, value->string.value_label);
1972 case PIVOT_VALUE_VARIABLE:
1973 show = interpret_show (settings_get_show_variables (),
1975 value->variable.show,
1976 value->variable.var_label != NULL);
1977 if (show & SETTINGS_VALUE_SHOW_VALUE)
1978 ds_put_cstr (out, value->variable.var_name);
1979 if (show & SETTINGS_VALUE_SHOW_LABEL)
1981 if (show & SETTINGS_VALUE_SHOW_VALUE)
1982 ds_put_byte (out, ' ');
1983 ds_put_cstr (out, value->variable.var_label);
1987 case PIVOT_VALUE_TEXT:
1988 ds_put_cstr (out, value->text.local);
1991 case PIVOT_VALUE_TEMPLATE:
1992 pivot_format_template (out, value->template.local, value->template.args,
1993 value->template.n_args, show_values,
2001 /* Appends a text representation of VALUE to OUT. SHOW_VALUES and
2002 SHOW_VARIABLES control whether variable and value labels are included.
2004 Subscripts and superscripts and footnotes are included. */
2006 pivot_value_format (const struct pivot_value *value,
2007 enum settings_value_show show_values,
2008 enum settings_value_show show_variables,
2011 pivot_value_format_body (value, show_values, show_variables, out);
2013 if (value->n_subscripts)
2015 for (size_t i = 0; i < value->n_subscripts; i++)
2016 ds_put_format (out, "%c%s", i ? ',' : '_', value->subscripts[i]);
2019 if (value->superscript)
2020 ds_put_format (out, "^%s", value->superscript);
2022 for (size_t i = 0; i < value->n_footnotes; i++)
2024 ds_put_byte (out, '^');
2025 pivot_value_format (value->footnotes[i]->marker,
2026 show_values, show_variables, out);
2030 /* Returns a text representation of VALUE. The caller must free the string,
2033 pivot_value_to_string (const struct pivot_value *value,
2034 enum settings_value_show show_values,
2035 enum settings_value_show show_variables)
2037 struct string s = DS_EMPTY_INITIALIZER;
2038 pivot_value_format (value, show_values, show_variables, &s);
2039 return ds_steal_cstr (&s);
2042 /* Frees the data owned by V. */
2044 pivot_value_destroy (struct pivot_value *value)
2048 font_style_uninit (value->font_style);
2049 free (value->font_style);
2050 free (value->cell_style);
2051 /* Do not free the elements of footnotes because VALUE does not own
2053 free (value->footnotes);
2055 for (size_t i = 0; i < value->n_subscripts; i++)
2056 free (value->subscripts[i]);
2057 free (value->subscripts);
2059 free (value->superscript);
2061 switch (value->type)
2063 case PIVOT_VALUE_NUMERIC:
2064 free (value->numeric.var_name);
2065 free (value->numeric.value_label);
2068 case PIVOT_VALUE_STRING:
2069 free (value->string.s);
2070 free (value->string.var_name);
2071 free (value->string.value_label);
2074 case PIVOT_VALUE_VARIABLE:
2075 free (value->variable.var_name);
2076 free (value->variable.var_label);
2079 case PIVOT_VALUE_TEXT:
2080 free (value->text.local);
2081 if (value->text.c != value->text.local)
2082 free (value->text.c);
2083 if (value->text.id != value->text.local
2084 && value->text.id != value->text.c)
2085 free (value->text.id);
2088 case PIVOT_VALUE_TEMPLATE:
2089 free (value->template.local);
2090 if (value->template.id != value->template.local)
2091 free (value->template.id);
2092 for (size_t i = 0; i < value->template.n_args; i++)
2093 pivot_argument_uninit (&value->template.args[i]);
2094 free (value->template.args);
2101 /* Sets AREA to the style to use for VALUE, with defaults coming from
2102 DEFAULT_STYLE for the parts of the style that VALUE doesn't override. */
2104 pivot_value_get_style (struct pivot_value *value,
2105 const struct font_style *base_font_style,
2106 const struct cell_style *base_cell_style,
2107 struct table_area_style *area)
2109 font_style_copy (NULL, &area->font_style, (value->font_style
2111 : base_font_style));
2112 area->cell_style = *(value->cell_style
2117 /* Copies AREA into VALUE's style. */
2119 pivot_value_set_style (struct pivot_value *value,
2120 const struct table_area_style *area)
2122 if (value->font_style)
2123 font_style_uninit (value->font_style);
2125 value->font_style = xmalloc (sizeof *value->font_style);
2126 font_style_copy (NULL, value->font_style, &area->font_style);
2128 if (!value->cell_style)
2129 value->cell_style = xmalloc (sizeof *value->cell_style);
2130 *value->cell_style = area->cell_style;
2133 /* Frees the data owned by ARG (but not ARG itself). */
2135 pivot_argument_uninit (struct pivot_argument *arg)
2139 for (size_t i = 0; i < arg->n; i++)
2140 pivot_value_destroy (arg->values[i]);
2145 /* Creates and returns a new pivot_value whose contents is the null-terminated
2146 string TEXT. Takes ownership of TEXT.
2148 This function is for text strings provided by the user (with the exception
2149 that pivot_value_new_variable() should be used for variable names). For
2150 strings that are part of the PSPP user interface, such as names of
2151 procedures, statistics, annotations, error messages, etc., use
2152 pivot_value_new_text(). */
2153 struct pivot_value *
2154 pivot_value_new_user_text_nocopy (char *text)
2156 struct pivot_value *value = xmalloc (sizeof *value);
2157 *value = (struct pivot_value) {
2158 .type = PIVOT_VALUE_TEXT,
2163 .user_provided = true,
2169 /* Creates and returns a new pivot_value whose contents is the LENGTH bytes of
2170 TEXT. Use SIZE_MAX if TEXT is null-teriminated and its length is not known
2173 This function is for text strings provided by the user (with the exception
2174 that pivot_value_new_variable() should be used for variable names). For
2175 strings that are part of the PSPP user interface, such as names of
2176 procedures, statistics, annotations, error messages, etc., use
2177 pivot_value_new_text().j
2179 The caller retains ownership of TEXT.*/
2180 struct pivot_value *
2181 pivot_value_new_user_text (const char *text, size_t length)
2183 return pivot_value_new_user_text_nocopy (
2184 xmemdup0 (text, length != SIZE_MAX ? length : strlen (text)));
2187 /* Creates and returns new pivot_value whose contents is TEXT, which should be
2188 a translatable string, but not actually translated yet, e.g. enclosed in
2189 N_(). This function is for text strings that are part of the PSPP user
2190 interface, such as names of procedures, statistics, annotations, error
2191 messages, etc. For strings that come from the user, use
2192 pivot_value_new_user_text(). */
2193 struct pivot_value *
2194 pivot_value_new_text (const char *text)
2196 char *c = xstrdup (text);
2197 char *local = xstrdup (gettext (c));
2199 struct pivot_value *value = xmalloc (sizeof *value);
2200 *value = (struct pivot_value) {
2201 .type = PIVOT_VALUE_TEXT,
2206 .user_provided = false,
2212 /* Same as pivot_value_new_text() but its argument is a printf()-like format
2214 struct pivot_value * PRINTF_FORMAT (1, 2)
2215 pivot_value_new_text_format (const char *format, ...)
2218 va_start (args, format);
2219 char *c = xvasprintf (format, args);
2222 va_start (args, format);
2223 char *local = xvasprintf (gettext (format), args);
2226 struct pivot_value *value = xmalloc (sizeof *value);
2227 *value = (struct pivot_value) {
2228 .type = PIVOT_VALUE_TEXT,
2233 .user_provided = false,
2239 /* Returns a new pivot_value that represents X.
2241 The format to use for X is unspecified. Usually the easiest way to specify
2242 a format is through assigning a result class to one of the categories that
2243 the pivot_value will end up in. If that is not suitable, then the caller
2244 can use pivot_value_set_rc() or assign directly to value->numeric.format. */
2245 struct pivot_value *
2246 pivot_value_new_number (double x)
2248 struct pivot_value *value = xmalloc (sizeof *value);
2249 *value = (struct pivot_value) {
2250 .type = PIVOT_VALUE_NUMERIC,
2251 .numeric = { .x = x, },
2256 /* Returns a new pivot_value that represents X, formatted as an integer. */
2257 struct pivot_value *
2258 pivot_value_new_integer (double x)
2260 struct pivot_value *value = pivot_value_new_number (x);
2261 value->numeric.format = (struct fmt_spec) { FMT_F, 40, 0 };
2265 /* Returns a new pivot_value that represents VALUE, formatted as for
2267 struct pivot_value *
2268 pivot_value_new_var_value (const struct variable *variable,
2269 const union value *value)
2271 struct pivot_value *pv = pivot_value_new_value (
2272 value, var_get_width (variable), var_get_print_format (variable),
2273 var_get_encoding (variable));
2275 char *var_name = xstrdup (var_get_name (variable));
2276 if (var_is_alpha (variable))
2277 pv->string.var_name = var_name;
2279 pv->numeric.var_name = var_name;
2281 const char *label = var_lookup_value_label (variable, value);
2284 if (var_is_alpha (variable))
2285 pv->string.value_label = xstrdup (label);
2287 pv->numeric.value_label = xstrdup (label);
2293 /* Returns a new pivot_value that represents VALUE, with the given WIDTH,
2294 formatted with FORMAT. For a string value, ENCODING must be its character
2296 struct pivot_value *
2297 pivot_value_new_value (const union value *value, int width,
2298 const struct fmt_spec *format, const char *encoding)
2300 struct pivot_value *pv = xzalloc (sizeof *pv);
2303 char *s = recode_string (UTF8, encoding, CHAR_CAST (char *, value->s),
2305 size_t n = strlen (s);
2306 while (n > 0 && s[n - 1] == ' ')
2309 pv->type = PIVOT_VALUE_STRING;
2311 pv->string.hex = format->type == FMT_AHEX;
2315 pv->type = PIVOT_VALUE_NUMERIC;
2316 pv->numeric.x = value->f;
2317 pv->numeric.format = *format;
2323 /* Returns a new pivot_value for VARIABLE. */
2324 struct pivot_value *
2325 pivot_value_new_variable (const struct variable *variable)
2327 struct pivot_value *value = xmalloc (sizeof *value);
2328 *value = (struct pivot_value) {
2329 .type = PIVOT_VALUE_VARIABLE,
2331 .var_name = xstrdup (var_get_name (variable)),
2332 .var_label = xstrdup_if_nonempty (var_get_label (variable)),
2338 /* Attaches a reference to FOOTNOTE to V. */
2340 pivot_value_add_footnote (struct pivot_value *v,
2341 const struct pivot_footnote *footnote)
2343 /* Some legacy tables include numerous duplicate footnotes. Suppress
2345 for (size_t i = 0; i < v->n_footnotes; i++)
2346 if (v->footnotes[i] == footnote)
2349 v->footnotes = xrealloc (v->footnotes,
2350 (v->n_footnotes + 1) * sizeof *v->footnotes);
2351 v->footnotes[v->n_footnotes++] = footnote;
2354 /* If VALUE is a numeric value, and RC is a result class such as
2355 PIVOT_RC_COUNT, changes VALUE's format to the result class's. */
2357 pivot_value_set_rc (const struct pivot_table *table, struct pivot_value *value,
2360 if (value->type == PIVOT_VALUE_NUMERIC)
2362 const struct fmt_spec *f = pivot_table_get_format (table, rc);
2364 value->numeric.format = *f;