sys-file-reader: Handle SPSS 21 change in representation of LOWEST.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 3 Aug 2013 19:20:46 +0000 (12:20 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 3 Aug 2013 22:12:30 +0000 (15:12 -0700)
Thanks to Mindaugus for reporting this issue.
Bug #39502.

doc/dev/system-file-format.texi
src/data/sys-file-reader.c

index 8315762cef52cb26ea20f1aa2757ca3d6f622554..e98b718883e1ef7507e48c4f39fdc0d19fd9198f 100644 (file)
@@ -33,12 +33,28 @@ floating-point numbers, and translates as needed.  However, only IEEE
 has actually been observed in system files, and it is likely that
 other formats are obsolete or were never used.
 
-The PSPP system-missing value is represented by the largest possible
-negative number in the floating point format (@code{-DBL_MAX}).  Two
-other values are important for use as missing values: @code{HIGHEST},
-represented by the largest possible positive number (@code{DBL_MAX}),
-and @code{LOWEST}, represented by the second-largest negative number
-(in IEEE 754 format, @code{0xffeffffffffffffe}).
+System files use a few floating point values for special purposes:
+
+@table @asis
+@item SYSMIS
+The system-missing value is represented by the largest possible
+negative number in the floating point format (@code{-DBL_MAX}).
+
+@item HIGHEST
+HIGHEST is used as the high end of a missing value range with an
+unbounded maximum.  It is represented by the largest possible positive
+number (@code{DBL_MAX}).
+
+@item LOWEST
+LOWEST is used as the low end of a missing value range with an
+unbounded minimum.  It was originally represented by the
+second-largest negative number (in IEEE 754 format,
+@code{0xffeffffffffffffe}).  System files written by SPSS 21 and later
+instead use the largest negative number (@code{-DBL_MAX}), the same
+value as SYSMIS.  This does not lead to ambiguity because LOWEST
+appears in system files only in missing value ranges, which never
+contain SYSMIS.
+@end table
 
 System files are divided into records, each of which begins with a
 4-byte record type, usually regarded as an @code{int32}.
index c9d49129732062db02de437568f42cd27fdb0cfc..a03a317a450720760926e19d2c2a076b34f84e81 100644 (file)
@@ -1040,6 +1040,11 @@ parse_variable_records (struct sfm_reader *r, struct dictionary *dict,
                 {
                   double low = parse_float (r, rec->missing, 0);
                   double high = parse_float (r, rec->missing, 8);
+
+                  /* Deal with SPSS 21 change in representation. */
+                  if (low == SYSMIS)
+                    low = LOWEST;
+
                   mv_add_range (&mv, low, high);
                   ofs += 16;
                 }
@@ -1269,11 +1274,14 @@ parse_machine_float_info (struct sfm_reader *r,
                 "instead of %g (%a)."),
               highest, highest, "HIGHEST", HIGHEST, HIGHEST);
 
-  if (lowest != LOWEST)
+  /* SPSS before version 21 used a unique value just bigger than SYSMIS as
+     LOWEST.  SPSS 21 uses SYSMIS for LOWEST, which is OK because LOWEST only
+     appears in a context (missing values) where SYSMIS cannot. */
+  if (lowest != LOWEST && lowest != SYSMIS)
     sys_warn (r, record->pos,
               _("File specifies unexpected value %g (%a) as %s, "
-                "instead of %g (%a)."),
-              lowest, lowest, "LOWEST", LOWEST, LOWEST);
+                "instead of %g (%a) or %g (%a)."),
+              lowest, lowest, "LOWEST", LOWEST, LOWEST, SYSMIS, SYSMIS);
 }
 
 /* Parses record type 7, subtype 7 or 19. */