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();
723 int n_subcategories = get_u32();
725 assert (leaf_idx == 0);
728 assert (leaf_idx == *n_leaves);
731 for (int k = 0; k < n_subcategories; k++)
732 parse_category(level + 1, k, n_leaves);
736 parse_dimension(int i)
738 printf ("%#x: dimension %d\n", pos, i);
741 match_zeros_assert(5);
746 match_zeros_assert(6);
748 int n_units16 = get_u32();
750 for (int j = 0; j < n_units16; j++)
753 match_byte_assert(0);
755 int n_units32 = get_u32();
757 for (int j = 0; j < n_units32; j++)
760 get_u16(); match_byte_assert(0);
762 get_u16(); match_byte_assert(0);
763 get_u16(); match_byte_assert(0);
769 if (!match_u16(0xffff))
770 match_u16_assert(0x0e74);
771 match_byte_assert(0);
772 match_DspSimpleText();
776 int n_categories = get_u32();
777 for (int j = 0; j < n_categories; j++)
778 parse_category(1, j, &n_leaves);
782 parse_PMModelItemInfo(void)
784 for (int i = 0; i < n_dims; i++)
786 printf("%#x: end of model\n", pos);
791 match_PMModelItemInfo(void)
793 match_byte_assert(0x54);
794 match_byte_assert(0x80);
795 parse_PMModelItemInfo();
801 match_PMPivotItemTree(void)
803 match_byte_assert(0x52);
804 match_byte_assert(0x80);
805 match_byte_assert(0);
806 match_PMModelItemInfo();
812 match_byte_assert(2);
813 match_zeros_assert(24);
814 match_byte_assert(1);
815 match_zeros_assert(3);
817 match_byte_assert(0);
818 match_zeros_assert(3);
823 parse_NavOleItem(void)
825 match_byte_assert(0);
826 match_byte_assert(1);
827 match_zeros_assert(2);
829 match_zeros_assert(9);
830 match_byte_assert(1);
831 match_zeros_assert(10);
832 match_byte_assert(1);
833 match_zeros_assert(5);
835 match_byte_assert(1);
837 match_byte_assert(0);
839 match_zeros_assert(11);
840 match_byte_assert(1);
841 match_zeros_assert(3);
843 match_byte_assert(0);
847 match_NavOleItem(void)
848 { /* 0e 80 or 12 80*/
849 if (!match_byte(0x12))
850 match_byte_assert(0x0e);
851 match_byte_assert(0x80);
858 match_byte_assert(2);
859 match_zeros_assert(8);
860 match_u32_assert(24);
864 match_byte_assert(4);
865 match_zeros_assert(2);
875 match_byte_assert(2);
876 match_zeros_assert(8);
877 match_u32_assert(24);
878 if (!match_u32(0) && !match_u32(0xffffff4b))
879 match_u32_assert(-40);
887 parse_PTPivotController(void)
889 match_byte_assert(2);
891 match_u32_assert(100);
892 match_u32_assert(100);
893 match_u32_assert(100);
894 match_u32_assert(100);
898 parse_PVPivotView(void)
900 match_byte_assert(5);
901 printf ("PVPivotView(%d)\n", get_u32());
905 parse_NDimensional__DspCell(void)
907 match_byte_assert(0);
909 printf ("NDimensional__DspCell(n_dims=%d)\n", n_dims);
913 parse_IndexedCollection(void)
915 printf("IndexedCollection");
916 for (size_t i = 0; ; i++)
918 match_byte_assert(0);
919 printf("%c%d", i ? 'x' : '(', get_u32());
921 if (!match_u16(0x8011))
928 parse_PTTableLook(void)
930 match_byte_assert(2);
931 match_byte_assert(2);
932 match_zeros_assert(7);
933 match_u32_assert(0x36);
934 match_u32_assert(0x12);
938 parse_PVViewDimension(void)
940 while (data[pos + 1] != 0x80
941 && (data[pos] != 0xff || data[pos + 1] != 0xff))
949 parse_PVSeparatorStyle(void)
951 match_byte_assert(0);
952 match_byte_assert(1);
953 match_zeros_assert(15);
955 match_byte_assert(0x80);
956 match_byte_assert(0);
958 match_byte_assert(1);
959 match_zeros_assert(9);
960 while (data[pos + 1] != 0x80
961 && (data[pos] != 0xff || data[pos + 1] != 0xff))
969 parse_PVCellStyle(void)
971 match_byte_assert(0);
972 match_byte_assert(1);
973 match_zeros_assert(5);
974 match_u32_assert(0xffffff);
975 match_zeros_assert(2);
979 skip_item(const char *name)
982 printf("%#x: skipping %s bytes...", pos, name);
983 while (data[pos + 1] != 0x80
984 && !(data[pos] == 0xff && data[pos + 1] == 0xff
985 && data[pos + 2] == 0 && data[pos + 3] == 0))
990 printf("until %#x:", pos);
991 hex_dump(stdout, start_pos, pos - start_pos);
998 if (match_u16(0xffff))
1000 match_u16_assert(0);
1001 char *heading = get_string2();
1002 printf("%#x: %s\n", pos, heading);
1003 if (!strcmp(heading, "NavRoot"))
1005 match_byte_assert(2);
1006 match_zeros_assert(32);
1008 else if (!strcmp(heading, "NavPivot"))
1010 hex_dump(stdout, pos, 021);
1013 else if (!strcmp(heading, "DspCell"))
1015 else if (!strcmp(heading, "DspSimpleText"))
1016 parse_DspSimpleText();
1017 else if (!strcmp(heading, "DspNumber"))
1019 else if (!strcmp(heading, "DspString"))
1021 else if (!strcmp(heading, "NavHead"))
1023 else if (!strcmp(heading, "NavTreeViewItem"))
1026 parse_NavTreeViewItem();
1030 else if (!strcmp(heading, "IndexedCollection"))
1031 parse_IndexedCollection();
1032 else if (!strcmp(heading, "NavOleItem"))
1034 else if (!strcmp(heading, "NavTitle"))
1036 else if (!strcmp(heading, "NavNote"))
1038 else if (!strcmp(heading, "PTPivotController"))
1039 parse_PTPivotController();
1040 else if (!strcmp(heading, "PVPivotView"))
1041 parse_PVPivotView();
1042 else if (!strcmp(heading, "PMPivotModel"))
1043 match_byte_assert(3);
1044 else if (!strcmp(heading, "NDimensional__DspCell"))
1045 parse_NDimensional__DspCell();
1046 else if (!strcmp(heading, "PMPivotItemTree"))
1047 match_byte_assert(0);
1048 else if (!strcmp(heading, "PMModelItemInfo"))
1049 parse_PMModelItemInfo();
1050 else if (!strcmp(heading, "AbstractTreeBranch"))
1051 match_byte_assert(0);
1052 else if (!strcmp(heading, "PTTableLook"))
1053 parse_PTTableLook();
1054 else if (!strcmp(heading, "PVViewDimension"))
1055 parse_PVViewDimension();
1056 else if (!strcmp(heading, "PVSeparatorStyle"))
1057 parse_PVSeparatorStyle();
1058 else if (!strcmp(heading, "PVCellStyle"))
1059 parse_PVCellStyle();
1060 else if (!strcmp(heading, "PVTextStyle"))
1064 fprintf(stderr, "don't know %s at offset 0x%x: ", heading, start);
1065 hex_dump(stderr, pos, 128);
1069 else if (data[pos + 1] == 0x80)
1071 if ((data[pos] == 0x2a || data[pos] == 0x18 || data[pos] == 0x19) && data[pos + 1] == 0x80)
1073 else if (data[pos] == 0x27 && data[pos + 1] == 0x80)
1075 else if (data[pos] == 0x5 && data[pos + 1] == 0x80)
1077 else if (data[pos] == 0x7 && data[pos + 1] == 0x80)
1078 match_NavTreeViewItem();
1079 else if (data[pos] == 0x3 && data[pos + 1] == 0x80)
1080 match_DspSimpleText();
1081 else if ((data[pos] == 0x3c || data[pos] == 0x39)
1082 && data[pos + 1] == 0x80)
1086 printf("%#x: %02x %02x ", pos, data[pos], data[pos + 1]);
1090 /* match_byte_assert(0x01);
1091 match_byte_assert(0x02);
1092 match_byte_assert(0x0d); */
1094 else if ((data[pos] == 0x15 || data[pos] == 0x14)
1095 && data[pos + 1] == 0x80)
1102 printf ("%02x 80(%f", data[pos - 2], get_double());
1103 printf (" \"%s\")\n", get_string1());
1106 match_byte_assert(0);
1108 if (!match_byte(2) && !match_byte(3))
1109 match_byte_assert(0);
1110 match_zeros_assert(3);
1112 match_byte_assert(0);
1113 match_byte_assert(1);
1114 match_zeros_assert(3);
1115 match_byte_assert(1);
1116 match_byte_assert(0);
1121 match_byte_assert(0);
1124 else if (data[pos] == 0x17)
1126 printf("%02x %02x(%02x %02x %02x)\n",
1127 data[pos], data[pos + 1],
1128 data[pos + 2], data[pos + 3], data[pos + 4]);
1131 else if (data[pos] == 0x9 && data[pos + 1] == 0x80)
1135 else if (data[pos] == 0xe || data[pos] == 0x12)
1137 else if (data[pos] == 0x11 || data[pos] == 0x13)
1139 int type = data[pos];
1141 match_byte_assert(0);
1148 int index = get_u32();
1149 printf("%02x 80(footnote %d)\n", type, index);
1152 printf("%02x 80(%d %d)\n", type, x, y);
1155 match_zeros_assert(13);
1157 else if (data[pos] == 0x29 ||
1158 data[pos] == 0x2b ||
1159 data[pos] == 0x2d ||
1160 data[pos] == 0x31 ||
1161 data[pos] == 0x32 ||
1162 data[pos] == 0x4a ||
1163 data[pos] == 0x4c ||
1164 data[pos] == 0x4f ||
1165 data[pos] == 0x4d ||
1166 data[pos] == 0x50 ||
1167 data[pos] == 0x36 ||
1168 data[pos] == 0x52 ||
1169 data[pos] == 0x53 ||
1170 data[pos] == 0x54 ||
1171 data[pos] == 0x55 ||
1172 data[pos] == 0x57 ||
1173 data[pos] == 0x56 ||
1174 data[pos] == 0x58 ||
1175 data[pos] == 0x5c ||
1176 data[pos] == 0x5b ||
1177 data[pos] == 0x5e ||
1178 data[pos] == 0x62 ||
1179 data[pos] == 0x64 ||
1180 data[pos] == 0x4e ||
1181 data[pos] == 0x51 ||
1182 data[pos] == 0x59 ||
1183 data[pos] == 0x5a ||
1184 data[pos] == 0x5d ||
1185 data[pos] == 0x66 ||
1186 data[pos] == 0x60 ||
1187 data[pos] == 0x68 ||
1188 data[pos] == 0x48 ||
1189 data[pos] == 0x6a ||
1193 match_byte_assert(0);
1195 else if (data[pos] == 0x2c ||
1196 data[pos] == 0x2e ||
1197 data[pos] == 0x30 ||
1198 data[pos] == 0x34 ||
1199 data[pos] == 0x3d ||
1200 data[pos] == 0x40 ||
1201 data[pos] == 0x3f ||
1202 data[pos] == 0x42 ||
1203 data[pos] == 0x43 ||
1204 data[pos] == 0x44 ||
1205 data[pos] == 0x49 ||
1206 data[pos] == 0x3e ||
1209 printf ("%#x: %02x %02x(%02x %02x %02x)\n",
1210 pos, data[pos], data[pos + 1],
1211 data[pos + 2], data[pos + 3], data[pos + 4]);
1217 fprintf (stderr, "%#x: unknown record", pos);
1218 hex_dump (stderr, pos, 64);
1222 else if (match_byte(0xa))
1225 match_byte_assert(0);
1226 if (match_u16(0x0e74))
1227 match_byte_assert(0);
1230 match_zeros_assert(4);
1233 match_zeros_assert (2);
1237 else if (match_byte(1))
1239 match_byte_assert(0);
1242 match_byte_assert(0);
1245 match_zeros_assert(2);
1247 if (match_byte(0x08))
1249 match_byte_assert(0);
1250 match_u16_assert(0x0e74);
1251 match_byte_assert(0);
1253 else if (match_byte(3))
1255 match_byte_assert(0);
1256 if (match_u16(0x0e74))
1257 match_byte_assert(0);
1260 match_zeros_assert(6);
1261 if (!match_byte(0xe) && !match_byte(0x11))
1262 match_byte_assert(0);
1263 match_byte_assert(0);
1264 if (!match_u16(0x0e74))
1265 match_u16_assert(0);
1266 match_byte_assert(0);
1271 match_byte_assert(0);
1272 match_byte_assert(1);
1273 match_zeros_assert(3);
1274 match_byte_assert(1);
1275 match_byte_assert(0);
1280 else if (match_u16(1))
1282 int start_pos = pos;
1283 char *title = get_string1();
1284 printf("%#x: title(\"%s\", ", start_pos, title);
1286 match_u32_assert(0);
1287 char *id = get_string1();
1288 printf("\"%s\")\n", id);
1289 match_byte_assert(0);
1291 match_u32_assert(3);
1292 match_u16_assert(1);
1294 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))
1295 skip_item("unknown");
1297 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))
1300 match_byte_assert(0);
1301 if (!match_u16(0x0e74))
1302 match_byte_assert(0);
1303 match_byte_assert(0);
1305 else if (match_byte(2) || match_byte(3))
1307 match_byte_assert(0);
1308 if (!match_u16(0x0e74))
1310 match_zeros_assert(2);
1313 match_zeros_assert(3);
1315 match_zeros_assert(4);
1320 match_u16_assert(0x0e74);
1324 //match_byte_assert(0);
1326 else if (match_byte(0xd) || match_byte(0xe) || match_byte(0xf)
1327 || match_byte(0x11) || match_byte(0x12) || match_byte(0x13)
1328 || match_byte(0x14) || match_byte(0x1b))
1330 if (!match_byte(0x07))
1331 match_byte_assert(0);
1332 if (!match_u16(0x0e74))
1333 match_zeros_assert(11);
1335 match_byte_assert(0);
1337 else if (match_byte(0xe3) || match_byte(0xdb) || match_byte(0xd8) || match_byte(0xe9) || match_byte(0xf3))
1339 match_byte_assert(0x0e);
1340 match_byte_assert(0x74);
1341 match_byte_assert(0x0e);
1342 match_byte_assert(0);
1344 else if (match_byte(0x9d) || match_byte(0x9e) || match_byte(0x9c))
1345 match_u32_assert(0x000e741a);
1346 else if (match_byte(0x10))
1348 match_byte_assert(0);
1350 match_zeros_assert(10);
1353 match_u16_assert(0x0e74);
1354 match_byte_assert(0);
1357 else if (match_byte(0x39) || match_byte(0x3a) || match_byte(0x3b))
1358 match_u32_assert(0x000e7409);
1361 //fprintf (stderr, "bad record start at offset %x: ", pos);
1362 hex_dump (stderr, pos, 64);
1371 main(int argc, char *argv[])
1373 bool print_offsets = false;
1376 int c = getopt (argc, argv, "o");
1383 print_offsets = true;
1390 if (argc - optind != 1)
1392 fprintf (stderr, "usage: %s FILE.bin", argv[0]);
1396 const char *filename = argv[optind];
1397 int fd = open(filename, O_RDONLY);
1400 fprintf (stderr, "%s: open failed (%s)", filename, strerror (errno));
1411 data = malloc(n + 256);
1417 if (read(fd, data, n) != n)
1422 for (int i = 0; i < 256; i++)
1423 data[n + i] = i % 2 ? 0xaa : 0x55;
1426 setvbuf (stdout, NULL, _IONBF, 0);
1428 match_byte_assert(4);
1429 match_u32_assert(0);
1430 match_string1_assert("SPSS Output Document");
1431 match_u32_assert(1);
1432 match_byte_assert(0x63);
1446 parse_heading("NavRoot");
1447 match_byte_assert(2);
1448 match_zeros_assert(32);
1450 parse_heading("DspSimpleText");
1451 match_zeros_assert(10);
1453 parse_heading("DspString");
1456 parse_heading("NavTreeViewItem");
1457 match_byte_assert(0);
1459 match_u32_assert(0);
1460 match_byte_assert(2);
1461 match_byte_assert(0);
1462 match_byte_assert(1);
1463 match_zeros_assert(9);
1464 match_u32_assert(1);
1466 match_u32_assert(0);
1467 match_u32_assert(0x18);
1469 match_u32_assert(0xffffffd8);
1470 match_u32_assert(0xffffffde);
1471 match_u32_assert(0x18);
1473 match_u32_assert(0xffffffd8);
1474 match_u32_assert(0x28);
1475 match_u32_assert(0x28);
1479 match_zeros_assert(5);
1481 if (match_u32(8500))
1482 match_u32_assert(11000);
1485 match_u32_assert(11000);
1486 match_u32_assert(8500);
1491 match_byte_assert(1);
1496 get_string4(); /* page title */
1497 match_byte_assert(1);
1498 match_byte_assert(1);
1499 match_zeros_assert(3);
1500 get_string4(); /* page number */
1501 match_byte_assert(0);
1503 match_u16_assert(2);
1506 if (data[pos + 9] != 'L')
1508 parse_heading("NavLog");
1521 puts(get_padded_string(32));
1523 match_u32_assert(132);
1524 match_zeros_assert(8);
1525 match_u32_assert(1);
1526 printf ("0x%x\n", pos);
1528 match_byte_assert(0);
1530 parse_heading("NavHead");
1532 match_NavTreeViewItem();
1533 match_zeros_assert(3);
1535 parse_heading("NavTitle");
1537 match_DspSimpleText();
1539 match_NavTreeViewItem();
1541 match_byte_assert(1);
1542 match_byte_assert(1);
1543 match_u32_assert(-19);
1544 match_zeros_assert(12);
1545 match_byte_assert(0xbc);
1546 match_byte_assert(2);
1547 match_zeros_assert(9);
1548 match_byte_assert(0x22);
1549 puts(get_padded_string(32));
1550 match_u32_assert(80);
1551 match_zeros_assert(8);
1552 match_u32_assert(1);
1554 match_byte_assert(0);
1556 parse_heading("NavNote");
1557 match_byte_assert(2);
1558 match_zeros_assert(8);
1559 match_u32_assert(24);
1561 match_u32_assert(-40);
1563 match_u32_assert(2);
1564 match_u32_assert(1);
1565 match_DspSimpleText();
1567 match_NavTreeViewItem();
1568 match_byte_assert(1);
1570 parse_heading("PTPivotController");
1571 match_byte_assert(2);
1573 match_u32_assert(100);
1574 match_u32_assert(100);
1575 match_u32_assert(100);
1576 match_u32_assert(100);
1578 parse_heading("PVPivotView");
1579 match_u32_assert(5);
1580 match_byte_assert(0);
1582 parse_heading("PMPivotModel");
1583 match_byte_assert(3);
1585 parse_heading("NDimensional__DspCell");
1586 match_byte_assert(0);
1587 match_u32_assert(1);
1589 parse_heading("IndexedCollection");
1590 match_byte_assert(0);
1592 match_zeros_assert(3);
1593 match_byte_assert(1);
1594 match_byte_assert(0);
1595 match_zeros_assert(7);
1597 while (data[pos] != 1)
1608 match_byte_assert(1);
1609 match_byte_assert(0);
1610 puts(get_string1());
1612 match_u32_assert(2);
1613 puts(get_string1());
1615 match_byte_assert(0);
1616 match_byte_assert(1);
1617 match_byte_assert(0);
1618 match_byte_assert(0);
1619 match_byte_assert(0);
1620 match_byte_assert(1);
1621 match_byte_assert(0);
1625 parse_heading("PMPivotItemTree");
1626 match_byte_assert(0);
1628 parse_heading("AbstractTreeBranch");
1629 match_byte_assert(0);
1631 parse_heading("PMModelItemInfo");
1632 parse_PMModelItemInfo();
1633 match_DspSimpleText();
1636 match_u32_assert(7);
1637 match_PMPivotItemTree();
1639 match_u32_assert(0);
1640 match_PMPivotItemTree();
1642 match_u32_assert(0);
1643 match_PMPivotItemTree();
1645 match_u32_assert(6);
1646 match_PMPivotItemTree();
1648 match_u32_assert(0);
1649 match_PMPivotItemTree();
1651 match_u32_assert(0);
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(2);
1667 match_PMPivotItemTree();
1669 match_u32_assert(0);
1670 match_PMPivotItemTree();
1672 match_u32_assert(0);
1673 match_PMPivotItemTree();
1675 match_u32_assert(0);
1676 match_PMPivotItemTree();
1678 match_u32_assert(0);
1679 match_PMPivotItemTree();
1681 match_u32_assert(2);
1682 match_PMPivotItemTree();
1684 match_u32_assert(0);
1685 match_PMPivotItemTree();
1687 match_u32_assert(0);
1691 while (data[pos] != 0xff || data[pos + 1] != 0xff)
1693 parse_heading("PVViewDimension");
1696 for (i = 0; data[pos + i] != 0xff || data[pos + i + 1] != 0xff; i++)
1698 hex_dump(stdout, pos, i);
1700 printf ("%#x: end of successful parse\n", pos);