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.var_name = xstrdup (in->type_04.var_name);
325 out->string.value_label = xstrdup_if_nonempty (in->type_04.value_label);
329 vm = in->type_05.value_mod;
330 out->type = PIVOT_VALUE_VARIABLE;
331 error = decode_spvlb_value_show (in->type_05.show, &out->variable.show);
334 out->variable.var_name = xstrdup (in->type_05.var_name);
335 out->variable.var_label = xstrdup_if_nonempty (in->type_05.var_label);
339 vm = in->type_06.value_mod;
340 out->type = PIVOT_VALUE_TEXT;
341 out->text.local = xstrdup (in->type_06.local);
342 out->text.c = xstrdup (in->type_06.c);
343 out->text.id = xstrdup (in->type_06.id);
344 out->text.user_provided = false;
348 vm = in->type_else.value_mod;
349 out->type = PIVOT_VALUE_TEMPLATE;
350 out->template.local = xstrdup (in->type_else.template);
351 out->template.id = out->template.local;
352 out->template.n_args = 0;
353 out->template.args = xnmalloc (in->type_else.n_args,
354 sizeof *out->template.args);
355 for (size_t i = 0; i < in->type_else.n_args; i++)
357 error = decode_spvlb_argument (table, in->type_else.args[i],
358 &out->template.args[i]);
361 pivot_value_destroy (out);
364 out->template.n_args++;
374 if (vm->n_subscripts)
376 out->n_subscripts = vm->n_subscripts;
377 out->subscripts = xnmalloc (vm->n_subscripts,
378 sizeof *out->subscripts);
379 for (size_t i = 0; i < vm->n_subscripts; i++)
380 out->subscripts[i] = xstrdup (vm->subscripts[i]);
385 out->footnote_indexes = xnmalloc (vm->n_refs,
386 sizeof *out->footnote_indexes);
387 for (size_t i = 0; i < vm->n_refs; i++)
389 uint16_t idx = vm->refs[i];
390 if (idx >= table->n_footnotes)
392 pivot_value_destroy (out);
393 return xasprintf ("bad footnote index: %"PRIu16" >= %zu",
394 idx, table->n_footnotes);
397 out->footnote_indexes[out->n_footnotes++] = idx;
403 error = decode_spvlb_font_style (vm->style_pair->font_style,
406 error = decode_spvlb_cell_style (vm->style_pair->cell_style,
410 pivot_value_destroy (out);
415 if (vm->template_string
416 && vm->template_string->id
417 && vm->template_string->id[0]
418 && out->type == PIVOT_VALUE_TEMPLATE)
419 out->template.id = xstrdup (vm->template_string->id);
426 static char * WARN_UNUSED_RESULT
427 decode_spvlb_area (const struct spvlb_area *in, struct table_area_style *out)
431 struct cell_color fg0, fg1, bg0, bg1;
432 error = decode_spvlb_color_string (in->fg_color, 0x00, &fg0);
434 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg0);
435 if (!error && in->alternate)
436 error = decode_spvlb_color_string (in->alt_fg_color, 0x00, &fg1);
437 if (!error && in->alternate)
438 error = decode_spvlb_color_string (in->alt_bg_color, 0xff, &bg1);
440 enum table_halign halign;
443 error = decode_spvlb_halign (in->halign, &halign);
445 /* TABLE_HALIGN_DECIMAL doesn't seem to be a real halign for areas, which
446 is good because there's no way to indicate the decimal offset. Just
448 if (!error && halign == TABLE_HALIGN_DECIMAL)
449 halign = TABLE_HALIGN_MIXED;
452 enum table_valign valign;
454 error = decode_spvlb_valign (in->valign, &valign);
459 table_area_style_uninit (out);
460 *out = (struct table_area_style) {
462 .bold = (in->style & 1) != 0,
463 .italic = (in->style & 2) != 0,
464 .underline = in->underline,
465 .fg = { fg0, in->alternate ? fg1 : fg0 },
466 .bg = { bg0, in->alternate ? bg1 : bg0 },
467 .typeface = xstrdup (in->typeface),
468 .size = in->size / 1.33,
474 [TABLE_HORZ] = { in->left_margin, in->right_margin },
475 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
482 static char * WARN_UNUSED_RESULT
483 decode_spvlb_group (const struct pivot_table *,
484 struct spvlb_category **,
487 struct pivot_category *parent,
488 struct pivot_dimension *);
490 static char * WARN_UNUSED_RESULT
491 decode_spvlb_categories (const struct pivot_table *table,
492 struct spvlb_category **categories,
494 struct pivot_category *parent,
495 struct pivot_dimension *dimension)
497 for (size_t i = 0; i < n_categories; i++)
499 const struct spvlb_category *in = categories[i];
500 if (in->group && in->group->merge)
502 char *error = decode_spvlb_categories (
503 table, in->group->subcategories, in->group->n_subcategories,
511 struct pivot_value *name;
512 char *error = decode_spvlb_value (table, in->name, &name);
516 struct pivot_category *out = xzalloc (sizeof *out);
518 out->parent = parent;
519 out->dimension = dimension;
522 char *error = decode_spvlb_group (table, in->group->subcategories,
523 in->group->n_subcategories,
524 true, out, dimension);
527 pivot_category_destroy (out);
531 out->data_index = SIZE_MAX;
532 out->presentation_index = SIZE_MAX;
536 out->data_index = in->leaf->leaf_index;
537 out->presentation_index = dimension->n_leaves;
538 dimension->n_leaves++;
541 if (parent->n_subs >= parent->allocated_subs)
542 parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
543 sizeof *parent->subs);
544 parent->subs[parent->n_subs++] = out;
549 static char * WARN_UNUSED_RESULT
550 decode_spvlb_group (const struct pivot_table *table,
551 struct spvlb_category **categories,
552 size_t n_categories, bool show_label,
553 struct pivot_category *category,
554 struct pivot_dimension *dimension)
556 category->subs = XCALLOC (n_categories, struct pivot_category *);
557 category->n_subs = 0;
558 category->allocated_subs = 0;
559 category->show_label = show_label;
561 return decode_spvlb_categories (table, categories, n_categories, category,
565 static char * WARN_UNUSED_RESULT
566 fill_leaves (struct pivot_category *category,
567 struct pivot_dimension *dimension)
569 if (pivot_category_is_group (category))
571 for (size_t i = 0; i < category->n_subs; i++)
573 char *error = fill_leaves (category->subs[i], dimension);
580 if (category->data_index >= dimension->n_leaves)
581 return xasprintf ("leaf_index %zu >= n_leaves %zu",
582 category->data_index, dimension->n_leaves);
583 if (dimension->data_leaves[category->data_index])
584 return xasprintf ("two leaves with data_index %zu",
585 category->data_index);
586 dimension->data_leaves[category->data_index] = category;
587 dimension->presentation_leaves[category->presentation_index] = category;
592 static char * WARN_UNUSED_RESULT
593 decode_spvlb_dimension (const struct pivot_table *table,
594 const struct spvlb_dimension *in,
595 size_t idx, struct pivot_dimension **outp)
597 /* Convert most of the dimension. */
598 struct pivot_value *name;
599 char *error = decode_spvlb_value (table, in->name, &name);
603 struct pivot_dimension *out = xzalloc (sizeof *out);
604 out->level = UINT_MAX;
605 out->top_index = idx;
606 out->hide_all_labels = in->props->hide_all_labels;
608 out->root = xzalloc (sizeof *out->root);
609 *out->root = (struct pivot_category) {
612 .data_index = SIZE_MAX,
613 .presentation_index = SIZE_MAX,
615 error = decode_spvlb_group (table, in->categories, in->n_categories,
616 !in->props->hide_dim_label, out->root,
621 /* Allocate and fill the array of leaves now that we know how many there
623 out->data_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
624 out->presentation_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
625 out->allocated_leaves = out->n_leaves;
626 error = fill_leaves (out->root, out);
629 for (size_t i = 0; i < out->n_leaves; i++)
631 assert (out->data_leaves[i] != NULL);
632 assert (out->presentation_leaves[i] != NULL);
638 pivot_dimension_destroy (out);
642 static char * WARN_UNUSED_RESULT
643 decode_spvlb_stroke (uint32_t stroke_type, enum table_stroke *strokep)
645 enum table_stroke strokes[] = {
654 if (stroke_type >= sizeof strokes / sizeof *strokes)
655 return xasprintf ("bad stroke %"PRIu32, stroke_type);
657 *strokep = strokes[stroke_type];
661 static char * WARN_UNUSED_RESULT
662 decode_spvlb_border (const struct spvlb_border *in, struct pivot_table *table)
665 if (in->border_type >= PIVOT_N_BORDERS)
666 return xasprintf ("bad border type %"PRIu32, in->border_type);
668 struct table_border_style *out = &table->look->borders[in->border_type];
669 out->color = decode_spvlb_color_u32 (in->color);
670 return decode_spvlb_stroke (in->stroke_type, &out->stroke);
673 static char * WARN_UNUSED_RESULT
674 decode_spvlb_axis (const uint32_t *dimension_indexes, size_t n_dimensions,
675 enum pivot_axis_type axis_type, struct pivot_table *table)
677 struct pivot_axis *axis = &table->axes[axis_type];
678 axis->dimensions = XCALLOC (n_dimensions, struct pivot_dimension *);
679 axis->n_dimensions = n_dimensions;
681 for (size_t i = 0; i < n_dimensions; i++)
683 uint32_t idx = dimension_indexes[i];
684 if (idx >= table->n_dimensions)
685 return xasprintf ("bad dimension index %"PRIu32" >= %zu",
686 idx, table->n_dimensions);
688 struct pivot_dimension *d = table->dimensions[idx];
689 if (d->level != UINT_MAX)
690 return xasprintf ("duplicate dimension %"PRIu32, idx);
692 axis->dimensions[i] = d;
693 d->axis_type = axis_type;
696 axis->extent *= d->n_leaves;
703 decode_data_index (uint64_t in, const struct pivot_table *table,
706 uint64_t remainder = in;
707 for (size_t i = table->n_dimensions - 1; i > 0; i--)
709 const struct pivot_dimension *d = table->dimensions[i];
712 out[i] = remainder % d->n_leaves;
713 remainder /= d->n_leaves;
718 if (remainder >= table->dimensions[0]->n_leaves)
719 return xasprintf ("out of range cell data index %"PRIu64, in);
725 static char * WARN_UNUSED_RESULT
726 decode_spvlb_cells (struct spvlb_cell **in, size_t n_in,
727 struct pivot_table *table)
729 if (!table->n_dimensions)
732 size_t *dindexes = xnmalloc (table->n_dimensions, sizeof *dindexes);
733 for (size_t i = 0; i < n_in; i++)
735 struct pivot_value *value;
736 char *error = decode_data_index (in[i]->index, table, dindexes);
738 error = decode_spvlb_value (table, in[i]->value, &value);
744 pivot_table_put (table, dindexes, table->n_dimensions, value);
751 static char * WARN_UNUSED_RESULT
752 decode_spvlb_footnote (const struct spvlb_footnote *in,
753 size_t idx, struct pivot_table *table)
755 struct pivot_value *content;
756 char *error = decode_spvlb_value (table, in->text, &content);
760 struct pivot_value *marker = NULL;
763 error = decode_spvlb_value (table, in->marker, &marker);
766 pivot_value_destroy (content);
769 if (marker->type == PIVOT_VALUE_TEXT)
770 marker->text.user_provided = false;
773 struct pivot_footnote *f = pivot_table_create_footnote__ (
774 table, idx, marker, content);
775 f->show = (int32_t) in->show > 0;
779 static char * WARN_UNUSED_RESULT
780 decode_current_layer (uint64_t current_layer, struct pivot_table *table)
782 const struct pivot_axis *axis = &table->axes[PIVOT_AXIS_LAYER];
783 table->current_layer = xnmalloc (axis->n_dimensions,
784 sizeof *table->current_layer);
786 for (size_t i = 0; i < axis->n_dimensions; i++)
788 const struct pivot_dimension *d = axis->dimensions[i];
791 table->current_layer[i] = current_layer % d->n_leaves;
792 current_layer /= d->n_leaves;
795 table->current_layer[i] = 0;
797 if (current_layer > 0)
798 return xasprintf ("out of range layer data index %"PRIu64, current_layer);
802 char * WARN_UNUSED_RESULT
803 decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp)
806 if (in->header->version != 1 && in->header->version != 3)
807 return xasprintf ("unknown version %"PRIu32" (expected 1 or 3)",
808 in->header->version);
811 struct pivot_table *out = xzalloc (sizeof *out);
813 hmap_init (&out->cells);
814 out->look = pivot_table_look_new_builtin_default ();
815 out->settings = (struct fmt_settings) FMT_SETTINGS_INIT;
817 /* Display settings. */
818 out->look->show_numeric_markers = !in->ts->show_alphabetic_markers;
819 out->rotate_inner_column_labels = in->header->rotate_inner_column_labels;
820 out->rotate_outer_row_labels = in->header->rotate_outer_row_labels;
821 out->look->row_labels_in_corner = in->ts->show_row_labels_in_corner;
822 out->show_grid_lines = in->borders->show_grid_lines;
823 out->show_title = true;
824 out->show_caption = true;
825 out->look->footnote_marker_superscripts = in->ts->footnote_marker_superscripts;
826 out->look->omit_empty = in->ts->omit_empty;
828 const struct spvlb_x1 *x1 = in->formats->x1;
831 error = decode_spvlb_value_show (x1->show_values, &out->show_values);
833 error = decode_spvlb_value_show (x1->show_variables,
834 &out->show_variables);
838 out->show_caption = x1->show_caption;
839 out->show_title = x1->show_title != 10;
842 /* Column and row display settings. */
843 out->look->width_ranges[TABLE_VERT][0] = in->header->min_row_height;
844 out->look->width_ranges[TABLE_VERT][1] = in->header->max_row_height;
845 out->look->width_ranges[TABLE_HORZ][0] = in->header->min_col_width;
846 out->look->width_ranges[TABLE_HORZ][1] = in->header->max_col_width;
848 convert_widths (in->formats->widths, in->formats->n_widths,
849 &out->sizing[TABLE_HORZ].widths,
850 &out->sizing[TABLE_HORZ].n_widths);
852 const struct spvlb_x2 *x2 = in->formats->x2;
854 convert_widths (x2->row_heights, x2->n_row_heights,
855 &out->sizing[TABLE_VERT].widths,
856 &out->sizing[TABLE_VERT].n_widths);
858 convert_breakpoints (in->ts->row_breaks,
859 &out->sizing[TABLE_VERT].breaks,
860 &out->sizing[TABLE_VERT].n_breaks);
861 convert_breakpoints (in->ts->col_breaks,
862 &out->sizing[TABLE_HORZ].breaks,
863 &out->sizing[TABLE_HORZ].n_breaks);
865 convert_keeps (in->ts->row_keeps,
866 &out->sizing[TABLE_VERT].keeps,
867 &out->sizing[TABLE_VERT].n_keeps);
868 convert_keeps (in->ts->col_keeps,
869 &out->sizing[TABLE_HORZ].keeps,
870 &out->sizing[TABLE_HORZ].n_keeps);
872 out->notes = xstrdup_if_nonempty (in->ts->notes);
873 out->look->name = xstrdup_if_nonempty (in->ts->table_look);
875 /* Print settings. */
876 out->look->print_all_layers = in->ps->all_layers;
877 out->look->paginate_layers = in->ps->paginate_layers;
878 out->look->shrink_to_fit[TABLE_HORZ] = in->ps->fit_width;
879 out->look->shrink_to_fit[TABLE_VERT] = in->ps->fit_length;
880 out->look->top_continuation = in->ps->top_continuation;
881 out->look->bottom_continuation = in->ps->bottom_continuation;
882 out->look->continuation = xstrdup (in->ps->continuation_string);
883 out->look->n_orphan_lines = in->ps->n_orphan_lines;
885 /* Format settings. */
886 int epoch = in->formats->y0->epoch;
887 if (epoch >= 1000 && epoch <= 9999)
888 out->settings.epoch = epoch;
889 char decimal = in->formats->y0->decimal;
890 if (decimal == '.' || decimal == '.')
891 out->settings.decimal = decimal;
894 /* XXX warn about bad decimal point */
896 out->grouping = in->formats->y0->grouping;
897 const struct spvlb_custom_currency *cc = in->formats->custom_currency;
898 for (int i = 0; i < 5; i++)
900 if (cc && i < cc->n_ccs)
902 out->settings.ccs[i] = fmt_number_style_from_string (cc->ccs[i]);
903 /* XXX warn if parsing fails */
906 out->small = in->formats->x3 ? in->formats->x3->small : 0;
908 /* Command information. */
909 const struct spvlb_y1 *y1 = (in->formats->x0 ? in->formats->x0->y1
910 : in->formats->x3 ? in->formats->x3->y1
914 out->command_local = xstrdup (y1->command_local);
915 out->command_c = xstrdup (y1->command);
916 out->language = xstrdup (y1->language);
918 out->locale = xstrdup (y1->locale);
921 /* Source information. */
922 const struct spvlb_x3 *x3 = in->formats->x3;
925 if (x3->dataset && x3->dataset[0] && x3->dataset[0] != 4)
926 out->dataset = xstrdup (x3->dataset);
927 out->datafile = xstrdup_if_nonempty (x3->datafile);
928 out->date = x3->date;
933 Any pivot_value might refer to footnotes, so it's important to process the
934 footnotes early to ensure that those references can be resolved. There is
935 a possible problem that a footnote might itself reference an
936 as-yet-unprocessed footnote, but that's OK because footnote references
937 don't actually look at the footnote contents but only resolve a pointer to
938 where the footnote will go later.
940 Before we really start, create all the footnotes we'll fill in. This is
941 because sometimes footnotes refer to themselves or to each other and we
942 don't want to reject those references. */
943 const struct spvlb_footnotes *fn = in->footnotes;
944 if (fn->n_footnotes > 0)
946 pivot_table_create_footnote__ (out, fn->n_footnotes - 1, NULL, NULL);
947 for (size_t i = 0; i < fn->n_footnotes; i++)
949 error = decode_spvlb_footnote (in->footnotes->footnotes[i], i, out);
955 /* Title and caption. */
956 error = decode_spvlb_value (out, in->titles->user_title, &out->title);
960 error = decode_spvlb_value (out, in->titles->subtype, &out->subtype);
964 if (in->titles->corner_text)
966 error = decode_spvlb_value (out, in->titles->corner_text,
972 if (in->titles->caption)
974 error = decode_spvlb_value (out, in->titles->caption, &out->caption);
981 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
983 error = decode_spvlb_area (in->areas->areas[i], &out->look->areas[i]);
987 for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
989 error = decode_spvlb_border (in->borders->borders[i], out);
995 out->n_dimensions = in->dimensions->n_dims;
996 out->dimensions = XCALLOC (out->n_dimensions, struct pivot_dimension *);
997 for (size_t i = 0; i < out->n_dimensions; i++)
999 error = decode_spvlb_dimension (out, in->dimensions->dims[i],
1000 i, &out->dimensions[i]);
1006 size_t a = in->axes->n_layers;
1007 size_t b = in->axes->n_rows;
1008 size_t c = in->axes->n_columns;
1009 if (size_overflow_p (xsum3 (a, b, c)) || a + b + c != out->n_dimensions)
1011 error = xasprintf ("dimensions do not sum correctly "
1012 "(%zu + %zu + %zu != %zu)",
1013 a, b, c, out->n_dimensions);
1016 error = decode_spvlb_axis (in->axes->layers, in->axes->n_layers,
1017 PIVOT_AXIS_LAYER, out);
1020 error = decode_spvlb_axis (in->axes->rows, in->axes->n_rows,
1021 PIVOT_AXIS_ROW, out);
1024 error = decode_spvlb_axis (in->axes->columns, in->axes->n_columns,
1025 PIVOT_AXIS_COLUMN, out);
1029 pivot_table_assign_label_depth (out);
1031 error = decode_current_layer (in->ts->current_layer, out);
1036 error = decode_spvlb_cells (in->cells->cells, in->cells->n_cells, out);
1042 pivot_table_unref (out);