X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=dump2.c;h=d7f8ad3d68abbcff43539cae1f56ef4515aa2e06;hb=0ed91de68e9149be640b996c21c8121296ded298;hp=9eb0f5b2ac7b7a425c313fd4dd9670213cc0f35d;hpb=ab8051153e6b8c3428539d540d8e45528e1b5215;p=pspp diff --git a/dump2.c b/dump2.c index 9eb0f5b2ac..d7f8ad3d68 100644 --- a/dump2.c +++ b/dump2.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -5,9 +7,267 @@ #include #include #include +#include "u8-mbtouc.h" static uint8_t *data; -static size_t n; +static size_t n, pos; + +#define XSTR(x) #x +#define STR(x) XSTR(x) +#define WHERE __FILE__":" STR(__LINE__) + +static unsigned int +get_u32(void) +{ + uint32_t x; + memcpy(&x, &data[pos], 4); + pos += 4; + return x; +} + +static double +get_double(void) +{ + double x; + memcpy(&x, &data[pos], 8); + pos += 8; + return x; +} + +static bool +match_u32(uint32_t x) +{ + if (get_u32() == x) + return true; + pos -= 4; + return false; +} + +static void +match_u32_assert(uint32_t x, const char *where) +{ + unsigned int y = get_u32(); + if (x != y) + { + fprintf(stderr, "%s: 0x%x: expected i%u, got i%u\n", where, pos - 4, x, y); + exit(1); + } +} +#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) +{ + for (; *p; p++) + if (*p < 32 || *p > 126) + return false; + 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_utf8(&data[pos])) + { + fprintf(stderr, "%s: 0x%x: bad fixed-width string\n", where, pos); + exit(1); + } + char *s = (char *) &data[pos]; + pos += len; + return s; +} +#define get_fixed_string(len) get_fixed_string(len, WHERE) + +static bool +all_ascii2(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 char * +get_string(const char *where) +{ + if (1 + /*data[pos + 1] == 0 && data[pos + 2] == 0 && data[pos + 3] == 0*/ + /*&& all_ascii(&data[pos + 4], data[pos])*/) + { + int len = data[pos] + data[pos + 1] * 256; + char *s = malloc(len + 1); + + memcpy(s, &data[pos + 4], len); + s[len] = 0; + pos += 4 + len; + return s; + } + else + { + fprintf(stderr, "%s: 0x%x: expected string\n", where, pos); + exit(1); + } +} +#define get_string() get_string(WHERE) + +static void +dump_raw(FILE *stream, int start, int end, const char *separator) +{ + for (size_t i = start; i < end; ) + { + if (i + 5 <= n + && data[i] > 0 + //&& !data[i + 1] + && !data[i + 2] + && !data[i + 3] + && i + 4 + data[i] + data[i + 1] * 256 <= end + && all_ascii2(&data[i + 4], data[i] + data[i + 1] * 256)) + { + fprintf(stream, "%s\"", separator); + 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)%s", data[i], data[i], d, separator); + i += 12; + } + 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)%s", data[i], data[i], d, separator); + i += 12; + } + else if (i + 4 <= end + && !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 void +dump_source(int end, int count, int n_series) +{ + const union + { + uint8_t b[8]; + double d; + } + sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}}; + int n_sysmis = 0; + for (int i = 0; i < n_series; i++) + { + 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 (" ."); + n_sysmis++; + } + else + printf (" %.*g", DBL_DIG, d); + } + printf ("\n"); + } + + 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); + int n_more_series = get_u32(); + printf (" %d series to come\n", n_more_series); + + for (int i = 0; i < n_more_series; i++) + { + printf ("%08x:", pos); + printf (" \"%s\"", get_string()); + int n_pairs = get_u32(); + for (int j = 0; j < n_pairs; j++) + { + int x = get_u32(); + int y = get_u32(); + printf (" (%d,%d)", x, y); + } + printf ("\n"); + } + + printf ("\n%08x:", pos); + int n_strings = get_u32(); + printf (" %d strings\n", n_strings); + for (int i = 0; i < n_strings; i++) + { + int x = get_u32(); + char *s = get_string(); + printf ("%d: \"%s\" (%d)\n", i, s, x); + } + printf ("\n"); +} int main(int argc, char **argv) @@ -38,19 +298,46 @@ main(int argc, char **argv) exit(1); } - if (argc < 3) + 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 { - fprintf(stderr, "bad arguments"); - exit(1); + 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; } - start = strtol(argv[1], NULL, 0); - int end = strtol(argv[2], NULL, 0); - for (int pos = start; pos < end; pos += 8) + for (int i = 0; i < n_sources; i++) { - double d; - memcpy(&d, &data[pos], sizeof d); - printf("%g\n", d); + 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); + return 0; }