dump: Some things are related to a version number.
[pspp] / dump.c
diff --git a/dump.c b/dump.c
index 90c32bf64d89a2245fdf33ce7ccce0ef4663ff8d..bc3fe39388a26c6b65f103c655ac7320e949f618 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -10,6 +10,8 @@
 static uint8_t *data;
 static size_t n;
 
+int version;
+
 static bool
 all_ascii(const uint8_t *p, size_t n)
 {
@@ -246,27 +248,42 @@ dump_value_31(FILE *stream)
           else
             match_u32_assert (0);
 
-          int outer_end = pos + get_u32();
-          int inner_end = pos + get_u32();
-          match_u32_assert(0);
-          if (match_byte(0x31))
+          if (version == 1)
             {
-              /* Appears to be a template string, e.g. '^1 cells (^2) expf < 5. Min exp = ^3...'.
-                 Probably doesn't actually appear in output because many examples look unpolished,
-                 e.g. 'partial list cases value ^1 shown upper...' */
-              get_string();
+              /* We only have one SPV file for this version (with many
+                 tables). */
+              match_u32_assert(0x200);
+              match_u32_assert(0x1000000);
+              match_u32_assert(0);
+              match_byte_assert(0);
+              return;
             }
-          else
-            match_byte_assert(0x58);
+
+          int outer_end = pos + get_u32();
+          int inner_end = pos + get_u32();
           if (pos != inner_end)
             {
-              fprintf(stderr, "inner end discrepancy\n");
-              exit(1);
+              match_u32_assert(0);
+              if (match_byte(0x31))
+                {
+                  /* Appears to be a template string, e.g. '^1 cells (^2) expf < 5. Min exp = ^3...'.
+                     Probably doesn't actually appear in output because many examples look unpolished,
+                     e.g. 'partial list cases value ^1 shown upper...' */
+                  get_string();
+                }
+              else
+                match_byte_assert(0x58);
+              if (pos != inner_end)
+                {
+                  fprintf(stderr, "inner end discrepancy\n");
+                  exit(1);
+                }
             }
 
           if (match_byte(0x31))
             {
               /* Only one example in the corpus. */
+              match_byte(1);
               match_byte(0);
               match_byte(0);
               match_byte(0);
@@ -274,11 +291,30 @@ dump_value_31(FILE *stream)
               get_string();     /* foreground */
               get_string();     /* background */
               get_string();     /* font */
-              match_byte_assert(12); /* size? */
+              if (!match_byte(14))
+                match_byte_assert(12); /* size? */
+            }
+          else
+            match_byte_assert(0x58);
+          if (match_byte(0x31))
+            {
+              /* All the examples in the corpus, all from one SPV file, are
+                 exactly like this. */
+              match_u32_assert(0);
+              match_u32_assert(0);
+              match_u32_assert(0);
+              match_u32_assert(0);
+              match_byte_assert(1);
+              match_byte_assert(0);
+              match_byte_assert(8);
+              match_byte_assert(0);
+              match_byte_assert(8);
+              match_byte_assert(0);
+              match_byte_assert(10);
+              match_byte_assert(0);
             }
           else
             match_byte_assert(0x58);
-          match_byte_assert(0x58);
           if (pos != outer_end)
             {
               fprintf(stderr, "outer end discrepancy\n");
@@ -708,26 +744,29 @@ dump_fonts(void)
       match_u32_assert(0);
       match_byte_assert(0);
 
-      /* These seem unlikely to be correct too. */
-      if (i != 3)
-        {
-          match_u32_assert(8);
-          if (!match_u32(10))
-            match_u32_assert(11);
-          match_u32_assert(1);
-        }
-      else
+      if (version > 1)
         {
+          /* These seem unlikely to be correct too. */
+          if (i != 3)
+            {
+              match_u32_assert(8);
+              if (!match_u32(10))
+                match_u32_assert(11);
+              match_u32_assert(1);
+            }
+          else
+            {
+              get_u32();
+              if (!match_u32(-1) && !match_u32(8))
+                match_u32_assert(24);
+              if (!match_u32(-1) && !match_u32(2))
+                match_u32_assert(3);
+            }
+
+          /* Who knows? Ranges from -1 to 8 with no obvious pattern. */
           get_u32();
-          if (!match_u32(-1) && !match_u32(8))
-            match_u32_assert(24);
-          if (!match_u32(-1) && !match_u32(2))
-            match_u32_assert(3);
         }
 
-      /* Who knows? Ranges from -1 to 8 with no obvious pattern. */
-      get_u32();
-
       printf ("/>\n");
     }
 
@@ -739,10 +778,12 @@ dump_fonts(void)
 
   if (match_u32(117))
     pos += 117;
+  else if (match_u32(142))
+    pos += 142;
   else
     {
-      match_u32_assert(142);
-      pos += 142;
+      match_u32_assert(16);
+      pos += 16;
     }
 
   int count = get_u32();
@@ -757,11 +798,16 @@ dump_fonts(void)
   match_byte_assert(0);
   if (!match_byte(0))
     match_byte_assert(1);
-  if (!match_byte(0x97) && !match_byte(0x98) && !match_byte(0x99))
-    match_byte_assert(0x9a);
-  match_byte_assert(7);
-  match_byte_assert(0);
-  match_byte_assert(0);
+  if (version > 1)
+    {
+      if (!match_byte(0x97) && !match_byte(0x98) && !match_byte(0x99))
+        match_byte_assert(0x9a);
+      match_byte_assert(7);
+      match_byte_assert(0);
+      match_byte_assert(0);
+    }
+  else
+    match_u32_assert(UINT32_MAX);
   if (match_byte('.'))
     match_byte_assert(',');
   else
@@ -847,7 +893,15 @@ main(int argc, char *argv[])
           pos = 0;
           match_byte_assert(1);
           match_byte_assert(0);
-          match_u32_assert(3);
+
+          /* 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_31(). */
+          version = get_u32();
+          pos -= 4;
+          if (!match_u32(1))
+            match_u32_assert(3);
+
           match_byte_assert(1);
           if (!match_byte(0))
             match_byte_assert(1);