14 #include "u8-mbtouc.h"
16 static const char *filename;
27 #define STR(x) XSTR(x)
28 #define WHERE __FILE__":" STR(__LINE__)
30 static void __attribute__((unused))
31 hex_dump(FILE *stream, int ofs, int n);
43 memcpy(&x, &data[pos], 4);
48 static unsigned long long int
52 memcpy(&x, &data[pos], 8);
61 x = (data[pos] << 24) | (data[pos + 1] << 16) | (data[pos + 2] << 8) | data[pos + 3];
70 memcpy(&x, &data[pos], 2);
79 memcpy(&x, &data[pos], 8);
84 static double __attribute__((unused))
88 memcpy(&x, &data[pos], 4);
103 match_u16(uint16_t x)
112 match_u32_assert(uint32_t x, const char *where)
114 unsigned int y = get_u32();
117 fprintf(stderr, "%s: 0x%x: expected i%u, got i%u: ", where, pos - 4, x, y);
118 hex_dump(stderr, pos - 4, 64);
122 #define match_u32_assert(x) match_u32_assert(x, WHERE)
125 match_u16_assert(uint16_t x, const char *where)
127 unsigned int y = get_u16();
130 fprintf(stderr, "%s: 0x%x: expected u16:%u, got u16:%u: ", where, pos - 2, x, y);
131 hex_dump(stderr, pos - 2, 64);
135 #define match_u16_assert(x) match_u16_assert(x, WHERE)
137 static bool __attribute__((unused))
138 match_u64(uint64_t x)
146 static void __attribute__((unused))
147 match_u64_assert(uint64_t x, const char *where)
149 unsigned long long int y = get_u64();
152 fprintf(stderr, "%s: 0x%x: expected u64:%lu, got u64:%llu\n", where, pos - 8, x, y);
156 #define match_u64_assert(x) match_u64_assert(x, WHERE)
158 static bool __attribute__((unused))
159 match_be32(uint32_t x)
168 match_be32_assert(uint32_t x, const char *where)
170 unsigned int y = get_be32();
173 fprintf(stderr, "%s: 0x%x: expected be%u, got be%u\n", where, pos - 4, x, y);
177 #define match_be32_assert(x) match_be32_assert(x, WHERE)
180 match_byte(uint8_t b)
182 if (pos < n && data[pos] == b)
192 match_byte_assert(uint8_t b, const char *where)
196 fprintf(stderr, "%s: 0x%x: expected %02x, got %02x: ", where, pos, b, data[pos]);
197 hex_dump(stderr, pos, 64);
201 #define match_byte_assert(b) match_byte_assert(b, WHERE)
204 match_bytes(int start, const int *bytes, size_t n_bytes)
206 for (size_t i = 0; i < n_bytes; i++)
207 if (bytes[i] >= 0 && data[start + i] != bytes[i])
213 xmemdup0(const void *p, size_t n)
215 char *s = malloc(n + 1);
226 match_byte_assert(1);
230 static bool __attribute__((unused))
233 return (p >= ' ' && p < 127) || p == '\r' || p == '\n' || p == '\t';
237 count_zeros(const uint8_t *p)
245 static bool __attribute__((unused))
246 all_utf8(const char *p_, size_t len)
248 const uint8_t *p = (const uint8_t *) p_;
249 for (size_t ofs = 0, mblen; ofs < len; ofs += mblen)
253 mblen = u8_mbtouc (&uc, p + ofs, len - ofs);
254 if ((uc < 32 && uc != '\n') || uc == 127 || uc == 0xfffd)
261 pull_string(int len, const char *where)
264 for (int i = 0; i < len - 1; i++)
267 fprintf(stderr, "%s: %d-byte string starting at 0x%x has null byte "
268 "at offset %d: ", where, len, pos, i);
269 hex_dump(stderr, pos, len + 64);
273 char *s = xmemdup0(&data[pos], len);
279 get_string2(const char *where)
281 return pull_string(get_u16(), where);
283 #define get_string2() get_string2(WHERE)
286 get_string1(const char *where)
288 int len = data[pos++];
289 return len == 0xff ? (get_string2)(where) : pull_string(len, where);
291 #define get_string1() get_string1(WHERE)
294 match_string1_assert(const char *exp, const char *where)
297 char *act = (get_string1)(where);
298 if (strcmp(act, exp))
300 fprintf(stderr, "%s: 0x%x: expected \"%s\", got \"%s\"\n",
301 where, start, exp, act);
305 #define match_string1_assert(x) match_string1_assert(x, WHERE)
308 match_string2_assert(const char *exp, const char *where)
311 char *act = (get_string2)(where);
312 if (strcmp(act, exp))
314 fprintf(stderr, "%s: 0x%x: expected \"%s\", got \"%s\"\n",
315 where, start, exp, act);
319 #define match_string2_assert(x) match_string2_assert(x, WHERE)
322 get_string4(const char *where)
324 assert(data[pos + 3] == 0);
325 return pull_string(get_u32(), where);
327 #define get_string4() get_string4(WHERE)
330 get_padded_string(int len)
332 char *s = xmemdup0(&data[pos], len);
338 get_string_be(const char *where)
341 /*data[pos + 1] == 0 && data[pos + 2] == 0 && data[pos + 3] == 0*/
342 /*&& all_ascii(&data[pos + 4], data[pos])*/)
344 int len = data[pos + 2] * 256 + data[pos + 3];
345 char *s = malloc(len + 1);
347 memcpy(s, &data[pos + 4], len);
354 fprintf(stderr, "%s: 0x%x: expected string\n", where, pos);
358 #define get_string_be() get_string_be(WHERE)
367 static void __attribute__((unused))
368 hex_dump(FILE *stream, int ofs, int n)
371 for (int i = 0; i < n; i++)
373 int c = data[ofs + i];
374 n_ascii += is_ascii(c);
375 fprintf(stream, " %02x", c);
380 for (int i = 0; i < n; i++)
382 int c = data[ofs + i];
383 putc(c >= 32 && c < 127 ? c : '.', stream);
389 static void __attribute__((unused))
390 char_dump(FILE *stream, int ofs, int n)
392 for (int i = 0; i < n; i++)
394 int c = data[ofs + i];
395 putc(c >= 32 && c < 127 ? c : '.', stream);
402 compare_int(const void *a_, const void *b_)
406 return *a < *b ? -1 : *a > *b;
411 format_name (int format, char *buf)
416 case 2: return "AHEX";
417 case 3: return "COMMA";
418 case 4: return "DOLLAR";
419 case 5: case 40: return "F";
421 case 7: return "PIBHEX";
423 case 9: return "PIB";
424 case 10: return "PK";
425 case 11: return "RB";
426 case 12: return "RBHEX";
430 case 20: return "DATE";
431 case 21: return "TIME";
432 case 22: return "DATETIME";
433 case 23: return "ADATE";
434 case 24: return "JDATE";
435 case 25: return "DTIME";
436 case 26: return "WKDAY";
437 case 27: return "MONTH";
438 case 28: return "MOYR";
439 case 29: return "QYR";
440 case 30: return "WKYR";
441 case 31: return "PCT";
442 case 32: return "DOT";
443 case 33: return "CCA";
444 case 34: return "CCB";
445 case 35: return "CCC";
446 case 36: return "CCD";
447 case 37: return "CCE";
448 case 38: return "EDATE";
449 case 39: return "SDATE";
450 default: sprintf(buf, "(%d)", format); return buf;
459 int fmt = data[pos++];
461 printf ("%s%d.%d", format_name(fmt, buf), w, d);
465 parse_heading(const char *name)
467 match_u16_assert(0xffff);
469 match_string2_assert(name);
470 printf("%#x: %s\n", pos, name);
474 match_zeros_assert(int count, const char *where)
476 for (int i = 0; i < count; i++)
480 "%s: %#x: expected %d zeros here but offset %d is %#"PRIx8": ",
481 where, pos, count, i, data[pos + i]);
482 hex_dump (stderr, pos, 64);
487 #define match_zeros_assert(count) match_zeros_assert(count, WHERE)
490 put_safe(const char *s)
498 else if (*s < 0x20 || *s > 0x7e)
499 printf ("\\x%02"PRIx8, (uint8_t) *s);
506 static void parse_flexible(void);
510 parse_DspString(void)
512 printf("%#x: DspString#%d(", pos, count++);
515 printf("%f, \"", get_double());
516 printf("%s\")\n", get_string1());
520 match_byte_assert(1);
523 match_byte_assert(0);
524 match_byte_assert(1);
525 put_safe(get_string1());
532 match_DspString(void)
534 match_byte_assert(5);
535 match_byte_assert(0x80);
540 parse_DspSimpleText(void)
542 match_byte_assert(0);
545 match_zeros_assert(3);
546 if (!match_byte(0x10))
547 match_byte_assert(0);
548 match_zeros_assert(4);
550 /* Followed by DspString or DspNumber. */
554 match_DspSimpleText(void)
556 match_byte_assert(3);
557 match_byte_assert(0x80);
558 parse_DspSimpleText();
562 parse_weirdness(void)
564 match_byte_assert(1);
566 match_zeros_assert(12);
567 pos++; /* 90 or BC */
569 match_byte_assert(1);
570 match_zeros_assert(5);
572 match_zeros_assert(3);
573 puts(get_padded_string(32));
577 parse_NavTreeViewItem(void)
580 match_zeros_assert(1);
581 if (!match_byte(0) && !match_byte(7) && !match_byte(2) && !match_byte(0xc))
582 match_byte_assert(8);
583 match_zeros_assert(3);
585 match_byte_assert(0);
586 match_byte_assert(1);
587 match_byte_assert(0);
590 match_byte_assert(0);
592 match_byte_assert(0);
593 match_zeros_assert(5);
595 match_byte_assert(1);
596 match_zeros_assert(5);
603 match_byte_assert(0);
605 match_zeros_assert(11);
606 match_byte_assert(1);
607 match_zeros_assert(3);
609 match_byte_assert(0);
612 match_zeros_assert(2);
614 match_u32_assert(11000);
617 match_u32_assert(11000);
618 match_u32_assert(8500);
623 match_byte_assert(1);
628 get_string4(); /* page title */
629 match_byte_assert(1);
630 match_byte_assert(1);
631 match_zeros_assert(3);
632 get_string4(); /* page number */
633 match_byte_assert(0);
641 match_zeros_assert(3);
643 //fprintf(stderr, "%#x ", pos - 16);
644 hex_dump(stdout, start_pos, pos - start_pos);
648 match_NavTreeViewItem(void)
650 match_byte_assert(7);
651 match_byte_assert(0x80);
652 parse_NavTreeViewItem();
656 parse_DspNumber(void)
658 printf("%#x: DspNumber#%d(", pos, count++);
659 match_byte_assert(1);
661 match_byte_assert(0x80);
663 printf (" %f", get_double());
664 printf (" \"%s\")\n", get_string1());
668 match_DspNumber(void)
670 if (!match_byte(0x18) && !match_byte(0x19))
671 match_byte_assert(0x2a);
672 match_byte_assert(0x80);
679 match_byte_assert(0);
685 match_byte_assert(0x27);
686 match_byte_assert(0x80);
693 match_byte_assert(2);
700 match_byte_assert(9);
701 match_byte_assert(0x80);
706 parse_category(int level, int j, int *n_leaves)
708 for (size_t k = 0; k < level; k++)
710 get_u16(); match_byte_assert(0);
711 get_u16(); match_byte_assert(0);
712 int leaf_idx = get_u32();
713 printf("%d ", leaf_idx);
715 if (get_u16() == 0xffff)
716 match_u16_assert(0xffff);
718 match_u16_assert(0x0e74);
719 match_byte_assert(0);
720 match_DspSimpleText();
721 if (match_u16(0x8018))
723 printf("18 80(%02x %02x %02x) ",
724 data[pos], data[pos + 1], data[pos + 2]);
729 int n_subcategories = get_u32();
731 assert (leaf_idx == 0);
734 assert (leaf_idx == *n_leaves);
737 for (int k = 0; k < n_subcategories; k++)
738 parse_category(level + 1, k, n_leaves);
742 parse_dimension(int i)
744 printf ("%#x: dimension %d\n", pos, i);
747 match_zeros_assert(5);
752 match_zeros_assert(6);
754 int n_units16 = get_u32();
756 for (int j = 0; j < n_units16; j++)
759 match_byte_assert(0);
761 int n_units32 = get_u32();
763 for (int j = 0; j < n_units32; j++)
766 get_u16(); match_byte_assert(0);
768 get_u16(); match_byte_assert(0);
769 get_u16(); match_byte_assert(0);
775 if (!match_u16(0xffff))
776 match_u16_assert(0x0e74);
777 match_byte_assert(0);
778 match_DspSimpleText();
782 int n_categories = get_u32();
783 for (int j = 0; j < n_categories; j++)
784 parse_category(1, j, &n_leaves);
788 parse_PMModelItemInfo(void)
790 for (int i = 0; i < n_dims; i++)
792 printf("%#x: end of model\n", pos);
797 match_PMModelItemInfo(void)
799 match_byte_assert(0x54);
800 match_byte_assert(0x80);
801 parse_PMModelItemInfo();
807 match_PMPivotItemTree(void)
809 match_byte_assert(0x52);
810 match_byte_assert(0x80);
811 match_byte_assert(0);
812 match_PMModelItemInfo();
818 match_byte_assert(2);
819 match_zeros_assert(24);
820 match_byte_assert(1);
821 match_zeros_assert(3);
823 match_byte_assert(0);
824 match_zeros_assert(3);
829 parse_NavOleItem(void)
831 match_byte_assert(0);
832 match_byte_assert(1);
833 match_zeros_assert(2);
835 match_zeros_assert(9);
836 match_byte_assert(1);
837 match_zeros_assert(10);
838 match_byte_assert(1);
839 match_zeros_assert(5);
841 match_byte_assert(1);
843 match_byte_assert(0);
845 match_zeros_assert(11);
846 match_byte_assert(1);
847 match_zeros_assert(3);
849 match_byte_assert(0);
853 match_NavOleItem(void)
854 { /* 0e 80 or 12 80*/
855 if (!match_byte(0x12))
856 match_byte_assert(0x0e);
857 match_byte_assert(0x80);
864 match_byte_assert(2);
865 match_zeros_assert(8);
866 match_u32_assert(24);
870 match_byte_assert(4);
871 match_zeros_assert(2);
881 match_byte_assert(2);
882 match_zeros_assert(8);
883 match_u32_assert(24);
884 if (!match_u32(0) && !match_u32(0xffffff4b))
885 match_u32_assert(-40);
893 parse_PTPivotController(void)
895 match_byte_assert(2);
897 match_u32_assert(100);
898 match_u32_assert(100);
899 match_u32_assert(100);
900 match_u32_assert(100);
904 parse_PVPivotView(void)
906 match_byte_assert(5);
907 printf ("PVPivotView(%d)\n", get_u32());
911 parse_NDimensional__DspCell(void)
913 match_byte_assert(0);
915 printf ("NDimensional__DspCell(n_dims=%d)\n", n_dims);
919 parse_IndexedCollection(void)
921 printf("IndexedCollection");
922 for (size_t i = 0; ; i++)
924 match_byte_assert(0);
925 printf("%c%d", i ? 'x' : '(', get_u32());
927 if (!match_u16(0x8011))
934 parse_PTTableLook(void)
936 match_byte_assert(2);
937 match_byte_assert(2);
938 match_zeros_assert(7);
939 match_u32_assert(0x36);
940 match_u32_assert(0x12);
944 parse_PVViewDimension(void)
946 while (data[pos + 1] != 0x80
947 && (data[pos] != 0xff || data[pos + 1] != 0xff))
955 parse_PVSeparatorStyle(void)
957 match_byte_assert(0);
958 match_byte_assert(1);
959 match_zeros_assert(15);
961 match_byte_assert(0x80);
962 match_byte_assert(0);
964 match_byte_assert(1);
965 match_zeros_assert(9);
966 while (data[pos + 1] != 0x80
967 && (data[pos] != 0xff || data[pos + 1] != 0xff))
975 parse_PVCellStyle(void)
977 match_byte_assert(0);
978 match_byte_assert(1);
979 match_zeros_assert(5);
980 match_u32_assert(0xffffff);
981 match_zeros_assert(2);
985 skip_item(const char *name)
988 printf("%#x: skipping %s bytes...", pos, name);
989 while (data[pos + 1] != 0x80
990 && !(data[pos] == 0xff && data[pos + 1] == 0xff
991 && data[pos + 2] == 0 && data[pos + 3] == 0))
996 printf("until %#x:", pos);
997 hex_dump(stdout, start_pos, pos - start_pos);
1001 parse_flexible(void)
1004 if (match_u16(0xffff))
1006 match_u16_assert(0);
1007 char *heading = get_string2();
1008 printf("%#x: %s\n", pos, heading);
1009 if (!strcmp(heading, "NavRoot"))
1011 match_byte_assert(2);
1012 match_zeros_assert(32);
1014 else if (!strcmp(heading, "NavPivot"))
1016 hex_dump(stdout, pos, 021);
1019 else if (!strcmp(heading, "DspCell"))
1021 else if (!strcmp(heading, "DspSimpleText"))
1022 parse_DspSimpleText();
1023 else if (!strcmp(heading, "DspNumber"))
1025 else if (!strcmp(heading, "DspString"))
1027 else if (!strcmp(heading, "NavHead"))
1029 else if (!strcmp(heading, "NavTreeViewItem"))
1032 parse_NavTreeViewItem();
1036 else if (!strcmp(heading, "IndexedCollection"))
1037 parse_IndexedCollection();
1038 else if (!strcmp(heading, "NavOleItem"))
1040 else if (!strcmp(heading, "NavTitle"))
1042 else if (!strcmp(heading, "NavNote"))
1044 else if (!strcmp(heading, "PTPivotController"))
1045 parse_PTPivotController();
1046 else if (!strcmp(heading, "PVPivotView"))
1047 parse_PVPivotView();
1048 else if (!strcmp(heading, "PMPivotModel"))
1049 match_byte_assert(3);
1050 else if (!strcmp(heading, "NDimensional__DspCell"))
1051 parse_NDimensional__DspCell();
1052 else if (!strcmp(heading, "PMPivotItemTree"))
1053 match_byte_assert(0);
1054 else if (!strcmp(heading, "PMModelItemInfo"))
1055 parse_PMModelItemInfo();
1056 else if (!strcmp(heading, "AbstractTreeBranch"))
1057 match_byte_assert(0);
1058 else if (!strcmp(heading, "PTTableLook"))
1059 parse_PTTableLook();
1060 else if (!strcmp(heading, "PVViewDimension"))
1061 parse_PVViewDimension();
1062 else if (!strcmp(heading, "PVSeparatorStyle"))
1063 parse_PVSeparatorStyle();
1064 else if (!strcmp(heading, "PVCellStyle"))
1065 parse_PVCellStyle();
1066 else if (!strcmp(heading, "PVTextStyle"))
1070 fprintf(stderr, "don't know %s at offset 0x%x: ", heading, start);
1071 hex_dump(stderr, pos, 128);
1075 else if (data[pos + 1] == 0x80)
1077 if ((data[pos] == 0x2a || data[pos] == 0x18 || data[pos] == 0x19) && data[pos + 1] == 0x80)
1079 else if (data[pos] == 0x27 && data[pos + 1] == 0x80)
1081 else if (data[pos] == 0x5 && data[pos + 1] == 0x80)
1083 else if (data[pos] == 0x7 && data[pos + 1] == 0x80)
1084 match_NavTreeViewItem();
1085 else if (data[pos] == 0x3 && data[pos + 1] == 0x80)
1086 match_DspSimpleText();
1087 else if ((data[pos] == 0x3c || data[pos] == 0x39)
1088 && data[pos + 1] == 0x80)
1092 printf("%#x: %02x %02x ", pos, data[pos], data[pos + 1]);
1096 /* match_byte_assert(0x01);
1097 match_byte_assert(0x02);
1098 match_byte_assert(0x0d); */
1100 else if ((data[pos] == 0x15 || data[pos] == 0x14)
1101 && data[pos + 1] == 0x80)
1108 printf ("%02x 80(%f", data[pos - 2], get_double());
1109 printf (" \"%s\")\n", get_string1());
1112 match_byte_assert(0);
1114 if (!match_byte(2) && !match_byte(3))
1115 match_byte_assert(0);
1116 match_zeros_assert(3);
1118 match_byte_assert(0);
1119 match_byte_assert(1);
1120 match_zeros_assert(3);
1121 match_byte_assert(1);
1122 match_byte_assert(0);
1127 match_byte_assert(0);
1130 else if (data[pos] == 0x17)
1132 printf("%02x %02x(%02x %02x %02x)\n",
1133 data[pos], data[pos + 1],
1134 data[pos + 2], data[pos + 3], data[pos + 4]);
1137 else if (data[pos] == 0x9 && data[pos + 1] == 0x80)
1141 else if (data[pos] == 0xe || data[pos] == 0x12)
1143 else if (data[pos] == 0x11 || data[pos] == 0x13)
1145 int type = data[pos];
1147 match_byte_assert(0);
1154 int index = get_u32();
1155 printf("%02x 80(footnote %d)\n", type, index);
1158 printf("%02x 80(%d %d)\n", type, x, y);
1161 match_zeros_assert(13);
1163 else if (data[pos] == 0x29 ||
1164 data[pos] == 0x2b ||
1165 data[pos] == 0x2d ||
1166 data[pos] == 0x31 ||
1167 data[pos] == 0x32 ||
1168 data[pos] == 0x4a ||
1169 data[pos] == 0x4c ||
1170 data[pos] == 0x4f ||
1171 data[pos] == 0x4d ||
1172 data[pos] == 0x50 ||
1173 data[pos] == 0x36 ||
1174 data[pos] == 0x52 ||
1175 data[pos] == 0x53 ||
1176 data[pos] == 0x54 ||
1177 data[pos] == 0x55 ||
1178 data[pos] == 0x57 ||
1179 data[pos] == 0x56 ||
1180 data[pos] == 0x58 ||
1181 data[pos] == 0x5c ||
1182 data[pos] == 0x5b ||
1183 data[pos] == 0x5e ||
1184 data[pos] == 0x62 ||
1185 data[pos] == 0x64 ||
1186 data[pos] == 0x4e ||
1187 data[pos] == 0x51 ||
1188 data[pos] == 0x59 ||
1189 data[pos] == 0x5a ||
1190 data[pos] == 0x5d ||
1191 data[pos] == 0x66 ||
1192 data[pos] == 0x60 ||
1193 data[pos] == 0x68 ||
1194 data[pos] == 0x48 ||
1195 data[pos] == 0x6a ||
1199 match_byte_assert(0);
1201 else if (data[pos] == 0x2c ||
1202 data[pos] == 0x2e ||
1203 data[pos] == 0x30 ||
1204 data[pos] == 0x34 ||
1205 data[pos] == 0x3d ||
1206 data[pos] == 0x40 ||
1207 data[pos] == 0x3f ||
1208 data[pos] == 0x42 ||
1209 data[pos] == 0x43 ||
1210 data[pos] == 0x44 ||
1211 data[pos] == 0x49 ||
1212 data[pos] == 0x3e ||
1215 printf ("%#x: %02x %02x(%02x %02x %02x)\n",
1216 pos, data[pos], data[pos + 1],
1217 data[pos + 2], data[pos + 3], data[pos + 4]);
1223 fprintf (stderr, "%#x: unknown record", pos);
1224 hex_dump (stderr, pos, 64);
1228 else if (match_byte(0xa))
1231 match_byte_assert(0);
1232 if (match_u16(0x0e74))
1233 match_byte_assert(0);
1236 match_zeros_assert(4);
1239 match_zeros_assert (2);
1243 else if (match_byte(1))
1245 match_byte_assert(0);
1248 match_byte_assert(0);
1251 match_zeros_assert(2);
1253 if (match_byte(0x08))
1255 match_byte_assert(0);
1256 match_u16_assert(0x0e74);
1257 match_byte_assert(0);
1259 else if (match_byte(3))
1261 match_byte_assert(0);
1262 if (match_u16(0x0e74))
1263 match_byte_assert(0);
1266 match_zeros_assert(6);
1267 if (!match_byte(0xe) && !match_byte(0x11))
1268 match_byte_assert(0);
1269 match_byte_assert(0);
1270 if (!match_u16(0x0e74))
1271 match_u16_assert(0);
1272 match_byte_assert(0);
1277 match_byte_assert(0);
1278 match_byte_assert(1);
1279 match_zeros_assert(3);
1280 match_byte_assert(1);
1281 match_byte_assert(0);
1286 else if (match_u16(1))
1288 int start_pos = pos;
1289 char *title = get_string1();
1290 printf("%#x: title(\"%s\", ", start_pos, title);
1292 match_u32_assert(0);
1293 char *id = get_string1();
1294 printf("\"%s\")\n", id);
1295 match_byte_assert(0);
1297 match_u32_assert(3);
1298 match_u16_assert(1);
1300 else //if (match_u16(2) || match_u16(3) || match_u16(4) || match_u16(5) || match_u16(6) || match_u16(7) || match_u16(8) || match_u16(9))
1301 skip_item("unknown");
1303 else if (match_byte(7) || match_byte(4) || match_byte(5) || match_byte(6) || match_byte(8) || match_byte(9) || match_byte(0xb) || match_byte(0xc) || match_byte(0x15) || match_byte(0x16) || match_byte(0x17) || match_byte(0x18) || match_byte(0x1e) || match_byte(0x1a))
1306 match_byte_assert(0);
1307 if (!match_u16(0x0e74))
1308 match_byte_assert(0);
1309 match_byte_assert(0);
1311 else if (match_byte(2) || match_byte(3))
1313 match_byte_assert(0);
1314 if (!match_u16(0x0e74))
1316 match_zeros_assert(2);
1319 match_zeros_assert(3);
1321 match_zeros_assert(4);
1326 match_u16_assert(0x0e74);
1330 //match_byte_assert(0);
1332 else if (match_byte(0xd) || match_byte(0xe) || match_byte(0xf)
1333 || match_byte(0x11) || match_byte(0x12) || match_byte(0x13)
1334 || match_byte(0x14) || match_byte(0x1b))
1336 if (!match_byte(0x07))
1337 match_byte_assert(0);
1338 if (!match_u16(0x0e74))
1339 match_zeros_assert(11);
1341 match_byte_assert(0);
1343 else if (match_byte(0xe3) || match_byte(0xdb) || match_byte(0xd8) || match_byte(0xe9) || match_byte(0xf3))
1345 match_byte_assert(0x0e);
1346 match_byte_assert(0x74);
1347 match_byte_assert(0x0e);
1348 match_byte_assert(0);
1350 else if (match_byte(0x9d) || match_byte(0x9e) || match_byte(0x9c))
1351 match_u32_assert(0x000e741a);
1352 else if (match_byte(0x10))
1354 match_byte_assert(0);
1356 match_zeros_assert(10);
1359 match_u16_assert(0x0e74);
1360 match_byte_assert(0);
1363 else if (match_byte(0x39) || match_byte(0x3a) || match_byte(0x3b))
1364 match_u32_assert(0x000e7409);
1367 //fprintf (stderr, "bad record start at offset %x: ", pos);
1368 hex_dump (stderr, pos, 64);
1377 main(int argc, char *argv[])
1379 bool print_offsets = false;
1382 int c = getopt (argc, argv, "o");
1389 print_offsets = true;
1396 if (argc - optind != 1)
1398 fprintf (stderr, "usage: %s FILE.bin", argv[0]);
1402 const char *filename = argv[optind];
1403 int fd = open(filename, O_RDONLY);
1406 fprintf (stderr, "%s: open failed (%s)", filename, strerror (errno));
1417 data = malloc(n + 256);
1423 if (read(fd, data, n) != n)
1428 for (int i = 0; i < 256; i++)
1429 data[n + i] = i % 2 ? 0xaa : 0x55;
1432 setvbuf (stdout, NULL, _IONBF, 0);
1434 match_byte_assert(4);
1435 match_u32_assert(0);
1436 match_string1_assert("SPSS Output Document");
1437 match_u32_assert(1);
1438 match_byte_assert(0x63);
1452 parse_heading("NavRoot");
1453 match_byte_assert(2);
1454 match_zeros_assert(32);
1456 parse_heading("DspSimpleText");
1457 match_zeros_assert(10);
1459 parse_heading("DspString");
1462 parse_heading("NavTreeViewItem");
1463 match_byte_assert(0);
1465 match_u32_assert(0);
1466 match_byte_assert(2);
1467 match_byte_assert(0);
1468 match_byte_assert(1);
1469 match_zeros_assert(9);
1470 match_u32_assert(1);
1472 match_u32_assert(0);
1473 match_u32_assert(0x18);
1475 match_u32_assert(0xffffffd8);
1476 match_u32_assert(0xffffffde);
1477 match_u32_assert(0x18);
1479 match_u32_assert(0xffffffd8);
1480 match_u32_assert(0x28);
1481 match_u32_assert(0x28);
1485 match_zeros_assert(5);
1487 if (match_u32(8500))
1488 match_u32_assert(11000);
1491 match_u32_assert(11000);
1492 match_u32_assert(8500);
1497 match_byte_assert(1);
1502 get_string4(); /* page title */
1503 match_byte_assert(1);
1504 match_byte_assert(1);
1505 match_zeros_assert(3);
1506 get_string4(); /* page number */
1507 match_byte_assert(0);
1509 match_u16_assert(2);
1512 if (data[pos + 9] != 'L')
1514 parse_heading("NavLog");
1527 puts(get_padded_string(32));
1529 match_u32_assert(132);
1530 match_zeros_assert(8);
1531 match_u32_assert(1);
1532 printf ("0x%x\n", pos);
1534 match_byte_assert(0);
1536 parse_heading("NavHead");
1538 match_NavTreeViewItem();
1539 match_zeros_assert(3);
1541 parse_heading("NavTitle");
1543 match_DspSimpleText();
1545 match_NavTreeViewItem();
1547 match_byte_assert(1);
1548 match_byte_assert(1);
1549 match_u32_assert(-19);
1550 match_zeros_assert(12);
1551 match_byte_assert(0xbc);
1552 match_byte_assert(2);
1553 match_zeros_assert(9);
1554 match_byte_assert(0x22);
1555 puts(get_padded_string(32));
1556 match_u32_assert(80);
1557 match_zeros_assert(8);
1558 match_u32_assert(1);
1560 match_byte_assert(0);
1562 parse_heading("NavNote");
1563 match_byte_assert(2);
1564 match_zeros_assert(8);
1565 match_u32_assert(24);
1567 match_u32_assert(-40);
1569 match_u32_assert(2);
1570 match_u32_assert(1);
1571 match_DspSimpleText();
1573 match_NavTreeViewItem();
1574 match_byte_assert(1);
1576 parse_heading("PTPivotController");
1577 match_byte_assert(2);
1579 match_u32_assert(100);
1580 match_u32_assert(100);
1581 match_u32_assert(100);
1582 match_u32_assert(100);
1584 parse_heading("PVPivotView");
1585 match_u32_assert(5);
1586 match_byte_assert(0);
1588 parse_heading("PMPivotModel");
1589 match_byte_assert(3);
1591 parse_heading("NDimensional__DspCell");
1592 match_byte_assert(0);
1593 match_u32_assert(1);
1595 parse_heading("IndexedCollection");
1596 match_byte_assert(0);
1598 match_zeros_assert(3);
1599 match_byte_assert(1);
1600 match_byte_assert(0);
1601 match_zeros_assert(7);
1603 while (data[pos] != 1)
1614 match_byte_assert(1);
1615 match_byte_assert(0);
1616 puts(get_string1());
1618 match_u32_assert(2);
1619 puts(get_string1());
1621 match_byte_assert(0);
1622 match_byte_assert(1);
1623 match_byte_assert(0);
1624 match_byte_assert(0);
1625 match_byte_assert(0);
1626 match_byte_assert(1);
1627 match_byte_assert(0);
1631 parse_heading("PMPivotItemTree");
1632 match_byte_assert(0);
1634 parse_heading("AbstractTreeBranch");
1635 match_byte_assert(0);
1637 parse_heading("PMModelItemInfo");
1638 parse_PMModelItemInfo();
1639 match_DspSimpleText();
1642 match_u32_assert(7);
1643 match_PMPivotItemTree();
1645 match_u32_assert(0);
1646 match_PMPivotItemTree();
1648 match_u32_assert(0);
1649 match_PMPivotItemTree();
1651 match_u32_assert(6);
1652 match_PMPivotItemTree();
1654 match_u32_assert(0);
1655 match_PMPivotItemTree();
1657 match_u32_assert(0);
1658 match_PMPivotItemTree();
1660 match_u32_assert(0);
1661 match_PMPivotItemTree();
1663 match_u32_assert(0);
1664 match_PMPivotItemTree();
1666 match_u32_assert(0);
1667 match_PMPivotItemTree();
1669 match_u32_assert(0);
1670 match_PMPivotItemTree();
1672 match_u32_assert(2);
1673 match_PMPivotItemTree();
1675 match_u32_assert(0);
1676 match_PMPivotItemTree();
1678 match_u32_assert(0);
1679 match_PMPivotItemTree();
1681 match_u32_assert(0);
1682 match_PMPivotItemTree();
1684 match_u32_assert(0);
1685 match_PMPivotItemTree();
1687 match_u32_assert(2);
1688 match_PMPivotItemTree();
1690 match_u32_assert(0);
1691 match_PMPivotItemTree();
1693 match_u32_assert(0);
1697 while (data[pos] != 0xff || data[pos + 1] != 0xff)
1699 parse_heading("PVViewDimension");
1702 for (i = 0; data[pos + i] != 0xff || data[pos + i + 1] != 0xff; i++)
1704 hex_dump(stdout, pos, i);
1706 printf ("%#x: end of successful parse\n", pos);