more cleanup
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 13 Jul 2025 22:10:24 +0000 (15:10 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 13 Jul 2025 22:10:24 +0000 (15:10 -0700)
31 files changed:
rust/pspp/src/sys/raw.rs
rust/pspp/src/sys/raw/records.rs
rust/pspp/src/sys/testdata/bad_machine_float_info_size.expected
rust/pspp/src/sys/testdata/bad_machine_integer_info_count.expected
rust/pspp/src/sys/testdata/bad_variable_name_in_variable_value_pair.expected
rust/pspp/src/sys/testdata/compressed_data_other_bias.expected
rust/pspp/src/sys/testdata/duplicate_attribute_name.expected
rust/pspp/src/sys/testdata/duplicate_long_variable_name.expected
rust/pspp/src/sys/testdata/integer_overflows_in_long_string_missing_values.expected
rust/pspp/src/sys/testdata/invalid_long_string_missing_values.expected
rust/pspp/src/sys/testdata/missing_attribute_value.expected
rust/pspp/src/sys/testdata/multiple_response_sets_bad_counted_string.expected
rust/pspp/src/sys/testdata/multiple_response_sets_counted_string_bad_length.expected
rust/pspp/src/sys/testdata/multiple_response_sets_counted_string_missing_space.expected
rust/pspp/src/sys/testdata/multiple_response_sets_missing_label_source.expected
rust/pspp/src/sys/testdata/multiple_response_sets_missing_newline_after_variable_name.expected
rust/pspp/src/sys/testdata/multiple_response_sets_missing_space_after_c.expected
rust/pspp/src/sys/testdata/multiple_response_sets_missing_space_after_counted_string.expected
rust/pspp/src/sys/testdata/multiple_response_sets_missing_space_after_e.expected
rust/pspp/src/sys/testdata/multiple_response_sets_unexpected_label_source.expected
rust/pspp/src/sys/testdata/null_dereference_skipping_bad_extension_record_18.expected
rust/pspp/src/sys/testdata/unquoted_attribute_value.expected
rust/pspp/src/sys/testdata/value_label_variable_indexes_must_be_in_correct_range.expected
rust/pspp/src/sys/testdata/value_label_variable_indexes_must_not_be_long_string_continuation.expected
rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.expected
rust/pspp/src/sys/testdata/variables_for_value_label_must_all_be_same_type.expected
rust/pspp/src/sys/testdata/wrong_display_alignment.expected
rust/pspp/src/sys/testdata/wrong_display_measurement_level.expected
rust/pspp/src/sys/testdata/wrong_display_parameter_count.expected
rust/pspp/src/sys/testdata/wrong_display_parameter_size.expected
rust/pspp/src/sys/testdata/zcompressed_data_uncompressed_size_block_size.expected

index 6e822be41ed4e18894d2519c37af1c6aaccdbca4..8be83dea2a5f005116c458f2f0e7595d39b1e9e5 100644 (file)
@@ -265,8 +265,11 @@ pub struct Warning {
 impl std::error::Error for Warning {}
 
 impl Warning {
-    pub fn new(offsets: Option<Range<u64>>, details: WarningDetails) -> Self {
-        Self { offsets, details }
+    pub fn new(offsets: Option<Range<u64>>, details: impl Into<WarningDetails>) -> Self {
+        Self {
+            offsets,
+            details: details.into(),
+        }
     }
 }
 
@@ -289,27 +292,100 @@ impl Display for Warning {
     }
 }
 
+/// Details of a [Warning].
 #[derive(ThisError, Debug)]
 pub enum WarningDetails {
-    #[error("Unexpected end of data inside extension record.")]
-    UnexpectedEndOfData,
+    /// Warning for file header.
+    #[error("In file header: {0}")]
+    Header(#[from] HeaderWarning),
 
-    #[error(
-        "At least one valid variable index for value labels is required but none were specified."
-    )]
-    NoVarIndexes,
+    /// Warning for variable records.
+    #[error("In variable record: {0}")]
+    Variable(#[from] VariableWarning),
 
-    #[error("The first variable index is for a {var_type} variable but the following variable indexes are for {} variables: {wrong_types:?}", !var_type)]
-    MixedVarTypes {
-        var_type: VarType,
-        wrong_types: Vec<u32>,
-    },
+    /// Warning for extension records.
+    #[error("In extension record: {0}")]
+    Extension(#[from] ExtensionWarning),
 
-    #[error(
-        "One or more variable indexes for value labels were not in the valid range [1,{max}] or referred to string continuations: {invalid:?}"
-    )]
-    InvalidVarIndexes { max: usize, invalid: Vec<u32> },
+    /// Warning for value labels.
+    #[error("In value label record: {0}")]
+    ValueLabel(#[from] ValueLabelWarning),
+
+    /// Warning for long string missing values.
+    #[error("In long string missing values record: {0}")]
+    LongStringMissingValues(#[from] LongStringMissingValuesWarning),
+
+    /// Warning for long string value labels.
+    #[error("In long string value label record: {0}")]
+    LongStringValueLabel(#[from] LongStringValueLabelWarning),
+
+    /// Warning for long variable names.
+    #[error("In long variable name record: {0}")]
+    LongName(#[from] LongNameWarning),
+
+    /// Warning for very long strings.
+    #[error("In very long string record: {0}")]
+    VeryLongString(#[from] VeryLongStringWarning),
+
+    /// Warning for multiple response record.
+    #[error("In multiple response set record: {0}")]
+    MultipleResponse(#[from] MultipleResponseWarning),
+
+    /// Warning for attribute record.
+    #[error("In file or variable attribute record: {0}")]
+    Attribute(#[from] AttributeWarning),
+
+    /// Warning for variable display record.
+    #[error("In variable display record: {0}")]
+    VariableDisplay(#[from] VariableDisplayWarning),
+
+    /// Warning for variable set record.
+    #[error("In variable set record: {0}")]
+    VariableSet(#[from] VariableSetWarning),
+
+    /// Warning for ZLIB trailer.
+    #[error("In ZLIB trailer: {0}")]
+    ZlibTrailer(#[from] ZlibTrailerWarning),
+
+    #[error("Encoding record contains an encoding name that is not valid UTF-8.")]
+    BadEncodingName,
+
+    // XXX This is risky because `text` might be arbitarily long.
+    #[error("Text string contains invalid bytes for {encoding} encoding: {text:?}")]
+    MalformedString { encoding: String, text: String },
+
+    #[error("{0}")]
+    EncodingError(EncodingError),
+}
+
+impl From<IoError> for WarningDetails {
+    fn from(_source: IoError) -> Self {
+        Self::Extension(ExtensionWarning::UnexpectedEndOfData)
+    }
+}
+
+#[derive(ThisError, Debug)]
+pub enum HeaderWarning {
+    #[error("Compression bias is {0} instead of the usual values of 0 or 100.")]
+    UnexpectedBias(f64),
+}
 
+#[derive(ThisError, Debug)]
+pub enum VariableWarning {
+    #[error("Missing value record with range not allowed for string variable")]
+    MissingValueStringRange,
+
+    #[error("Missing value not allowed for long string continuation")]
+    MissingValueContinuation,
+}
+
+#[derive(ThisError, Debug)]
+pub enum ExtensionWarning {
+    /// Unexpected end of data.
+    #[error("Unexpected end of data.")]
+    UnexpectedEndOfData,
+
+    /// Invalid record size.
     #[error("{record} has bad size {size} bytes instead of the expected {expected_size}.")]
     BadRecordSize {
         record: String,
@@ -317,111 +393,111 @@ pub enum WarningDetails {
         expected_size: u32,
     },
 
+    /// Invalid record count.
     #[error("{record} has bad count {count} instead of the expected {expected_count}.")]
     BadRecordCount {
         record: String,
         count: u32,
         expected_count: u32,
     },
+}
 
-    #[error(
-        "In long string missing values record, value length at offset {offset:#x} is {value_len} instead of the expected 8."
-    )]
-    BadLongMissingValueLength { offset: u64, value_len: u32 },
-
-    #[error("Encoding record contains an encoding name that is not valid UTF-8.")]
-    BadEncodingName,
+#[derive(ThisError, Debug)]
+pub enum ValueLabelWarning {
+    /// At least one valid variable index for value labels is required but none were specified.
+    #[error("At least one valid variable index is required but none were specified.")]
+    NoVarIndexes,
 
-    // XXX This is risky because `text` might be arbitarily long.
-    #[error("Text string contains invalid bytes for {encoding} encoding: {text:?}")]
-    MalformedString { encoding: String, text: String },
+    /// Mixed variable types in value label record.
+    #[error("First variable index is for a {var_type} variable but the following variable indexes are for {} variables: {wrong_types:?}", !var_type)]
+    MixedVarTypes {
+        var_type: VarType,
+        wrong_types: Vec<u32>,
+    },
 
-    #[error("Invalid variable measurement level value {0}")]
-    InvalidMeasurement(u32),
+    /// Value label invalid variable indexes.
+    #[error(
+        "One or more variable indexes were not in the valid range [1,{max}] or referred to string continuations: {invalid:?}"
+    )]
+    InvalidVarIndexes { max: usize, invalid: Vec<u32> },
+}
 
-    #[error("Invalid variable display alignment value {0}")]
-    InvalidAlignment(u32),
+#[derive(ThisError, Debug)]
+pub enum LongStringMissingValuesWarning {
+    #[error("Value length at offset {offset:#x} is {value_len} instead of the expected 8.")]
+    BadValueLength { offset: u64, value_len: u32 },
 
-    #[error("Invalid attribute name.  {0}")]
-    InvalidAttributeName(IdError),
+    #[error("Invalid variable name.  {0}")]
+    InvalidVariableName(IdError),
+}
 
-    #[error("Invalid variable name in attribute record.  {0}")]
-    InvalidAttributeVariableName(IdError),
+#[derive(ThisError, Debug)]
+pub enum LongStringValueLabelWarning {
+    #[error("Invalid variable name.  {0}")]
+    InvalidVariableName(IdError),
+}
 
-    #[error("Missing `=` separator in long variable name record.")]
+#[derive(ThisError, Debug)]
+pub enum LongNameWarning {
+    #[error("Missing `=` separator.")]
     LongNameMissingEquals,
 
-    #[error("Invalid short name in long variable name record.  {0}")]
+    #[error("Invalid short name.  {0}")]
     InvalidShortName(IdError),
 
-    #[error("Invalid name in long variable name record.  {0}")]
+    #[error("Invalid long name.  {0}")]
     InvalidLongName(IdError),
+}
 
-    #[error("Invalid variable name in very long string record.  {0}")]
+#[derive(ThisError, Debug)]
+pub enum VeryLongStringWarning {
+    #[error("Invalid variable name.  {0}")]
     InvalidLongStringName(IdError),
 
-    #[error("Invalid variable name in variable set record.  {0}")]
-    InvalidVariableSetName(IdError),
+    #[error("Missing delimiter in {0:?}.")]
+    VeryLongStringMissingDelimiter(String),
 
-    #[error("Variable set missing name delimiter.")]
-    VariableSetMissingEquals,
+    #[error("Invalid length in {0:?}.")]
+    VeryLongStringInvalidLength(String),
+}
 
+#[derive(ThisError, Debug)]
+pub enum MultipleResponseWarning {
     #[error("Invalid multiple response set name.  {0}")]
     InvalidMrSetName(IdError),
 
-    #[error("Invalid multiple response set variable name.  {0}")]
+    #[error("Invalid variable name.  {0}")]
     InvalidMrSetVariableName(IdError),
 
-    #[error("Invalid variable name in long string missing values record.  {0}")]
-    InvalidLongStringMissingValueVariableName(IdError),
-
-    #[error("Invalid variable name in long string value label record.  {0}")]
-    InvalidLongStringValueLabelName(IdError),
-
-    #[error("{0}")]
-    EncodingError(EncodingError),
-
-    #[error("Missing value record with range not allowed for string variable")]
-    MissingValueStringRange,
-
-    #[error("Missing value not allowed for long string continuation")]
-    MissingValueContinuation,
-
-    #[error("Invalid multiple dichotomy label type")]
+    #[error("Invalid multiple dichotomy label type.")]
     InvalidMultipleDichotomyLabelType,
 
-    #[error("Invalid multiple response type")]
+    #[error("Invalid multiple response type.")]
     InvalidMultipleResponseType,
 
-    #[error("Syntax error in multiple response record ({0})")]
+    #[error("Syntax error ({0}).")]
     MultipleResponseSyntaxError(&'static str),
 
-    #[error("Syntax error parsing counted string (missing trailing space)")]
+    #[error("Syntax error parsing counted string (missing trailing space).")]
     CountedStringMissingSpace,
 
-    #[error("Syntax error parsing counted string (invalid UTF-8)")]
+    #[error("Syntax error parsing counted string (invalid UTF-8).")]
     CountedStringInvalidUTF8,
 
-    #[error("Syntax error parsing counted string (invalid length {0:?})")]
+    #[error("Syntax error parsing counted string (invalid length {0:?}).")]
     CountedStringInvalidLength(String),
 
-    #[error("Syntax error parsing counted string (length {0:?} goes past end of input)")]
+    #[error("Syntax error parsing counted string (length {0:?} goes past end of input).")]
     CountedStringTooLong(usize),
+}
 
-    #[error(
-        "Variable display record contains {count} items but should contain either {first} or {second}."
-    )]
-    InvalidVariableDisplayCount {
-        count: usize,
-        first: usize,
-        second: usize,
-    },
-
-    #[error("Very long string record missing delimiter in {0:?}.")]
-    VeryLongStringMissingDelimiter(String),
+#[derive(ThisError, Debug)]
+pub enum AttributeWarning {
+    #[error("Invalid attribute name.  {0}")]
+    InvalidAttributeName(IdError),
 
-    #[error("Very long string record has invalid length in {0:?}.")]
-    VeryLongStringInvalidLength(String),
+    #[error("Invalid variable name in attribute record.  {0}")]
+    InvalidAttributeVariableName(IdError),
 
     #[error("Attribute record missing left parenthesis, in {0:?}.")]
     AttributeMissingLParen(String),
@@ -446,10 +522,35 @@ pub enum WarningDetails {
 
     #[error("File attributes record contains trailing garbage.")]
     FileAttributesTrailingGarbage,
+}
 
-    #[error("Compression bias is {0} instead of the usual values of 0 or 100.")]
-    UnexpectedBias(f64),
+#[derive(ThisError, Debug)]
+pub enum VariableDisplayWarning {
+    #[error("Record contains {count} items but should contain either {first} or {second}.")]
+    InvalidVariableDisplayCount {
+        count: usize,
+        first: usize,
+        second: usize,
+    },
 
+    #[error("Invalid variable measurement level value {0}.")]
+    InvalidMeasurement(u32),
+
+    #[error("Invalid variable display alignment value {0}.")]
+    InvalidAlignment(u32),
+}
+
+#[derive(ThisError, Debug)]
+pub enum VariableSetWarning {
+    #[error("Invalid variable name.  {0}")]
+    InvalidVariableSetName(IdError),
+
+    #[error("Missing name delimiter.")]
+    VariableSetMissingEquals,
+}
+
+#[derive(ThisError, Debug)]
+pub enum ZlibTrailerWarning {
     #[error(
         "ZLIB block descriptor {index} reported block size {actual:#x}, when {expected:#x} was expected."
     )]
@@ -469,12 +570,6 @@ pub enum WarningDetails {
     },
 }
 
-impl From<IoError> for WarningDetails {
-    fn from(_source: IoError) -> Self {
-        Self::UnexpectedEndOfData
-    }
-}
-
 /// A raw record in a system file.
 #[allow(missing_docs)] // Don't warn for missing docs on tuple members.
 #[derive(Clone, Debug)]
@@ -821,6 +916,9 @@ impl<'de> Decoder<'de> {
     }
 }
 
+/// System file type, inferred from its "magic number".
+///
+/// The magic number is the first four bytes of the file.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub enum Magic {
     /// Regular system file.
@@ -1638,8 +1736,8 @@ fn read_string<R: Read>(r: &mut R, endian: Endian) -> Result<RawString, IoError>
 }
 
 #[derive(Default)]
-pub struct VarTypes {
-    pub types: Vec<Option<VarWidth>>,
+struct VarTypes {
+    types: Vec<Option<VarWidth>>,
 }
 
 impl VarTypes {
index 996762be49221dfae21a1bc01d483b2ce0deecd1..2561d32c841de22a8875ea8db0d76fec83ba1ab8 100644 (file)
@@ -20,8 +20,12 @@ use crate::{
     endian::{Endian, Parse},
     identifier::{Error as IdError, Identifier},
     sys::raw::{
-        read_bytes, read_string, read_vec, DecodedRecord, Decoder, Error, ErrorDetails, Magic,
-        RawDatum, RawStrArray, RawWidth, Record, UntypedDatum, VarTypes, Warning, WarningDetails,
+        read_bytes, read_string, read_vec, AttributeWarning, DecodedRecord, Decoder, Error,
+        ErrorDetails, ExtensionWarning, HeaderWarning, LongNameWarning,
+        LongStringMissingValuesWarning, LongStringValueLabelWarning, Magic,
+        MultipleResponseWarning, RawDatum, RawStrArray, RawWidth, Record, UntypedDatum,
+        ValueLabelWarning, VarTypes, VariableDisplayWarning, VariableSetWarning, VariableWarning,
+        VeryLongStringWarning, Warning, WarningDetails, ZlibTrailerWarning,
     },
 };
 
@@ -181,7 +185,7 @@ impl HeaderRecord<RawString> {
         if header.bias != 100.0 && header.bias != 0.0 {
             warn(Warning::new(
                 Some(84..92),
-                WarningDetails::UnexpectedBias(header.bias),
+                HeaderWarning::UnexpectedBias(header.bias),
             ));
         }
 
@@ -371,7 +375,7 @@ impl MissingValues {
             }
             Ok(VarWidth::String(_)) if range.is_some() => warn(Warning::new(
                 Some(offsets),
-                WarningDetails::MissingValueStringRange,
+                VariableWarning::MissingValueStringRange,
             )),
             Ok(VarWidth::String(width)) => {
                 let width = width.min(8) as usize;
@@ -383,7 +387,7 @@ impl MissingValues {
             }
             Err(()) => warn(Warning::new(
                 Some(offsets),
-                WarningDetails::MissingValueContinuation,
+                VariableWarning::MissingValueContinuation,
             )),
         }
         Ok(Self::default())
@@ -579,7 +583,7 @@ where
 }
 
 impl ValueLabelRecord<RawDatum, RawString> {
-    pub fn read<R: Read + Seek>(
+    pub(super) fn read<R: Read + Seek>(
         r: &mut R,
         endian: Endian,
         var_types: &VarTypes,
@@ -629,7 +633,10 @@ impl ValueLabelRecord<RawDatum, RawString> {
                 },
             ));
         } else if n == 0 {
-            warn(Warning::new(Some(n_offsets), WarningDetails::NoVarIndexes));
+            warn(Warning::new(
+                Some(n_offsets),
+                ValueLabelWarning::NoVarIndexes,
+            ));
             return Ok(None);
         }
 
@@ -648,7 +655,7 @@ impl ValueLabelRecord<RawDatum, RawString> {
         if !invalid_indexes.is_empty() {
             warn(Warning::new(
                 Some(index_offsets.clone()),
-                WarningDetails::InvalidVarIndexes {
+                ValueLabelWarning::InvalidVarIndexes {
                     max: var_types.n_values(),
                     invalid: invalid_indexes,
                 },
@@ -671,7 +678,7 @@ impl ValueLabelRecord<RawDatum, RawString> {
         if !wrong_type_indexes.is_empty() {
             warn(Warning::new(
                 Some(index_offsets),
-                WarningDetails::MixedVarTypes {
+                ValueLabelWarning::MixedVarTypes {
                     var_type,
                     wrong_types: wrong_type_indexes,
                 },
@@ -904,15 +911,15 @@ pub struct VeryLongString {
 impl VeryLongString {
     fn parse(decoder: &Decoder, input: &str) -> Result<VeryLongString, WarningDetails> {
         let Some((short_name, length)) = input.split_once('=') else {
-            return Err(WarningDetails::VeryLongStringMissingDelimiter(input.into()));
+            return Err(VeryLongStringWarning::VeryLongStringMissingDelimiter(input.into()).into());
         };
         let short_name = decoder
             .new_identifier(short_name)
             .and_then(Identifier::must_be_ordinary)
-            .map_err(WarningDetails::InvalidLongStringName)?;
+            .map_err(VeryLongStringWarning::InvalidLongStringName)?;
         let length = length
             .parse()
-            .map_err(|_| WarningDetails::VeryLongStringInvalidLength(input.into()))?;
+            .map_err(|_| VeryLongStringWarning::VeryLongStringInvalidLength(input.into()))?;
         Ok(VeryLongString { short_name, length })
     }
 }
@@ -977,7 +984,7 @@ impl MultipleResponseType {
                 } else if let Some(rest) = input.strip_prefix(b" 11 ") {
                     (CategoryLabels::VarLabels, rest)
                 } else {
-                    return Err(WarningDetails::InvalidMultipleDichotomyLabelType);
+                    return Err(MultipleResponseWarning::InvalidMultipleDichotomyLabelType.into());
                 };
                 let (value, input) = parse_counted_string(input)?;
                 (
@@ -985,7 +992,7 @@ impl MultipleResponseType {
                     input,
                 )
             }
-            _ => return Err(WarningDetails::InvalidMultipleResponseType),
+            _ => return Err(MultipleResponseWarning::InvalidMultipleResponseType.into()),
         };
         Ok((mr_type, input))
     }
@@ -1006,15 +1013,16 @@ where
 impl MultipleResponseSet<RawString, RawString> {
     fn parse(input: &[u8]) -> Result<(Self, &[u8]), WarningDetails> {
         let Some(equals) = input.iter().position(|&b| b == b'=') else {
-            return Err(WarningDetails::MultipleResponseSyntaxError("missing `=`"));
+            return Err(MultipleResponseWarning::MultipleResponseSyntaxError("missing `=`").into());
         };
         let (name, input) = input.split_at(equals);
         let input = input.strip_prefix(b"=").unwrap();
         let (mr_type, input) = MultipleResponseType::parse(input)?;
         let Some(input) = input.strip_prefix(b" ") else {
-            return Err(WarningDetails::MultipleResponseSyntaxError(
+            return Err(MultipleResponseWarning::MultipleResponseSyntaxError(
                 "missing space after multiple response type",
-            ));
+            )
+            .into());
         };
         let (label, mut input) = parse_counted_string(input)?;
         let mut vars = Vec::new();
@@ -1022,9 +1030,10 @@ impl MultipleResponseSet<RawString, RawString> {
             match input.split_first() {
                 Some((b' ', rest)) => {
                     let Some(length) = rest.iter().position(|b| b" \n".contains(b)) else {
-                        return Err(WarningDetails::MultipleResponseSyntaxError(
+                        return Err(MultipleResponseWarning::MultipleResponseSyntaxError(
                             "missing variable name delimiter",
-                        ));
+                        )
+                        .into());
                     };
                     let (var, rest) = rest.split_at(length);
                     if !var.is_empty() {
@@ -1033,9 +1042,10 @@ impl MultipleResponseSet<RawString, RawString> {
                     input = rest;
                 }
                 _ => {
-                    return Err(WarningDetails::MultipleResponseSyntaxError(
+                    return Err(MultipleResponseWarning::MultipleResponseSyntaxError(
                         "missing space preceding variable name",
-                    ));
+                    )
+                    .into());
                 }
             }
         }
@@ -1062,7 +1072,7 @@ impl MultipleResponseSet<RawString, RawString> {
         for short_name in self.short_names.iter() {
             if let Some(short_name) = decoder
                 .decode_identifier(short_name)
-                .map_err(WarningDetails::InvalidMrSetName)
+                .map_err(MultipleResponseWarning::InvalidMrSetName)
                 .issue_warning(offsets, &mut decoder.warn)
             {
                 short_names.push(short_name);
@@ -1071,7 +1081,7 @@ impl MultipleResponseSet<RawString, RawString> {
         Ok(MultipleResponseSet {
             name: decoder
                 .decode_identifier(&self.name)
-                .map_err(WarningDetails::InvalidMrSetVariableName)?,
+                .map_err(MultipleResponseWarning::InvalidMrSetVariableName)?,
             label: decoder.decode(&self.label).to_string(),
             mr_type: self.mr_type.clone(),
             short_names,
@@ -1139,17 +1149,17 @@ impl MultipleResponseRecord<RawString, RawString> {
 
 fn parse_counted_string(input: &[u8]) -> Result<(RawString, &[u8]), WarningDetails> {
     let Some(space) = input.iter().position(|&b| b == b' ') else {
-        return Err(WarningDetails::CountedStringMissingSpace);
+        return Err(MultipleResponseWarning::CountedStringMissingSpace.into());
     };
     let Ok(length) = from_utf8(&input[..space]) else {
-        return Err(WarningDetails::CountedStringInvalidUTF8);
+        return Err(MultipleResponseWarning::CountedStringInvalidUTF8.into());
     };
     let Ok(length): Result<usize, _> = length.parse() else {
-        return Err(WarningDetails::CountedStringInvalidLength(length.into()));
+        return Err(MultipleResponseWarning::CountedStringInvalidLength(length.into()).into());
     };
 
     let Some((string, rest)) = input[space + 1..].split_at_checked(length) else {
-        return Err(WarningDetails::CountedStringTooLong(length));
+        return Err(MultipleResponseWarning::CountedStringTooLong(length).into());
     };
     Ok((string.into(), rest))
 }
@@ -1161,7 +1171,7 @@ impl Measure {
             1 => Ok(Some(Measure::Nominal)),
             2 => Ok(Some(Measure::Ordinal)),
             3 => Ok(Some(Measure::Scale)),
-            _ => Err(WarningDetails::InvalidMeasurement(source)),
+            _ => Err(VariableDisplayWarning::InvalidMeasurement(source).into()),
         }
     }
 }
@@ -1172,7 +1182,7 @@ impl Alignment {
             0 => Ok(Some(Alignment::Left)),
             1 => Ok(Some(Alignment::Right)),
             2 => Ok(Some(Alignment::Center)),
-            _ => Err(WarningDetails::InvalidAlignment(source)),
+            _ => Err(VariableDisplayWarning::InvalidAlignment(source).into()),
         }
     }
 }
@@ -1194,13 +1204,12 @@ impl VarDisplayRecord {
         endian: Endian,
         warn: &mut dyn FnMut(Warning),
     ) -> Result<Record, WarningDetails> {
-        if ext.size != 4 {
-            return Err(WarningDetails::BadRecordSize {
-                record: String::from("variable display record"),
-                size: ext.size,
-                expected_size: 4,
-            });
-        }
+        static VAR_DISPLAY_RECORD: ExtensionRecord = ExtensionRecord {
+            size: Some(4),
+            count: None,
+            name: "variable display record",
+        };
+        ext.check_size(&VAR_DISPLAY_RECORD)?;
 
         let n_vars = var_types.n_vars();
         let has_width = if ext.count as usize == 3 * n_vars {
@@ -1208,11 +1217,12 @@ impl VarDisplayRecord {
         } else if ext.count as usize == 2 * n_vars {
             false
         } else {
-            return Err(WarningDetails::InvalidVariableDisplayCount {
+            return Err(VariableDisplayWarning::InvalidVariableDisplayCount {
                 count: ext.count as usize,
                 first: 2 * n_vars,
                 second: 3 * n_vars,
-            });
+            }
+            .into());
         };
 
         let mut var_displays = Vec::new();
@@ -1292,7 +1302,7 @@ impl LongStringMissingValueRecord<RawString> {
                 let offset = (ext.data.len() - input.len() - 8) as u64 + ext.offsets.start;
                 warn(Warning::new(
                     Some(ext.offsets.clone()),
-                    WarningDetails::BadLongMissingValueLength { offset, value_len },
+                    LongStringMissingValuesWarning::BadValueLength { offset, value_len },
                 ));
                 read_vec(&mut input, value_len as usize * n_missing_values as usize)?;
                 continue;
@@ -1333,7 +1343,7 @@ impl LongStringMissingValueRecord<RawString> {
         for mv in self.values.iter() {
             if let Some(mv) = mv
                 .decode(decoder)
-                .map_err(WarningDetails::InvalidLongStringMissingValueVariableName)
+                .map_err(LongStringMissingValuesWarning::InvalidVariableName)
                 .issue_warning(&self.offsets, &mut decoder.warn)
             {
                 mvs.push(mv);
@@ -1447,18 +1457,19 @@ impl Attribute {
         input: &'a str,
     ) -> Result<(Attribute, &'a str), WarningDetails> {
         let Some((name, mut input)) = input.split_once('(') else {
-            return Err(WarningDetails::AttributeMissingLParen(input.into()));
+            return Err(AttributeWarning::AttributeMissingLParen(input.into()).into());
         };
         let name = decoder
             .new_identifier(name)
-            .map_err(WarningDetails::InvalidAttributeName)?;
+            .map_err(AttributeWarning::InvalidAttributeName)?;
         let mut values = Vec::new();
         loop {
             let Some((value, rest)) = input.split_once('\n') else {
-                return Err(WarningDetails::AttributeMissingValue {
+                return Err(AttributeWarning::AttributeMissingValue {
                     name: name.clone(),
                     index: values.len(),
-                });
+                }
+                .into());
             };
             if let Some(stripped) = value
                 .strip_prefix('\'')
@@ -1468,7 +1479,7 @@ impl Attribute {
             } else {
                 decoder.warn(Warning::new(
                     Some(offsets.clone()),
-                    WarningDetails::AttributeMissingQuotes {
+                    AttributeWarning::AttributeMissingQuotes {
                         name: name.clone(),
                         index: values.len(),
                     },
@@ -1533,7 +1544,7 @@ impl RawFileAttributesRecord {
                 if !duplicates.is_empty() {
                     decoder.warn(Warning::new(
                         Some(self.0.offsets.clone()),
-                        WarningDetails::DuplicateFileAttributes {
+                        AttributeWarning::DuplicateFileAttributes {
                             attributes: duplicates,
                         },
                     ));
@@ -1541,7 +1552,7 @@ impl RawFileAttributesRecord {
                 if !rest.is_empty() {
                     decoder.warn(Warning::new(
                         Some(self.0.offsets.clone()),
-                        WarningDetails::FileAttributesTrailingGarbage,
+                        AttributeWarning::FileAttributesTrailingGarbage,
                     ));
                 }
                 FileAttributesRecord(set)
@@ -1564,17 +1575,17 @@ impl VarAttributes {
         input: &'a str,
     ) -> Result<(VarAttributes, &'a str), WarningDetails> {
         let Some((long_var_name, rest)) = input.split_once(':') else {
-            return Err(WarningDetails::VariableAttributeMissingColon);
+            return Err(AttributeWarning::VariableAttributeMissingColon.into());
         };
         let long_var_name = decoder
             .new_identifier(long_var_name)
             .and_then(Identifier::must_be_ordinary)
-            .map_err(WarningDetails::InvalidAttributeVariableName)?;
+            .map_err(AttributeWarning::InvalidAttributeVariableName)?;
         let (attributes, rest, duplicates) = Attributes::parse(decoder, offsets, rest, Some('/'))?;
         if !duplicates.is_empty() {
             decoder.warn(Warning::new(
                 Some(offsets.clone()),
-                WarningDetails::DuplicateVariableAttributes {
+                AttributeWarning::DuplicateVariableAttributes {
                     variable: long_var_name.clone(),
                     attributes: duplicates,
                 },
@@ -1627,16 +1638,16 @@ pub struct LongName {
 impl LongName {
     fn parse(input: &str, decoder: &Decoder) -> Result<Self, WarningDetails> {
         let Some((short_name, long_name)) = input.split_once('=') else {
-            return Err(WarningDetails::LongNameMissingEquals);
+            return Err(LongNameWarning::LongNameMissingEquals.into());
         };
         let short_name = decoder
             .new_identifier(short_name)
             .and_then(Identifier::must_be_ordinary)
-            .map_err(WarningDetails::InvalidShortName)?;
+            .map_err(LongNameWarning::InvalidShortName)?;
         let long_name = decoder
             .new_identifier(long_name)
             .and_then(Identifier::must_be_ordinary)
-            .map_err(WarningDetails::InvalidLongName)?;
+            .map_err(LongNameWarning::InvalidLongName)?;
         Ok(LongName {
             short_name,
             long_name,
@@ -1664,13 +1675,13 @@ impl VariableSet {
     ) -> Result<Self, WarningDetails> {
         let (name, input) = input
             .split_once('=')
-            .ok_or(WarningDetails::VariableSetMissingEquals)?;
+            .ok_or(VariableSetWarning::VariableSetMissingEquals)?;
         let mut vars = Vec::new();
         for var in input.split_ascii_whitespace() {
             if let Some(identifier) = decoder
                 .new_identifier(var)
                 .and_then(Identifier::must_be_ordinary)
-                .map_err(WarningDetails::InvalidVariableSetName)
+                .map_err(VariableSetWarning::InvalidVariableSetName)
                 .issue_warning(offsets, &mut decoder.warn)
             {
                 vars.push(identifier);
@@ -1692,12 +1703,15 @@ pub struct VariableSetRecord {
 trait IssueWarning<T> {
     fn issue_warning(self, offsets: &Range<u64>, warn: &mut dyn FnMut(Warning)) -> Option<T>;
 }
-impl<T> IssueWarning<T> for Result<T, WarningDetails> {
+impl<T, W> IssueWarning<T> for Result<T, W>
+where
+    W: Into<WarningDetails>,
+{
     fn issue_warning(self, offsets: &Range<u64>, warn: &mut dyn FnMut(Warning)) -> Option<T> {
         match self {
             Ok(result) => Some(result),
             Err(error) => {
-                warn(Warning::new(Some(offsets.clone()), error));
+                warn(Warning::new(Some(offsets.clone()), error.into()));
                 None
             }
         }
@@ -1725,28 +1739,30 @@ impl Extension {
     pub fn check_size(&self, expected: &ExtensionRecord) -> Result<(), WarningDetails> {
         match expected.size {
             Some(expected_size) if self.size != expected_size => {
-                return Err(WarningDetails::BadRecordSize {
+                return Err(ExtensionWarning::BadRecordSize {
                     record: expected.name.into(),
                     size: self.size,
                     expected_size,
-                });
+                }
+                .into());
             }
             _ => (),
         }
         match expected.count {
             Some(expected_count) if self.count != expected_count => {
-                return Err(WarningDetails::BadRecordCount {
+                return Err(ExtensionWarning::BadRecordCount {
                     record: expected.name.into(),
                     count: self.count,
                     expected_count,
-                });
+                }
+                .into());
             }
             _ => (),
         }
         Ok(())
     }
 
-    pub fn read<R: Read + Seek>(
+    pub(super) fn read<R: Read + Seek>(
         r: &mut R,
         endian: Endian,
         var_types: &VarTypes,
@@ -1823,7 +1839,7 @@ impl LongStringValueLabels<RawString, RawString> {
     ) -> Result<LongStringValueLabels<Identifier, String>, WarningDetails> {
         let var_name = decoder.decode(&self.var_name);
         let var_name = Identifier::from_encoding(var_name.trim_end(), decoder.encoding)
-            .map_err(WarningDetails::InvalidLongStringValueLabelName)?;
+            .map_err(LongStringValueLabelWarning::InvalidVariableName)?;
 
         let mut labels = Vec::with_capacity(self.labels.len());
         for (value, label) in self.labels.iter() {
@@ -2081,7 +2097,7 @@ impl ZTrailer {
                 if block.uncompressed_size != block_size {
                     warn(Warning::new(
                         Some(block_offsets),
-                        WarningDetails::ZlibTrailerBlockWrongSize {
+                        ZlibTrailerWarning::ZlibTrailerBlockWrongSize {
                             index,
                             actual: block.uncompressed_size,
                             expected: block_size,
@@ -2092,7 +2108,7 @@ impl ZTrailer {
                 if block.uncompressed_size > block_size {
                     warn(Warning::new(
                         Some(block_offsets),
-                        WarningDetails::ZlibTrailerBlockTooBig {
+                        ZlibTrailerWarning::ZlibTrailerBlockTooBig {
                             index,
                             actual: block.uncompressed_size,
                             max_expected: block_size,
index 5ebd48f3700abe71020c7bb089e8eb17cad1c929..d2542a1194fb406f8362657f8b4c2edc91876ac4 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0x100: floating point record has bad count 4 instead of the expected 3.
+Warning at file offsets 0xe0 to 0x100: In extension record: floating point record has bad count 4 instead of the expected 3.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index d08b9606ee46f001034109a7470510726657d813..0587a131f8d6098eb12e54a3157d4dac1a80ab75 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0x104: integer record has bad count 9 instead of the expected 8.
+Warning at file offsets 0xe0 to 0x104: In extension record: integer record has bad count 9 instead of the expected 8.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 14471714749a3aa6734d1d5acc58580a31d03fe3..13d3fb715e0da9080c0a21c604dcda454dca6522 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe5: Missing `=` separator in long variable name record.
+Warning at file offsets 0xe0 to 0xe5: In long variable name record: Missing `=` separator.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 7b7f43ebd9fa5da1ac35858b0cf8b5641832dd15..21cd5347021fe6e7c67ea85b7d05038289aa3631 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0x54 to 0x5c: Compression bias is 50 instead of the usual values of 0 or 100.
+Warning at file offsets 0x54 to 0x5c: In file header: Compression bias is 50 instead of the usual values of 0 or 100.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index ec072796535b8e3e40b55d9fcbbccb3e619d43dd..3a70ef81caf256ac50f07e0f992109d53aae349c 100644 (file)
@@ -1,6 +1,6 @@
-Warning at file offsets 0xe0 to 0xfe: Duplicate dataset attributes with names: Attr1.
+Warning at file offsets 0xe0 to 0xfe: In file or variable attribute record: Duplicate dataset attributes with names: Attr1.
 
-Warning at file offsets 0x10e to 0x12d: Duplicate attributes for variable FIRSTVAR: fred.
+Warning at file offsets 0x10e to 0x12d: In file or variable attribute record: Duplicate attributes for variable FIRSTVAR: fred.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 7a00f13ff310fbc061ff7d935629c0e62f436fc2..6f17a31f67543b1061e813fa9e7f97f6802403ac 100644 (file)
@@ -1,8 +1,8 @@
-Warning at file offsets 0x140 to 0x1aa: Invalid name in long variable name record.  "_Invalid" may not be used as an identifier because it begins with disallowed character '_'.
+Warning at file offsets 0x140 to 0x1aa: In long variable name record: Invalid long name.  "_Invalid" may not be used as an identifier because it begins with disallowed character '_'.
 
-Warning at file offsets 0x140 to 0x1aa: Invalid name in long variable name record.  "$Invalid" may not be used as an identifier because it begins with disallowed character '$'.
+Warning at file offsets 0x140 to 0x1aa: In long variable name record: Invalid long name.  "$Invalid" may not be used as an identifier because it begins with disallowed character '$'.
 
-Warning at file offsets 0x140 to 0x1aa: Invalid name in long variable name record.  "#Invalid" may not be used as an identifier because it begins with disallowed character '#'.
+Warning at file offsets 0x140 to 0x1aa: In long variable name record: Invalid long name.  "#Invalid" may not be used as an identifier because it begins with disallowed character '#'.
 
 Duplicate long variable name LONGVARIABLENAME.
 
index 4dd9691195a69074db86c436397a483fb9016f23..ea2d86612b86828fe190ce6f8fe08102fa1904bc 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0x1d8 to 0x21f: Unexpected end of data inside extension record.
+Warning at file offsets 0x1d8 to 0x21f: In extension record: Unexpected end of data.
 
 This system file does not indicate its own character encoding.  For best results, specify an encoding explicitly.  Use SYSFILE INFO with ENCODING="DETECT" to analyze the possible encodings.
 
index f749ae8de9ea888917bbe837846dca3a47050884..654448b13180e8d35decd970880fc6fe3954bc8b 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0x238 to 0x2f2: In long string missing values record, value length at offset 0x2a8 is 12 instead of the expected 8.
+Warning at file offsets 0x238 to 0x2f2: In long string missing values record: Value length at offset 0x2a8 is 12 instead of the expected 8.
 
 File header claims 8 variable positions but 9 were read from file.
 
index 980b0dcd25c534b27c43ac8c72bd585d77a65a67..141a5a0bc73fa00ddfc0467a1d09c3b075312ccd 100644 (file)
@@ -1,6 +1,6 @@
-Warning at file offsets 0xe0 to 0xe6: Attribute for Attr1[1] lacks value.
+Warning at file offsets 0xe0 to 0xe6: In file or variable attribute record: Attribute for Attr1[1] lacks value.
 
-Warning at file offsets 0xf6 to 0x109: Attribute for fred[2] lacks value.
+Warning at file offsets 0xf6 to 0x109: In file or variable attribute record: Attribute for fred[2] lacks value.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 477dc239682adac6c73632438688887fd21e9325..9b849999e5b411702ff7b99627bac051db98d339 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe5: Syntax error parsing counted string (missing trailing space)
+Warning at file offsets 0xe0 to 0xe5: In multiple response set record: Syntax error parsing counted string (missing trailing space).
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index ccd09bde382a166efa9a733206483e4fb1c5f939..8fb97dbb0c2860892ff36e497c0e1a3376db4ac7 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe9: Syntax error parsing counted string (length 4 goes past end of input)
+Warning at file offsets 0xe0 to 0xe9: In multiple response set record: Syntax error parsing counted string (length 4 goes past end of input).
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 03591009150e86d423fdf78452955de83d28b5e3..f6e6e03234ce94db4829dac38dad51a50011c494 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe6: Syntax error parsing counted string (missing trailing space)
+Warning at file offsets 0xe0 to 0xe6: In multiple response set record: Syntax error parsing counted string (missing trailing space).
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 19c5be342f25e70d3b2f48156240aede21a023f7..fe138f630bfce43212e02ea7fae8dcab88108a56 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe5: Invalid multiple dichotomy label type
+Warning at file offsets 0xe0 to 0xe5: In multiple response set record: Invalid multiple dichotomy label type.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 94929e747c9e9a5474d7b7b056503adb42ee719b..d4c8ec03cb9c0458095c28363c14d05c58b0bdd2 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xec: Syntax error in multiple response record (missing variable name delimiter)
+Warning at file offsets 0xe0 to 0xec: In multiple response set record: Syntax error (missing variable name delimiter).
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 021c411872bb0b404ac368ce64895e3ea733a4c1..5c60f29d73e0e3a8b2b1bfd352c1814e23ee315b 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe5: Syntax error in multiple response record (missing space after multiple response type)
+Warning at file offsets 0xe0 to 0xe5: In multiple response set record: Syntax error (missing space after multiple response type).
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 208826b8ba4e30f35ac34212b366e68e7b9e7842..05d8d77537608a2b2243369c20c1cf44a00e59a0 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xea: Syntax error in multiple response record (missing space after multiple response type)
+Warning at file offsets 0xe0 to 0xea: In multiple response set record: Syntax error (missing space after multiple response type).
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 19c5be342f25e70d3b2f48156240aede21a023f7..fe138f630bfce43212e02ea7fae8dcab88108a56 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe5: Invalid multiple dichotomy label type
+Warning at file offsets 0xe0 to 0xe5: In multiple response set record: Invalid multiple dichotomy label type.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index f7f3dd6f0c0622aa412a508a4f552a46a78cefbd..4b0d62e2856b20e53e5caaddcf8067b90d88923a 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe6: Invalid multiple dichotomy label type
+Warning at file offsets 0xe0 to 0xe6: In multiple response set record: Invalid multiple dichotomy label type.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 5ed52fce1af9d2f18a110d0660a0feac08ee6e76..64940a388027eebbc65c0bf0c9e5a863de95a530 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0x1c8 to 0x1e8: variable attributes record has bad size 4 bytes instead of the expected 1.
+Warning at file offsets 0x1c8 to 0x1e8: In extension record: variable attributes record has bad size 4 bytes instead of the expected 1.
 
 This system file does not indicate its own character encoding.  For best results, specify an encoding explicitly.  Use SYSFILE INFO with ENCODING="DETECT" to analyze the possible encodings.
 
index b6db9e1bc27968645a68ded0438383c3b98f3e36..5a45874292a833bb031fbebbff00c8cfc8699a6f 100644 (file)
@@ -1,6 +1,6 @@
-Warning at file offsets 0xe0 to 0xed: Attribute for Attr1[1] missing quotations.
+Warning at file offsets 0xe0 to 0xed: In file or variable attribute record: Attribute for Attr1[1] missing quotations.
 
-Warning at file offsets 0xfd to 0x10f: Attribute for fred[1] missing quotations.
+Warning at file offsets 0xfd to 0x10f: In file or variable attribute record: Attribute for fred[1] missing quotations.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 7b5bbb9115c7fe0c972f99fa6ba87bea0ea4c2cd..8469f599a886c0663b062a5ca7e930b86de15e16 100644 (file)
@@ -1,8 +1,8 @@
-Warning at file offsets 0x110 to 0x118: One or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [3, 4]
+Warning at file offsets 0x110 to 0x118: In value label record: One or more variable indexes were not in the valid range [1,2] or referred to string continuations: [3, 4]
 
-Warning at file offsets 0x138 to 0x140: One or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [5, 6]
+Warning at file offsets 0x138 to 0x140: In value label record: One or more variable indexes were not in the valid range [1,2] or referred to string continuations: [5, 6]
 
-Warning at file offsets 0x160 to 0x168: One or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [7, 8]
+Warning at file offsets 0x160 to 0x168: In value label record: One or more variable indexes were not in the valid range [1,2] or referred to string continuations: [7, 8]
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 54dba1a367362e3703295669af7d4a8ae9bc635e..54880f864805c74bd0f20fb35100b37835eb999f 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0x110 to 0x114: One or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [2]
+Warning at file offsets 0x110 to 0x114: In value label record: One or more variable indexes were not in the valid range [1,2] or referred to string continuations: [2]
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 60cd0f5597e75357e7daaca35905ba0217ab7a12..1230c0a499ad424a8b6dcc086b0143bfc230a75f 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xec to 0xf0: At least one valid variable index for value labels is required but none were specified.
+Warning at file offsets 0xec to 0xf0: In value label record: At least one valid variable index is required but none were specified.
 
 This system file does not indicate its own character encoding.  For best results, specify an encoding explicitly.  Use SYSFILE INFO with ENCODING="DETECT" to analyze the possible encodings.
 
index 749b0e9d0829c0d4b636c572f3f87d2a55741254..0723dc8d92dbe20cad981376a903de0abc8b371b 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0x110 to 0x118: The first variable index is for a string variable but the following variable indexes are for numeric variables: [2]
+Warning at file offsets 0x110 to 0x118: In value label record: First variable index is for a string variable but the following variable indexes are for numeric variables: [2]
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 866fd2adb464ddcb4914a17f18c65797feac5ecf..7628df79a2b8557d237cdc118a133b7b3d149b9b 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe8: Invalid variable display alignment value 4294967295
+Warning at file offsets 0xe0 to 0xe8: In variable display record: Invalid variable display alignment value 4294967295.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index a3878bcbd215c21ff46a97240f5f6b10cfe4ffa0..783766c84ae5b2dc14b39bd29c67430554e66d48 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xe8: Invalid variable measurement level value 4
+Warning at file offsets 0xe0 to 0xe8: In variable display record: Invalid variable measurement level value 4.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index 7137241dfa564c35518360a3d44742ebc1d0cf6c..cefc24fa1b4b1c8642ca0788ea0c998ec42a8079 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xf0: Variable display record contains 4 items but should contain either 2 or 3.
+Warning at file offsets 0xe0 to 0xf0: In variable display record: Record contains 4 items but should contain either 2 or 3.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index cff6b227e259d9b2ba315f6d4281c1c81d60cc12..06a93186ed2816ad4957c5f0b0df04546bd72a8e 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0xe0 to 0xf0: variable display record has bad size 8 bytes instead of the expected 4.
+Warning at file offsets 0xe0 to 0xf0: In extension record: variable display record has bad size 8 bytes instead of the expected 4.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│
index d79d528952447e51bb3ae4de0e9f6380ccb94361..00be8d426781c171b62414ca3cd4a511ab890353 100644 (file)
@@ -1,4 +1,4 @@
-Warning at file offsets 0x1c4 to 0x1dc: ZLIB block descriptor 0 reported block size 0x400000, when at most 0x3ff000 was expected.
+Warning at file offsets 0x1c4 to 0x1dc: In ZLIB trailer: ZLIB block descriptor 0 reported block size 0x400000, when at most 0x3ff000 was expected.
 
 ╭──────────────────────┬────────────────────────╮
 │       Created        │    01-JAN-2011 20:53:52│