return false;
}
+bool
+match_u16(uint16_t x)
+{
+ if (get_u16() == x)
+ return true;
+ pos -= 2;
+ return false;
+}
+
static void
match_u32_assert(uint32_t x, const char *where)
{
}
#define match_u32_assert(x) match_u32_assert(x, WHERE)
+static void
+match_u16_assert(uint16_t x, const char *where)
+{
+ unsigned int y = get_u16();
+ if (x != y)
+ {
+ fprintf(stderr, "%s: 0x%x: expected u16:%u, got u16:%u\n", where, pos - 2, x, y);
+ exit(1);
+ }
+}
+#define match_u16_assert(x) match_u16_assert(x, WHERE)
+
static bool __attribute__((unused))
match_u64(uint64_t x)
{
return true;
}
+static char *
+xmemdup0(const void *p, size_t n)
+{
+ char *s = malloc(n + 1);
+ memcpy(s, p, n);
+ s[n] = 0;
+ return s;
+}
+
static bool
get_bool(void)
{
return (p >= ' ' && p < 127) || p == '\r' || p == '\n' || p == '\t';
}
+static int
+count_zeros(const uint8_t *p)
+{
+ size_t n = 0;
+ while (p[n] == 0)
+ n++;
+ return n;
+}
+
static bool __attribute__((unused))
all_utf8(const char *p_, size_t len)
{
return true;
}
+static char *
+get_string1(void)
+{
+ int len = data[pos++];
+ char *s = xmemdup0(&data[pos], len);
+ pos += len;
+ return s;
+}
+
+static char *
+get_string2(void)
+{
+ int len = data[pos] + data[pos + 1] * 256;
+ char *s = xmemdup0(&data[pos + 2], len);
+ pos += 2 + len;
+ return s;
+}
+
static char *
get_string(const char *where)
{
putc('\n', stream);
}
-static char *
-dump_counted_string(void)
-{
- int inner_end = get_end();
- if (pos == inner_end)
- return NULL;
-
- if (match_u32(5))
- {
- match_u32_assert(0);
- match_byte_assert(0x58);
- }
- else
- match_u32_assert(0);
-
- char *s = NULL;
- if (match_byte(0x31))
- s = get_string();
- else
- match_byte_assert(0x58);
- if (pos != inner_end)
- {
- fprintf(stderr, "inner end discrepancy\n");
- exit(1);
- }
- return s;
-}
-
-static void
-dump_style(FILE *stream)
-{
- if (match_byte(0x58))
- return;
-
- match_byte_assert(0x31);
- if (get_bool())
- printf (" bold=\"yes\"");
- if (get_bool())
- printf (" italic=\"yes\"");
- if (get_bool())
- printf (" underline=\"yes\"");
- if (!get_bool())
- printf (" show=\"no\"");
- char *fg = get_string(); /* foreground */
- char *bg = get_string(); /* background */
- char *font = get_string(); /* font */
- int size = get_byte() * (72. / 96.);
- fprintf(stream, " fgcolor=\"%s\" bgcolor=\"%s\" font=\"%s\" size=\"%dpt\"",
- fg, bg, font, size);
-}
-
-static void
-dump_style2(FILE *stream)
-{
- if (match_byte(0x58))
- return;
-
- match_byte_assert(0x31);
- uint32_t halign = get_u32();
- printf (" halign=\"%s\"",
- halign == 0 ? "center"
- : halign == 2 ? "left"
- : halign == 4 ? "right"
- : halign == 6 ? "decimal"
- : halign == 0xffffffad ? "mixed"
- : "<error>");
- int valign = get_u32();
- printf (" valign=\"%s\"",
- valign == 0 ? "center"
- : valign == 1 ? "top"
- : valign == 3 ? "bottom"
- : "<error>");
- printf (" offset=\"%gpt\"", get_double());
- int l = get_u16();
- int r = get_u16();
- int t = get_u16();
- int b = get_u16();
- printf (" margins=\"%d %d %d %d\"", l, r, t, b);
-}
-static char *
-dump_nested_string(FILE *stream)
+static int
+compare_int(const void *a_, const void *b_)
{
- char *s = NULL;
-
- match_byte_assert (0);
- match_byte_assert (0);
- int outer_end = get_end();
- s = dump_counted_string();
- if (s)
- fprintf(stream, " \"%s\"", s);
- dump_style(stream);
- match_byte_assert(0x58);
- if (pos != outer_end)
- {
- fprintf(stderr, "outer end discrepancy\n");
- exit(1);
- }
-
- return s;
+ const int *a = a_;
+ const int *b = b_;
+ return *a < *b ? -1 : *a > *b;
}
-static void
-dump_value_modifier(FILE *stream)
-{
- if (match_byte (0x31))
- {
- if (match_u32 (0))
- {
- fprintf(stream, "<special0");
- if (match_u32 (1))
- {
- /* Corpus frequencies:
- 124 "a"
- 12 "b"
- 8 "a, b"
-
- The given text is appended to the cell in a subscript font.
- */
- fprintf(stream, " subscript=\"%s\"", get_string());
- }
- else
- match_u32_assert (0);
-
- if (version == 1)
- {
- /* We only have one SPV file for this version (with many
- tables). */
- match_byte(0);
- if (!match_u32(1))
- match_u32_assert(2);
- match_byte(0);
- match_byte(0);
- 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))
- match_u32_assert(10);
- match_byte(0);
- match_byte(0);
- fprintf(stream, "/>\n");
- return;
- }
-
- int outer_end = get_end();
-
- /* This counted-string appears to be a template string,
- e.g. "Design\: [:^1:]1 Within Subjects Design\: [:^1:]2". */
- char *template = dump_counted_string();
- if (template)
- fprintf(stream, " template=\"%s\"", template);
-
- dump_style(stream);
- dump_style2(stream);
- if (pos != outer_end)
- {
- fprintf(stderr, "outer end discrepancy\n");
- exit(1);
- }
- fprintf(stream, "/>\n");
- }
- else
- {
- int count = get_u32();
- fprintf(stream, "<footnote-ref indexes=\"");
- for (int i = 0; i < count; i++)
- {
- if (i)
- putc(' ', stream);
- fprintf(stream, "%d", get_u16());
- }
- putc('"', stream);
- match_byte_assert(0);
- match_byte_assert(0);
- dump_nested_string(stream);
- fprintf(stream, "/>\n");
- }
- }
- else
- match_byte_assert (0x58);
-}
static const char *
-format_to_string (int type)
+format_name (int format, char *buf)
{
- static char tmp[16];
- switch (type)
+ switch (format)
{
case 1: return "A";
case 2: return "AHEX";
case 37: return "CCE";
case 38: return "EDATE";
case 39: return "SDATE";
- default:
- abort();
- sprintf(tmp, "<%d>", type);
- return tmp;
+ default: sprintf(buf, "(%d)", format); return buf;
}
}
static void
-dump_value(FILE *stream, int level)
+dump_DspNumber(void)
{
- match_byte(0);
- match_byte(0);
- match_byte(0);
- match_byte(0);
-
- for (int i = 0; i <= level; i++)
- fprintf (stream, " ");
-
- printf ("%02x: value (%d)\n", pos, data[pos]);
- if (match_byte (1))
- {
- unsigned int format;
- double value;
-
- dump_value_modifier(stream);
- format = get_u32 ();
- value = get_double ();
- fprintf (stream, "<number value=\"%.*g\" format=\"%s%d.%d\"/>\n",
- DBL_DIG, value, format_to_string(format >> 16), (format >> 8) & 0xff, format & 0xff);
- }
- else if (match_byte (2))
- {
- unsigned int format;
- char *var, *vallab;
- double value;
-
- dump_value_modifier (stream);
- format = get_u32 ();
- value = get_double ();
- var = get_string ();
- vallab = get_string ();
- fprintf (stream, "<numeric-datum value=\"%.*g\" format=\"%s%d.%d\"",
- DBL_DIG, value, format_to_string(format >> 16), (format >> 8) & 0xff, format & 0xff);
- if (var[0])
- fprintf (stream, " variable=\"%s\"", var);
- if (vallab[0])
- fprintf (stream, " label=\"%s\"", vallab);
- fprintf (stream, "/>\n");
- if (!match_byte (1) && !match_byte(2))
- match_byte_assert (3);
- }
- else if (match_byte (3))
- {
- char *text = get_string();
- dump_value_modifier(stream);
- char *identifier = get_string();
- char *text_eng = get_string();
- fprintf (stream, "<string c=\"%s\"", text_eng);
- if (identifier[0])
- fprintf (stream, " identifier=\"%s\"", identifier);
- if (strcmp(text_eng, text))
- fprintf (stream, " local=\"%s\"", text);
- fprintf (stream, "/>\n");
- if (!match_byte (0))
- match_byte_assert(1);
- }
- else if (match_byte (4))
- {
- unsigned int format;
- char *var, *vallab, *value;
-
- dump_value_modifier(stream);
- format = get_u32 ();
- vallab = get_string ();
- var = get_string ();
- if (!match_byte(1) && !match_byte(2))
- match_byte_assert (3);
- value = get_string ();
- fprintf (stream, "<string-datum value=\"%s\" format=\"%s%d.%d\"",
- value, format_to_string(format >> 16), (format >> 8) & 0xff, format & 0xff);
- if (var[0])
- fprintf (stream, " variable=\"%s\"", var);
- if (vallab[0])
- fprintf (stream, " label=\"%s\"/>\n", vallab);
- fprintf (stream, "/>\n");
- }
- else if (match_byte (5))
- {
- dump_value_modifier(stream);
- char *name = get_string ();
- char *label = get_string ();
- fprintf (stream, "<variable name=\"%s\"", name);
- if (label[0])
- fprintf (stream, " label=\"%s\"", label);
- fprintf (stream, "/>\n");
- if (!match_byte(1) && !match_byte(2))
- match_byte_assert(3);
- }
- else
+ match_byte_assert(1);
+ int d = get_byte();
+ int w = get_byte();
+ int fmt = get_byte();
+ char buf[64];
+ printf ("%s%d.%d ", format_name (fmt, buf), w, d);
+
+ match_byte_assert(0x80);
+ match_byte_assert(2);
+ printf ("%f ", get_double ());
+ printf ("\"%s\"\n", get_string1 ());
+
+ for (;;)
{
- printf ("else %#x\n", pos);
- dump_value_modifier(stream);
-
- char *base = get_string();
- int x = get_u32();
- fprintf (stream, "<template format=\"%s\">\n", base);
- for (int i = 0; i < x; i++)
+ if (data[pos] == 0xff)
{
- int y = get_u32();
- if (!y)
- y = 1;
- else
- match_u32_assert(0);
- for (int j = 0; j <= level + 1; j++)
- fprintf (stream, " ");
- fprintf (stream, "<substitution index=\"%d\">\n", i + 1);
- for (int j = 0; j < y; j++)
- dump_value (stream, level + 2);
- for (int j = 0; j <= level + 1; j++)
- fprintf (stream, " ");
- fprintf (stream, "</substitution>\n");
+ printf ("\nff exit");
+ break;
}
- for (int j = 0; j <= level; j++)
- fprintf (stream, " ");
- fprintf (stream, "</template>\n");
- }
-}
-
-static int
-compare_int(const void *a_, const void *b_)
-{
- const int *a = a_;
- const int *b = b_;
- return *a < *b ? -1 : *a > *b;
-}
-
-static void
-check_permutation(int *a, int n, const char *name)
-{
- int b[n];
- memcpy(b, a, n * sizeof *a);
- qsort(b, n, sizeof *b, compare_int);
- for (int i = 0; i < n; i++)
- if (b[i] != i)
- {
- fprintf(stderr, "bad %s permutation:", name);
- for (int i = 0; i < n; i++)
- fprintf(stderr, " %d", a[i]);
- putc('\n', stderr);
- exit(1);
- }
-}
-
-static void
-dump_category(FILE *stream, int level, int **indexes, int *allocated_indexes,
- int *n_indexes)
-{
- for (int i = 0; i <= level; i++)
- fprintf (stream, " ");
- printf ("<category>\n");
- dump_value (stream, level + 1);
-
- bool merge = get_bool();
- match_byte_assert (0);
- int unindexed = get_bool();
-
- int x = get_u32 ();
- pos -= 4;
- if (!match_u32 (0))
- match_u32_assert (2);
- int indx = get_u32();
- int n_categories = get_u32();
- if (indx == -1)
- {
- if (merge)
+ if (data[pos] == 0x80 && data[pos + 1] == 1)
{
- for (int i = 0; i <= level + 1; i++)
- fprintf (stream, " ");
- fprintf (stream, "<merge/>\n");
+ pos += 2;
+ int d = get_byte();
+ int w = get_byte();
+ int fmt = get_byte();
+ char buf[64];
+ printf ("\n%% %s%d.%d\n", format_name (fmt, buf), w, d);
}
- assert (unindexed);
- }
- else
- {
- assert (!merge);
- assert (!unindexed);
- assert (x == 2);
- assert (n_categories == 0);
- if (*n_indexes >= *allocated_indexes)
+ else if (data[pos] == 0x80 && data[pos + 1] == 2)
{
- *allocated_indexes = *allocated_indexes ? 2 * *allocated_indexes : 16;
- *indexes = realloc(*indexes, *allocated_indexes * sizeof **indexes);
+ pos += 2;
+ printf ("\n%f ", get_double ());
+ printf ("'%s'\n", get_string1 ());
}
- (*indexes)[(*n_indexes)++] = indx;
- }
-
- if (n_categories == 0)
- {
- for (int i = 0; i <= level + 1; i++)
- fprintf (stream, " ");
- fprintf (stream, "<category-index>%d</category-index>\n", indx);
- }
- for (int i = 0; i < n_categories; i++)
- dump_category (stream, level + 1, indexes, allocated_indexes, n_indexes);
- for (int i = 0; i <= level; i++)
- fprintf (stream, " ");
- printf ("</category>\n");
-}
-
-static int
-dump_dim(int indx)
-{
- int n_categories;
-
- printf ("<dimension index=\"%d\">\n", indx);
- dump_value (stdout, 0);
-
- /* This byte is usually 0 but many other values have been spotted.
- No visible effect. */
- pos++;
-
- /* This byte can cause data to be oddly replicated. */
- if (!match_byte(0) && !match_byte(1))
- match_byte_assert(2);
-
- if (!match_u32(0))
- match_u32_assert(2);
-
- bool show_dim_label = get_bool();
- if (show_dim_label)
- printf(" <show-dim-label/>\n");
-
- bool hide_all_labels = get_bool();
- if (hide_all_labels)
- printf(" <hide-all-labels/>\n");
-
- match_byte_assert(1);
- if (!match_u32(UINT32_MAX))
- match_u32_assert(indx);
-
- n_categories = get_u32();
-
- int *indexes = NULL;
- int n_indexes = 0;
- int allocated_indexes = 0;
- for (int i = 0; i < n_categories; i++)
- dump_category (stdout, 0, &indexes, &allocated_indexes, &n_indexes);
- check_permutation(indexes, n_indexes, "categories");
-
- fprintf (stdout, "</dimension>\n");
- return n_indexes;
-}
-
-int n_dims;
-static int dim_n_cats[64];
-#define MAX_DIMS (sizeof dim_n_cats / sizeof *dim_n_cats)
-
-static void
-dump_dims(void)
-{
- n_dims = get_u32();
- assert(n_dims < MAX_DIMS);
- for (int i = 0; i < n_dims; i++)
- dim_n_cats[i] = dump_dim (i);
-}
-
-static void
-dump_data(void)
-{
- /* The first three numbers add to the number of dimensions. */
- int l = get_u32();
- int r = get_u32();
- int c = n_dims - l - r;
- match_u32_assert(c);
-
- /* The next n_dims numbers are a permutation of the dimension numbers. */
- int a[n_dims];
- for (int i = 0; i < n_dims; i++)
- {
- int dim = get_u32();
- a[i] = dim;
-
- const char *name = i < l ? "layer" : i < l + r ? "row" : "column";
- printf ("<%s dimension=\"%d\"/>\n", name, dim);
- }
- check_permutation(a, n_dims, "dimensions");
-
- int x = get_u32();
- printf ("<data>\n");
- for (int i = 0; i < x; i++)
- {
- unsigned int indx = get_u32();
- printf (" <datum index=\"%d\" coords=", indx);
-
- int coords[MAX_DIMS];
- for (int i = n_dims; i-- > 0; )
+ else if (data[pos] == 0x80 && data[pos + 1] == 0 && data[pos + 2] == 3)
+ pos += 3;
+ else if (data[pos] == 0x80 && count_zeros(&data[pos + 1]) == 10)
+ pos += 11;
+ else if (data[pos] == 0x1 && data[pos + 1] == 0xff)
+ {
+ pos += 2;
+ printf ("\n\"%s\"\n", get_string2 ());
+ }
+ else if (data[pos] == 0x1 && data[pos + 1])
{
- coords[i] = indx % dim_n_cats[i];
- indx /= dim_n_cats[i];
+ pos += 1;
+ printf ("\n\"%s\"\n", get_string1 ());
}
- for (int i = 0; i < n_dims; i++)
- printf("%c%d", i ? ',' : '"', coords[i]);
-
- printf ("\">\n");
- match_u32_assert(0);
- if (version == 1)
- match_byte(0);
- dump_value(stdout, 1);
- fprintf (stdout, " </datum>\n");
+ else
+ printf ("%02x ", get_byte());
}
- printf ("</data>\n");
}
static void
-dump_title(void)
+dump_cell(void)
{
- printf ("<title-local>\n");
- dump_value(stdout, 0);
- match_byte(1);
- printf ("</title-local>\n");
-
- printf ("<subtype>\n");
- dump_value(stdout, 0);
- match_byte(1);
- printf ("</subtype>\n");
-
- match_byte_assert(0x31);
-
- printf ("<title-c>\n");
- dump_value(stdout, 0);
- match_byte(1);
- printf ("</title-c>\n");
-
- if (match_byte(0x31))
+ static const int cell_prefix[] = {
+ 0x00, 0x03, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, -1 /* 00 or 10 */, 0x00, 0x00, 0x00, 0x00,
+
+ /*13 14 15 16 17 18 19 */
+ -1, 0x80, 0x01, -1, -1, -1, -1,
+ };
+ size_t cell_prefix_len = sizeof cell_prefix / sizeof *cell_prefix;
+ if (!match_bytes(pos, cell_prefix, cell_prefix_len))
{
- printf ("<user-caption>\n");
- dump_value(stdout, 0);
- printf ("</user-caption>\n");
+ printf ("match failed at %x\n", pos);
+ return;
}
- else
- match_byte_assert(0x58);
- if (match_byte(0x31))
- {
- printf ("<caption>\n");
- dump_value(stdout, 0);
- printf ("</caption>\n");
- }
- else
- match_byte_assert(0x58);
- int n_footnotes = get_u32();
- for (int i = 0; i < n_footnotes; i++)
+ char buf[64];
+ printf ("cell %s%d.%d ",
+ format_name (data[pos + 18], buf),
+ data[pos + 17],
+ data[pos + 16]);
+
+ int len = cell_prefix_len;
+ if (data[pos + 19] == 0)
{
- printf ("<footnote index=\"%d\">\n", i);
- dump_value(stdout, 0);
- /* Custom footnote marker string. */
- if (match_byte (0x31))
- dump_value(stdout, 0);
- else
- match_byte_assert (0x58);
- int n = get_u32();
- if (n >= 0)
+ assert (data[pos + 13] == 5);
+ if (data[pos + 20] == 0)
+ {
+ int count = (data[pos + 22]);
+ printf ("%d %d \"%.*s\"",
+ data[pos + 21], data[pos + 22],
+ count, &data[pos + 23]);
+ len = 23 + count;
+ }
+ else if (data[pos + 20] == 1
+ && data[pos + 21] == 0xff
+ && data[pos + 22] == 0xff)
{
- /* Appears to be the number of references to a footnote. */
- printf (" <references n=\"%d\"/>\n", n);
+ int count = 255;
+ printf ("%d \"%.*s\"", count, data[pos + 23],
+ &data[pos + 24]);
+ len = 23 + count;
}
- else if (n == -2)
+ else if (data[pos + 20] == 1 && data[pos + 21] == 255)
{
- /* The user deleted the footnote references. */
- printf (" <deleted/>\n");
+ int count = data[pos + 22] + (data[pos + 23] << 8);
+ printf ("\"%.*s\"",
+ count, &data[pos + 24]);
+ len = 24 + count;
+ }
+ else if (data[pos + 20] == 1)
+ {
+ int count = (data[pos + 21]);
+ printf ("\"%.*s\"",
+ count, &data[pos + 22]);
+ len = 22 + count;
}
else
- assert(0);
- printf ("</footnote>\n");
+ assert (false);
}
-}
-
-static void
-dump_fonts(void)
-{
- match_byte(0);
- for (int i = 1; i <= 8; i++)
+ else if (data[pos + 19] == 128 && data[pos + 20] == 2)
{
- printf ("<style index=\"%d\"", i);
- match_byte_assert(i);
- match_byte_assert(0x31);
- printf(" font=\"%s\"", get_string());
-
- printf(" size=\"%gpt\"", get_float());
-
- int style = get_u32();
- if (style & 1)
- printf(" bold=\"true\"");
- if (style & 2)
- printf(" italic=\"true\"");
-
- bool underline = data[pos++];
- if (underline)
- printf(" underline=\"true\"");
-
- int halign = get_u32();
- printf(" halign=%d", halign);
-
- int valign = get_u32();
- printf(" valign=%d", valign);
-
- printf (" fgcolor=\"%s\"", get_string());
- printf (" bgcolor=\"%s\"", get_string());
-
- if (!match_byte(0))
- match_byte_assert(1);
-
- char *alt_fgcolor = get_string();
- if (alt_fgcolor[0])
- printf (" altfg=\"%s\"", alt_fgcolor);
- char *alt_bgcolor = get_string();
- if (alt_bgcolor[0])
- printf (" altbg=\"%s\"", alt_bgcolor);
-
- if (version > 1)
+ /* pos + 13 is usually 22...53, and it's 3 more than the
+ " xx 80" separator between cells */
+ printf ("xxx%x ", data[pos + 13]);
+ double d = *(double *) &data[pos + 21];
+ len = 29;
+ const union
{
- printf(" margins=\"");
- for (int i = 0; i < 4; i++)
- {
- if (i)
- putchar(' ');
- printf("%d", get_u32());
- }
- putchar('"');
+ uint8_t b[8];
+ double d;
}
+ sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}};
+ if (d == sysmis.d)
+ printf ("sysmis");
+ else
+ printf ("%f", d);
- printf ("/>\n");
- }
-
- int x1 = get_u32();
- int x1_end = pos + x1;
- printf("<borders>\n");
- match_be32_assert(1);
- int n_borders = get_be32();
- for (int i = 0; i < n_borders; i++)
- {
- int type = get_be32();
- int stroke = get_be32();
- int color = get_be32();
- printf(" <border type=\"%d\" stroke=\"%s\" color=\"#%06x\"/>\n",
- type,
- (stroke == 0 ? "none"
- : stroke == 1 ? "solid"
- : stroke == 2 ? "dashed"
- : stroke == 3 ? "thick"
- : stroke == 4 ? "thin"
- : stroke == 5 ? "double"
- : "<error>"),
- color);
- }
- bool grid = get_byte();
- pos += 3;
- printf(" <grid show=\"%s\"/>\n", grid ? "yes" : "no");
- printf("</borders>\n");
- assert(pos == x1_end);
-
- int skip = get_u32();
- assert(skip == 18 || skip == 25);
- pos += skip;
-
- int x3 = get_u32();
- int x3_end = pos + x3;
- if (version == 3)
- {
- match_be32_assert(1);
- get_be32();
- printf("<settings layer=\"%d\"", get_be32());
- if (!get_bool())
- printf(" skipempty=\"false\"");
- if (!get_bool())
- printf(" showdimensionincorner=\"false\"");
- if (!get_bool())
- printf(" markers=\"numeric\"");
- if (!get_bool())
- printf(" footnoteposition=\"subscript\"");
- get_byte();
- int nbytes = get_be32();
- int end = pos + nbytes;
- printf("\n");
- while (pos + 4 <= end)
- printf(" %d", get_be32());
- pos = end;
- printf("\n");
- pos += nbytes;
- char *notes = get_string_be();
- if (notes[0])
- printf(" notes=\"%s\"", notes);
- char *look = get_string_be();
- if (look[0])
- printf(" look=\"%s\"", look);
- printf(">\n");
- }
- pos = x3_end;
-
- /* Manual column widths, if present. */
- int count = get_u32();
- if (count > 0)
- {
- printf("<columnwidths>");
- for (int i = 0; i < count; i++)
+ if (data[pos + 29] < 0xff
+ && all_utf8((char *) &data[pos + 30], data[pos + 29]))
{
- if (i)
- putchar(' ');
- printf("%d", get_u32());
+ printf (" \"%.*s\"", (int) data[pos + 29],
+ &data[pos + 30]);
+ len += data[pos + 29] + 1;
}
- printf("</columnwidths>\n");
+ else
+ assert (false);
}
-
- const char *locale = get_string();
- printf ("<locale>%s</locale>\n", locale);
-
- printf ("<layer>%d</layer>\n", get_u32());
- if (!match_byte(0))
- match_byte_assert(1);
- if (!match_byte(0))
- match_byte_assert(1);
- if (!match_byte(0))
- match_byte_assert(1);
- printf("<epoch>%d</epoch>\n", get_u32());
-
- int decimal = data[pos];
- int grouping = data[pos + 1];
- if (match_byte('.'))
+ else if (data[pos + 19] == 128 && data[pos + 20] == 1 &&
+ data[pos + 21] == 0)
{
- if (!match_byte(',') && !match_byte('\''))
- match_byte_assert(' ');
+ if (data[pos + 23] < 0xff
+ && all_utf8((char *) &data[pos + 24], data[pos + 23]))
+ {
+ printf (" \"%.*s\"", (int) data[pos + 23],
+ &data[pos + 24]);
+ len = 24 + data[pos + 23];
+ }
+ else
+ assert (false);
}
else
{
- match_byte_assert(',');
- if (!match_byte('.') && !match_byte(' ') && !match_byte(','))
- match_byte_assert(0);
- }
- printf("<format decimal=\"%c\"", decimal);
- if (grouping)
- printf(" grouping=\"%c\"", grouping);
- printf("\"/>\n");
- if (match_u32(5))
- {
- for (int i = 0; i < 5; i++)
- printf("<CC%c>%s</CC%c>\n", 'A' + i, get_string(), 'A' + i);
+ printf ("xxx%d %d %d %d",
+ data[pos + 19], data[pos + 20],
+ data[pos + 21], data[pos + 22]);
+ assert(false);
}
- else
- match_u32_assert(0);
-
- /* The last chunk is an outer envelope that contains two inner envelopes.
- The second inner envelope has some interesting data like the encoding and
- the locale. */
- int outer_end = get_end();
- if (version == 3)
- {
- /* First inner envelope: byte*33 int[n] int*[n]. */
- int inner_len = get_u32();
- int inner_end = pos + inner_len;
- int array_start = pos + 33;
- match_byte_assert(0);
- pos++; /* 0, 1, 10 seen. */
- get_bool();
-
- /* 0=en 1=de 2=es 3=it 5=ko 6=pl 8=zh-tw 10=pt_BR 11=fr */
- printf("lang=%d ", get_byte());
-
- printf ("variable_mode=%d\n", get_byte());
- printf ("value_mode=%d\n", get_byte());
- if (!match_u64(0))
- match_u64_assert(UINT64_MAX);
- match_u32_assert(0);
- match_u32_assert(0);
- match_u32_assert(0);
- match_u32_assert(0);
- match_byte_assert(0);
- get_bool();
- match_byte_assert(1);
- pos = array_start;
-
- assert(get_end() == inner_end);
- printf("<heights>");
- int n_heights = get_u32();
- for (int i = 0; i < n_heights; i++)
- {
- if (i)
- putchar(' ');
- printf("%d", get_u32());
- }
- printf("</heights>\n");
+ pos += len;
+}
- int n_style_map = get_u32();
- for (int i = 0; i < n_style_map; i++)
- {
- uint64_t cell = get_u64();
- int style = get_u16();
- printf("<style-map cell=\"%lu\" style=\"%d\"/>\n", cell, style);
- }
+static void
+dump_category (int level, uint8_t *delim, int *delim_len)
+{
+ int cat_index = get_u32();
+ assert (cat_index < 256);
- int n_styles = get_u32();
- for (int i = 0; i < n_styles; i++)
- {
- printf("<cell-style index=\"%d\"", i);
- dump_style(stdout);
- dump_style2(stdout);
- printf("/>\n");
- }
+ if (!match_u32 (0))
+ match_u32_assert (1);
- pos = get_end();
- assert(pos == inner_end);
+ get_u16();
- /* Second inner envelope. */
- assert(get_end() == outer_end);
+ if (!match_u16(0xe74) && !match_u16(0xffff))
+ match_u16_assert(0);
- match_byte_assert(1);
- match_byte_assert(0);
- if (!match_byte(3) && !match_byte(4))
- match_byte_assert(5);
- match_byte_assert(0);
- match_byte_assert(0);
- match_byte_assert(0);
+ for (int i = 0; i < level; i++)
+ printf (" ");
- printf("<command>%s</command>\n", get_string());
- printf("<command-local>%s</command-local>\n", get_string());
- printf("<language>%s</language>\n", get_string());
- printf("<charset>%s</charset>\n", get_string());
- printf("<locale>%s</locale>\n", get_string());
+ for (int i = 0; ; i++, pos++)
+ if (data[pos] == 5 && data[pos + 1] == 0x80)
+ break;
+ else if (i >= 100)
+ assert(false);
- get_bool();
- get_bool();
- get_bool();
- get_bool();
+ match_byte_assert (5);
+ match_byte_assert (0x80);
+ if (match_byte(2))
+ get_double ();
+ else
+ {
+ match_byte_assert (1);
+ match_byte_assert (2);
+ match_byte_assert (0x28);
+ match_byte_assert (5);
+ match_byte_assert (0);
+ match_byte_assert (1);
+ }
+ printf (" \"%s\"", get_string1());
- printf("<epoch2>%d</epoch2>\n", get_u32());
+ int n_children = get_u32();
+ assert (n_children < 256);
+ if (n_children)
+ printf (" (group with %d children)", n_children);
+ else
+ printf (" (category #%d)", cat_index);
+ printf ("\n");
- if (match_byte('.'))
- {
- if (!match_byte(',') && !match_byte('\''))
- match_byte_assert(' ');
- }
+ int dlen = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ if (data[pos + dlen] == 0xff)
+ dlen += 7;
else
- {
- match_byte_assert(',');
- if (!match_byte('.') && !match_byte(' ') && !match_byte(','))
- match_byte_assert(0);
- }
-
- printf ("small: %g\n", get_double());
-
- match_byte_assert(1);
- if (outer_end - pos > 6)
- {
- /* There might be a pair of strings representing a dataset and
- datafile name, or there might be a set of custom currency strings.
- The custom currency strings start with a pair of integers, so we
- can distinguish these from a string by checking for a null byte; a
- small 32-bit integer will always contain a null and a text string
- never will. */
- int save_pos = pos;
- int len = get_u32();
- bool has_dataset = !memchr(&data[pos], '\0', len);
- pos = save_pos;
-
- if (has_dataset)
- {
- printf("<dataset>%s</dataset>\n", get_string());
- printf("<datafile>%s</datafile>\n", get_string());
-
- match_u32_assert(0);
-
- time_t date = get_u32();
- struct tm tm = *localtime(&date);
- char s[128];
- strftime(s, sizeof s, "%a, %d %b %Y %H:%M:%S %z", &tm);
- printf("<date>%s</date>\n", s);
-
- match_u32_assert(0);
- }
- }
+ dlen += 3;
+ }
+ if (!*delim_len)
+ {
+ *delim_len = dlen;
+ memcpy(delim, &data[pos], dlen);
+ }
+ pos += dlen;
- if (match_u32(5))
- {
- for (int i = 0; i < 5; i++)
- printf("<CC%c>%s</CC%c>\n", 'A' + i, get_string(), 'A' + i);
- }
- else
- match_u32_assert(0);
+ for (int i = 0; i < n_children; i++)
+ dump_category (level + 1, delim, delim_len);
+}
- match_byte_assert('.');
- get_bool();
+static void
+dump_PMModelItemInfo(int ndims)
+{
+#if 0
+ if (data[pos + 9] && data[pos + 9] != 0xff)//count_zeros (&data[pos + 9]) < 4)
+ return;
+#endif
+
+ match_byte_assert (0);
- if (pos < outer_end)
- {
- get_u32();
- match_u32_assert(0);
- }
- assert(pos == outer_end);
+ uint8_t delim[14];
+ int delim_len = 0;
+ dump_category (0, delim, &delim_len);
+ assert(delim_len);
- pos = outer_end;
- }
- else if (outer_end != pos)
+ for (int i = 1; i < ndims; i++)
{
- pos += 14;
- printf("<command>%s</command>\n", get_string());
- printf("<command-local>%s</command-local>\n", get_string());
- printf("<language>%s</command>\n", get_string());
- printf("<charset>%s</charset>\n", get_string());
- printf("<locale>%s</locale>\n", get_string());
- get_bool();
- match_byte_assert(0);
- get_bool();
- get_bool();
-
- printf("<epoch2>%d</epoch2>\n", get_u32());
- int decimal = data[pos];
- int grouping = data[pos + 1];
- if (match_byte('.'))
- {
- if (!match_byte(',') && !match_byte('\''))
- match_byte_assert(' ');
- }
- else
+ for (int j = 0; ; j++, pos++)
{
- match_byte_assert(',');
- if (!match_byte('.') && !match_byte(' ') && !match_byte(','))
- match_byte_assert(0);
+ assert (pos + j + delim_len < n);
+ if (!memcmp(&data[pos], delim, delim_len))
+ break;
}
- printf("<format decimal=\"%c\"", decimal);
- if (grouping)
- printf(" grouping=\"%c\"", grouping);
- printf("\"/>\n");
- if (match_u32(5))
- {
- for (int i = 0; i < 5; i++)
- printf("<CC%c>%s</CC%c>\n", 'A' + i, get_string(), 'A' + i);
- }
- else
- match_u32_assert(0);
+ pos += delim_len;
- match_byte_assert('.');
- get_bool();
-
- assert(pos == outer_end);
- pos = outer_end;
- }
-}
-
-static const char *
-format_name (int format, char *buf)
-{
- switch (format)
- {
- case 1: return "A";
- case 2: return "AHEX";
- case 3: return "COMMA";
- case 4: return "DOLLAR";
- case 5: return "F";
- case 6: return "IB";
- case 7: return "PIBHEX";
- case 8: return "P";
- case 9: return "PIB";
- case 10: return "PK";
- case 11: return "RB";
- case 12: return "RBHEX";
- case 15: return "Z";
- case 16: return "N";
- case 17: return "E";
- case 20: return "DATE";
- case 21: return "TIME";
- case 22: return "DATETIME";
- case 23: return "ADATE";
- case 24: return "JDATE";
- case 25: return "DTIME";
- case 26: return "WKDAY";
- case 27: return "MONTH";
- case 28: return "MOYR";
- case 29: return "QYR";
- case 30: return "WKYR";
- case 31: return "PCT";
- case 32: return "DOT";
- case 33: return "CCA";
- case 34: return "CCB";
- case 35: return "CCC";
- case 36: return "CCD";
- case 37: return "CCE";
- case 38: return "EDATE";
- case 39: return "SDATE";
- case 40: return "MTIME";
- case 41: return "YMDHMS";
- default: sprintf(buf, "(%d)", format); return buf;
+ dump_category (0, delim, &delim_len);
}
}
int
main(int argc, char *argv[])
{
- if (argc != 2)
+ bool print_offsets = false;
+ for (;;)
+ {
+ int c = getopt (argc, argv, "o");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 'o':
+ print_offsets = true;
+ break;
+
+ case '?':
+ exit (-1);
+ }
+ }
+ if (argc - optind != 1)
{
fprintf (stderr, "usage: %s FILE.bin", argv[0]);
exit (1);
}
- filename = argv[1];
+ const char *filename = argv[optind];
int fd = open(filename, O_RDONLY);
if (fd < 0)
{
}
close(fd);
+ setvbuf (stdout, NULL, _IOLBF, 0);
+
+ pos = 0x39b;
+ unsigned int rtflen = get_u32();
+ pos += rtflen - 1; /* Almost past SPSS syntax */
+ assert(pos < n);
+ pos += 0x45 + data[pos + 0x44]; /* Just past the string */
+ pos += 0x1a + data[pos + 0x19]; /* Just past the string again */
+ pos += 0x66 + data[pos + 0x65]; /* Just past the third string */
+ pos += 0x4e;
+ rtflen = get_u32();
+ pos += rtflen - 1; /* Almost past 2nd RTF */
+ pos += 0x64 + data[pos + 0x63]; /* Just past the fourth string */
+ /* as-number: */
+ if (data[pos + 0x114] == 0xff)
+ pos += 0x117 + data[pos + 0x115] + 256 * data[pos + 0x116];
+ else
+ pos += 0x115 + data[pos + 0x114];
+ pos += 0x18 + data[pos + 0x17]; /* Just past "<none>" or dataset name. */
+ pos += 0x18 + data[pos + 0x17]; /* Just past "<none>" or dataset name. */
+ pos += count_zeros(&data[pos]); /* Skip optional zeros. */
+ pos += 0x18 + data[pos + 0x17]; /* Just past "<none>" or dataset name. */
+ pos += 0x3e + data[pos + 0x3d]; /* Skip past "100" etc. */
+ pos += count_zeros(&data[pos]); /* Skip optional zeros. */
+ pos += 0x18 + data[pos + 0x17]; /* Just past "User-defined...". */
+ pos += 0x18 + data[pos + 0x17]; /* Just past "Statistics are based... */
+ if (data[pos + 0x19] == 0xff)
+ pos += 0x1c + data[pos + 0x1a] + 256 * data[pos + 0x1b];
+ else
+ pos += 0x1a + data[pos + 0x19];
+ pos += 0x61 + data[pos + 0x60]; /* Just past "Cluster_Notes". */
+ pos += 0x992 + data[pos + 0x991]; /* Just past "Cluster". */
+ pos += 0x4e;
+ rtflen = get_u32();
+ pos += rtflen - 1; /* Almost past RTF with filesystem path */
+ pos += 0x45 + data[pos + 0x44]; /* Just past "Statistics" */
+ pos += 0x1a + data[pos + 0x19]; /* Just past "Cluster". */
+ fwrite (&data[pos], 1, n - pos, stdout);
+ exit (0);
+
+ int sum = 0;
+
#if 0
unsigned int prev_end = 0;
for (pos = 0; pos + 50 < n; pos++)
!all_utf8((char *) &data[pos + 3], 1) &&
data[pos - 1] != 'v')
{
- //printf ("%04x: ", pos);
+ if (print_offsets)
+ printf ("%04x: ", pos);
unsigned int p = pos;
while (all_utf8 ((char *) &data[p], 1))
p--;
}
#endif
unsigned int prev_end = 0;
- for (pos = 2; pos + 50 < n; pos++)
+ char *title = "";
+ int ndims = 0;
+ for (pos = 2; pos + 50 < n; )
{
static const int cell_prefix[] = {
0x00, 0x03,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, -1 /* 00 or 10 */, 0x00, 0x00, 0x00, 0x00, -1,
+
+ /*14 15 16 17 18 19 */
0x80, 0x01, -1, -1, -1, -1,
};
size_t cell_prefix_len = sizeof cell_prefix / sizeof *cell_prefix;
{
if (prev_end != pos)
{
- //printf ("%04x ", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
&data[pos + 24]);
len = 23 + count;
}
+ else if (data[pos + 20] == 1 && data[pos + 21] == 255)
+ {
+ int count = data[pos + 22] + (data[pos + 23] << 8);
+ printf ("\"%.*s\"\n",
+ count, &data[pos + 24]);
+ len = 24 + count;
+ }
else if (data[pos + 20] == 1)
{
int count = (data[pos + 21]);
len = 22 + count;
}
else
- abort ();
+ assert (false);
}
- else if (data[pos + 19] == 128)
+ else if (data[pos + 19] == 128 && data[pos + 20] == 2)
{
- /* pos + 13 is usually 22...53 but also 5 or 69 */
- /* pos + 20 is 2 most of the time, occasionally 1 */
- printf ("%d %d ", data[pos + 13], data[pos + 20]);
+ /* pos + 13 is usually 22...53, and it's 3 more than the
+ " xx 80" separator between cells */
+ printf ("xxx%x ", data[pos + 13]);
double d = *(double *) &data[pos + 21];
len = 29;
const union
}
sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}};
if (d == sysmis.d)
- printf ("sysmis\n");
+ printf ("sysmis");
+ else
+ printf ("%f", d);
+
+ if (data[pos + 29] < 0xff
+ && all_utf8((char *) &data[pos + 30], data[pos + 29]))
+ {
+ printf (" \"%.*s\"", (int) data[pos + 29],
+ &data[pos + 30]);
+ len += data[pos + 29] + 1;
+ }
else
- printf ("%f\n", d);
+ assert (false);
+
+ putchar ('\n');
+ }
+ else if (data[pos + 19] == 128 && data[pos + 20] == 1 &&
+ data[pos + 21] == 0)
+ {
+ if (data[pos + 23] < 0xff
+ && all_utf8((char *) &data[pos + 24], data[pos + 23]))
+ {
+ printf (" \"%.*s\"\n", (int) data[pos + 23],
+ &data[pos + 24]);
+ len = 24 + data[pos + 23];
+ }
+ else
+ assert (false);
}
else
- abort ();
- pos += len - 1;
- prev_end = pos + 1;
- continue;
- }
-
- static const int col_prefix[] = {
- 0x11, 0x80, 0x00, -1, 0x00, 0x00, 0x00, 0x01, 0x00
- };
- size_t col_prefix_len = sizeof col_prefix / sizeof *col_prefix;
- if (match_bytes(pos, col_prefix, col_prefix_len))
- {
- if (prev_end != pos)
{
- //printf ("%04x ", prev_end);
- hex_dump (stdout, prev_end, pos - prev_end);
+ printf ("xxx%d %d %d %d\n",
+ data[pos + 19], data[pos + 20],
+ data[pos + 21], data[pos + 22]);
+ assert(false);
}
-
- printf ("col %d\n", data[pos + 3]);
- pos += col_prefix_len - 1;
- prev_end = pos + 1;
+ pos += len;
+ prev_end = pos;
continue;
}
size_t record_prefix_len = sizeof record_prefix / sizeof *record_prefix;
if (match_bytes(pos, record_prefix, record_prefix_len))
{
- if (prev_end != pos)
- {
- //printf ("%04x ", prev_end);
- hex_dump (stdout, prev_end, pos - prev_end);
- }
-
- putchar ('\n');
-
- //printf ("%d ", pos % 4);
int len = record_prefix_len;
int slen = data[pos + 4] + (data[pos + 5] << 8);
- if (slen > 2 && slen < 256 && all_utf8((char *) &data[pos + 6], slen))
+ if (slen >= 2 && slen < 256 && all_utf8((char *) &data[pos + 6], slen))
{
- printf ("%.*s ", slen, &data[pos + 6]);
+ if (prev_end != pos)
+ {
+ if (print_offsets)
+ printf ("%04x ", prev_end);
+ hex_dump (stdout, prev_end, pos - prev_end);
+ }
+
+ putchar ('\n');
+
+ printf ("rec:%-20.*s ", slen, &data[pos + 6]);
len = slen + 6;
- }
- else
- printf ("notitle ");
+ title = xmemdup0(&data[pos + 6], slen);
+ sum += data[pos+len];
- pos += len - 1;
- prev_end = pos + 1;
- continue;
+ pos += len;
+
+ if (!strcmp(title, "DspNumber"))
+ dump_DspNumber();
+ else if (!strcmp(title, "PMModelItemInfo"))
+ {
+ assert(ndims);
+ dump_PMModelItemInfo(ndims);
+ }
+ else if (!strcmp(title, "NDimensional__DspCell"))
+ {
+ match_byte_assert(0);
+ ndims = get_u32();
+ assert(ndims < 10);
+ }
+ prev_end = pos;
+ continue;
+ }
}
static const int number_prefix[] = {
{
if (prev_end != pos)
{
- //printf ("%04x ", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
prev_end = pos;
double d = *(double *) &data[pos + number_prefix_len];
- printf ("float%f ", d);
- pos += 10 - 9;
- prev_end = pos + 1;
+ printf ("float %f\n", d);
+
+ pos += 10;
+ prev_end = pos;
continue;
}
- static const int string_prefix[] = {
- 0x80, 0x01, 0x02, 0x28, 0x05, 0x00, 0x01
- };
- size_t string_prefix_len = sizeof string_prefix / sizeof *string_prefix;
- if (match_bytes(pos, string_prefix, string_prefix_len) && data[pos + string_prefix_len] != 255)
+ if (!memcmp (&data[pos + 4], "{\\rtf", 5))
{
- if (prev_end != pos)
+ int len = data[pos] + (data[pos + 1] << 8) + (data[pos + 2] << 16)
+ + (data[pos + 3] << 24);
+ if (len < n - pos - 4)
{
- //printf ("%04x ", prev_end);
- hex_dump (stdout, prev_end, pos - prev_end);
- }
- prev_end = pos;
+ if (prev_end != pos)
+ {
+ if (print_offsets)
+ printf ("%04x ", prev_end);
+ hex_dump (stdout, prev_end, pos - prev_end);
+ }
+ prev_end = pos;
- printf ("\nstring %.*s\n", (int) data[pos + 7], &data[pos + 8]);
- }
- if (match_bytes(pos, string_prefix, string_prefix_len) && data[pos + string_prefix_len] == 255)
- {
- if (prev_end != pos)
- {
- //printf ("%04x ", prev_end);
- hex_dump (stdout, prev_end, pos - prev_end);
+ printf ("rtf\n");
+ pos += 4 + len;
+ prev_end = pos;
+ continue;
}
- prev_end = pos;
-
- int len = data[pos + 8] + (data[pos + 9] << 8);
- printf ("\nlongstring %.*s\n", len, &data[pos + 10]);
}
-
-
-#if 0
- static const int heading_prefix[] = {
- -1, 0x00, 0x00, 0x00, 0x50, 0x80, 0x00, 0x52, 0x80, 0x00, -1, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x00, 0x05, 0x80, 0x01, 0x02, 0x28, 0x05, 0x00, 0x01
- };
- size_t heading_prefix_len = sizeof heading_prefix / sizeof *heading_prefix;
- if (match_bytes(pos, heading_prefix, heading_prefix_len))
+ if (data[pos] && data[pos + 1] && data[pos + 2] >= 0xfe
+ && data[pos + 3] == 0xff && data[pos + 4] && data[pos + 4] != 0xff)
{
if (prev_end != pos)
{
- //printf ("%04x ", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
+ prev_end = pos;
- printf ("heading %d %d\n", data[pos],data[pos + 10]);
- pos += heading_prefix_len - 1;
- prev_end = pos + 1;
+ static int prev_num;
+ int32_t num = data[pos] + (data[pos + 1] << 8)
+ + (data[pos + 2] << 16) + (data[pos + 3] << 24);
+ printf ("%d (%+d) ", num, num - prev_num);
+ prev_num = num;
+ pos += 4;
+ prev_end = pos;
continue;
}
- static const int font_prefix[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1, 0x80, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, -1,
- 0x80, 0x00, -1, 0x00, -1, 0x00, 0xc8, 0x00, -1, -1, -1, -1, -1,
- 0x00, -1, 0x00, 0x00, 0x00, 0x01, 0x00, -1,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, -1 /* 12 or 22 */,
- };
+ static const int font_prefix[] =
+ {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x41, 0x72, 0x69, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ };
size_t font_prefix_len = sizeof font_prefix / sizeof *font_prefix;
if (match_bytes(pos, font_prefix, font_prefix_len))
{
if (prev_end != pos)
{
- //printf ("%04x", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
+ prev_end = pos;
+
+ printf ("font\n");
- printf ("font %d %d %d %d %d %d %d %d %d %d\n",
- data[pos + 24], data[pos + 26],
- data[pos + 30], data[pos + 31], data[pos + 32],
- data[pos + 33], data[pos + 34], data[pos + 36],
- data[pos + 58], data[pos + 59]);
- pos += font_prefix_len - 1;
- prev_end = pos + 1;
+ pos += font_prefix_len;
+ prev_end = pos;
continue;
}
- static const int table_prefix[] = {
- -1 /* ed or e9 */, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x41, 0x72, 0x69,
- 0x61, 0x6c, 0x00, -1, 0x00, -1, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, -1, 0x00, 0x00, 0x00, -1,
+ static const int string_prefix[] = {
+ 0x05, 0x80, 0x01, 0x02, 0x28, 0x05, 0x00, 0x01
};
- size_t table_prefix_len = sizeof table_prefix / sizeof *table_prefix;
- if (match_bytes(pos, table_prefix, table_prefix_len))
+ size_t string_prefix_len = sizeof string_prefix / sizeof *string_prefix;
+ if (match_bytes(pos, string_prefix, string_prefix_len) && data[pos + string_prefix_len] != 255)
{
if (prev_end != pos)
{
- //printf ("%04x", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
+ prev_end = pos;
- printf ("table %d\n", data[pos + 72]);
- pos += table_prefix_len - 1;
- prev_end = pos + 1;
+ int len = data[pos + 8];
+ printf ("string %.*s\n", len, &data[pos + 9]);
+ pos += 8 + len;
+ prev_end = pos;
continue;
}
-#endif
-
- static const int dim_prefix[] = {
- 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, -1,
- 0x00, 0x00, 0x00, 0x00, -1, 0x80, 0x01, 0x02, -1,
- -1, -1, -1 /* 00 or 01 */,
- };
- size_t dim_prefix_len = sizeof dim_prefix / sizeof *dim_prefix;
- if (match_bytes(pos, dim_prefix, dim_prefix_len))
+ if (match_bytes(pos, string_prefix, string_prefix_len) && data[pos + string_prefix_len] == 255)
{
if (prev_end != pos)
{
- //printf ("%04x", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
+ prev_end = pos;
- printf ("dim %d %d %d %d %d\n", data[pos + 8], data[pos + 13],
- data[pos + 17], data[pos + 18], data[pos + 19]);
- pos += dim_prefix_len - 1;
- prev_end = pos + 1;
+ int len = data[pos + 9] + (data[pos + 10] << 8);
+ printf ("\nlongstring %.*s\n", len, &data[pos + 11]);
+ pos += 11 + len;
+ prev_end = pos;
continue;
}
- static const int dim2_prefix[] = {
- 0x50, 0x80, 0x00, 0x52, 0x80, 0x00, -1, 0x00, 0x00, 0x00, -1, 0, 0, 0,
- -1, -1, -1, -1
- };
- size_t dim2_prefix_len = sizeof dim2_prefix / sizeof *dim2_prefix;
- if (match_bytes(pos, dim2_prefix, dim2_prefix_len))
+ if (data[pos] == 0 && data[pos + 1] == 0xff
+ && (!data[pos + 2] || data[pos + 2] == 0xff) && data[pos + 3] == 0xff
+ && data[pos + 4] == 0)
{
+ pos++;
if (prev_end != pos)
{
- //printf ("%04x", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
-
- int16_t x = *(int16_t *) &data[pos + 14];
- int16_t y = *(int16_t *) &data[pos + 16];
- printf ("dim2 %d %d %d %d\n", data[pos + 6], data[pos + 10], x, y);
- pos += dim2_prefix_len - 1;
- prev_end = pos + 1;
+ prev_end = pos;
continue;
}
+
if (!is_ascii(data[pos]))
- continue;
+ {
+ pos++;
+ continue;
+ }
unsigned int start = pos;
unsigned int end = pos + 1;
unsigned int len = end - start;
if (len < 3)
- continue;
+ {
+ pos++;
+ continue;
+ }
unsigned int len2 = data[start - 2] + (data[start - 1] << 8);
unsigned int len3 = data[start - 1];
len = len3;
}
else
- continue;
+ {
+ pos++;
+ continue;
+ }
if (len < 3)
- continue;
+ {
+ pos++;
+ continue;
+ }
end = start + len;
unsigned real_start = start - length_bytes;
if (prev_end != real_start)
{
- //printf ("%04x ", prev_end);
+ if (print_offsets)
+ printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, real_start - prev_end);
}
- //printf ("%04x ", real_start);
+ if (print_offsets)
+ printf ("%04x ", real_start);
printf ("\"%.*s\"\n",
(int) end - start, (char *) &data[start]);
prev_end = end;
- pos = end - 1;
+ pos = end;
}
exit(0);