From d8138f420420eaf84ee809a83cef35407bec5183 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 12 Nov 2014 20:59:44 -0800 Subject: [PATCH] dump2: Now dumps basics of most non-"light" bin files. --- Makefile | 3 +- dump2.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- notes2 | 9 +++ 3 files changed, 229 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 59fcc0beb2..3172b3dddc 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -CFLAGS = -std=gnu99 -Wall -Werror -g -D_GNU_SOURCE=1 +dump.o: CFLAGS = -std=gnu99 -Wall -Werror -g -D_GNU_SOURCE=1 +dump2.o: CFLAGS = -std=gnu99 -Wall -Werror -g -D_GNU_SOURCE=1 -Wno-unused all: dump dump2 dump: dump.o dump2: dump2.o diff --git a/dump2.c b/dump2.c index 9eb0f5b2ac..56d8163ebb 100644 --- a/dump2.c +++ b/dump2.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,7 +8,162 @@ #include 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 +all_ascii(const uint8_t *p) +{ + for (; *p; p++) + if (*p < 32 || *p > 126) + 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])) + { + 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++; + } + } +} int main(int argc, char **argv) @@ -38,19 +194,71 @@ main(int argc, char **argv) exit(1); } - if (argc < 3) + 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 { - fprintf(stderr, "bad arguments"); - exit(1); + uint8_t b[8]; + double d; + } + sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}}; + pos = 0x58; + for (int i = 0; i < n_series; i++) + { + printf ("%08x:", pos); + printf (" %s\n", get_fixed_string(288)); + printf ("%08x:", pos); + for (int i = 0; i < count; i++) + { + double d = get_double(); + if (d == sysmis.d) + printf (" ."); + else + printf (" %.*g", DBL_DIG, d); + } + printf ("\n"); } - start = strtol(argv[1], NULL, 0); - int end = strtol(argv[2], NULL, 0); - for (int pos = start; pos < end; pos += 8) + printf ("%08x:", pos); + 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++) { - double d; - memcpy(&d, &data[pos], sizeof d); - printf("%g\n", d); + 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); + } + + dump_raw (stdout, pos, n, "\n"); + putchar('\n'); return 0; } diff --git a/notes2 b/notes2 index 0022c6b2bd..8fd115cab0 100644 --- a/notes2 +++ b/notes2 @@ -73,3 +73,12 @@ i0 dimension0group0Label i0 i2 i3 i3 i3 i4 i4 i5 i4 i6 i5 i7 i5 i20 "dimension1categories" i0 i16 "dimension1labels" i8 i0 i1 i1 i2 i2 i1 i3 i2 i4 i1 i5 i2 i6 i1 i7 i2 i8 i2 i5 "Valid" i4 i6 "Gender" i4 i9 "Education" i2 i7 "Missing" i2 i7 "Minimum" i2 i7 "Maximum" i4 i1 "N" i4 i0 + +i1 i9 "tableData" +i8 i4 "cell" +i0 i10 "cellFormat" +i0 i20 "dimension0categories" i0 i16 "dimension0group0" +i0 i21 "dimension0group0Label" i8 i0 i6 i1 i6 i2 i6 i3 i6 i4 i7 i5 i7 i6 i7 i7 i7 i16 "dimension0labels" i8 i0 i0 i1 +i0 i2 i3 i3 i3 i4 i4 i5 i4 i6 i5 i7 i5 i20 "dimension1categories" i0 i16 "dimension1labels" i8 i0 i1 +i1 i2 i2 i1 i3 i2 i4 i1 i5 i2 i6 i1 i7 i2 i8 i2 i5 "Valid" i4 i6 "Gender" i4 i9 "Education" i2 i7 "Missing" i2 i7 +"Minimum" i2 i7 "Maximum" i4 i1 "N" i4 i0 -- 2.30.2