static void __attribute__((unused))
hex_dump(FILE *stream, int ofs, int n)
{
+ int n_ascii = 0;
for (int i = 0; i < n; i++)
{
int c = data[ofs + i];
+ n_ascii += is_ascii(c);
fprintf(stream, " %02x", c);
}
- putc(' ', stream);
- for (int i = 0; i < n; i++)
+ if (n_ascii >= 3)
{
- int c = data[ofs + i];
- putc(c >= 32 && c < 127 ? c : '.', stream);
+ putc(' ', stream);
+ for (int i = 0; i < n; i++)
+ {
+ int c = data[ofs + i];
+ putc(c >= 32 && c < 127 ? c : '.', stream);
+ }
}
putc('\n', stream);
}
}
}
+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;
+ }
+}
+
int
main(int argc, char *argv[])
{
for (pos = 2; pos + 50 < n; pos++)
{
static const int cell_prefix[] = {
- 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, -1, 0x80, 0x01, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0x00, 0x03,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -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))
{
if (prev_end != pos)
{
- printf ("%04x ", prev_end);
+ //printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
- double d = *(double *) &data[pos + cell_prefix_len - 8];
- const union
+ 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)
+ {
+ assert (data[pos + 13] == 5);
+ if (data[pos + 20] == 0)
+ {
+ int count = (data[pos + 22]);
+ printf ("%d %d \"%.*s\"\n",
+ 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)
+ {
+ int count = 255;
+ printf ("%d \"%.*s\"\n", count, data[pos + 23],
+ &data[pos + 24]);
+ len = 23 + count;
+ }
+ else if (data[pos + 20] == 1)
+ {
+ int count = (data[pos + 21]);
+ printf ("\"%.*s\"\n",
+ count, &data[pos + 22]);
+ len = 22 + count;
+ }
+ else
+ abort ();
+ }
+ else if (data[pos + 19] == 128)
{
- uint8_t b[8];
- double d;
+ /* 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]);
+ double d = *(double *) &data[pos + 21];
+ len = 29;
+ const union
+ {
+ uint8_t b[8];
+ double d;
+ }
+ sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}};
+ if (d == sysmis.d)
+ printf ("sysmis\n");
+ else
+ printf ("%f\n", d);
}
- sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}};
- if (d == sysmis.d)
- printf ("cell sysmis\n");
else
- printf ("cell %f\n", d);
- pos += cell_prefix_len - 1;
+ abort ();
+ pos += len - 1;
prev_end = pos + 1;
continue;
}
{
if (prev_end != pos)
{
- printf ("%04x ", prev_end);
+ //printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
continue;
}
+ static const int record_prefix[] = {
+ 0xff, 0xff, 0x00, 0x00,
+ };
+ 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))
+ {
+ printf ("%.*s ", slen, &data[pos + 6]);
+ len = slen + 6;
+ }
+ else
+ printf ("notitle ");
+
+ pos += len - 1;
+ prev_end = pos + 1;
+ continue;
+ }
+
+ static const int number_prefix[] = {
+ 0x80, 0x02
+ };
+ size_t number_prefix_len = sizeof number_prefix / sizeof *number_prefix;
+ if (match_bytes(pos, number_prefix, number_prefix_len))
+ {
+ if (prev_end != pos)
+ {
+ //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;
+ 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 (prev_end != pos)
+ {
+ //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);
+ }
+ 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,
{
if (prev_end != pos)
{
- printf ("%04x ", prev_end);
+ //printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
}
static const int font_prefix[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x80, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xa9,
+ 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, 0xf3,
+ 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, 0x22,
+ 0x00, 0x00, -1 /* 12 or 22 */,
};
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);
+ //printf ("%04x", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
}
static const int table_prefix[] = {
- 0x00, 0x00, 0xed, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ -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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 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, 0x01, 0x00, 0x00, 0x00, -1, 0x01, 0x00,
- 0x00,
+ 0x00, 0x00, 0x00, 0x00, -1, 0x00, 0x00, 0x00, -1,
};
size_t table_prefix_len = sizeof table_prefix / sizeof *table_prefix;
if (match_bytes(pos, table_prefix, table_prefix_len))
{
if (prev_end != pos)
{
- printf ("%04x", prev_end);
+ //printf ("%04x", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
- printf ("table %d\n", data[pos + 74]);
+ printf ("table %d\n", data[pos + 72]);
pos += table_prefix_len - 1;
prev_end = pos + 1;
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, 0x01,
+ -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 (prev_end != pos)
{
- printf ("%04x", prev_end);
+ //printf ("%04x", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
{
if (prev_end != pos)
{
- printf ("%04x", prev_end);
+ //printf ("%04x", prev_end);
hex_dump (stdout, prev_end, pos - prev_end);
}
unsigned real_start = start - length_bytes;
if (prev_end != real_start)
{
- printf ("%04x ", prev_end);
+ //printf ("%04x ", prev_end);
hex_dump (stdout, prev_end, real_start - prev_end);
}
- printf ("%04x \"%.*s\"\n", real_start,
+ //printf ("%04x ", real_start);
+ printf ("\"%.*s\"\n",
(int) end - start, (char *) &data[start]);
prev_end = end;
pos = end - 1;