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 <inttypes.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -257,6 +258,20 @@ get_string1(void)
   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)
 {
@@ -266,6 +281,20 @@ get_string2(void)
   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)
 {
@@ -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[])
@@ -463,5 +526,26 @@ main(int argc, char *argv[])
 
   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;
 }
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
-       "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"
-       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
-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}"
@@ -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"
-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.
@@ -728,16 +742,14 @@ When the top-level "Output" node is selected for save:
 
 Almost past SPSS syntax (only the } included):
 0000   '}' 00
+
 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:
-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
@@ -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"
-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
@@ -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"
-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