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 xstrdup_if_nonempty (const char *s)
38 return s && s[0] ? xstrdup (s) : NULL;
42 convert_widths (const uint32_t *in, uint32_t n, int **out, size_t *n_out)
47 *out = xnmalloc (n, sizeof **out);
48 for (size_t i = 0; i < n; i++)
54 convert_breakpoints (const struct spvlb_breakpoints *in,
55 size_t **out, size_t *n_out)
57 if (in && in->n_breaks)
59 *n_out = in->n_breaks;
60 *out = xnmalloc (in->n_breaks, sizeof *out);
61 for (size_t i = 0; i < in->n_breaks; i++)
62 (*out)[i] = in->breaks[i];
67 convert_keeps (const struct spvlb_keeps *in,
68 struct pivot_keep **out, size_t *n_out)
70 if (in && in->n_keeps)
73 *out = xnmalloc (*n_out, sizeof **out);
74 for (size_t i = 0; i < *n_out; i++)
76 (*out)[i].ofs = in->keeps[i]->offset;
77 (*out)[i].n = in->keeps[i]->n;
82 static char * WARN_UNUSED_RESULT
83 decode_spvlb_color_string (const char *s, uint8_t def,
84 struct cell_color *colorp)
89 else if (sscanf (s, "#%2x%2x%2x", &r, &g, &b) != 3)
90 return xasprintf ("bad color %s", s);
92 *colorp = (struct cell_color) CELL_COLOR (r, g, b);
96 static struct cell_color
97 decode_spvlb_color_u32 (uint32_t x)
99 return (struct cell_color) { x >> 24, x >> 16, x >> 8, x };
102 static char * WARN_UNUSED_RESULT
103 decode_spvlb_font_style (const struct spvlb_font_style *in,
104 struct font_style **outp)
112 struct cell_color fg, bg;
113 char *error = decode_spvlb_color_string (in->fg_color, 0x00, &fg);
115 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg);
119 *outp = xmalloc (sizeof **outp);
120 **outp = (struct font_style) {
122 .italic = in->italic,
123 .underline = in->underline,
126 .typeface = xstrdup (in->typeface),
127 .size = in->size / 1.33,
132 static char * WARN_UNUSED_RESULT
133 decode_spvlb_halign (uint32_t in, enum table_halign *halignp)
138 *halignp = TABLE_HALIGN_CENTER;
142 *halignp = TABLE_HALIGN_LEFT;
146 *halignp = TABLE_HALIGN_RIGHT;
151 *halignp = TABLE_HALIGN_DECIMAL;
156 *halignp = TABLE_HALIGN_MIXED;
160 return xasprintf ("bad cell style halign %"PRIu32, in);
164 static char * WARN_UNUSED_RESULT
165 decode_spvlb_valign (uint32_t in, enum table_valign *valignp)
170 *valignp = TABLE_VALIGN_CENTER;
174 *valignp = TABLE_VALIGN_TOP;
178 *valignp = TABLE_VALIGN_BOTTOM;
183 return xasprintf ("bad cell style valign %"PRIu32, in);
187 static char * WARN_UNUSED_RESULT
188 decode_spvlb_cell_style (const struct spvlb_cell_style *in,
189 struct cell_style **outp)
197 enum table_halign halign;
198 char *error = decode_spvlb_halign (in->halign, &halign);
202 enum table_valign valign;
203 error = decode_spvlb_valign (in->valign, &valign);
207 *outp = xzalloc (sizeof **outp);
208 **outp = (struct cell_style) {
211 .decimal_offset = in->decimal_offset,
213 [TABLE_HORZ] = { in->left_margin, in->right_margin },
214 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
220 static char *decode_spvlb_value (
221 const struct pivot_table *, const struct spvlb_value *,
222 struct pivot_value **) WARN_UNUSED_RESULT;
224 static char * WARN_UNUSED_RESULT
225 decode_spvlb_argument (const struct pivot_table *table,
226 const struct spvlb_argument *in,
227 struct pivot_argument *out)
231 struct pivot_value *value;
232 char *error = decode_spvlb_value (table, in->value, &value);
237 out->values = xmalloc (sizeof *out->values);
238 out->values[0] = value;
243 out->values = xnmalloc (in->n_values, sizeof *out->values);
244 for (size_t i = 0; i < in->n_values; i++)
246 char *error = decode_spvlb_value (table, in->values[i],
250 pivot_argument_uninit (out);
260 static char * WARN_UNUSED_RESULT
261 decode_spvlb_value_show (uint8_t in, enum settings_value_show *out)
265 case 0: *out = SETTINGS_VALUE_SHOW_DEFAULT; return NULL;
266 case 1: *out = SETTINGS_VALUE_SHOW_VALUE; return NULL;
267 case 2: *out = SETTINGS_VALUE_SHOW_LABEL; return NULL;
268 case 3: *out = SETTINGS_VALUE_SHOW_BOTH; return NULL;
270 return xasprintf ("bad value show %"PRIu8, in);
274 static char * WARN_UNUSED_RESULT
275 decode_spvlb_value (const struct pivot_table *table,
276 const struct spvlb_value *in, struct pivot_value **outp)
280 struct pivot_value *out = xzalloc (sizeof *out);
281 const struct spvlb_value_mod *vm;
287 vm = in->type_01.value_mod;
288 out->type = PIVOT_VALUE_NUMERIC;
289 out->numeric.x = in->type_01.x;
290 error = spv_decode_fmt_spec (in->type_01.format, &out->numeric.format);
296 vm = in->type_02.value_mod;
297 out->type = PIVOT_VALUE_NUMERIC;
298 out->numeric.x = in->type_02.x;
299 error = spv_decode_fmt_spec (in->type_02.format, &out->numeric.format);
301 error = decode_spvlb_value_show (in->type_02.show, &out->numeric.show);
304 out->numeric.var_name = xstrdup_if_nonempty (in->type_02.var_name);
305 out->numeric.value_label = xstrdup_if_nonempty (in->type_02.value_label);
309 vm = in->type_03.value_mod;
310 out->type = PIVOT_VALUE_TEXT;
311 out->text.local = xstrdup (in->type_03.local);
312 out->text.c = xstrdup (in->type_03.c);
313 out->text.id = xstrdup (in->type_03.id);
314 out->text.user_provided = !in->type_03.fixed;
318 vm = in->type_04.value_mod;
319 out->type = PIVOT_VALUE_STRING;
320 error = decode_spvlb_value_show (in->type_04.show, &out->string.show);
323 out->string.s = xstrdup (in->type_04.s);
324 out->string.hex = (in->type_04.format >> 16) == fmt_to_io (FMT_AHEX);
325 out->string.var_name = xstrdup (in->type_04.var_name);
326 out->string.value_label = xstrdup_if_nonempty (in->type_04.value_label);
330 vm = in->type_05.value_mod;
331 out->type = PIVOT_VALUE_VARIABLE;
332 error = decode_spvlb_value_show (in->type_05.show, &out->variable.show);
335 out->variable.var_name = xstrdup (in->type_05.var_name);
336 out->variable.var_label = xstrdup_if_nonempty (in->type_05.var_label);
340 vm = in->type_06.value_mod;
341 out->type = PIVOT_VALUE_TEXT;
342 out->text.local = xstrdup (in->type_06.local);
343 out->text.c = xstrdup (in->type_06.c);
344 out->text.id = xstrdup (in->type_06.id);
345 out->text.user_provided = false;
349 vm = in->type_else.value_mod;
350 out->type = PIVOT_VALUE_TEMPLATE;
351 out->template.local = xstrdup (in->type_else.template);
352 out->template.id = out->template.local;
353 out->template.n_args = 0;
354 out->template.args = xnmalloc (in->type_else.n_args,
355 sizeof *out->template.args);
356 for (size_t i = 0; i < in->type_else.n_args; i++)
358 error = decode_spvlb_argument (table, in->type_else.args[i],
359 &out->template.args[i]);
362 pivot_value_destroy (out);
365 out->template.n_args++;
375 if (vm->n_subscripts)
377 out->n_subscripts = vm->n_subscripts;
378 out->subscripts = xnmalloc (vm->n_subscripts,
379 sizeof *out->subscripts);
380 for (size_t i = 0; i < vm->n_subscripts; i++)
381 out->subscripts[i] = xstrdup (vm->subscripts[i]);
386 out->footnote_indexes = xnmalloc (vm->n_refs,
387 sizeof *out->footnote_indexes);
388 for (size_t i = 0; i < vm->n_refs; i++)
390 uint16_t idx = vm->refs[i];
391 if (idx >= table->n_footnotes)
393 pivot_value_destroy (out);
394 return xasprintf ("bad footnote index: %"PRIu16" >= %zu",
395 idx, table->n_footnotes);
398 out->footnote_indexes[out->n_footnotes++] = idx;
404 error = decode_spvlb_font_style (vm->style_pair->font_style,
407 error = decode_spvlb_cell_style (vm->style_pair->cell_style,
411 pivot_value_destroy (out);
416 if (vm->template_string
417 && vm->template_string->id
418 && vm->template_string->id[0]
419 && out->type == PIVOT_VALUE_TEMPLATE)
420 out->template.id = xstrdup (vm->template_string->id);
427 static char * WARN_UNUSED_RESULT
428 decode_spvlb_area (const struct spvlb_area *in, struct table_area_style *out)
432 struct cell_color fg0, fg1, bg0, bg1;
433 error = decode_spvlb_color_string (in->fg_color, 0x00, &fg0);
435 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg0);
436 if (!error && in->alternate)
437 error = decode_spvlb_color_string (in->alt_fg_color, 0x00, &fg1);
438 if (!error && in->alternate)
439 error = decode_spvlb_color_string (in->alt_bg_color, 0xff, &bg1);
441 enum table_halign halign;
444 error = decode_spvlb_halign (in->halign, &halign);
446 /* TABLE_HALIGN_DECIMAL doesn't seem to be a real halign for areas, which
447 is good because there's no way to indicate the decimal offset. Just
449 if (!error && halign == TABLE_HALIGN_DECIMAL)
450 halign = TABLE_HALIGN_MIXED;
453 enum table_valign valign;
455 error = decode_spvlb_valign (in->valign, &valign);
460 table_area_style_uninit (out);
461 *out = (struct table_area_style) {
463 .bold = (in->style & 1) != 0,
464 .italic = (in->style & 2) != 0,
465 .underline = in->underline,
466 .fg = { fg0, in->alternate ? fg1 : fg0 },
467 .bg = { bg0, in->alternate ? bg1 : bg0 },
468 .typeface = xstrdup (in->typeface),
469 .size = in->size / 1.33,
475 [TABLE_HORZ] = { in->left_margin, in->right_margin },
476 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
483 static char * WARN_UNUSED_RESULT
484 decode_spvlb_group (const struct pivot_table *,
485 struct spvlb_category **,
488 struct pivot_category *parent,
489 struct pivot_dimension *);
491 static char * WARN_UNUSED_RESULT
492 decode_spvlb_categories (const struct pivot_table *table,
493 struct spvlb_category **categories,
495 struct pivot_category *parent,
496 struct pivot_dimension *dimension)
498 for (size_t i = 0; i < n_categories; i++)
500 const struct spvlb_category *in = categories[i];
501 if (in->group && in->group->merge)
503 char *error = decode_spvlb_categories (
504 table, in->group->subcategories, in->group->n_subcategories,
512 struct pivot_value *name;
513 char *error = decode_spvlb_value (table, in->name, &name);
517 struct pivot_category *out = xzalloc (sizeof *out);
519 out->parent = parent;
520 out->dimension = dimension;
523 char *error = decode_spvlb_group (table, in->group->subcategories,
524 in->group->n_subcategories,
525 true, out, dimension);
528 pivot_category_destroy (out);
532 out->data_index = SIZE_MAX;
533 out->presentation_index = SIZE_MAX;
537 out->data_index = in->leaf->leaf_index;
538 out->presentation_index = dimension->n_leaves;
539 dimension->n_leaves++;
542 if (parent->n_subs >= parent->allocated_subs)
543 parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
544 sizeof *parent->subs);
545 parent->subs[parent->n_subs++] = out;
550 static char * WARN_UNUSED_RESULT
551 decode_spvlb_group (const struct pivot_table *table,
552 struct spvlb_category **categories,
553 size_t n_categories, bool show_label,
554 struct pivot_category *category,
555 struct pivot_dimension *dimension)
557 category->subs = XCALLOC (n_categories, struct pivot_category *);
558 category->n_subs = 0;
559 category->allocated_subs = 0;
560 category->show_label = show_label;
562 return decode_spvlb_categories (table, categories, n_categories, category,
566 static char * WARN_UNUSED_RESULT
567 fill_leaves (struct pivot_category *category,
568 struct pivot_dimension *dimension)
570 if (pivot_category_is_group (category))
572 for (size_t i = 0; i < category->n_subs; i++)
574 char *error = fill_leaves (category->subs[i], dimension);
581 if (category->data_index >= dimension->n_leaves)
582 return xasprintf ("leaf_index %zu >= n_leaves %zu",
583 category->data_index, dimension->n_leaves);
584 if (dimension->data_leaves[category->data_index])
585 return xasprintf ("two leaves with data_index %zu",
586 category->data_index);
587 dimension->data_leaves[category->data_index] = category;
588 dimension->presentation_leaves[category->presentation_index] = category;
593 static char * WARN_UNUSED_RESULT
594 decode_spvlb_dimension (const struct pivot_table *table,
595 const struct spvlb_dimension *in,
596 size_t idx, struct pivot_dimension **outp)
598 /* Convert most of the dimension. */
599 struct pivot_value *name;
600 char *error = decode_spvlb_value (table, in->name, &name);
604 struct pivot_dimension *out = xzalloc (sizeof *out);
605 out->level = UINT_MAX;
606 out->top_index = idx;
607 out->hide_all_labels = in->props->hide_all_labels;
609 out->root = xzalloc (sizeof *out->root);
610 *out->root = (struct pivot_category) {
613 .data_index = SIZE_MAX,
614 .presentation_index = SIZE_MAX,
616 error = decode_spvlb_group (table, in->categories, in->n_categories,
617 !in->props->hide_dim_label, out->root,
622 /* Allocate and fill the array of leaves now that we know how many there
624 out->data_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
625 out->presentation_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
626 out->allocated_leaves = out->n_leaves;
627 error = fill_leaves (out->root, out);
630 for (size_t i = 0; i < out->n_leaves; i++)
632 assert (out->data_leaves[i] != NULL);
633 assert (out->presentation_leaves[i] != NULL);
639 pivot_dimension_destroy (out);
643 static char * WARN_UNUSED_RESULT
644 decode_spvlb_stroke (uint32_t stroke_type, enum table_stroke *strokep)
646 enum table_stroke strokes[] = {
655 if (stroke_type >= sizeof strokes / sizeof *strokes)
656 return xasprintf ("bad stroke %"PRIu32, stroke_type);
658 *strokep = strokes[stroke_type];
662 static char * WARN_UNUSED_RESULT
663 decode_spvlb_border (const struct spvlb_border *in, struct pivot_table *table)
666 if (in->border_type >= PIVOT_N_BORDERS)
667 return xasprintf ("bad border type %"PRIu32, in->border_type);
669 struct table_border_style *out = &table->look->borders[in->border_type];
670 out->color = decode_spvlb_color_u32 (in->color);
671 return decode_spvlb_stroke (in->stroke_type, &out->stroke);
674 static char * WARN_UNUSED_RESULT
675 decode_spvlb_axis (const uint32_t *dimension_indexes, size_t n_dimensions,
676 enum pivot_axis_type axis_type, struct pivot_table *table)
678 struct pivot_axis *axis = &table->axes[axis_type];
679 axis->dimensions = XCALLOC (n_dimensions, struct pivot_dimension *);
680 axis->n_dimensions = n_dimensions;
682 for (size_t i = 0; i < n_dimensions; i++)
684 uint32_t idx = dimension_indexes[i];
685 if (idx >= table->n_dimensions)
686 return xasprintf ("bad dimension index %"PRIu32" >= %zu",
687 idx, table->n_dimensions);
689 struct pivot_dimension *d = table->dimensions[idx];
690 if (d->level != UINT_MAX)
691 return xasprintf ("duplicate dimension %"PRIu32, idx);
693 axis->dimensions[i] = d;
694 d->axis_type = axis_type;
697 axis->extent *= d->n_leaves;
704 decode_data_index (uint64_t in, const struct pivot_table *table,
707 uint64_t remainder = in;
708 for (size_t i = table->n_dimensions - 1; i > 0; i--)
710 const struct pivot_dimension *d = table->dimensions[i];
713 out[i] = remainder % d->n_leaves;
714 remainder /= d->n_leaves;
719 if (remainder >= table->dimensions[0]->n_leaves)
720 return xasprintf ("out of range cell data index %"PRIu64, in);
726 static char * WARN_UNUSED_RESULT
727 decode_spvlb_cells (struct spvlb_cell **in, size_t n_in,
728 struct pivot_table *table)
730 if (!table->n_dimensions)
733 size_t *dindexes = xnmalloc (table->n_dimensions, sizeof *dindexes);
734 for (size_t i = 0; i < n_in; i++)
736 struct pivot_value *value;
737 char *error = decode_data_index (in[i]->index, table, dindexes);
739 error = decode_spvlb_value (table, in[i]->value, &value);
745 pivot_table_put (table, dindexes, table->n_dimensions, value);
752 static char * WARN_UNUSED_RESULT
753 decode_spvlb_footnote (const struct spvlb_footnote *in,
754 size_t idx, struct pivot_table *table)
756 struct pivot_value *content;
757 char *error = decode_spvlb_value (table, in->text, &content);
761 struct pivot_value *marker = NULL;
764 error = decode_spvlb_value (table, in->marker, &marker);
767 pivot_value_destroy (content);
770 if (marker->type == PIVOT_VALUE_TEXT)
771 marker->text.user_provided = false;
774 struct pivot_footnote *f = pivot_table_create_footnote__ (
775 table, idx, marker, content);
776 f->show = (int32_t) in->show > 0;
780 static char * WARN_UNUSED_RESULT
781 decode_current_layer (uint64_t current_layer, struct pivot_table *table)
783 const struct pivot_axis *axis = &table->axes[PIVOT_AXIS_LAYER];
784 table->current_layer = xnmalloc (axis->n_dimensions,
785 sizeof *table->current_layer);
787 for (size_t i = 0; i < axis->n_dimensions; i++)
789 const struct pivot_dimension *d = axis->dimensions[i];
792 table->current_layer[i] = current_layer % d->n_leaves;
793 current_layer /= d->n_leaves;
796 table->current_layer[i] = 0;
798 if (current_layer > 0)
799 return xasprintf ("out of range layer data index %"PRIu64, current_layer);
803 char * WARN_UNUSED_RESULT
804 decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp)
807 if (in->header->version != 1 && in->header->version != 3)
808 return xasprintf ("unknown version %"PRIu32" (expected 1 or 3)",
809 in->header->version);
812 struct pivot_table *out = xzalloc (sizeof *out);
814 hmap_init (&out->cells);
815 out->look = pivot_table_look_new_builtin_default ();
816 out->settings = (struct fmt_settings) FMT_SETTINGS_INIT;
818 /* Display settings. */
819 out->look->show_numeric_markers = !in->ts->show_alphabetic_markers;
820 out->rotate_inner_column_labels = in->header->rotate_inner_column_labels;
821 out->rotate_outer_row_labels = in->header->rotate_outer_row_labels;
822 out->look->row_labels_in_corner = in->ts->show_row_labels_in_corner;
823 out->show_grid_lines = in->borders->show_grid_lines;
824 out->show_title = true;
825 out->show_caption = true;
826 out->look->footnote_marker_superscripts = in->ts->footnote_marker_superscripts;
827 out->look->omit_empty = in->ts->omit_empty;
829 const struct spvlb_x1 *x1 = in->formats->x1;
832 error = decode_spvlb_value_show (x1->show_values, &out->show_values);
834 error = decode_spvlb_value_show (x1->show_variables,
835 &out->show_variables);
839 out->show_caption = x1->show_caption;
840 out->show_title = x1->show_title != 10;
843 /* Column and row display settings. */
844 out->look->width_ranges[TABLE_VERT][0] = in->header->min_row_height;
845 out->look->width_ranges[TABLE_VERT][1] = in->header->max_row_height;
846 out->look->width_ranges[TABLE_HORZ][0] = in->header->min_col_width;
847 out->look->width_ranges[TABLE_HORZ][1] = in->header->max_col_width;
849 convert_widths (in->formats->widths, in->formats->n_widths,
850 &out->sizing[TABLE_HORZ].widths,
851 &out->sizing[TABLE_HORZ].n_widths);
853 const struct spvlb_x2 *x2 = in->formats->x2;
855 convert_widths (x2->row_heights, x2->n_row_heights,
856 &out->sizing[TABLE_VERT].widths,
857 &out->sizing[TABLE_VERT].n_widths);
859 convert_breakpoints (in->ts->row_breaks,
860 &out->sizing[TABLE_VERT].breaks,
861 &out->sizing[TABLE_VERT].n_breaks);
862 convert_breakpoints (in->ts->col_breaks,
863 &out->sizing[TABLE_HORZ].breaks,
864 &out->sizing[TABLE_HORZ].n_breaks);
866 convert_keeps (in->ts->row_keeps,
867 &out->sizing[TABLE_VERT].keeps,
868 &out->sizing[TABLE_VERT].n_keeps);
869 convert_keeps (in->ts->col_keeps,
870 &out->sizing[TABLE_HORZ].keeps,
871 &out->sizing[TABLE_HORZ].n_keeps);
873 out->notes = xstrdup_if_nonempty (in->ts->notes);
874 out->look->name = xstrdup_if_nonempty (in->ts->table_look);
876 /* Print settings. */
877 out->look->print_all_layers = in->ps->all_layers;
878 out->look->paginate_layers = in->ps->paginate_layers;
879 out->look->shrink_to_fit[TABLE_HORZ] = in->ps->fit_width;
880 out->look->shrink_to_fit[TABLE_VERT] = in->ps->fit_length;
881 out->look->top_continuation = in->ps->top_continuation;
882 out->look->bottom_continuation = in->ps->bottom_continuation;
883 out->look->continuation = xstrdup (in->ps->continuation_string);
884 out->look->n_orphan_lines = in->ps->n_orphan_lines;
886 /* Format settings. */
887 int epoch = in->formats->y0->epoch;
888 if (epoch >= 1000 && epoch <= 9999)
889 out->settings.epoch = epoch;
890 char decimal = in->formats->y0->decimal;
891 if (decimal == '.' || decimal == '.')
892 out->settings.decimal = decimal;
895 /* XXX warn about bad decimal point */
897 out->grouping = in->formats->y0->grouping;
898 const struct spvlb_custom_currency *cc = in->formats->custom_currency;
899 for (int i = 0; i < 5; i++)
901 if (cc && i < cc->n_ccs)
903 out->settings.ccs[i] = fmt_number_style_from_string (cc->ccs[i]);
904 /* XXX warn if parsing fails */
907 out->small = in->formats->x3 ? in->formats->x3->small : 0;
909 /* Command information. */
910 const struct spvlb_y1 *y1 = (in->formats->x0 ? in->formats->x0->y1
911 : in->formats->x3 ? in->formats->x3->y1
915 out->command_local = xstrdup (y1->command_local);
916 out->command_c = xstrdup (y1->command);
917 out->language = xstrdup (y1->language);
919 out->locale = xstrdup (y1->locale);
922 /* Source information. */
923 const struct spvlb_x3 *x3 = in->formats->x3;
926 if (x3->dataset && x3->dataset[0] && x3->dataset[0] != 4)
927 out->dataset = xstrdup (x3->dataset);
928 out->datafile = xstrdup_if_nonempty (x3->datafile);
929 out->date = x3->date;
934 Any pivot_value might refer to footnotes, so it's important to process the
935 footnotes early to ensure that those references can be resolved. There is
936 a possible problem that a footnote might itself reference an
937 as-yet-unprocessed footnote, but that's OK because footnote references
938 don't actually look at the footnote contents but only resolve a pointer to
939 where the footnote will go later.
941 Before we really start, create all the footnotes we'll fill in. This is
942 because sometimes footnotes refer to themselves or to each other and we
943 don't want to reject those references. */
944 const struct spvlb_footnotes *fn = in->footnotes;
945 if (fn->n_footnotes > 0)
947 pivot_table_create_footnote__ (out, fn->n_footnotes - 1, NULL, NULL);
948 for (size_t i = 0; i < fn->n_footnotes; i++)
950 error = decode_spvlb_footnote (in->footnotes->footnotes[i], i, out);
956 /* Title and caption. */
957 error = decode_spvlb_value (out, in->titles->user_title, &out->title);
961 error = decode_spvlb_value (out, in->titles->subtype, &out->subtype);
965 if (in->titles->corner_text)
967 error = decode_spvlb_value (out, in->titles->corner_text,
973 if (in->titles->caption)
975 error = decode_spvlb_value (out, in->titles->caption, &out->caption);
982 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
984 error = decode_spvlb_area (in->areas->areas[i], &out->look->areas[i]);
988 for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
990 error = decode_spvlb_border (in->borders->borders[i], out);
996 out->n_dimensions = in->dimensions->n_dims;
997 out->dimensions = XCALLOC (out->n_dimensions, struct pivot_dimension *);
998 for (size_t i = 0; i < out->n_dimensions; i++)
1000 error = decode_spvlb_dimension (out, in->dimensions->dims[i],
1001 i, &out->dimensions[i]);
1007 size_t a = in->axes->n_layers;
1008 size_t b = in->axes->n_rows;
1009 size_t c = in->axes->n_columns;
1010 if (size_overflow_p (xsum3 (a, b, c)) || a + b + c != out->n_dimensions)
1012 error = xasprintf ("dimensions do not sum correctly "
1013 "(%zu + %zu + %zu != %zu)",
1014 a, b, c, out->n_dimensions);
1017 error = decode_spvlb_axis (in->axes->layers, in->axes->n_layers,
1018 PIVOT_AXIS_LAYER, out);
1021 error = decode_spvlb_axis (in->axes->rows, in->axes->n_rows,
1022 PIVOT_AXIS_ROW, out);
1025 error = decode_spvlb_axis (in->axes->columns, in->axes->n_columns,
1026 PIVOT_AXIS_COLUMN, out);
1030 pivot_table_assign_label_depth (out);
1032 error = decode_current_layer (in->ts->current_layer, out);
1037 error = decode_spvlb_cells (in->cells->cells, in->cells->n_cells, out);
1043 pivot_table_unref (out);