+static void
+parse_NavHead(void)
+{
+ match_byte_assert(2);
+ match_zeros_assert(24);
+ match_byte_assert(1);
+ match_zeros_assert(3);
+ if (!match_byte(1))
+ match_byte_assert(0);
+ match_zeros_assert(3);
+ /* DspSimpleText */
+}
+
+static void
+parse_NavOleItem(void)
+{
+ match_byte_assert(0);
+ match_byte_assert(1);
+ match_zeros_assert(2);
+ pos++;
+ match_zeros_assert(9);
+ match_byte_assert(1);
+ match_zeros_assert(10);
+ match_byte_assert(1);
+ match_zeros_assert(5);
+ get_string1();
+ match_byte_assert(1);
+ parse_weirdness();
+ match_byte_assert(0);
+ pos++;
+ match_zeros_assert(11);
+ match_byte_assert(1);
+ match_zeros_assert(3);
+ get_string4();
+ match_byte_assert(0);
+}
+
+static void
+match_NavOleItem(void)
+{ /* 0e 80 or 12 80*/
+ if (!match_byte(0x12))
+ match_byte_assert(0x0e);
+ match_byte_assert(0x80);
+ parse_NavOleItem();
+}
+
+static void
+parse_NavTitle(void)
+{
+ match_byte_assert(2);
+ match_zeros_assert(8);
+ match_u32_assert(24);
+ get_u32();
+ pos++;
+ if (!match_byte(3))
+ match_byte_assert(4);
+ match_zeros_assert(2);
+ get_u32();
+ match_u32_assert(2);
+ if (!match_u32(2))
+ match_u32_assert(1);
+}
+
+static void
+parse_NavNote(void)
+{
+ match_byte_assert(2);
+ match_zeros_assert(8);
+ match_u32_assert(24);
+ if (!match_u32(0) && !match_u32(0xffffff4b))
+ match_u32_assert(-40);
+ pos += 8;
+ match_u32_assert(2);
+ if (!match_u32(2))
+ match_u32_assert(1);
+}
+
+static void
+parse_PTPivotController(void)
+{
+ match_byte_assert(2);
+ pos += 8;
+ match_u32_assert(100);
+ match_u32_assert(100);
+ match_u32_assert(100);
+ match_u32_assert(100);
+}
+
+static void
+parse_PVPivotView(void)
+{
+ match_byte_assert(5);
+ printf ("PVPivotView(%d)\n", get_u32());
+}
+
+static void
+parse_NDimensional__DspCell(void)
+{
+ match_byte_assert(0);
+ n_dims = get_u32();
+ printf ("NDimensional__DspCell(n_dims=%d)\n", n_dims);
+}
+
+static void
+parse_IndexedCollection(void)
+{
+ printf("IndexedCollection");
+ for (size_t i = 0; ; i++)
+ {
+ match_byte_assert(0);
+ printf("%c%d", i ? 'x' : '(', get_u32());
+ match_u16_assert(1);
+ if (!match_u16(0x8011))
+ break;
+ }
+ printf(")\n");
+}
+
+static void
+parse_PTTableLook(void)
+{
+ match_byte_assert(2);
+ match_byte_assert(2);
+ match_zeros_assert(7);
+ match_u32_assert(0x36);
+ match_u32_assert(0x12);
+}
+
+static void
+parse_PVViewDimension(void)
+{
+ while (data[pos + 1] != 0x80
+ && (data[pos] != 0xff || data[pos + 1] != 0xff))
+ {
+ assert(pos < n);
+ pos++;
+ }
+}
+
+static void
+parse_PVSeparatorStyle(void)
+{
+ match_byte_assert(0);
+ match_byte_assert(1);
+ match_zeros_assert(15);
+ pos++;
+ match_byte_assert(0x80);
+ match_byte_assert(0);
+
+ match_byte_assert(1);
+ match_zeros_assert(9);
+ while (data[pos + 1] != 0x80
+ && (data[pos] != 0xff || data[pos + 1] != 0xff))
+ {
+ assert(pos < n);
+ pos++;
+ }
+}
+
+static void
+parse_PVCellStyle(void)
+{
+ match_byte_assert(0);
+ match_byte_assert(1);
+ match_zeros_assert(5);
+ match_u32_assert(0xffffff);
+ match_zeros_assert(2);
+}
+
+static void
+skip_item(const char *name)
+{
+ int start_pos = pos;
+ printf("%#x: skipping %s bytes...", pos, name);
+ while (data[pos + 1] != 0x80
+ && !(data[pos] == 0xff && data[pos + 1] == 0xff
+ && data[pos + 2] == 0 && data[pos + 3] == 0))
+ {
+ assert(pos < n);
+ pos++;
+ }
+ printf("until %#x:", pos);
+ hex_dump(stdout, start_pos, pos - start_pos);
+}
+
+static void
+parse_flexible(void)
+{
+ int start = pos;
+ if (match_u16(0xffff))
+ {
+ match_u16_assert(0);
+ char *heading = get_string2();
+ printf("%#x: %s\n", pos, heading);
+ if (!strcmp(heading, "NavRoot"))
+ {
+ match_byte_assert(2);
+ match_zeros_assert(32);
+ }
+ else if (!strcmp(heading, "NavPivot"))
+ {
+ hex_dump(stdout, pos, 021);
+ pos += 0x21;
+ }
+ else if (!strcmp(heading, "DspCell"))
+ parse_DspCell();
+ else if (!strcmp(heading, "DspSimpleText"))
+ parse_DspSimpleText();
+ else if (!strcmp(heading, "DspNumber"))
+ parse_DspNumber();
+ else if (!strcmp(heading, "DspString"))
+ parse_DspString();
+ else if (!strcmp(heading, "NavHead"))
+ parse_NavHead();
+ else if (!strcmp(heading, "NavTreeViewItem"))
+ {
+ if (0)
+ parse_NavTreeViewItem();
+ else
+ skip_item(heading);
+ }
+ else if (!strcmp(heading, "IndexedCollection"))
+ parse_IndexedCollection();
+ else if (!strcmp(heading, "NavOleItem"))
+ parse_NavOleItem();
+ else if (!strcmp(heading, "NavTitle"))
+ parse_NavTitle();
+ else if (!strcmp(heading, "NavNote"))
+ parse_NavNote();
+ else if (!strcmp(heading, "PTPivotController"))
+ parse_PTPivotController();
+ else if (!strcmp(heading, "PVPivotView"))
+ parse_PVPivotView();
+ else if (!strcmp(heading, "PMPivotModel"))
+ match_byte_assert(3);
+ else if (!strcmp(heading, "NDimensional__DspCell"))
+ parse_NDimensional__DspCell();
+ else if (!strcmp(heading, "PMPivotItemTree"))
+ match_byte_assert(0);
+ else if (!strcmp(heading, "PMModelItemInfo"))
+ parse_PMModelItemInfo();
+ else if (!strcmp(heading, "AbstractTreeBranch"))
+ match_byte_assert(0);
+ else if (!strcmp(heading, "PTTableLook"))
+ parse_PTTableLook();
+ else if (!strcmp(heading, "PVViewDimension"))
+ parse_PVViewDimension();
+ else if (!strcmp(heading, "PVSeparatorStyle"))
+ parse_PVSeparatorStyle();
+ else if (!strcmp(heading, "PVCellStyle"))
+ parse_PVCellStyle();
+ else if (!strcmp(heading, "PVTextStyle"))
+ exit(0);
+ else
+ {
+ fprintf(stderr, "don't know %s at offset 0x%x: ", heading, start);
+ hex_dump(stderr, pos, 128);
+ assert(0);
+ }
+ }
+ else if (data[pos + 1] == 0x80)
+ {
+ if ((data[pos] == 0x2a || data[pos] == 0x18 || data[pos] == 0x19) && data[pos + 1] == 0x80)
+ match_DspNumber();
+ else if (data[pos] == 0x27 && data[pos + 1] == 0x80)
+ match_DspCell();
+ else if (data[pos] == 0x5 && data[pos + 1] == 0x80)
+ match_DspString();
+ else if (data[pos] == 0x7 && data[pos + 1] == 0x80)
+ match_NavTreeViewItem();
+ else if (data[pos] == 0x3 && data[pos + 1] == 0x80)
+ match_DspSimpleText();
+ else if ((data[pos] == 0x3c || data[pos] == 0x39)
+ && data[pos + 1] == 0x80)
+ {
+ /* 3c 80 */
+ /* 39 80 */
+ printf("%#x: %02x %02x ", pos, data[pos], data[pos + 1]);
+ pos += 2;
+ parse_format();
+ printf ("\n");
+/* match_byte_assert(0x01);
+ match_byte_assert(0x02);
+ match_byte_assert(0x0d); */
+ }
+ else if ((data[pos] == 0x15 || data[pos] == 0x14)
+ && data[pos + 1] == 0x80)
+ {
+ /* 14 80 */
+ /* 15 80 */
+ pos += 2;
+ if (match_byte(2))
+ {
+ printf ("%02x 80(%f", data[pos - 2], get_double());
+ printf (" \"%s\")\n", get_string1());
+ if (match_byte(1))
+ {
+ match_byte_assert(0);
+ get_string1();
+ if (!match_byte(2) && !match_byte(3))
+ match_byte_assert(0);
+ match_zeros_assert(3);
+ get_string1();
+ match_byte_assert(0);
+ match_byte_assert(1);
+ match_zeros_assert(3);
+ match_byte_assert(1);
+ match_byte_assert(0);
+ }
+ }
+ else
+ {
+ match_byte_assert(0);
+ }
+ }
+ else if (data[pos] == 0x17)
+ {
+ printf("%02x %02x(%02x %02x %02x)\n",
+ data[pos], data[pos + 1],
+ data[pos + 2], data[pos + 3], data[pos + 4]);
+ pos += 5;
+ }
+ else if (data[pos] == 0x9 && data[pos + 1] == 0x80)
+ {
+ match_NavLog();
+ }
+ else if (data[pos] == 0xe || data[pos] == 0x12)
+ match_NavOleItem();
+ else if (data[pos] == 0x11 || data[pos] == 0x13)
+ {
+ int type = data[pos];
+ pos += 2;
+ match_byte_assert(0);
+ if (data[pos] != 0)
+ {
+ int x = get_u32();
+ int y = get_u16();
+ if (y == 0)
+ {
+ int index = get_u32();
+ printf("%02x 80(footnote %d)\n", type, index);
+ }
+ else
+ printf("%02x 80(%d %d)\n", type, x, y);
+ }
+ else
+ match_zeros_assert(13);
+ }
+ else if (data[pos] == 0x29 ||
+ data[pos] == 0x2b ||
+ data[pos] == 0x2d ||
+ data[pos] == 0x31 ||
+ data[pos] == 0x32 ||
+ data[pos] == 0x4a ||
+ data[pos] == 0x4c ||
+ data[pos] == 0x4f ||
+ data[pos] == 0x4d ||
+ data[pos] == 0x50 ||
+ data[pos] == 0x36 ||
+ data[pos] == 0x52 ||
+ data[pos] == 0x53 ||
+ data[pos] == 0x54 ||
+ data[pos] == 0x55 ||
+ data[pos] == 0x57 ||
+ data[pos] == 0x56 ||
+ data[pos] == 0x58 ||
+ data[pos] == 0x5c ||
+ data[pos] == 0x5b ||
+ data[pos] == 0x5e ||
+ data[pos] == 0x62 ||
+ data[pos] == 0x64 ||
+ data[pos] == 0x4e ||
+ data[pos] == 0x51 ||
+ data[pos] == 0x59 ||
+ data[pos] == 0x5a ||
+ data[pos] == 0x5d ||
+ data[pos] == 0x66 ||
+ data[pos] == 0x60 ||
+ data[pos] == 0x68 ||
+ data[pos] == 0x48 ||
+ data[pos] == 0x6a ||
+ data[pos] == 0x37)
+ {
+ pos += 2;
+ match_byte_assert(0);
+ }
+ else if (data[pos] == 0x2c ||
+ data[pos] == 0x2e ||
+ data[pos] == 0x30 ||
+ data[pos] == 0x34 ||
+ data[pos] == 0x3d ||
+ data[pos] == 0x40 ||
+ data[pos] == 0x3f ||
+ data[pos] == 0x42 ||
+ data[pos] == 0x43 ||
+ data[pos] == 0x44 ||
+ data[pos] == 0x49 ||
+ data[pos] == 0x3e ||
+ data[pos] == 0x46)
+ {
+ printf ("%#x: %02x %02x(%02x %02x %02x)\n",
+ pos, data[pos], data[pos + 1],
+ data[pos + 2], data[pos + 3], data[pos + 4]);
+ pos += 2;
+ pos += 3;
+ }
+ else
+ {
+ fprintf (stderr, "%#x: unknown record", pos);
+ hex_dump (stderr, pos, 64);
+ exit(1);
+ }
+ }
+ else if (match_byte(0xa))
+ {
+ if (!match_byte(7))
+ match_byte_assert(0);
+ if (match_u16(0x0e74))
+ match_byte_assert(0);
+ else
+ {
+ match_zeros_assert(4);
+ if (pos == n)
+ exit (0);
+ match_zeros_assert (2);
+ }
+ }
+#if 0
+ else if (match_byte(1))
+ {
+ match_byte_assert(0);
+ get_string1();
+ if (!match_byte(2))
+ match_byte_assert(0);
+ if (match_byte(0))
+ {
+ match_zeros_assert(2);
+ get_string1();
+ if (match_byte(0x08))
+ {
+ match_byte_assert(0);
+ match_u16_assert(0x0e74);
+ match_byte_assert(0);
+ }
+ else if (match_byte(3))
+ {
+ match_byte_assert(0);
+ if (match_u16(0x0e74))
+ match_byte_assert(0);
+ else
+ {
+ match_zeros_assert(6);
+ if (!match_byte(0xe) && !match_byte(0x11))
+ match_byte_assert(0);
+ match_byte_assert(0);
+ if (!match_u16(0x0e74))
+ match_u16_assert(0);
+ match_byte_assert(0);
+ }
+ }
+ else
+ {
+ match_byte_assert(0);
+ match_byte_assert(1);
+ match_zeros_assert(3);
+ match_byte_assert(1);
+ match_byte_assert(0);
+ }
+ }
+ }
+#endif
+ else if (match_u16(1))
+ {
+ int start_pos = pos;
+ char *title = get_string1();
+ printf("%#x: title(\"%s\", ", start_pos, title);
+ if (!match_u32(2))
+ match_u32_assert(0);
+ char *id = get_string1();
+ printf("\"%s\")\n", id);
+ match_byte_assert(0);
+ if (!match_u32(2))
+ match_u32_assert(3);
+ match_u16_assert(1);
+ }
+ 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))
+ skip_item("unknown");
+#if 0
+ 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))
+ {
+ if (!match_byte(7))
+ match_byte_assert(0);
+ if (!match_u16(0x0e74))
+ match_byte_assert(0);
+ match_byte_assert(0);
+ }
+ else if (match_byte(2) || match_byte(3))
+ {
+ match_byte_assert(0);
+ if (!match_u16(0x0e74))
+ {
+ match_zeros_assert(2);
+ if (match_byte(0))
+ {
+ match_zeros_assert(3);
+ if (match_byte(0))
+ match_zeros_assert(4);
+ else
+ {
+ pos++;
+ match_byte(0);
+ match_u16_assert(0x0e74);
+ }
+ }
+ }
+ //match_byte_assert(0);
+ }
+ else if (match_byte(0xd) || match_byte(0xe) || match_byte(0xf)
+ || match_byte(0x11) || match_byte(0x12) || match_byte(0x13)
+ || match_byte(0x14) || match_byte(0x1b))
+ {
+ if (!match_byte(0x07))
+ match_byte_assert(0);
+ if (!match_u16(0x0e74))
+ match_zeros_assert(11);
+ else
+ match_byte_assert(0);
+ }
+ else if (match_byte(0xe3) || match_byte(0xdb) || match_byte(0xd8) || match_byte(0xe9) || match_byte(0xf3))
+ {
+ match_byte_assert(0x0e);
+ match_byte_assert(0x74);
+ match_byte_assert(0x0e);
+ match_byte_assert(0);
+ }
+ else if (match_byte(0x9d) || match_byte(0x9e) || match_byte(0x9c))
+ match_u32_assert(0x000e741a);
+ else if (match_byte(0x10))
+ {
+ match_byte_assert(0);
+ if (match_byte(0))
+ match_zeros_assert(10);
+ else
+ {
+ match_u16_assert(0x0e74);
+ match_byte_assert(0);
+ }
+ }
+ else if (match_byte(0x39) || match_byte(0x3a) || match_byte(0x3b))
+ match_u32_assert(0x000e7409);
+ else
+ {
+ //fprintf (stderr, "bad record start at offset %x: ", pos);
+ hex_dump (stderr, pos, 64);
+ assert(0);
+ }
+#endif
+}
+
+
+