learned some things about spos
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 23 Jun 2020 02:25:08 +0000 (02:25 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 23 Jun 2020 02:25:08 +0000 (02:25 +0000)
dump-spo2.c
spo-notes

index 33671632755321814dcae1ac86a1d78983fbf1cb..d50d861fa428260e4d99bdde812da3517da056c7 100644 (file)
@@ -2,6 +2,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <float.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <float.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -257,6 +258,20 @@ get_string1(void)
   return s;
 }
 
   return s;
 }
 
+static void
+match_string1_assert(const char *exp, const char *where)
+{
+  int start = pos;
+  char *act = get_string1();
+  if (strcmp(act, exp)) 
+    {
+      fprintf(stderr, "%s: 0x%x: expected \"%s\", got \"%s\"\n",
+              where, start, exp, act);
+      exit(1);
+    }
+}
+#define match_string1_assert(x) match_string1_assert(x, WHERE)
+
 static char *
 get_string2(void)
 {
 static char *
 get_string2(void)
 {
@@ -266,6 +281,20 @@ get_string2(void)
   return s;
 }
 
   return s;
 }
 
+static void
+match_string2_assert(const char *exp, const char *where)
+{
+  int start = pos;
+  char *act = get_string2();
+  if (strcmp(act, exp)) 
+    {
+      fprintf(stderr, "%s: 0x%x: expected \"%s\", got \"%s\"\n",
+              where, start, exp, act);
+      exit(1);
+    }
+}
+#define match_string2_assert(x) match_string2_assert(x, WHERE)
+
 static char *
 get_string(const char *where)
 {
 static char *
 get_string(const char *where)
 {
@@ -406,6 +435,40 @@ format_name (int format, char *buf)
     }
 }
 
     }
 }
 
+static void
+parse_heading(const char *name)
+{
+  match_u16_assert(0xffff);
+  match_u16_assert(0);
+  match_string2_assert(name);
+}
+
+static void
+match_zeros_assert(int count)
+{
+  for (int i = 0; i < count; i++)
+    if (data[pos + i])
+      {
+        fprintf (stderr,
+                 "%#x: expected %d zeros here but offset %d is %#"PRIx8"\n",
+                 pos, count, i, data[pos + i]);
+        exit (1);
+      }
+  pos += count;
+}
+
+static void
+parse_DspString(void)
+{
+  match_byte_assert(1);
+  match_byte_assert(2);
+  match_byte_assert(40);
+  if (!match_byte(0))
+    match_byte_assert(5);
+  match_byte_assert(0);
+  match_byte_assert(1);
+  printf ("DspString(\"%s\")\n", get_string1());
+}
 
 int
 main(int argc, char *argv[])
 
 int
 main(int argc, char *argv[])
@@ -463,5 +526,26 @@ main(int argc, char *argv[])
 
   setvbuf (stdout, NULL, _IOLBF, 0);
 
 
   setvbuf (stdout, NULL, _IOLBF, 0);
 
+  match_byte_assert(4);
+  match_u32_assert(0);
+  match_string1_assert("SPSS Output Document");
+  match_u32_assert(1);
+  match_byte_assert(0x63);
+
+  parse_heading("NavRoot");
+  match_byte_assert(2);
+  match_zeros_assert(32);
+
+  parse_heading("DspSimpleText");
+  match_zeros_assert(10);
+
+  parse_heading("DspString");
+  parse_DspString();
+
+  parse_heading("NavTreeViewItem");
+  
+
+  printf ("%#x: end of successful parse\n", pos);
+
   return 0;
 }
   return 0;
 }
index 30132d6f5c87d1ebc62aa089f8bf6f8914b6dc40..93682571b9c6e46b5a433a49623e46ae67a11cc0 100644 (file)
--- a/spo-notes
+++ b/spo-notes
@@ -692,20 +692,32 @@ correspondence:
 
 When the top-level "Output" node is selected for save:
        04 i0
 
 When the top-level "Output" node is selected for save:
        04 i0
-       "SPSS Output Document"
+       b"SPSS Output Document"
        i1 63
        ffff 0000 "NavRoot" 02 00*32
        ffff 0000 "DspSimpleText" 00*10
        ffff 0000 "DspString" 01 02 28 00 00 01 b"Output"
        i1 63
        ffff 0000 "NavRoot" 02 00*32
        ffff 0000 "DspSimpleText" 00*10
        ffff 0000 "DspString" 01 02 28 00 00 01 b"Output"
-       ffff 0000 "NavTreeViewItem" 00 i0 02 00 01 00*9 i1
+       ffff 0000 "NavTreeViewItem"
+       00 i0 02 00 01 00*9 i1
 00c0   (i0 | i24) (i24 | i-40) (i0 | i40 | i-40) (i40 | i-34)
 00d0   (i1048 | some other 3-hex-digit number | i0)
 00d4   (i0 | some 3 to 4-hex-digit number | i-40)
 00d8   00*5
 00c0   (i0 | i24) (i24 | i-40) (i0 | i40 | i-40) (i40 | i-34)
 00d0   (i1048 | some other 3-hex-digit number | i0)
 00d4   (i0 | some 3 to 4-hex-digit number | i-40)
 00d8   00*5
