#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
#include <float.h>
#include <stdbool.h>
#include <stdint.h>
int version;
-static bool
-all_ascii(const uint8_t *p, size_t n)
-{
- for (size_t i = 0; i < n; i++)
- if (p[i] < 32 || p[i] > 126)
- return false;
- return true;
-}
-
-static size_t
-try_find(const char *target, size_t target_len)
-{
- const uint8_t *pos = (const uint8_t *) memmem (data, n, target, target_len);
- return pos ? pos - data : 0;
-}
-
-static size_t
-find(const char *target, size_t target_len)
-{
- size_t pos = try_find(target, target_len);
- if (!pos)
- {
- fprintf (stderr, "not found\n");
- exit(1);
- }
- return pos;
-}
-
size_t pos;
#define XSTR(x) #x
return true;
}
-static void
-newline(FILE *stream, int pos)
-{
- fprintf(stream, "\n%08x: ", pos);
-}
-
-static void
-dump_raw(FILE *stream, int start, int end)
-{
- for (size_t i = start; i < end; )
- {
- if (i + 5 <= n
- && data[i]
- //&& !data[i + 1]
- && !data[i + 2]
- && !data[i + 3]
- && i + 4 + data[i] + data[i + 1] * 256 <= end
- && all_ascii(&data[i + 4], data[i] + data[i + 1] * 256))
- {
- newline(stream, i);
- fprintf(stream, "\"");
- fwrite(&data[i + 4], 1, data[i] + data[i + 1] * 256, stream);
- fputs("\" ", stream);
-
- i += 4 + data[i] + data[i + 1] * 256;
- }
- else if (i + 12 <= end
- && data[i + 1] == 40
- && data[i + 2] == 5
- && data[i + 3] == 0)
- {
- double d;
-
- memcpy (&d, &data[i + 4], 8);
- fprintf (stream, "F40.%d(%.*f)", data[i], data[i], d);
- i += 12;
- newline (stream, i);
- }
- else if (i + 12 <= end
- && data[i + 1] == 40
- && data[i + 2] == 31
- && data[i + 3] == 0)
- {
- double d;
-
- memcpy (&d, &data[i + 4], 8);
- fprintf (stream, "PCT40.%d(%.*f)", data[i], data[i], d);
- i += 12;
- newline(stream, i);
- }
- else if (i + 4 <= end
- && (data[i] && data[i] != 88 && data[i] != 0x41)
- && !data[i + 1]
- && !data[i + 2]
- && !data[i + 3])
- {
- fprintf (stream, "i%d ", data[i]);
- i += 4;
- }
- else
- {
- fprintf(stream, "%02x ", data[i]);
- i++;
- }
- }
-
-
-}
-
static bool __attribute__((unused))
all_utf8(const char *p_)
{
int
main(int argc, char *argv[])
{
- size_t start;
- struct stat s;
+ if (argc != 2)
+ {
+ fprintf (stderr, "usage: %s FILE.bin", argv[0]);
+ exit (1);
+ }
- if (isatty(STDIN_FILENO))
+ int fd = open(argv[1], O_RDONLY);
+ if (fd < 0)
{
- fprintf(stderr, "redirect stdin from a .bin file\n");
- exit(1);
+ fprintf (stderr, "%s: open failed (%s)", argv[1], strerror (errno));
+ exit (1);
}
- if (fstat(STDIN_FILENO, &s))
+
+ struct stat s;
+ if (fstat(fd, &s))
{
perror("fstat");
exit(1);
perror("malloc");
exit(1);
}
- if (read(STDIN_FILENO, data, n) != n)
+ if (read(fd, data, n) != n)
{
perror("read");
exit(1);
}
+ close(fd);
- if (argc != 2)
- {
- fprintf (stderr, "usage: %s TYPE < .bin", argv[0]);
- exit (1);
- }
-
- if (!strcmp(argv[1], "title0"))
- {
- pos = 0x27;
- if (match_byte (0x03)
- || (match_byte (0x05) && match_byte (0x58)))
- printf ("%s\n", get_string());
- else
- printf ("<unknown>\n");
- return 0;
- }
- else if (!strcmp(argv[1], "title"))
- {
- pos = 0x27;
- dump_title();
- exit(0);
- }
- else if (!strcmp(argv[1], "titleraw"))
- {
- const char fonts[] = "\x01\x31\x09\0\0\0SansSerif";
- start = 0x27;
- n = find(fonts, sizeof fonts - 1);
- }
- else if (!strcmp(argv[1], "fonts"))
- {
- const char fonts[] = "\x01\x31\x09\0\0\0SansSerif";
- const char styles[] = "\xf0\0\0\0";
- start = find(fonts, sizeof fonts - 1);
- n = find(styles, sizeof styles - 1);
- }
- else if (!strcmp(argv[1], "styles"))
- {
- const char styles[] = "\xf0\0\0\0";
- const char dimensions[] = "-,,,.\0";
- start = find(styles, sizeof styles - 1);
- n = find(dimensions, sizeof dimensions - 1) + sizeof dimensions - 1;
- }
- else if (!strcmp(argv[1], "dimensions") || !strcmp(argv[1], "all"))
- {
- pos = 0;
- match_byte_assert(1);
- match_byte_assert(0);
-
- /* This might be a version number of some kind, because value 1 seems
- to only appear in an SPV file that also required its own weird
- special cases in dump_value_modifier(). */
- version = get_u32();
- pos -= 4;
- if (!match_u32(1))
- match_u32_assert(3);
+ pos = 0;
+ match_byte_assert(1);
+ match_byte_assert(0);
- match_byte_assert(1);
- for (int i = 0; i < 4; i++)
- if (!match_byte(0))
- match_byte_assert(1);
- get_u32();
-
- int min_col_width = get_u32();
- int max_col_width = get_u32();
- int min_row_width = get_u32();
- int max_row_width = get_u32();
- printf("<label-width min-col=\"%d\" max-col=\"%d\" min-row=\"%d\" "
- "max-row=\"%d\"/>\n",
- min_col_width, max_col_width,
- min_row_width, max_row_width);
-
- /* Offset 31. */
- printf("<tableid>%lld</tableid>", get_u64());
-
- dump_title ();
- dump_fonts();
- dump_dims ();
- dump_data ();
- match_byte (1);
- if (pos != n)
- {
- fprintf (stderr, "%x / %x\n", pos, n);
- exit(1);
- }
- exit(0);
- }
- else if (!strcmp(argv[1], "raw"))
- {
- start = 0x27;
+ version = get_u32();
+ assert(version == 1 || version == 3);
- dump_raw(stdout, start, n);
- }
- else
+ match_byte_assert(1);
+ for (int i = 0; i < 4; i++)
+ get_bool();
+ get_u32();
+
+ int min_col_width = get_u32();
+ int max_col_width = get_u32();
+ int min_row_width = get_u32();
+ int max_row_width = get_u32();
+ printf("<label-width min-col=\"%d\" max-col=\"%d\" min-row=\"%d\" "
+ "max-row=\"%d\"/>\n",
+ min_col_width, max_col_width,
+ min_row_width, max_row_width);
+
+ /* Offset 31. */
+ printf("<tableid>%lld</tableid>", get_u64());
+
+ dump_title ();
+ dump_fonts();
+ dump_dims ();
+ dump_data ();
+ match_byte (1);
+ if (pos != n)
{
- fprintf (stderr, "unknown section %s\n", argv[1]);
+ fprintf (stderr, "%x / %x\n", pos, n);
exit(1);
}
+ exit(0);
return 0;
}