dump2: Now dumps basics of most non-"light" bin files.
authorBen Pfaff <blp@cs.stanford.edu>
Thu, 13 Nov 2014 04:59:44 +0000 (20:59 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Thu, 13 Nov 2014 04:59:44 +0000 (20:59 -0800)
Makefile
dump2.c
notes2

index 59fcc0beb2393cb02fbd73010a9cc1f98ada0884..3172b3dddcd9076d47de6b8695f20e33acd24da1 100644 (file)
--- 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 9eb0f5b2ac7b7a425c313fd4dd9670213cc0f35d..56d8163ebbf12ab0102339967786a148fe9cd883 100644 (file)
--- a/dump2.c
+++ b/dump2.c
@@ -1,3 +1,4 @@
+#include <float.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -7,7 +8,162 @@
 #include <unistd.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
+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 0022c6b2bd2e425884387e1eb5afe340484854d1..8fd115cab0021b63d081cf8eabb959d57c433c06 100644 (file)
--- 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