pspp-dump-sav: More gracefully handle empty multiple response sets.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 16 Feb 2014 07:06:13 +0000 (23:06 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 16 Feb 2014 07:06:13 +0000 (23:06 -0800)
Some multiple response sets have no variables, although I don't know why,
and pspp-dump-sav is more useful if it doesn't stop reading when it arrives
at one.

doc/dev/system-file-format.texi
src/data/sys-file-reader.c
tests/data/sys-file-reader.at
utilities/pspp-dump-sav.c

index be6433b9a0f75c3877dc5915e446a6c90e09fa4b..2d576733081d3018e402bf7072fae9a3ca63eb6d 100644 (file)
@@ -785,6 +785,12 @@ A space.
 The short names of the variables in the set, converted to lowercase,
 each separated from the previous by a single space.
 
+Even though a multiple response set must have at least two variables,
+some system files contain multiple response sets with no variables at
+all.  The source and meaning of these multiple response sets is
+unknown.  (Perhaps they arise from creating a multiple response set
+then deleting all the variables that it contains?)
+
 @item
 One line feed (byte 0x0a).  Sometimes multiple, even hundreds, of line
 feeds are present.
index b7c5984466e43ac0439e53d69c7facfc3462388b..abaab6f25d9bffd75d0fc41098e24c0874179ec1 100644 (file)
@@ -1495,10 +1495,11 @@ parse_mrsets (struct sfm_reader *r, const struct sfm_extension_record *record,
           raw_var_name = text_get_token (text, ss_cstr (" \n"), &delimiter);
           if (raw_var_name == NULL)
             {
-              sys_warn (r, record->pos,
-                        _("Missing new-line parsing variable names "
-                          "at offset %zu in MRSETS record."),
-                        text_pos (text));
+              if (delimiter != '\n')
+                sys_warn (r, record->pos,
+                          _("Missing new-line parsing variable names "
+                            "at offset %zu in MRSETS record."),
+                          text_pos (text));
               break;
             }
           var_name = recode_string ("UTF-8", r->encoding, raw_var_name, -1);
index 3c29a33bbaaf0cf3ff380d17b13cce4bc10be073..26ac6431dbe32e19876cf3e7be7098459bae039a 100644 (file)
@@ -2872,7 +2872,7 @@ warning: `sys-file.sav' near offset 0xd8: MRSET $a has only 1 variables.
 done
 AT_CLEANUP
 
-AT_SETUP([only one variable in mrset])
+AT_SETUP([zero or one variable in mrset])
 AT_KEYWORDS([sack synthetic system file negative multiple response])
 AT_DATA([sys-file.sack], [dnl
 dnl File header.
@@ -2883,13 +2883,13 @@ dnl Numeric variable, no label or missing values.
 2; 0; 0; 0; 0x050800 *2; s8 "NUM1";
 
 dnl Multiple response sets.
-7; 7; 1; COUNT("$a=C 0  NUM1"; i8 10);
+7; 7; 1; COUNT("$a=C 0  NUM1"; i8 10; "$b=C 0  "; i8 10);
 
 999; 0;
 ])
 for variant in \
-       "be 3a891e0a467afb3d622629c70f329ada" \
-       "le 432998ec08370510411af4f5207c015e"
+       "be d94549fece75560fe5b47f32713b63a1" \
+       "le 63028521d460df9e998b40a75a93c330"
 do
   set $variant
   AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2]
@@ -2898,6 +2898,8 @@ do
 ])
   AT_CHECK([pspp -O format=csv sys-file.sps], [0], [dnl
 warning: `sys-file.sav' near offset 0xd8: MRSET $a has only 1 variables.
+
+warning: `sys-file.sav' near offset 0xd8: MRSET $b has only 0 variables.
 ])
 done
 AT_CLEANUP
index c31c02a9277185f05cb7cadc5103cd370cd1dd70..879c3748d3de9b78bf9505b9f8a526883df58d7b 100644 (file)
@@ -832,12 +832,6 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count)
         break;
 
       variables = text_tokenize (text, '\n');
-      if (variables == NULL)
-        {
-          sys_warn (r, "missing variable names following label "
-                    "at offset %zu in mrsets record", text_pos (text));
-          break;
-        }
 
       printf ("\t\"%s\": multiple %s set",
               name, type == MRSET_MC ? "category" : "dichotomy");
@@ -849,7 +843,10 @@ read_mrsets (struct sfm_reader *r, size_t size, size_t count)
         printf (", label \"%s\"", label);
       if (label_from_var_label)
         printf (", label from variable label");
-      printf(", variables \"%s\"\n", variables);
+      if (variables != NULL)
+        printf(", variables \"%s\"\n", variables);
+      else
+        printf(", no variables\n");
     }
   close_text_record (text);
 }