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/spv/spv-light-decoder.h"
26 #include "libpspp/i18n.h"
27 #include "libpspp/message.h"
28 #include "output/pivot-table.h"
29 #include "output/spv/light-binary-parser.h"
30 #include "output/spv/spv.h"
32 #include "gl/xalloc.h"
36 to_utf8 (const char *s, const char *encoding)
38 return recode_string ("UTF-8", encoding, s, strlen (s));
42 to_utf8_if_nonempty (const char *s, const char *encoding)
44 return s && s[0] ? to_utf8 (s, encoding) : NULL;
48 convert_widths (const uint32_t *in, uint32_t n, int **out, size_t *n_out)
53 *out = xnmalloc (n, sizeof **out);
54 for (size_t i = 0; i < n; i++)
60 convert_breakpoints (const struct spvlb_breakpoints *in,
61 size_t **out, size_t *n_out)
63 if (in && in->n_breaks)
65 *n_out = in->n_breaks;
66 *out = xnmalloc (in->n_breaks, sizeof *out);
67 for (size_t i = 0; i < in->n_breaks; i++)
68 (*out)[i] = in->breaks[i];
73 convert_keeps (const struct spvlb_keeps *in,
74 struct pivot_keep **out, size_t *n_out)
76 if (in && in->n_keeps)
79 *out = xnmalloc (*n_out, sizeof **out);
80 for (size_t i = 0; i < *n_out; i++)
82 (*out)[i].ofs = in->keeps[i]->offset;
83 (*out)[i].n = in->keeps[i]->n;
88 static char * WARN_UNUSED_RESULT
89 decode_spvlb_color_string (const char *s, uint8_t def,
90 struct cell_color *colorp)
95 else if (sscanf (s, "#%2x%2x%2x", &r, &g, &b) != 3)
96 return xasprintf ("bad color %s", s);
98 *colorp = (struct cell_color) CELL_COLOR (r, g, b);
102 static struct cell_color
103 decode_spvlb_color_u32 (uint32_t x)
105 return (struct cell_color) { x >> 24, x >> 16, x >> 8, x };
108 static char * WARN_UNUSED_RESULT
109 decode_spvlb_font_style (const struct spvlb_font_style *in,
110 const char *encoding, struct font_style **outp)
118 struct cell_color fg, bg;
119 char *error = decode_spvlb_color_string (in->fg_color, 0x00, &fg);
121 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg);
125 *outp = xmalloc (sizeof **outp);
126 **outp = (struct font_style) {
128 .italic = in->italic,
129 .underline = in->underline,
132 .typeface = to_utf8 (in->typeface, encoding),
133 .size = in->size / 1.33,
138 static char * WARN_UNUSED_RESULT
139 decode_spvlb_halign (uint32_t in, enum table_halign *halignp)
144 *halignp = TABLE_HALIGN_CENTER;
148 *halignp = TABLE_HALIGN_LEFT;
152 *halignp = TABLE_HALIGN_RIGHT;
157 *halignp = TABLE_HALIGN_DECIMAL;
162 *halignp = TABLE_HALIGN_MIXED;
166 return xasprintf ("bad cell style halign %"PRIu32, in);
170 static char * WARN_UNUSED_RESULT
171 decode_spvlb_valign (uint32_t in, enum table_valign *valignp)
176 *valignp = TABLE_VALIGN_CENTER;
180 *valignp = TABLE_VALIGN_TOP;
184 *valignp = TABLE_VALIGN_BOTTOM;
189 return xasprintf ("bad cell style valign %"PRIu32, in);
193 static char * WARN_UNUSED_RESULT
194 decode_spvlb_cell_style (const struct spvlb_cell_style *in,
195 struct cell_style **outp)
203 enum table_halign halign;
204 char *error = decode_spvlb_halign (in->halign, &halign);
208 enum table_valign valign;
209 error = decode_spvlb_valign (in->valign, &valign);
213 *outp = xzalloc (sizeof **outp);
214 **outp = (struct cell_style) {
217 .decimal_offset = in->decimal_offset,
219 [TABLE_HORZ] = { in->left_margin, in->right_margin },
220 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
226 static char *decode_spvlb_value (
227 const struct pivot_table *, const struct spvlb_value *,
228 const char *encoding, struct pivot_value **) WARN_UNUSED_RESULT;
230 static char * WARN_UNUSED_RESULT
231 decode_spvlb_argument (const struct pivot_table *table,
232 const struct spvlb_argument *in,
233 const char *encoding, struct pivot_argument *out)
237 struct pivot_value *value;
238 char *error = decode_spvlb_value (table, in->value, encoding, &value);
243 out->values = xmalloc (sizeof *out->values);
244 out->values[0] = value;
249 out->values = xnmalloc (in->n_values, sizeof *out->values);
250 for (size_t i = 0; i < in->n_values; i++)
252 char *error = decode_spvlb_value (table, in->values[i], encoding,
256 pivot_argument_uninit (out);
266 static char * WARN_UNUSED_RESULT
267 decode_spvlb_value_show (uint8_t in, enum settings_value_show *out)
271 case 0: *out = SETTINGS_VALUE_SHOW_DEFAULT; return NULL;
272 case 1: *out = SETTINGS_VALUE_SHOW_VALUE; return NULL;
273 case 2: *out = SETTINGS_VALUE_SHOW_LABEL; return NULL;
274 case 3: *out = SETTINGS_VALUE_SHOW_BOTH; return NULL;
276 return xasprintf ("bad value show %"PRIu8, in);
280 static char * WARN_UNUSED_RESULT
281 decode_spvlb_value (const struct pivot_table *table,
282 const struct spvlb_value *in,
283 const char *encoding, struct pivot_value **outp)
287 struct pivot_value *out = xzalloc (sizeof *out);
288 const struct spvlb_value_mod *vm;
294 vm = in->type_01.value_mod;
295 out->type = PIVOT_VALUE_NUMERIC;
296 out->numeric.x = in->type_01.x;
297 error = spv_decode_fmt_spec (in->type_01.format, &out->numeric.format);
303 vm = in->type_02.value_mod;
304 out->type = PIVOT_VALUE_NUMERIC;
305 out->numeric.x = in->type_02.x;
306 error = spv_decode_fmt_spec (in->type_02.format, &out->numeric.format);
308 error = decode_spvlb_value_show (in->type_02.show, &out->numeric.show);
311 out->numeric.var_name = to_utf8_if_nonempty (in->type_02.var_name,
313 out->numeric.value_label = to_utf8_if_nonempty (in->type_02.value_label,
318 vm = in->type_03.value_mod;
319 out->type = PIVOT_VALUE_TEXT;
320 out->text.local = to_utf8 (in->type_03.local, encoding);
321 out->text.c = to_utf8 (in->type_03.c, encoding);
322 out->text.id = to_utf8 (in->type_03.id, encoding);
323 out->text.user_provided = !in->type_03.fixed;
327 vm = in->type_04.value_mod;
328 out->type = PIVOT_VALUE_STRING;
329 error = decode_spvlb_value_show (in->type_04.show, &out->string.show);
332 out->string.s = to_utf8 (in->type_04.s, encoding);
333 out->string.var_name = to_utf8 (in->type_04.var_name, encoding);
334 out->string.value_label = to_utf8_if_nonempty (in->type_04.value_label,
339 vm = in->type_05.value_mod;
340 out->type = PIVOT_VALUE_VARIABLE;
341 error = decode_spvlb_value_show (in->type_05.show, &out->variable.show);
344 out->variable.var_name = to_utf8 (in->type_05.var_name, encoding);
345 out->variable.var_label = to_utf8_if_nonempty (in->type_05.var_label,
350 vm = in->type_06.value_mod;
351 out->type = PIVOT_VALUE_TEXT;
352 out->text.local = to_utf8 (in->type_06.local, encoding);
353 out->text.c = to_utf8 (in->type_06.c, encoding);
354 out->text.id = to_utf8 (in->type_06.id, encoding);
355 out->text.user_provided = false;
359 vm = in->type_else.value_mod;
360 out->type = PIVOT_VALUE_TEMPLATE;
361 out->template.local = to_utf8 (in->type_else.template, encoding);
362 out->template.id = out->template.local;
363 out->template.n_args = 0;
364 out->template.args = xnmalloc (in->type_else.n_args,
365 sizeof *out->template.args);
366 for (size_t i = 0; i < in->type_else.n_args; i++)
368 error = decode_spvlb_argument (table, in->type_else.args[i],
369 encoding, &out->template.args[i]);
372 pivot_value_destroy (out);
375 out->template.n_args++;
385 if (vm->n_subscripts)
387 out->n_subscripts = vm->n_subscripts;
388 out->subscripts = xnmalloc (vm->n_subscripts,
389 sizeof *out->subscripts);
390 for (size_t i = 0; i < vm->n_subscripts; i++)
391 out->subscripts[i] = to_utf8 (vm->subscripts[i], encoding);
396 out->footnote_indexes = xnmalloc (vm->n_refs,
397 sizeof *out->footnote_indexes);
398 for (size_t i = 0; i < vm->n_refs; i++)
400 uint16_t idx = vm->refs[i];
401 if (idx >= table->n_footnotes)
403 pivot_value_destroy (out);
404 return xasprintf ("bad footnote index: %"PRIu16" >= %zu",
405 idx, table->n_footnotes);
408 out->footnote_indexes[out->n_footnotes++] = idx;
414 error = decode_spvlb_font_style (vm->style_pair->font_style,
415 encoding, &out->font_style);
417 error = decode_spvlb_cell_style (vm->style_pair->cell_style,
421 pivot_value_destroy (out);
426 if (vm->template_string
427 && vm->template_string->id
428 && vm->template_string->id[0]
429 && out->type == PIVOT_VALUE_TEMPLATE)
430 out->template.id = to_utf8 (vm->template_string->id, encoding);
437 static char * WARN_UNUSED_RESULT
438 decode_spvlb_area (const struct spvlb_area *in, struct table_area_style *out,
439 const char *encoding)
443 struct cell_color fg0, fg1, bg0, bg1;
444 error = decode_spvlb_color_string (in->fg_color, 0x00, &fg0);
446 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg0);
447 if (!error && in->alternate)
448 error = decode_spvlb_color_string (in->alt_fg_color, 0x00, &fg1);
449 if (!error && in->alternate)
450 error = decode_spvlb_color_string (in->alt_bg_color, 0xff, &bg1);
452 enum table_halign halign;
455 error = decode_spvlb_halign (in->halign, &halign);
457 /* TABLE_HALIGN_DECIMAL doesn't seem to be a real halign for areas, which
458 is good because there's no way to indicate the decimal offset. Just
460 if (!error && halign == TABLE_HALIGN_DECIMAL)
461 halign = TABLE_HALIGN_MIXED;
464 enum table_valign valign;
466 error = decode_spvlb_valign (in->valign, &valign);
471 table_area_style_uninit (out);
472 *out = (struct table_area_style) {
474 .bold = (in->style & 1) != 0,
475 .italic = (in->style & 2) != 0,
476 .underline = in->underline,
477 .fg = { fg0, in->alternate ? fg1 : fg0 },
478 .bg = { bg0, in->alternate ? bg1 : bg0 },
479 .typeface = to_utf8 (in->typeface, encoding),
480 .size = in->size / 1.33,
486 [TABLE_HORZ] = { in->left_margin, in->right_margin },
487 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
494 static char * WARN_UNUSED_RESULT
495 decode_spvlb_group (const struct pivot_table *,
496 struct spvlb_category **,
499 struct pivot_category *parent,
500 struct pivot_dimension *,
501 const char *encoding);
503 static char * WARN_UNUSED_RESULT
504 decode_spvlb_categories (const struct pivot_table *table,
505 struct spvlb_category **categories,
507 struct pivot_category *parent,
508 struct pivot_dimension *dimension,
509 const char *encoding)
511 for (size_t i = 0; i < n_categories; i++)
513 const struct spvlb_category *in = categories[i];
514 if (in->group && in->group->merge)
516 char *error = decode_spvlb_categories (
517 table, in->group->subcategories, in->group->n_subcategories,
518 parent, dimension, encoding);
525 struct pivot_value *name;
526 char *error = decode_spvlb_value (table, in->name, encoding, &name);
530 struct pivot_category *out = xzalloc (sizeof *out);
532 out->parent = parent;
533 out->dimension = dimension;
536 char *error = decode_spvlb_group (table, in->group->subcategories,
537 in->group->n_subcategories,
538 true, out, dimension, encoding);
541 pivot_category_destroy (out);
545 out->data_index = SIZE_MAX;
546 out->presentation_index = SIZE_MAX;
550 out->data_index = in->leaf->leaf_index;
551 out->presentation_index = dimension->n_leaves;
552 dimension->n_leaves++;
555 if (parent->n_subs >= parent->allocated_subs)
556 parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
557 sizeof *parent->subs);
558 parent->subs[parent->n_subs++] = out;
563 static char * WARN_UNUSED_RESULT
564 decode_spvlb_group (const struct pivot_table *table,
565 struct spvlb_category **categories,
566 size_t n_categories, bool show_label,
567 struct pivot_category *category,
568 struct pivot_dimension *dimension,
569 const char *encoding)
571 category->subs = XCALLOC (n_categories, struct pivot_category *);
572 category->n_subs = 0;
573 category->allocated_subs = 0;
574 category->show_label = show_label;
576 return decode_spvlb_categories (table, categories, n_categories, category,
577 dimension, encoding);
580 static char * WARN_UNUSED_RESULT
581 fill_leaves (struct pivot_category *category,
582 struct pivot_dimension *dimension)
584 if (pivot_category_is_group (category))
586 for (size_t i = 0; i < category->n_subs; i++)
588 char *error = fill_leaves (category->subs[i], dimension);
595 if (category->data_index >= dimension->n_leaves)
596 return xasprintf ("leaf_index %zu >= n_leaves %zu",
597 category->data_index, dimension->n_leaves);
598 if (dimension->data_leaves[category->data_index])
599 return xasprintf ("two leaves with data_index %zu",
600 category->data_index);
601 dimension->data_leaves[category->data_index] = category;
602 dimension->presentation_leaves[category->presentation_index] = category;
607 static char * WARN_UNUSED_RESULT
608 decode_spvlb_dimension (const struct pivot_table *table,
609 const struct spvlb_dimension *in,
610 size_t idx, const char *encoding,
611 struct pivot_dimension **outp)
613 /* Convert most of the dimension. */
614 struct pivot_value *name;
615 char *error = decode_spvlb_value (table, in->name, encoding, &name);
619 struct pivot_dimension *out = xzalloc (sizeof *out);
620 out->level = UINT_MAX;
621 out->top_index = idx;
622 out->hide_all_labels = in->props->hide_all_labels;
624 out->root = xzalloc (sizeof *out->root);
625 *out->root = (struct pivot_category) {
628 .data_index = SIZE_MAX,
629 .presentation_index = SIZE_MAX,
631 error = decode_spvlb_group (table, in->categories, in->n_categories,
632 !in->props->hide_dim_label, out->root,
637 /* Allocate and fill the array of leaves now that we know how many there
639 out->data_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
640 out->presentation_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
641 out->allocated_leaves = out->n_leaves;
642 error = fill_leaves (out->root, out);
645 for (size_t i = 0; i < out->n_leaves; i++)
647 assert (out->data_leaves[i] != NULL);
648 assert (out->presentation_leaves[i] != NULL);
654 pivot_dimension_destroy (out);
658 static char * WARN_UNUSED_RESULT
659 decode_spvlb_stroke (uint32_t stroke_type, enum table_stroke *strokep)
661 enum table_stroke strokes[] = {
670 if (stroke_type >= sizeof strokes / sizeof *strokes)
671 return xasprintf ("bad stroke %"PRIu32, stroke_type);
673 *strokep = strokes[stroke_type];
677 static char * WARN_UNUSED_RESULT
678 decode_spvlb_border (const struct spvlb_border *in, struct pivot_table *table)
681 if (in->border_type >= PIVOT_N_BORDERS)
682 return xasprintf ("bad border type %"PRIu32, in->border_type);
684 struct table_border_style *out = &table->look->borders[in->border_type];
685 out->color = decode_spvlb_color_u32 (in->color);
686 return decode_spvlb_stroke (in->stroke_type, &out->stroke);
689 static char * WARN_UNUSED_RESULT
690 decode_spvlb_axis (const uint32_t *dimension_indexes, size_t n_dimensions,
691 enum pivot_axis_type axis_type, struct pivot_table *table)
693 struct pivot_axis *axis = &table->axes[axis_type];
694 axis->dimensions = XCALLOC (n_dimensions, struct pivot_dimension *);
695 axis->n_dimensions = n_dimensions;
697 for (size_t i = 0; i < n_dimensions; i++)
699 uint32_t idx = dimension_indexes[i];
700 if (idx >= table->n_dimensions)
701 return xasprintf ("bad dimension index %"PRIu32" >= %zu",
702 idx, table->n_dimensions);
704 struct pivot_dimension *d = table->dimensions[idx];
705 if (d->level != UINT_MAX)
706 return xasprintf ("duplicate dimension %"PRIu32, idx);
708 axis->dimensions[i] = d;
709 d->axis_type = axis_type;
712 axis->extent *= d->n_leaves;
719 decode_data_index (uint64_t in, const struct pivot_table *table,
722 uint64_t remainder = in;
723 for (size_t i = table->n_dimensions - 1; i > 0; i--)
725 const struct pivot_dimension *d = table->dimensions[i];
728 out[i] = remainder % d->n_leaves;
729 remainder /= d->n_leaves;
734 if (remainder >= table->dimensions[0]->n_leaves)
735 return xasprintf ("out of range cell data index %"PRIu64, in);
741 static char * WARN_UNUSED_RESULT
742 decode_spvlb_cells (struct spvlb_cell **in, size_t n_in,
743 struct pivot_table *table, const char *encoding)
745 if (!table->n_dimensions)
748 size_t *dindexes = xnmalloc (table->n_dimensions, sizeof *dindexes);
749 for (size_t i = 0; i < n_in; i++)
751 struct pivot_value *value;
752 char *error = decode_data_index (in[i]->index, table, dindexes);
754 error = decode_spvlb_value (table, in[i]->value, encoding, &value);
760 pivot_table_put (table, dindexes, table->n_dimensions, value);
767 static char * WARN_UNUSED_RESULT
768 decode_spvlb_footnote (const struct spvlb_footnote *in, const char *encoding,
769 size_t idx, struct pivot_table *table)
771 struct pivot_value *content;
772 char *error = decode_spvlb_value (table, in->text, encoding, &content);
776 struct pivot_value *marker = NULL;
779 error = decode_spvlb_value (table, in->marker, encoding, &marker);
782 pivot_value_destroy (content);
785 if (marker->type == PIVOT_VALUE_TEXT)
786 marker->text.user_provided = false;
789 struct pivot_footnote *f = pivot_table_create_footnote__ (
790 table, idx, marker, content);
791 f->show = (int32_t) in->show > 0;
795 static char * WARN_UNUSED_RESULT
796 decode_current_layer (uint64_t current_layer, struct pivot_table *table)
798 const struct pivot_axis *axis = &table->axes[PIVOT_AXIS_LAYER];
799 table->current_layer = xnmalloc (axis->n_dimensions,
800 sizeof *table->current_layer);
802 for (size_t i = 0; i < axis->n_dimensions; i++)
804 const struct pivot_dimension *d = axis->dimensions[i];
807 table->current_layer[i] = current_layer % d->n_leaves;
808 current_layer /= d->n_leaves;
811 table->current_layer[i] = 0;
813 if (current_layer > 0)
814 return xasprintf ("out of range layer data index %"PRIu64, current_layer);
818 char * WARN_UNUSED_RESULT
819 decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp)
822 if (in->header->version != 1 && in->header->version != 3)
823 return xasprintf ("unknown version %"PRIu32" (expected 1 or 3)",
824 in->header->version);
827 struct pivot_table *out = xzalloc (sizeof *out);
829 hmap_init (&out->cells);
830 out->look = pivot_table_look_new_builtin_default ();
831 out->settings = (struct fmt_settings) FMT_SETTINGS_INIT;
833 const struct spvlb_y1 *y1 = (in->formats->x0 ? in->formats->x0->y1
834 : in->formats->x3 ? in->formats->x3->y1
836 const char *encoding;
838 encoding = y1->charset;
841 const char *dot = strchr (in->formats->locale, '.');
842 encoding = dot ? dot + 1 : "windows-1252";
845 /* Display settings. */
846 out->look->show_numeric_markers = !in->ts->show_alphabetic_markers;
847 out->rotate_inner_column_labels = in->header->rotate_inner_column_labels;
848 out->rotate_outer_row_labels = in->header->rotate_outer_row_labels;
849 out->look->row_labels_in_corner = in->ts->show_row_labels_in_corner;
850 out->show_grid_lines = in->borders->show_grid_lines;
851 out->show_title = true;
852 out->show_caption = true;
853 out->look->footnote_marker_superscripts = in->ts->footnote_marker_superscripts;
854 out->look->omit_empty = in->ts->omit_empty;
856 const struct spvlb_x1 *x1 = in->formats->x1;
859 error = decode_spvlb_value_show (x1->show_values, &out->show_values);
861 error = decode_spvlb_value_show (x1->show_variables,
862 &out->show_variables);
866 out->show_caption = x1->show_caption;
867 out->show_title = x1->show_title != 10;
870 /* Column and row display settings. */
871 out->look->width_ranges[TABLE_VERT][0] = in->header->min_row_height;
872 out->look->width_ranges[TABLE_VERT][1] = in->header->max_row_height;
873 out->look->width_ranges[TABLE_HORZ][0] = in->header->min_col_width;
874 out->look->width_ranges[TABLE_HORZ][1] = in->header->max_col_width;
876 convert_widths (in->formats->widths, in->formats->n_widths,
877 &out->sizing[TABLE_HORZ].widths,
878 &out->sizing[TABLE_HORZ].n_widths);
880 const struct spvlb_x2 *x2 = in->formats->x2;
882 convert_widths (x2->row_heights, x2->n_row_heights,
883 &out->sizing[TABLE_VERT].widths,
884 &out->sizing[TABLE_VERT].n_widths);
886 convert_breakpoints (in->ts->row_breaks,
887 &out->sizing[TABLE_VERT].breaks,
888 &out->sizing[TABLE_VERT].n_breaks);
889 convert_breakpoints (in->ts->col_breaks,
890 &out->sizing[TABLE_HORZ].breaks,
891 &out->sizing[TABLE_HORZ].n_breaks);
893 convert_keeps (in->ts->row_keeps,
894 &out->sizing[TABLE_VERT].keeps,
895 &out->sizing[TABLE_VERT].n_keeps);
896 convert_keeps (in->ts->col_keeps,
897 &out->sizing[TABLE_HORZ].keeps,
898 &out->sizing[TABLE_HORZ].n_keeps);
900 out->notes = to_utf8_if_nonempty (in->ts->notes, encoding);
901 out->look->name = to_utf8_if_nonempty (in->ts->table_look, encoding);
903 /* Print settings. */
904 out->look->print_all_layers = in->ps->all_layers;
905 out->look->paginate_layers = in->ps->paginate_layers;
906 out->look->shrink_to_fit[TABLE_HORZ] = in->ps->fit_width;
907 out->look->shrink_to_fit[TABLE_VERT] = in->ps->fit_length;
908 out->look->top_continuation = in->ps->top_continuation;
909 out->look->bottom_continuation = in->ps->bottom_continuation;
910 out->look->continuation = xstrdup (in->ps->continuation_string);
911 out->look->n_orphan_lines = in->ps->n_orphan_lines;
913 /* Format settings. */
914 int epoch = in->formats->y0->epoch;
915 if (epoch >= 1000 && epoch <= 9999)
916 out->settings.epoch = epoch;
917 char decimal = in->formats->y0->decimal;
918 if (decimal == '.' || decimal == '.')
919 out->settings.decimal = decimal;
922 /* XXX warn about bad decimal point */
924 out->grouping = in->formats->y0->grouping;
925 const struct spvlb_custom_currency *cc = in->formats->custom_currency;
926 for (int i = 0; i < 5; i++)
928 if (cc && i < cc->n_ccs)
930 out->settings.ccs[i] = fmt_number_style_from_string (cc->ccs[i]);
931 /* XXX warn if parsing fails */
934 out->small = in->formats->x3 ? in->formats->x3->small : 0;
936 /* Command information. */
939 out->command_local = to_utf8 (y1->command_local, encoding);
940 out->command_c = to_utf8 (y1->command, encoding);
941 out->language = xstrdup (y1->language);
943 out->locale = xstrdup (y1->locale);
946 /* Source information. */
947 const struct spvlb_x3 *x3 = in->formats->x3;
950 if (x3->dataset && x3->dataset[0] && x3->dataset[0] != 4)
951 out->dataset = to_utf8 (x3->dataset, encoding);
952 out->datafile = to_utf8_if_nonempty (x3->datafile, encoding);
953 out->date = x3->date;
958 Any pivot_value might refer to footnotes, so it's important to process the
959 footnotes early to ensure that those references can be resolved. There is
960 a possible problem that a footnote might itself reference an
961 as-yet-unprocessed footnote, but that's OK because footnote references
962 don't actually look at the footnote contents but only resolve a pointer to
963 where the footnote will go later.
965 Before we really start, create all the footnotes we'll fill in. This is
966 because sometimes footnotes refer to themselves or to each other and we
967 don't want to reject those references. */
968 const struct spvlb_footnotes *fn = in->footnotes;
969 if (fn->n_footnotes > 0)
971 pivot_table_create_footnote__ (out, fn->n_footnotes - 1, NULL, NULL);
972 for (size_t i = 0; i < fn->n_footnotes; i++)
974 error = decode_spvlb_footnote (in->footnotes->footnotes[i],
981 /* Title and caption. */
982 error = decode_spvlb_value (out, in->titles->user_title, encoding,
987 error = decode_spvlb_value (out, in->titles->subtype, encoding,
992 if (in->titles->corner_text)
994 error = decode_spvlb_value (out, in->titles->corner_text,
995 encoding, &out->corner_text);
1000 if (in->titles->caption)
1002 error = decode_spvlb_value (out, in->titles->caption, encoding,
1010 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
1012 error = decode_spvlb_area (in->areas->areas[i], &out->look->areas[i],
1017 for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
1019 error = decode_spvlb_border (in->borders->borders[i], out);
1025 out->n_dimensions = in->dimensions->n_dims;
1026 out->dimensions = XCALLOC (out->n_dimensions, struct pivot_dimension *);
1027 for (size_t i = 0; i < out->n_dimensions; i++)
1029 error = decode_spvlb_dimension (out, in->dimensions->dims[i],
1030 i, encoding, &out->dimensions[i]);
1036 size_t a = in->axes->n_layers;
1037 size_t b = in->axes->n_rows;
1038 size_t c = in->axes->n_columns;
1039 if (size_overflow_p (xsum3 (a, b, c)) || a + b + c != out->n_dimensions)
1041 error = xasprintf ("dimensions do not sum correctly "
1042 "(%zu + %zu + %zu != %zu)",
1043 a, b, c, out->n_dimensions);
1046 error = decode_spvlb_axis (in->axes->layers, in->axes->n_layers,
1047 PIVOT_AXIS_LAYER, out);
1050 error = decode_spvlb_axis (in->axes->rows, in->axes->n_rows,
1051 PIVOT_AXIS_ROW, out);
1054 error = decode_spvlb_axis (in->axes->columns, in->axes->n_columns,
1055 PIVOT_AXIS_COLUMN, out);
1059 pivot_table_assign_label_depth (out);
1061 error = decode_current_layer (in->ts->current_layer, out);
1066 error = decode_spvlb_cells (in->cells->cells, in->cells->n_cells, out,
1073 pivot_table_unref (out);