- fn read_value_label_record(&mut self) -> Result<()> {
- println!("{:08x}: value labels record", self.r.stream_position()?);
-
- // Read the labels.
- let n_labels: u32 = self.read_swap()?;
- for _ in 0..n_labels {
- let raw: [u8; 8] = read_bytes(&mut self.r)?;
- let value = UntypedValue::new(raw, self.fp_format);
- let label_len: u8 = self.read_swap()?;
- let padded_len = round_up(label_len as usize + 1, 8);
-
- let mut label = read_vec(&mut self.r, padded_len)?;
- label.truncate(label_len as usize);
- let label = String::from_utf8_lossy(&label);
-
- println!("\t{value}: {label}");
- }
-
- // Read the type-4 record with the corresponding variable indexes.
- let rec_type: u32 = self.read_swap()?;
- if rec_type != 4 {
- Err(anyhow!("Variable index record (type 4) does not immediately \
- follow value label record (type 3) as it should."))?;
- }
-
- println!("\t{:08x}: apply to variables", self.r.stream_position()?);
- let n_vars: u32 = self.read_swap()?;
- for _ in 0..n_vars {
- let index: u32 = self.read_swap()?;
- print!(" {index}");
- }
- println!();
-
- Ok(())
- }
-
- fn read_document_record(&mut self) -> Result<()> {
- println!("{:08x}: document record", self.r.stream_position()?);
- let n_lines: u32 = self.read_swap()?;
- println!("\t{n_lines} lines of documents");
-
- for i in 0..n_lines {
- print!("\t{:08x}: ", self.r.stream_position()?);
- let line: [u8; 64] = read_bytes(&mut self.r)?;
- let line = trim_end(Vec::from(line), b' ');
- println!("line {i}: \"{}\"", String::from_utf8_lossy(&line));
- }
- Ok(())
- }
-
- fn read_machine_integer_info(&mut self, size: u32, count: u32) -> Result<()> {
- let offset = self.r.stream_position()?;
- let version_major: u32 = self.read_swap()?;
- let version_minor: u32 = self.read_swap()?;
- let version_revision: u32 = self.read_swap()?;
- let machine_code: u32 = self.read_swap()?;
- let float_representation: u32 = self.read_swap()?;
- let compression_code: u32 = self.read_swap()?;
- let integer_representation: u32 = self.read_swap()?;
- let character_code: u32 = self.read_swap()?;
-
- println!("{offset:08x}: machine integer info");
- if size != 4 || count != 8 {
- Err(anyhow!("Bad size ({size}) or count ({count}) field on record type 7, subtype 3"))?;
- }
- println!("\tVersion: {version_major}.{version_minor}.{version_revision}");
- println!("\tMachine code: {machine_code}");
- println!("\tFloating point representation: {float_representation} ({})",
- match float_representation {
- 1 => "IEEE 754",
- 2 => "IBM 370",
- 3 => "DEC VAX",
- _ => "unknown"
- });
- println!("\tCompression code: {compression_code}");
- println!("\tEndianness: {integer_representation} ({})",
- match integer_representation {
- 1 => "big",
- 2 => "little",
- _ => "unknown"
- });
- println!("\tCharacter code: {character_code}");
- Ok(())
- }
-
- fn read_machine_float_info(&mut self, size: u32, count: u32) -> Result<()> {
- let offset = self.r.stream_position()?;
- let sysmis: f64 = self.read_swap()?;
- let highest: f64 = self.read_swap()?;
- let lowest: f64 = self.read_swap()?;
-
- println!("{offset:08x}: machine float info");
- if size != 4 || count != 8 {
- Err(anyhow!("Bad size ({size}) or count ({count}) field on extension 4."))?;
- }
-
- println!("\tsysmis: {sysmis} ({})", HexFloat(sysmis));
- println!("\thighest: {highest} ({})", HexFloat(highest));
- println!("\tlowest: {lowest} ({})", HexFloat(lowest));
- Ok(())
- }
-
- fn read_variable_sets(&mut self, size: u32, count: u32) -> Result<()> {
- println!("{:08x}: variable sets", self.r.stream_position()?);
- let mut text = self.open_text_record(size, count)?;
- loop {
- while text.match_byte(b'\n') {
- continue;
- }
- let set = match text.tokenize(b'=') {
- Some(set) => String::from_utf8_lossy(&set).into_owned(),
- None => break,
- };
-
- // Always present even for an empty set.
- text.match_byte(b' ');
-
- match text.tokenize(b'\n') {
- None => println!("\tset \"{set}\" is empty"),
- Some(variables) => {
- println!("\tset \"{set}\" contains \"{}\"", String::from_utf8_lossy(variables).trim_end_matches('\r'));
- },
- };
-
- }
- Ok(())
- }
-
- fn read_extra_product_info(&mut self, size: u32, count: u32) -> Result<()> {
- print!("{:08x}: extra product info", self.r.stream_position()?);
- let mut text = self.open_text_record(size, count)?;
-
- }
-
- fn open_text_record(&mut self, size: u32, count: u32) -> Result<TextRecord> {
- let n_bytes = match u32::checked_mul(size, count) {
- Some(n) => n,
- None => Err(anyhow!("Extension record too large."))?