X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=dump2.c;h=d7f8ad3d68abbcff43539cae1f56ef4515aa2e06;hb=0ed91de68e9149be640b996c21c8121296ded298;hp=56d8163ebbf12ab0102339967786a148fe9cd883;hpb=d8138f420420eaf84ee809a83cef35407bec5183;p=pspp diff --git a/dump2.c b/dump2.c index 56d8163ebb..d7f8ad3d68 100644 --- a/dump2.c +++ b/dump2.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include "u8-mbtouc.h" static uint8_t *data; static size_t n, pos; @@ -53,6 +55,29 @@ match_u32_assert(uint32_t x, const char *where) } #define match_u32_assert(x) match_u32_assert(x, WHERE) +static bool +match_byte(uint8_t b) +{ + if (pos < n && data[pos] == b) + { + pos++; + return true; + } + else + return false; +} + +static void +match_byte_assert(uint8_t b, const char *where) +{ + if (!match_byte(b)) + { + fprintf(stderr, "%s: 0x%x: expected %02x, got %02x\n", where, pos, b, data[pos]); + exit(1); + } +} +#define match_byte_assert(b) match_byte_assert(b, WHERE) + static bool all_ascii(const uint8_t *p) { @@ -62,10 +87,25 @@ all_ascii(const uint8_t *p) return true; } +static bool +all_utf8(const uint8_t *p) +{ + size_t len = strlen ((char *) p); + for (size_t ofs = 0, mblen; ofs < len; ofs += mblen) + { + ucs4_t uc; + + mblen = u8_mbtouc (&uc, p + ofs, len - ofs); + if (uc < 32 || uc == 127 || uc == 0xfffd) + return false; + } + return true; +} + static char * get_fixed_string(int len, const char *where) { - if (pos + len > n || !memchr(&data[pos], 0, len) || !all_ascii(&data[pos])) + if (pos + len > n || !memchr(&data[pos], 0, len) || !all_utf8(&data[pos])) { fprintf(stderr, "%s: 0x%x: bad fixed-width string\n", where, pos); exit(1); @@ -165,72 +205,41 @@ dump_raw(FILE *stream, int start, int end, const char *separator) } } -int -main(int argc, char **argv) +static void +dump_source(int end, int count, int n_series) { - size_t start; - struct stat s; - - if (isatty(STDIN_FILENO)) - { - fprintf(stderr, "redirect stdin from a .bin file\n"); - exit(1); - } - if (fstat(STDIN_FILENO, &s)) - { - perror("fstat"); - exit(1); - } - n = s.st_size; - data = malloc(n); - if (!data) - { - perror("malloc"); - exit(1); - } - if (read(STDIN_FILENO, data, n) != n) - { - perror("read"); - exit(1); - } - - pos = 0; - match_u32_assert(0x1b000); - match_u32_assert(s.st_size); - - printf ("%08x:", pos); - int count = get_u32(), n_series = get_u32(); - printf (" %d series, %d observations per series\n", n_series, count); - printf ("%08x\n\n", pos); - const union { uint8_t b[8]; double d; } sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}}; - pos = 0x58; + int n_sysmis = 0; for (int i = 0; i < n_series; i++) { - printf ("%08x:", pos); - printf (" %s\n", get_fixed_string(288)); - printf ("%08x:", pos); + printf (" series %d: \"%s\"\n ", i, get_fixed_string(288)); for (int i = 0; i < count; i++) { double d = get_double(); if (d == sysmis.d) - printf (" ."); + { + printf (" ."); + n_sysmis++; + } else printf (" %.*g", DBL_DIG, d); } printf ("\n"); } - printf ("%08x:", pos); + if (pos >= end) + return; + + printf ("\n %08x: (%d sysmis)", pos, n_sysmis); printf (" %d", get_u32()); printf (", \"%s\"\n", get_string()); - printf ("\n%08x:", pos); + printf ("\n %08x:", pos); int n_more_series = get_u32(); printf (" %d series to come\n", n_more_series); @@ -257,8 +266,78 @@ main(int argc, char **argv) char *s = get_string(); printf ("%d: \"%s\" (%d)\n", i, s, x); } + printf ("\n"); +} + +int +main(int argc, char **argv) +{ + size_t start; + struct stat s; + + if (isatty(STDIN_FILENO)) + { + fprintf(stderr, "redirect stdin from a .bin file\n"); + exit(1); + } + if (fstat(STDIN_FILENO, &s)) + { + perror("fstat"); + exit(1); + } + n = s.st_size; + data = malloc(n); + if (!data) + { + perror("malloc"); + exit(1); + } + if (read(STDIN_FILENO, data, n) != n) + { + perror("read"); + exit(1); + } + + pos = 0; + match_byte_assert(0); + int version = data[pos]; + if (!match_byte(0xaf)) + match_byte_assert(0xb0); + int n_sources = data[pos++]; + match_byte_assert(0); + + match_u32_assert(s.st_size); + printf ("%d sources\n", n_sources); + + struct source + { + int offset, count, n_series; + } + sources[n_sources]; + for (int i = 0; i < n_sources; i++) + { + int count = get_u32(); + int n_series = get_u32(); + int offset = get_u32(); + char *name = get_fixed_string(version == 0xb0 ? 64 : 28); + int dunno = version == 0xb0 ? get_u32() : 0; + printf ("source %d: %d series, %d observations per series, offset %08x, \"%s\", %x\n", + i, n_series, count, offset, name, dunno); + sources[i].offset = offset; + sources[i].count = count; + sources[i].n_series = n_series; + } + + for (int i = 0; i < n_sources; i++) + { + if (pos != sources[i].offset) + { + fprintf (stderr, "pos=0x%x expected=0x%x reading source %d\n", pos, sources[i].offset, i); + exit(1); + } + dump_source(i + 1 >= n_sources ? n : sources[i + 1].offset, sources[i].count, sources[i].n_series); + } + assert(pos == n); - dump_raw (stdout, pos, n, "\n"); - putchar('\n'); return 0; }