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 j)
708 get_u16(); match_byte_assert(0);
709 get_u16(); match_byte_assert(0);
712 if (get_u16() == 0xffff)
713 match_u16_assert(0xffff);
715 match_u16_assert(0x0e74);
716 match_byte_assert(0);
717 match_DspSimpleText();
723 parse_dimension(int i)
725 printf ("%#x: dimension %d\n", pos, i);
728 match_zeros_assert(5);
730 get_u16(); match_u16_assert(0x0e74); match_byte_assert(0);
731 match_DspSimpleText();
734 int n_categories = get_u32();
735 for (int j = 0; j < n_categories; j++)
740 match_zeros_assert(6);
742 int n_units16 = get_u32();
744 for (int j = 0; j < n_units16; j++)
747 match_byte_assert(0);
749 int n_units32 = get_u32();
751 for (int j = 0; j < n_units32; j++)
754 get_u16(); match_byte_assert(0);
756 get_u16(); match_byte_assert(0);
757 get_u16(); match_byte_assert(0);
761 get_u16(); match_u16_assert(0x0e74); match_byte_assert(0);
762 match_DspSimpleText();
765 int n_categories = get_u32();
766 for (int j = 0; j < n_categories; j++)
772 parse_PMModelItemInfo(void)
774 for (int i = 0; i < n_dims; i++)
776 printf("%#x: end of model\n", pos);
781 match_PMModelItemInfo(void)
783 match_byte_assert(0x54);
784 match_byte_assert(0x80);
785 parse_PMModelItemInfo();
791 match_PMPivotItemTree(void)
793 match_byte_assert(0x52);
794 match_byte_assert(0x80);
795 match_byte_assert(0);
796 match_PMModelItemInfo();
802 match_byte_assert(2);
803 match_zeros_assert(24);
804 match_byte_assert(1);
805 match_zeros_assert(3);
807 match_byte_assert(0);
808 match_zeros_assert(3);
813 parse_NavOleItem(void)
815 match_byte_assert(0);
816 match_byte_assert(1);
817 match_zeros_assert(2);
819 match_zeros_assert(9);
820 match_byte_assert(1);
821 match_zeros_assert(10);
822 match_byte_assert(1);
823 match_zeros_assert(5);
825 match_byte_assert(1);
827 match_byte_assert(0);
829 match_zeros_assert(11);
830 match_byte_assert(1);
831 match_zeros_assert(3);
833 match_byte_assert(0);
837 match_NavOleItem(void)
838 { /* 0e 80 or 12 80*/
839 if (!match_byte(0x12))
840 match_byte_assert(0x0e);
841 match_byte_assert(0x80);
848 match_byte_assert(2);
849 match_zeros_assert(8);
850 match_u32_assert(24);
854 match_byte_assert(4);
855 match_zeros_assert(2);
865 match_byte_assert(2);
866 match_zeros_assert(8);
867 match_u32_assert(24);
868 if (!match_u32(0) && !match_u32(0xffffff4b))
869 match_u32_assert(-40);
877 parse_PTPivotController(void)
879 match_byte_assert(2);
881 match_u32_assert(100);
882 match_u32_assert(100);
883 match_u32_assert(100);
884 match_u32_assert(100);
888 parse_PVPivotView(void)
890 match_byte_assert(5);
891 printf ("PVPivotView(%d)\n", get_u32());
895 parse_NDimensional__DspCell(void)
897 match_byte_assert(0);
899 printf ("NDimensional__DspCell(n_dims=%d)\n", n_dims);
903 parse_IndexedCollection(void)
905 printf("IndexedCollection");
906 for (size_t i = 0; ; i++)
908 match_byte_assert(0);
909 printf("%c%d", i ? 'x' : '(', get_u32());
911 if (!match_u16(0x8011))
918 parse_PTTableLook(void)
920 match_byte_assert(2);
921 match_byte_assert(2);
922 match_zeros_assert(7);
923 match_u32_assert(0x36);
924 match_u32_assert(0x12);
928 parse_PVViewDimension(void)
930 while (data[pos + 1] != 0x80
931 && (data[pos] != 0xff || data[pos + 1] != 0xff))
939 parse_PVSeparatorStyle(void)
941 match_byte_assert(0);
942 match_byte_assert(1);
943 match_zeros_assert(15);
945 match_byte_assert(0x80);
946 match_byte_assert(0);
948 match_byte_assert(1);
949 match_zeros_assert(9);
950 while (data[pos + 1] != 0x80
951 && (data[pos] != 0xff || data[pos + 1] != 0xff))
959 parse_PVCellStyle(void)
961 match_byte_assert(0);
962 match_byte_assert(1);
963 match_zeros_assert(5);
964 match_u32_assert(0xffffff);
965 match_zeros_assert(2);
969 skip_item(const char *name)
972 printf("%#x: skipping %s bytes...", pos, name);
973 while (data[pos + 1] != 0x80
974 && !(data[pos] == 0xff && data[pos + 1] == 0xff
975 && data[pos + 2] == 0 && data[pos + 3] == 0))
980 printf("until %#x:", pos);
981 hex_dump(stdout, start_pos, pos - start_pos);
988 if (match_u16(0xffff))
991 char *heading = get_string2();
992 printf("%#x: %s\n", pos, heading);
993 if (!strcmp(heading, "NavRoot"))
995 match_byte_assert(2);
996 match_zeros_assert(32);
998 else if (!strcmp(heading, "NavPivot"))
1000 hex_dump(stdout, pos, 021);
1003 else if (!strcmp(heading, "DspCell"))
1005 else if (!strcmp(heading, "DspSimpleText"))
1006 parse_DspSimpleText();
1007 else if (!strcmp(heading, "DspNumber"))
1009 else if (!strcmp(heading, "DspString"))
1011 else if (!strcmp(heading, "NavHead"))
1013 else if (!strcmp(heading, "NavTreeViewItem"))
1016 parse_NavTreeViewItem();
1020 else if (!strcmp(heading, "IndexedCollection"))
1021 parse_IndexedCollection();
1022 else if (!strcmp(heading, "NavOleItem"))
1024 else if (!strcmp(heading, "NavTitle"))
1026 else if (!strcmp(heading, "NavNote"))
1028 else if (!strcmp(heading, "PTPivotController"))
1029 parse_PTPivotController();
1030 else if (!strcmp(heading, "PVPivotView"))
1031 parse_PVPivotView();
1032 else if (!strcmp(heading, "PMPivotModel"))
1033 match_byte_assert(3);
1034 else if (!strcmp(heading, "NDimensional__DspCell"))
1035 parse_NDimensional__DspCell();
1036 else if (!strcmp(heading, "PMPivotItemTree"))
1037 match_byte_assert(0);
1038 else if (!strcmp(heading, "PMModelItemInfo"))
1039 parse_PMModelItemInfo();
1040 else if (!strcmp(heading, "AbstractTreeBranch"))
1041 match_byte_assert(0);
1042 else if (!strcmp(heading, "PTTableLook"))
1043 parse_PTTableLook();
1044 else if (!strcmp(heading, "PVViewDimension"))
1045 parse_PVViewDimension();
1046 else if (!strcmp(heading, "PVSeparatorStyle"))
1047 parse_PVSeparatorStyle();
1048 else if (!strcmp(heading, "PVCellStyle"))
1049 parse_PVCellStyle();
1050 else if (!strcmp(heading, "PVTextStyle"))
1054 fprintf(stderr, "don't know %s at offset 0x%x: ", heading, start);
1055 hex_dump(stderr, pos, 128);
1059 else if (data[pos + 1] == 0x80)
1061 if ((data[pos] == 0x2a || data[pos] == 0x18 || data[pos] == 0x19) && data[pos + 1] == 0x80)
1063 else if (data[pos] == 0x27 && data[pos + 1] == 0x80)
1065 else if (data[pos] == 0x5 && data[pos + 1] == 0x80)
1067 else if (data[pos] == 0x7 && data[pos + 1] == 0x80)
1068 match_NavTreeViewItem();
1069 else if (data[pos] == 0x3 && data[pos + 1] == 0x80)
1070 match_DspSimpleText();
1071 else if ((data[pos] == 0x3c || data[pos] == 0x39)
1072 && data[pos + 1] == 0x80)
1076 printf("%#x: %02x %02x ", pos, data[pos], data[pos + 1]);
1080 /* match_byte_assert(0x01);
1081 match_byte_assert(0x02);
1082 match_byte_assert(0x0d); */
1084 else if (data[pos] == 0x15 && data[pos + 1] == 0x80)
1090 printf ("15 80(%f", get_double());
1091 printf (" \"%s\")\n", get_string1());
1094 match_byte_assert(0);
1096 if (!match_byte(2) && !match_byte(3))
1097 match_byte_assert(0);
1098 match_zeros_assert(3);
1100 match_byte_assert(0);
1101 match_byte_assert(1);
1102 match_zeros_assert(3);
1103 match_byte_assert(1);
1104 match_byte_assert(0);
1109 match_byte_assert(0);
1111 match_u16_assert(1);
1114 else if (data[pos] == 0x9 && data[pos + 1] == 0x80)
1118 else if (data[pos] == 0xe || data[pos] == 0x12)
1120 else if (data[pos] == 0x11 || data[pos] == 0x13)
1122 int type = data[pos];
1124 match_byte_assert(0);
1131 int index = get_u32();
1132 printf("%02x 80(footnote %d)\n", type, index);
1135 printf("%02x 80(%d %d)\n", type, x, y);
1138 match_zeros_assert(13);
1140 else if (data[pos] == 0x29 ||
1141 data[pos] == 0x2b ||
1142 data[pos] == 0x2d ||
1143 data[pos] == 0x31 ||
1144 data[pos] == 0x32 ||
1145 data[pos] == 0x4a ||
1146 data[pos] == 0x4c ||
1147 data[pos] == 0x4f ||
1148 data[pos] == 0x4d ||
1149 data[pos] == 0x50 ||
1150 data[pos] == 0x36 ||
1151 data[pos] == 0x52 ||
1152 data[pos] == 0x53 ||
1153 data[pos] == 0x54 ||
1154 data[pos] == 0x55 ||
1155 data[pos] == 0x57 ||
1156 data[pos] == 0x56 ||
1157 data[pos] == 0x58 ||
1158 data[pos] == 0x5c ||
1159 data[pos] == 0x5b ||
1160 data[pos] == 0x5e ||
1161 data[pos] == 0x62 ||
1162 data[pos] == 0x64 ||
1163 data[pos] == 0x4e ||
1164 data[pos] == 0x51 ||
1165 data[pos] == 0x59 ||
1166 data[pos] == 0x5a ||
1167 data[pos] == 0x5d ||
1168 data[pos] == 0x66 ||
1169 data[pos] == 0x60 ||
1170 data[pos] == 0x68 ||
1171 data[pos] == 0x48 ||
1172 data[pos] == 0x6a ||
1176 match_byte_assert(0);
1178 else if (data[pos] == 0x2c ||
1179 data[pos] == 0x2e ||
1180 data[pos] == 0x30 ||
1181 data[pos] == 0x34 ||
1182 data[pos] == 0x3d ||
1183 data[pos] == 0x40 ||
1184 data[pos] == 0x3f ||
1185 data[pos] == 0x42 ||
1186 data[pos] == 0x43 ||
1187 data[pos] == 0x44 ||
1188 data[pos] == 0x49 ||
1189 data[pos] == 0x3e ||
1192 printf ("%#x: %02x %02x(%02x %02x %02x)\n",
1193 pos, data[pos], data[pos + 1],
1194 data[pos + 2], data[pos + 3], data[pos + 4]);
1201 fprintf (stderr, "bad record 0x%02x at offset %x: ",
1204 hex_dump (stderr, pos, 64);
1208 else if (match_byte(0xa))
1211 match_byte_assert(0);
1212 if (match_u16(0x0e74))
1213 match_byte_assert(0);
1216 match_zeros_assert(4);
1219 match_zeros_assert (2);
1223 else if (match_byte(1))
1225 match_byte_assert(0);
1228 match_byte_assert(0);
1231 match_zeros_assert(2);
1233 if (match_byte(0x08))
1235 match_byte_assert(0);
1236 match_u16_assert(0x0e74);
1237 match_byte_assert(0);
1239 else if (match_byte(3))
1241 match_byte_assert(0);
1242 if (match_u16(0x0e74))
1243 match_byte_assert(0);
1246 match_zeros_assert(6);
1247 if (!match_byte(0xe) && !match_byte(0x11))
1248 match_byte_assert(0);
1249 match_byte_assert(0);
1250 if (!match_u16(0x0e74))
1251 match_u16_assert(0);
1252 match_byte_assert(0);
1257 match_byte_assert(0);
1258 match_byte_assert(1);
1259 match_zeros_assert(3);
1260 match_byte_assert(1);
1261 match_byte_assert(0);
1266 else if (match_u16(1))
1268 int start_pos = pos;
1269 char *title = get_string1();
1270 printf("%#x: title(\"%s\", ", start_pos, title);
1271 match_u32_assert(0);
1272 char *id = get_string1();
1273 printf("\"%s\")\n", id);
1274 match_byte_assert(0);
1275 match_u32_assert(3);
1276 match_u16_assert(1);
1278 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))
1279 skip_item("unknown");
1281 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))
1284 match_byte_assert(0);
1285 if (!match_u16(0x0e74))
1286 match_byte_assert(0);
1287 match_byte_assert(0);
1289 else if (match_byte(2) || match_byte(3))
1291 match_byte_assert(0);
1292 if (!match_u16(0x0e74))
1294 match_zeros_assert(2);
1297 match_zeros_assert(3);
1299 match_zeros_assert(4);
1304 match_u16_assert(0x0e74);
1308 //match_byte_assert(0);
1310 else if (match_byte(0xd) || match_byte(0xe) || match_byte(0xf)
1311 || match_byte(0x11) || match_byte(0x12) || match_byte(0x13)
1312 || match_byte(0x14) || match_byte(0x1b))
1314 if (!match_byte(0x07))
1315 match_byte_assert(0);
1316 if (!match_u16(0x0e74))
1317 match_zeros_assert(11);
1319 match_byte_assert(0);
1321 else if (match_byte(0xe3) || match_byte(0xdb) || match_byte(0xd8) || match_byte(0xe9) || match_byte(0xf3))
1323 match_byte_assert(0x0e);
1324 match_byte_assert(0x74);
1325 match_byte_assert(0x0e);
1326 match_byte_assert(0);
1328 else if (match_byte(0x9d) || match_byte(0x9e) || match_byte(0x9c))
1329 match_u32_assert(0x000e741a);
1330 else if (match_byte(0x10))
1332 match_byte_assert(0);
1334 match_zeros_assert(10);
1337 match_u16_assert(0x0e74);
1338 match_byte_assert(0);
1341 else if (match_byte(0x39) || match_byte(0x3a) || match_byte(0x3b))
1342 match_u32_assert(0x000e7409);
1345 //fprintf (stderr, "bad record start at offset %x: ", pos);
1346 hex_dump (stderr, pos, 64);
1355 main(int argc, char *argv[])
1357 bool print_offsets = false;
1360 int c = getopt (argc, argv, "o");
1367 print_offsets = true;
1374 if (argc - optind != 1)
1376 fprintf (stderr, "usage: %s FILE.bin", argv[0]);
1380 const char *filename = argv[optind];
1381 int fd = open(filename, O_RDONLY);
1384 fprintf (stderr, "%s: open failed (%s)", filename, strerror (errno));
1395 data = malloc(n + 256);
1401 if (read(fd, data, n) != n)
1406 for (int i = 0; i < 256; i++)
1407 data[n + i] = i % 2 ? 0xaa : 0x55;
1410 setvbuf (stdout, NULL, _IONBF, 0);
1412 match_byte_assert(4);
1413 match_u32_assert(0);
1414 match_string1_assert("SPSS Output Document");
1415 match_u32_assert(1);
1416 match_byte_assert(0x63);
1430 parse_heading("NavRoot");
1431 match_byte_assert(2);
1432 match_zeros_assert(32);
1434 parse_heading("DspSimpleText");
1435 match_zeros_assert(10);
1437 parse_heading("DspString");
1440 parse_heading("NavTreeViewItem");
1441 match_byte_assert(0);
1443 match_u32_assert(0);
1444 match_byte_assert(2);
1445 match_byte_assert(0);
1446 match_byte_assert(1);
1447 match_zeros_assert(9);
1448 match_u32_assert(1);
1450 match_u32_assert(0);
1451 match_u32_assert(0x18);
1453 match_u32_assert(0xffffffd8);
1454 match_u32_assert(0xffffffde);
1455 match_u32_assert(0x18);
1457 match_u32_assert(0xffffffd8);
1458 match_u32_assert(0x28);
1459 match_u32_assert(0x28);
1463 match_zeros_assert(5);
1465 if (match_u32(8500))
1466 match_u32_assert(11000);
1469 match_u32_assert(11000);
1470 match_u32_assert(8500);
1475 match_byte_assert(1);
1480 get_string4(); /* page title */
1481 match_byte_assert(1);
1482 match_byte_assert(1);
1483 match_zeros_assert(3);
1484 get_string4(); /* page number */
1485 match_byte_assert(0);
1487 match_u16_assert(2);
1490 if (data[pos + 9] != 'L')
1492 parse_heading("NavLog");
1505 puts(get_padded_string(32));
1507 match_u32_assert(132);
1508 match_zeros_assert(8);
1509 match_u32_assert(1);
1510 printf ("0x%x\n", pos);
1512 match_byte_assert(0);
1514 parse_heading("NavHead");
1516 match_NavTreeViewItem();
1517 match_zeros_assert(3);
1519 parse_heading("NavTitle");
1521 match_DspSimpleText();
1523 match_NavTreeViewItem();
1525 match_byte_assert(1);
1526 match_byte_assert(1);
1527 match_u32_assert(-19);
1528 match_zeros_assert(12);
1529 match_byte_assert(0xbc);
1530 match_byte_assert(2);
1531 match_zeros_assert(9);
1532 match_byte_assert(0x22);
1533 puts(get_padded_string(32));
1534 match_u32_assert(80);
1535 match_zeros_assert(8);
1536 match_u32_assert(1);
1538 match_byte_assert(0);
1540 parse_heading("NavNote");
1541 match_byte_assert(2);
1542 match_zeros_assert(8);
1543 match_u32_assert(24);
1545 match_u32_assert(-40);
1547 match_u32_assert(2);
1548 match_u32_assert(1);
1549 match_DspSimpleText();
1551 match_NavTreeViewItem();
1552 match_byte_assert(1);
1554 parse_heading("PTPivotController");
1555 match_byte_assert(2);
1557 match_u32_assert(100);
1558 match_u32_assert(100);
1559 match_u32_assert(100);
1560 match_u32_assert(100);
1562 parse_heading("PVPivotView");
1563 match_u32_assert(5);
1564 match_byte_assert(0);
1566 parse_heading("PMPivotModel");
1567 match_byte_assert(3);
1569 parse_heading("NDimensional__DspCell");
1570 match_byte_assert(0);
1571 match_u32_assert(1);
1573 parse_heading("IndexedCollection");
1574 match_byte_assert(0);
1576 match_zeros_assert(3);
1577 match_byte_assert(1);
1578 match_byte_assert(0);
1579 match_zeros_assert(7);
1581 while (data[pos] != 1)
1592 match_byte_assert(1);
1593 match_byte_assert(0);
1594 puts(get_string1());
1596 match_u32_assert(2);
1597 puts(get_string1());
1599 match_byte_assert(0);
1600 match_byte_assert(1);
1601 match_byte_assert(0);
1602 match_byte_assert(0);
1603 match_byte_assert(0);
1604 match_byte_assert(1);
1605 match_byte_assert(0);
1609 parse_heading("PMPivotItemTree");
1610 match_byte_assert(0);
1612 parse_heading("AbstractTreeBranch");
1613 match_byte_assert(0);
1615 parse_heading("PMModelItemInfo");
1616 parse_PMModelItemInfo();
1617 match_DspSimpleText();
1620 match_u32_assert(7);
1621 match_PMPivotItemTree();
1623 match_u32_assert(0);
1624 match_PMPivotItemTree();
1626 match_u32_assert(0);
1627 match_PMPivotItemTree();
1629 match_u32_assert(6);
1630 match_PMPivotItemTree();
1632 match_u32_assert(0);
1633 match_PMPivotItemTree();
1635 match_u32_assert(0);
1636 match_PMPivotItemTree();
1638 match_u32_assert(0);
1639 match_PMPivotItemTree();
1641 match_u32_assert(0);
1642 match_PMPivotItemTree();
1644 match_u32_assert(0);
1645 match_PMPivotItemTree();
1647 match_u32_assert(0);
1648 match_PMPivotItemTree();
1650 match_u32_assert(2);
1651 match_PMPivotItemTree();
1653 match_u32_assert(0);
1654 match_PMPivotItemTree();
1656 match_u32_assert(0);
1657 match_PMPivotItemTree();
1659 match_u32_assert(0);
1660 match_PMPivotItemTree();
1662 match_u32_assert(0);
1663 match_PMPivotItemTree();
1665 match_u32_assert(2);
1666 match_PMPivotItemTree();
1668 match_u32_assert(0);
1669 match_PMPivotItemTree();
1671 match_u32_assert(0);
1675 while (data[pos] != 0xff || data[pos + 1] != 0xff)
1677 parse_heading("PVViewDimension");
1680 for (i = 0; data[pos + i] != 0xff || data[pos + i + 1] != 0xff; i++)
1682 hex_dump(stdout, pos, i);
1684 printf ("%#x: end of successful parse\n", pos);