13 #include "u8-mbtouc.h"
15 static const char *filename;
24 #define STR(x) XSTR(x)
25 #define WHERE __FILE__":" STR(__LINE__)
37 memcpy(&x, &data[pos], 4);
42 static unsigned long long int
46 memcpy(&x, &data[pos], 8);
55 x = (data[pos] << 24) | (data[pos + 1] << 16) | (data[pos + 2] << 8) | data[pos + 3];
64 memcpy(&x, &data[pos], 2);
73 memcpy(&x, &data[pos], 8);
78 static double __attribute__((unused))
82 memcpy(&x, &data[pos], 4);
97 match_u32_assert(uint32_t x, const char *where)
99 unsigned int y = get_u32();
102 fprintf(stderr, "%s: 0x%x: expected i%u, got i%u\n", where, pos - 4, x, y);
106 #define match_u32_assert(x) match_u32_assert(x, WHERE)
108 static bool __attribute__((unused))
109 match_u64(uint64_t x)
117 static void __attribute__((unused))
118 match_u64_assert(uint64_t x, const char *where)
120 unsigned long long int y = get_u64();
123 fprintf(stderr, "%s: 0x%x: expected u64:%llu, got u64:%llu\n", where, pos - 8, x, y);
127 #define match_u64_assert(x) match_u64_assert(x, WHERE)
129 static bool __attribute__((unused))
130 match_be32(uint32_t x)
139 match_be32_assert(uint32_t x, const char *where)
141 unsigned int y = get_be32();
144 fprintf(stderr, "%s: 0x%x: expected be%u, got be%u\n", where, pos - 4, x, y);
148 #define match_be32_assert(x) match_be32_assert(x, WHERE)
151 match_byte(uint8_t b)
153 if (pos < n && data[pos] == b)
163 match_byte_assert(uint8_t b, const char *where)
167 fprintf(stderr, "%s: 0x%x: expected %02x, got %02x\n", where, pos, b, data[pos]);
171 #define match_byte_assert(b) match_byte_assert(b, WHERE)
178 match_byte_assert(1);
182 static bool __attribute__((unused))
183 all_utf8(const char *p_)
185 const uint8_t *p = (const uint8_t *) p_;
186 size_t len = strlen ((char *) p);
187 for (size_t ofs = 0, mblen; ofs < len; ofs += mblen)
191 mblen = u8_mbtouc (&uc, p + ofs, len - ofs);
192 if ((uc < 32 && uc != '\n') || uc == 127 || uc == 0xfffd)
199 get_string(const char *where)
202 /*data[pos + 1] == 0 && data[pos + 2] == 0 && data[pos + 3] == 0*/
203 /*&& all_ascii(&data[pos + 4], data[pos])*/)
205 int len = data[pos] + data[pos + 1] * 256;
206 char *s = malloc(len + 1);
208 memcpy(s, &data[pos + 4], len);
215 fprintf(stderr, "%s: 0x%x: expected string\n", where, pos);
219 #define get_string() get_string(WHERE)
222 get_string_be(const char *where)
225 /*data[pos + 1] == 0 && data[pos + 2] == 0 && data[pos + 3] == 0*/
226 /*&& all_ascii(&data[pos + 4], data[pos])*/)
228 int len = data[pos + 2] * 256 + data[pos + 3];
229 char *s = malloc(len + 1);
231 memcpy(s, &data[pos + 4], len);
238 fprintf(stderr, "%s: 0x%x: expected string\n", where, pos);
242 #define get_string_be() get_string_be(WHERE)
251 static void __attribute__((unused))
252 hex_dump(FILE *stream, int ofs, int n)
254 for (int i = 0; i < n; i++)
256 int c = data[ofs + i];
263 fprintf(stream, "%02x", c);
265 for (int i = 0; i < n; i++)
267 int c = data[ofs + i];
268 putc(c >= 32 && c < 127 ? c : '.', stream);
274 dump_counted_string(void)
276 int inner_end = get_end();
277 if (pos == inner_end)
283 match_byte_assert(0x58);
289 if (match_byte(0x31))
292 match_byte_assert(0x58);
293 if (pos != inner_end)
295 fprintf(stderr, "inner end discrepancy\n");
302 dump_style(FILE *stream)
304 if (match_byte(0x58))
307 match_byte_assert(0x31);
309 printf (" bold=\"yes\"");
311 printf (" italic=\"yes\"");
313 printf (" underline=\"yes\"");
315 printf (" show=\"no\"");
316 char *fg = get_string(); /* foreground */
317 char *bg = get_string(); /* background */
318 char *font = get_string(); /* font */
319 int size = get_byte() * (72. / 96.);
320 fprintf(stream, " fgcolor=\"%s\" bgcolor=\"%s\" font=\"%s\" size=\"%dpt\"",
325 dump_style2(FILE *stream)
327 if (match_byte(0x58))
330 match_byte_assert(0x31);
331 uint32_t halign = get_u32();
332 printf (" halign=\"%s\"",
333 halign == 0 ? "center"
334 : halign == 2 ? "left"
335 : halign == 4 ? "right"
336 : halign == 6 ? "decimal"
337 : halign == 0xffffffad ? "mixed"
339 int valign = get_u32();
340 printf (" valign=\"%s\"",
341 valign == 0 ? "center"
342 : valign == 1 ? "top"
343 : valign == 3 ? "bottom"
345 printf (" offset=\"%gpt\"", get_double());
350 printf (" margins=\"%d %d %d %d\"", l, r, t, b);
354 dump_nested_string(FILE *stream)
358 match_byte_assert (0);
359 match_byte_assert (0);
360 int outer_end = get_end();
361 s = dump_counted_string();
363 fprintf(stream, " \"%s\"", s);
365 match_byte_assert(0x58);
366 if (pos != outer_end)
368 fprintf(stderr, "outer end discrepancy\n");
376 dump_value_modifier(FILE *stream)
378 if (match_byte (0x31))
382 fprintf(stream, "<special0");
385 /* Corpus frequencies:
390 The given text is appended to the cell in a subscript font.
392 fprintf(stream, " subscript=\"%s\"", get_string());
395 match_u32_assert (0);
399 /* We only have one SPV file for this version (with many
406 if (!match_u32(0) && !match_u32(1) && !match_u32(2) && !match_u32(3) && !match_u32(4) && !match_u32(5) && !match_u32(6) && !match_u32(7) && !match_u32(8) && !match_u32(9))
407 match_u32_assert(10);
410 fprintf(stream, "/>\n");
414 int outer_end = get_end();
416 /* This counted-string appears to be a template string,
417 e.g. "Design\: [:^1:]1 Within Subjects Design\: [:^1:]2". */
418 char *template = dump_counted_string();
420 fprintf(stream, " template=\"%s\"", template);
424 if (pos != outer_end)
426 fprintf(stderr, "outer end discrepancy\n");
429 fprintf(stream, "/>\n");
433 int count = get_u32();
434 fprintf(stream, "<footnote-ref indexes=\"");
435 for (int i = 0; i < count; i++)
439 fprintf(stream, "%d", get_u16());
442 match_byte_assert(0);
443 match_byte_assert(0);
444 dump_nested_string(stream);
445 fprintf(stream, "/>\n");
449 match_byte_assert (0x58);
453 format_to_string (int type)
459 case 2: return "AHEX";
460 case 3: return "COMMA";
461 case 4: return "DOLLAR";
462 case 5: case 40: return "F";
464 case 7: return "PIBHEX";
466 case 9: return "PIB";
467 case 10: return "PK";
468 case 11: return "RB";
469 case 12: return "RBHEX";
473 case 20: return "DATE";
474 case 21: return "TIME";
475 case 22: return "DATETIME";
476 case 23: return "ADATE";
477 case 24: return "JDATE";
478 case 25: return "DTIME";
479 case 26: return "WKDAY";
480 case 27: return "MONTH";
481 case 28: return "MOYR";
482 case 29: return "QYR";
483 case 30: return "WKYR";
484 case 31: return "PCT";
485 case 32: return "DOT";
486 case 33: return "CCA";
487 case 34: return "CCB";
488 case 35: return "CCC";
489 case 36: return "CCD";
490 case 37: return "CCE";
491 case 38: return "EDATE";
492 case 39: return "SDATE";
495 sprintf(tmp, "<%d>", type);
501 dump_value(FILE *stream, int level)
508 for (int i = 0; i <= level; i++)
509 fprintf (stream, " ");
516 dump_value_modifier(stream);
518 value = get_double ();
519 fprintf (stream, "<number value=\"%.*g\" format=\"%s%d.%d\"/>\n",
520 DBL_DIG, value, format_to_string(format >> 16), (format >> 8) & 0xff, format & 0xff);
522 else if (match_byte (2))
528 dump_value_modifier (stream);
530 value = get_double ();
532 vallab = get_string ();
533 fprintf (stream, "<numeric-datum value=\"%.*g\" format=\"%s%d.%d\"",
534 DBL_DIG, value, format_to_string(format >> 16), (format >> 8) & 0xff, format & 0xff);
536 fprintf (stream, " variable=\"%s\"", var);
538 fprintf (stream, " label=\"%s\"", vallab);
539 fprintf (stream, "/>\n");
540 if (!match_byte (1) && !match_byte(2))
541 match_byte_assert (3);
543 else if (match_byte (3))
545 char *text = get_string();
546 dump_value_modifier(stream);
547 char *identifier = get_string();
548 char *text_eng = get_string();
549 fprintf (stream, "<string c=\"%s\"", text_eng);
551 fprintf (stream, " identifier=\"%s\"", identifier);
552 if (strcmp(text_eng, text))
553 fprintf (stream, " local=\"%s\"", text);
554 fprintf (stream, "/>\n");
556 match_byte_assert(1);
558 else if (match_byte (4))
561 char *var, *vallab, *value;
563 dump_value_modifier(stream);
565 vallab = get_string ();
567 if (!match_byte(1) && !match_byte(2))
568 match_byte_assert (3);
569 value = get_string ();
570 fprintf (stream, "<string-datum value=\"%s\" format=\"%s%d.%d\"",
571 value, format_to_string(format >> 16), (format >> 8) & 0xff, format & 0xff);
573 fprintf (stream, " variable=\"%s\"", var);
575 fprintf (stream, " label=\"%s\"/>\n", vallab);
576 fprintf (stream, "/>\n");
578 else if (match_byte (5))
580 dump_value_modifier(stream);
581 char *name = get_string ();
582 char *label = get_string ();
583 fprintf (stream, "<variable name=\"%s\"", name);
585 fprintf (stream, " label=\"%s\"", label);
586 fprintf (stream, "/>\n");
587 if (!match_byte(1) && !match_byte(2))
588 match_byte_assert(3);
592 dump_value_modifier(stream);
594 char *base = get_string();
596 fprintf (stream, "<template format=\"%s\">\n", base);
597 for (int i = 0; i < x; i++)
604 for (int j = 0; j <= level + 1; j++)
605 fprintf (stream, " ");
606 fprintf (stream, "<substitution index=\"%d\">\n", i + 1);
607 for (int j = 0; j < y; j++)
608 dump_value (stream, level + 2);
609 for (int j = 0; j <= level + 1; j++)
610 fprintf (stream, " ");
611 fprintf (stream, "</substitution>\n");
613 for (int j = 0; j <= level; j++)
614 fprintf (stream, " ");
615 fprintf (stream, "</template>\n");
620 compare_int(const void *a_, const void *b_)
624 return *a < *b ? -1 : *a > *b;
628 check_permutation(int *a, int n, const char *name)
631 memcpy(b, a, n * sizeof *a);
632 qsort(b, n, sizeof *b, compare_int);
633 for (int i = 0; i < n; i++)
636 fprintf(stderr, "bad %s permutation:", name);
637 for (int i = 0; i < n; i++)
638 fprintf(stderr, " %d", a[i]);
645 dump_category(FILE *stream, int level, int **indexes, int *allocated_indexes,
648 for (int i = 0; i <= level; i++)
649 fprintf (stream, " ");
650 printf ("<category>\n");
651 dump_value (stream, level + 1);
653 bool merge = get_bool();
654 match_byte_assert (0);
655 int unindexed = get_bool();
660 match_u32_assert (2);
662 int indx = get_u32();
663 int n_categories = get_u32();
668 for (int i = 0; i <= level + 1; i++)
669 fprintf (stream, " ");
670 fprintf (stream, "<merge/>\n");
679 assert (n_categories == 0);
680 if (*n_indexes >= *allocated_indexes)
682 *allocated_indexes = *allocated_indexes ? 2 * *allocated_indexes : 16;
683 *indexes = realloc(*indexes, *allocated_indexes * sizeof **indexes);
685 (*indexes)[(*n_indexes)++] = indx;
688 if (n_categories == 0)
690 for (int i = 0; i <= level + 1; i++)
691 fprintf (stream, " ");
692 fprintf (stream, "<category-index>%d</category-index>\n", indx);
694 for (int i = 0; i < n_categories; i++)
695 dump_category (stream, level + 1, indexes, allocated_indexes, n_indexes);
696 for (int i = 0; i <= level; i++)
697 fprintf (stream, " ");
698 printf ("</category>\n");
706 printf ("<dimension index=\"%d\">\n", indx);
707 dump_value (stdout, 0);
709 /* This byte is usually 0 but many other values have been spotted.
710 No visible effect. */
713 /* This byte can cause data to be oddly replicated. */
714 if (!match_byte(0) && !match_byte(1))
715 match_byte_assert(2);
720 bool show_dim_label = get_bool();
722 printf(" <show-dim-label/>\n");
724 bool hide_all_labels = get_bool();
726 printf(" <hide-all-labels/>\n");
728 match_byte_assert(1);
729 if (!match_u32(UINT32_MAX))
730 match_u32_assert(indx);
732 n_categories = get_u32();
736 int allocated_indexes = 0;
737 for (int i = 0; i < n_categories; i++)
738 dump_category (stdout, 0, &indexes, &allocated_indexes, &n_indexes);
739 check_permutation(indexes, n_indexes, "categories");
741 fprintf (stdout, "</dimension>\n");
746 static int dim_n_cats[64];
747 #define MAX_DIMS (sizeof dim_n_cats / sizeof *dim_n_cats)
753 assert(n_dims < MAX_DIMS);
754 for (int i = 0; i < n_dims; i++)
755 dim_n_cats[i] = dump_dim (i);
761 /* The first three numbers add to the number of dimensions. */
764 int c = n_dims - l - r;
767 /* The next n_dims numbers are a permutation of the dimension numbers. */
769 for (int i = 0; i < n_dims; i++)
774 const char *name = i < l ? "layer" : i < l + r ? "row" : "column";
775 printf ("<%s dimension=\"%d\"/>\n", name, dim);
777 check_permutation(a, n_dims, "dimensions");
781 for (int i = 0; i < x; i++)
783 unsigned int indx = get_u32();
784 printf (" <datum index=\"%d\" coords=", indx);
786 int coords[MAX_DIMS];
787 for (int i = n_dims; i-- > 0; )
789 coords[i] = indx % dim_n_cats[i];
790 indx /= dim_n_cats[i];
792 for (int i = 0; i < n_dims; i++)
793 printf("%c%d", i ? ',' : '"', coords[i]);
799 dump_value(stdout, 1);
800 fprintf (stdout, " </datum>\n");
802 printf ("</data>\n");
808 printf ("<title-local>\n");
809 dump_value(stdout, 0);
811 printf ("</title-local>\n");
813 printf ("<subtype>\n");
814 dump_value(stdout, 0);
816 printf ("</subtype>\n");
818 match_byte_assert(0x31);
820 printf ("<title-c>\n");
821 dump_value(stdout, 0);
823 printf ("</title-c>\n");
825 if (match_byte(0x31))
827 printf ("<user-caption>\n");
828 dump_value(stdout, 0);
829 printf ("</user-caption>\n");
832 match_byte_assert(0x58);
833 if (match_byte(0x31))
835 printf ("<caption>\n");
836 dump_value(stdout, 0);
837 printf ("</caption>\n");
840 match_byte_assert(0x58);
842 int n_footnotes = get_u32();
843 for (int i = 0; i < n_footnotes; i++)
845 printf ("<footnote index=\"%d\">\n", i);
846 dump_value(stdout, 0);
847 /* Custom footnote marker string. */
848 if (match_byte (0x31))
849 dump_value(stdout, 0);
851 match_byte_assert (0x58);
855 /* Appears to be the number of references to a footnote. */
856 printf (" <references n=\"%d\"/>\n", n);
860 /* The user deleted the footnote references. */
861 printf (" <deleted/>\n");
865 printf ("</footnote>\n");
873 for (int i = 1; i <= 8; i++)
875 printf ("<style index=\"%d\"", i);
876 match_byte_assert(i);
877 match_byte_assert(0x31);
878 printf(" font=\"%s\"", get_string());
880 printf(" size=\"%gpt\"", get_float());
882 int style = get_u32();
884 printf(" bold=\"true\"");
886 printf(" italic=\"true\"");
888 bool underline = data[pos++];
890 printf(" underline=\"true\"");
892 int halign = get_u32();
893 printf(" halign=%d", halign);
895 int valign = get_u32();
896 printf(" valign=%d", valign);
898 printf (" fgcolor=\"%s\"", get_string());
899 printf (" bgcolor=\"%s\"", get_string());
902 match_byte_assert(1);
904 char *alt_fgcolor = get_string();
906 printf (" altfg=\"%s\"", alt_fgcolor);
907 char *alt_bgcolor = get_string();
909 printf (" altbg=\"%s\"", alt_bgcolor);
913 printf(" margins=\"");
914 for (int i = 0; i < 4; i++)
918 printf("%d", get_u32());
927 int x1_end = pos + x1;
928 printf("<borders>\n");
929 match_be32_assert(1);
930 int n_borders = get_be32();
931 for (int i = 0; i < n_borders; i++)
933 int type = get_be32();
934 int stroke = get_be32();
935 int color = get_be32();
936 printf(" <border type=\"%d\" stroke=\"%s\" color=\"#%06x\"/>\n",
938 (stroke == 0 ? "none"
939 : stroke == 1 ? "solid"
940 : stroke == 2 ? "dashed"
941 : stroke == 3 ? "thick"
942 : stroke == 4 ? "thin"
943 : stroke == 5 ? "double"
947 bool grid = get_byte();
949 printf(" <grid show=\"%s\"/>\n", grid ? "yes" : "no");
950 printf("</borders>\n");
951 assert(pos == x1_end);
953 int skip = get_u32();
954 assert(skip == 18 || skip == 25);
958 int x3_end = pos + x3;
961 match_be32_assert(1);
963 printf("<settings layer=\"%d\"", get_be32());
965 printf(" skipempty=\"false\"");
967 printf(" showdimensionincorner=\"false\"");
969 printf(" markers=\"numeric\"");
971 printf(" footnoteposition=\"subscript\"");
973 int nbytes = get_be32();
974 int end = pos + nbytes;
976 while (pos + 4 <= end)
977 printf(" %d", get_be32());
981 char *notes = get_string_be();
983 printf(" notes=\"%s\"", notes);
984 char *look = get_string_be();
986 printf(" look=\"%s\"", look);
991 /* Manual column widths, if present. */
992 int count = get_u32();
995 printf("<columnwidths>");
996 for (int i = 0; i < count; i++)
1000 printf("%d", get_u32());
1002 printf("</columnwidths>\n");
1005 const char *locale = get_string();
1006 printf ("<locale>%s</locale>\n", locale);
1008 printf ("<layer>%d</layer>\n", get_u32());
1010 match_byte_assert(1);
1011 match_byte_assert(0);
1013 match_byte_assert(1);
1014 printf("<epoch>%d</epoch>\n", get_u32());
1016 int decimal = data[pos];
1017 int grouping = data[pos + 1];
1018 if (match_byte('.'))
1020 if (!match_byte(',') && !match_byte('\''))
1021 match_byte_assert(' ');
1025 match_byte_assert(',');
1026 if (!match_byte('.') && !match_byte(' ') && !match_byte(','))
1027 match_byte_assert(0);
1029 printf("<format decimal=\"%c\"", decimal);
1031 printf(" grouping=\"%c\"", grouping);
1035 for (int i = 0; i < 5; i++)
1036 printf("<CC%c>%s</CC%c>\n", 'A' + i, get_string(), 'A' + i);
1039 match_u32_assert(0);
1041 /* The last chunk is an outer envelope that contains two inner envelopes.
1042 The second inner envelope has some interesting data like the encoding and
1044 int outer_end = get_end();
1047 /* First inner envelope: byte*33 int[n] int*[n]. */
1048 int inner_len = get_u32();
1049 int inner_end = pos + inner_len;
1050 int array_start = pos + 33;
1051 match_byte_assert(0);
1052 pos++; /* 0, 1, 10 seen. */
1055 /* 0=en 1=de 2=es 3=it 5=ko 6=pl 8=zh-tw 10=pt_BR 11=fr */
1056 printf("lang=%d ", get_byte());
1058 printf ("variable_mode=%d\n", get_byte());
1059 printf ("value_mode=%d\n", get_byte());
1061 match_u64_assert(UINT64_MAX);
1062 match_u32_assert(0);
1063 match_u32_assert(0);
1064 match_u32_assert(0);
1065 match_u32_assert(0);
1066 match_byte_assert(0);
1068 match_byte_assert(1);
1071 assert(get_end() == inner_end);
1072 printf("<heights>");
1073 int n_heights = get_u32();
1074 for (int i = 0; i < n_heights; i++)
1078 printf("%d", get_u32());
1080 printf("</heights>\n");
1082 int n_style_map = get_u32();
1083 for (int i = 0; i < n_style_map; i++)
1085 uint64_t cell = get_u64();
1086 int style = get_u16();
1087 printf("<style-map cell=\"%llu\" style=\"%d\"/>\n", cell, style);
1090 int n_styles = get_u32();
1091 for (int i = 0; i < n_styles; i++)
1093 printf("<cell-style index=\"%d\"", i);
1095 dump_style2(stdout);
1100 assert(pos == inner_end);
1102 /* Second inner envelope. */
1103 assert(get_end() == outer_end);
1105 match_byte_assert(1);
1106 match_byte_assert(0);
1107 if (!match_byte(3) && !match_byte(4))
1108 match_byte_assert(5);
1109 match_byte_assert(0);
1110 match_byte_assert(0);
1111 match_byte_assert(0);
1113 printf("<command>%s</command>\n", get_string());
1114 printf("<command-local>%s</command-local>\n", get_string());
1115 printf("<language>%s</language>\n", get_string());
1116 printf("<charset>%s</charset>\n", get_string());
1117 printf("<locale>%s</locale>\n", get_string());
1120 match_byte_assert(0);
1124 printf("<epoch2>%d</epoch2>\n", get_u32());
1126 if (match_byte('.'))
1128 if (!match_byte(',') && !match_byte('\''))
1129 match_byte_assert(' ');
1133 match_byte_assert(',');
1134 if (!match_byte('.') && !match_byte(' ') && !match_byte(','))
1135 match_byte_assert(0);
1138 printf ("small: %g\n", get_double());
1140 match_byte_assert(1);
1141 if (outer_end - pos > 6)
1143 /* There might be a pair of strings representing a dataset and
1144 datafile name, or there might be a set of custom currency strings.
1145 The custom currency strings start with a pair of integers, so we
1146 can distinguish these from a string by checking for a null byte; a
1147 small 32-bit integer will always contain a null and a text string
1150 int len = get_u32();
1151 bool has_dataset = !memchr(&data[pos], '\0', len);
1156 printf("<dataset>%s</dataset>\n", get_string());
1157 printf("<datafile>%s</datafile>\n", get_string());
1159 match_u32_assert(0);
1161 time_t date = get_u32();
1162 struct tm tm = *localtime(&date);
1164 strftime(s, sizeof s, "%a, %d %b %Y %H:%M:%S %z", &tm);
1165 printf("<date>%s</date>\n", s);
1167 match_u32_assert(0);
1173 for (int i = 0; i < 5; i++)
1174 printf("<CC%c>%s</CC%c>\n", 'A' + i, get_string(), 'A' + i);
1177 match_u32_assert(0);
1179 match_byte_assert('.');
1182 if (pos < outer_end)
1185 match_u32_assert(0);
1187 assert(pos == outer_end);
1191 else if (outer_end != pos)
1194 printf("<command>%s</command>\n", get_string());
1195 printf("<command-local>%s</command-local>\n", get_string());
1196 printf("<language>%s</command>\n", get_string());
1197 printf("<charset>%s</charset>\n", get_string());
1198 printf("<locale>%s</locale>\n", get_string());
1200 match_byte_assert(0);
1204 printf("<epoch2>%d</epoch2>\n", get_u32());
1205 int decimal = data[pos];
1206 int grouping = data[pos + 1];
1207 if (match_byte('.'))
1209 if (!match_byte(',') && !match_byte('\''))
1210 match_byte_assert(' ');
1214 match_byte_assert(',');
1215 if (!match_byte('.') && !match_byte(' ') && !match_byte(','))
1216 match_byte_assert(0);
1218 printf("<format decimal=\"%c\"", decimal);
1220 printf(" grouping=\"%c\"", grouping);
1224 for (int i = 0; i < 5; i++)
1225 printf("<CC%c>%s</CC%c>\n", 'A' + i, get_string(), 'A' + i);
1228 match_u32_assert(0);
1230 match_byte_assert('.');
1233 assert(pos == outer_end);
1239 main(int argc, char *argv[])
1243 fprintf (stderr, "usage: %s FILE.bin", argv[0]);
1248 int fd = open(filename, O_RDONLY);
1251 fprintf (stderr, "%s: open failed (%s)", filename, strerror (errno));
1268 if (read(fd, data, n) != n)
1276 match_byte_assert(1);
1277 match_byte_assert(0);
1279 version = get_u32();
1280 assert(version == 1 || version == 3);
1282 match_byte_assert(1);
1283 bool number_footnotes = get_bool();
1284 printf("<footnote markers=\"%s\"/>\n",
1285 number_footnotes ? "number" : "letter");
1286 bool rotate_inner_column_labels = get_bool();
1287 bool rotate_outer_row_labels = get_bool();
1288 printf("x=%d\n", get_bool());
1289 printf("<rotate-labels inner-column=\"%s\" outer-row=\"%s\"/>",
1290 rotate_inner_column_labels ? "yes" : "no",
1291 rotate_outer_row_labels ? "yes" : "no");
1292 //fprintf(stderr, "option-number=%d\n", get_u32());
1295 int min_col_width = get_u32();
1296 int max_col_width = get_u32();
1297 int min_row_width = get_u32();
1298 int max_row_width = get_u32();
1299 printf("<label-width min-col=\"%d\" max-col=\"%d\" min-row=\"%d\" "
1300 "max-row=\"%d\"/>\n",
1301 min_col_width, max_col_width,
1302 min_row_width, max_row_width);
1305 printf("<tableid>%lld</tableid>", get_u64());
1314 fprintf (stderr, "%x / %x\n", pos, n);