From: Ben Pfaff Date: Tue, 1 Aug 2023 17:07:06 +0000 (-0700) Subject: sack is fully implemented X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=613cad2297c1963101766a57adf1950f5013bcd8;p=pspp sack is fully implemented --- diff --git a/rust/src/sack.rs b/rust/src/sack.rs index 4dfcf335ef..ab35f8661e 100644 --- a/rust/src/sack.rs +++ b/rust/src/sack.rs @@ -101,14 +101,18 @@ fn parse_data_item( let initial_len = output.len(); match lexer.take()? { Token::Integer(integer) => { - let Ok(integer): Result = integer.try_into() else { + if let Ok(integer) = TryInto::::try_into(integer) { + output.extend_from_slice(&lexer.endian.to_bytes(integer)); + } else if let Ok(integer) = TryInto::::try_into(integer) { + output.extend_from_slice(&lexer.endian.to_bytes(integer)); + } else { Err(lexer.error(format!( "{integer} is not in the valid range [{},{}]", - u32::min_value(), + i32::min_value(), u32::max_value() - )))? + )))?; }; - output.extend_from_slice(&lexer.endian.to_bytes(integer))}, + } Token::Float(float) => output.extend_from_slice(&lexer.endian.to_bytes(float.0)), Token::PcSysmis => { output.extend_from_slice(&[0xf5, 0x1e, 0x26, 0x02, 0x8a, 0x8c, 0xed, 0xff]) @@ -143,18 +147,28 @@ fn parse_data_item( let Some((Token::String(ref string), _)) = lexer.token else { Err(lexer.error(String::from("string expected after 'hex'")))? }; - let mut i = string.chars(); + let mut string = &string[..]; loop { + string = string.trim_start(); + if string.is_empty() { + break; + }; + + let mut i = string.chars(); let Some(c0) = i.next() else { return Ok(true) }; let Some(c1) = i.next() else { Err(lexer.error(String::from("hex string has odd number of characters")))? }; + let (Some(digit0), Some(digit1)) = (c0.to_digit(16), c1.to_digit(16)) else { Err(lexer.error(String::from("invalid digit in hex string")))? }; let byte = digit0 * 16 + digit1; output.push(byte as u8); + + string = i.as_str(); } + lexer.get()?; } Token::Label(name) => { println!("define {name}"); @@ -177,11 +191,7 @@ fn parse_data_item( return Ok(true); } Token::At(name) => { - let mut value = symbol_table - .entry(name.clone()) - .or_insert(None) - .unwrap_or(0); - println!("{name} has value {value}"); + let mut value = *symbol_table.entry(name.clone()).or_insert(None); loop { let plus = match lexer.token { Some((Token::Plus, _)) => true, @@ -191,27 +201,33 @@ fn parse_data_item( lexer.get()?; let operand = match lexer.token { - Some((Token::At(ref name), _)) => if let Some(value) = symbol_table.get(name) { - *value - } else { - symbol_table.insert(name.clone(), None); - None + Some((Token::At(ref name), _)) => { + *symbol_table.entry(name.clone()).or_insert(None) } - .unwrap_or(0), - Some((Token::Integer(integer), _)) => integer - .try_into() - .map_err(|msg| lexer.error(format!("bad offset literal ({msg})")))?, + Some((Token::Integer(integer), _)) => Some( + integer + .try_into() + .map_err(|msg| lexer.error(format!("bad offset literal ({msg})")))?, + ), _ => Err(lexer.error(String::from("expecting @label or integer literal")))?, }; lexer.get()?; - value = if plus { - value.checked_add(operand) - } else { - value.checked_sub(operand) - } - .ok_or_else(|| lexer.error(String::from("overflow in offset arithmetic")))?; + value = match (value, operand) { + (Some(a), Some(b)) => Some( + if plus { + a.checked_add(b) + } else { + a.checked_sub(b) + } + .ok_or_else(|| { + lexer.error(String::from("overflow in offset arithmetic")) + })?, + ), + _ => None, + }; } + let value = value.unwrap_or(0); output.extend_from_slice(&lexer.endian.to_bytes(value)); } _ => (), diff --git a/rust/tests/sack.rs b/rust/tests/sack.rs index abb51abe2a..5db8d43bb3 100644 --- a/rust/tests/sack.rs +++ b/rust/tests/sack.rs @@ -67,15 +67,27 @@ struct Args { } fn main() -> Result<()> { - let Args { be, le, input_file_name, output_file_name } = Args::parse(); + let Args { + be, + le, + input_file_name, + output_file_name, + } = Args::parse(); let endian = match (be, le) { (false, false) | (true, false) => Endian::Big, (false, true) => Endian::Little, (true, true) => return Err(anyhow!("can't use both `--be` and `--le`")), }; - let input = read_to_string(&input_file_name)?; - let input_file_name = input_file_name.to_string_lossy(); - let output = sack(&input, Some(&input_file_name), endian)?; - std::fs::write(&output_file_name, &output)?; + + let input_file_str = input_file_name.to_string_lossy(); + let input = read_to_string(&input_file_name) + .map_err(|err| anyhow!("{input_file_str}: read failed ({err})"))?; + + let output = sack(&input, Some(&input_file_str), endian)?; + + let output_file_str = output_file_name.to_string_lossy(); + std::fs::write(&output_file_name, &output) + .map_err(|err| anyhow!("{output_file_str}: write failed ({err})"))?; + Ok(()) }