-00dd    (i8500 i11000 | i11000 i8500)
-00e5   (s1 | s9) (s1 | s7 | s15) (s1 | s2)
-00eb   i1270*4
-00fb   s0 i240 s?? s1 b"(Continued)" 01 01 00*3 byte 00*3
+00dd   i8500           # paper width in 1000/inch (i11000 for landscape)
+00e1   i11000          # paper length in 1000/inch (i8500 for landscape)
+00e5   s1              # letter paper (5=legal, 9=A4, etc.)
+00e7   s15             # s1, s7 also seen
+00e9   s1              # portrait; s2 = landscape
+00eb   i1270           # left margin in 2540/inch, e.g. 1270 = .5 inch
+00ef   i1270           # top margin in 2540/inch
+00f3   i1270           # right margin
+00f7   i1270           # bottom margin
+00fb   s0
+00fd   s240            # object spacing in 1440/inch, e.g. 240 = 12 pt
+00ff   s0              # charts: 0=asis, 1=full page, 2=half, 03=quarter
+0101   s??
+0103   s1              # starting page number
+0105   b"(Continued)" 01 01 00*3 byte 00*3
 0116   w"{\rtf... pagetitle}"
 01fd   01 01 00*3
 0202   w"{\rtf... page number}"
 0116   w"{\rtf... pagetitle}"
 01fd   01 01 00*3
 0202   w"{\rtf... page number}"
@@ -718,7 +730,9 @@ When the top-level "Output" node is selected for save:
 0317   i0
 0318   03 80 00*10
 0324   05 80 01 02 28 05 00 01 b"Log"
 0317   i0
 0318   03 80 00*10
 0324   05 80 01 02 28 05 00 01 b"Log"
-0333   07 80 00 i2 0a 00 01 00*9 i1 00*2 01 01 (f3|f4) ff ff ff 00*4
+
+0333   07 80 00 02 00 00 00 0a 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
+0347   00*2 01 01 (i-13 | i-12) i0
 0357   00*8 90 01 00*9 (22|31)
 036b   32-bytes of null-padded font name, e.g. "Courier New".
        Sometimes garbage after the first null.
 0357   00*8 90 01 00*9 (22|31)
 036b   32-bytes of null-padded font name, e.g. "Courier New".
        Sometimes garbage after the first null.
@@ -728,16 +742,14 @@ When the top-level "Output" node is selected for save:
 
 Almost past SPSS syntax (only the } included):
 0000   '}' 00
 
 Almost past SPSS syntax (only the } included):
 0000   '}' 00
+
 0002   ffff 0000 "NavHead" 02
 0010   00*24 i1 i0
 0002   ffff 0000 "NavHead" 02
 0010   00*24 i1 i0
-0030   03 80 00 00 00 00 00 00  00 00 00 00 05 80 01 02
-0040   28 05 00 01
-0044   b"Cluster|Crosstabs|..."
+0030   03 80 00 00 00 00 00 00  00 00 00 00
+       05 80 01 02 28 05 00 01 b"Cluster|Crosstabs|..."
 
 Just past the string:
 
 Just past the string:
-0000   07 80 00 00 00 00 00 0f  00 01 00 00 00 00 00 00
-0010   00 00 00 01 00 00 00 00  00
-0019   b"Cluster|Crosstabs|..."
+0000   07 80 00 00 00 00 00 0f 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 b"Cluster|Crosstabs|..."
 
 Just past the string again:
 0000   00*3
 
 Just past the string again:
 0000   00*3
@@ -746,10 +758,7 @@ Just past the string again:
 0020   ff ff 00 04 00 00 byte byte
 0028   ff ff 02 00 00 00 01 00  00 00 03 80 00*10
 003e   05 80  01 02 28 00 00 01 b"Title"
 0020   ff ff 00 04 00 00 byte byte
 0028   ff ff 02 00 00 00 01 00  00 00 03 80 00*10
 003e   05 80  01 02 28 00 00 01 b"Title"
-004c   07 80 00 08
-0050   00 00 00 14 00 01 00*9 01
-0060   00*5
-0065   b"Cluster|Crosstabs|..."
+004c   07 80 00 08 00 00 00 14 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 b"Cluster|Crosstabs|..."
 
 Just past the third string:
 0000   01 01 ed ff ff ff 00 00  00 00 00 00 00 00 00 00
 
 Just past the third string:
 0000   01 01 ed ff ff ff 00 00  00 00 00 00 00 00 00 00
@@ -765,8 +774,7 @@ Almost past the RTF (only } included):
 0020   int int i2 i1
 0030   03 80 00*10
 003c   05 80 01 02 28 05 00 01 b"Notes"
 0020   int int i2 i1
 0030   03 80 00*10
 003c   05 80 01 02 28 05 00 01 b"Notes"
-004a   07 80 00 i7 19 00 01 00 00*2 01 00*5 01 00*5
-0063   b"Cluster|Crosstabs|..."
+004a   07 80 00 07 00 00 00 19 00 01 00 00 00 01 00 00 00 00 00 01 00 00 00 00 00 b"Cluster|Crosstabs|..."
 
 Just past the fourth string:
 0000   01
 
 Just past the fourth string:
 0000   01