let initial_len = output.len();
match lexer.take()? {
Token::Integer(integer) => {
- let Ok(integer): Result<i32, _> = integer.try_into() else {
+ if let Ok(integer) = TryInto::<i32>::try_into(integer) {
+ output.extend_from_slice(&lexer.endian.to_bytes(integer));
+ } else if let Ok(integer) = TryInto::<u32>::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])
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}");
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,
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));
}
_ => (),
}
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(())
}