use crate::abend::{Abend, AbendCode};
use crate::unit::{Loader, RunUnit};
use crate::vocab::Pos;
type R<T> = Result<T, Abend>;
pub fn set<H, L: Loader<H>>(unit: &mut RunUnit<'_, H, L>, base: usize, buffer: Option<(u32, u32)>) {
if let Some((offset, len)) = buffer {
let at = base + offset as usize;
unit.mem[at..at + len as usize].fill(0xAA);
unit.mark(at, len as usize);
}
}
#[allow(clippy::too_many_arguments)]
pub fn test<'a, H, L: Loader<H>>(
unit: &mut RunUnit<'_, H, L>,
base: usize,
buffer: Option<(u32, u32)>,
arguments: impl IntoIterator<Item = (usize, &'a str)>,
called: impl FnOnce(&RunUnit<'_, H, L>) -> String,
caller: &str,
abd: bool,
pos: Pos,
) -> R<()> {
let Some((offset, len)) = buffer else { return Ok(()) };
let at = base + offset as usize;
if unit.mem[at..at + len as usize].iter().all(|&b| b == 0xAA) {
return Ok(());
}
let parameter = arguments.into_iter().filter(|&(a, _)| (base..at).contains(&a)).max_by_key(|&(a, _)| a);
let beyond = parameter.map_or(String::new(), |(_, name)| format!(", beyond parameter {name}"));
let id = if abd { "IGZ0317S" } else { "IGZ0318W" };
let message = format!("{id} The CALL statement on line {} in program {caller} caused corruption of data beyond the end of the WORKING-STORAGE SECTION. ({} wrote past it{beyond})", pos.line, called(unit));
if abd {
return Err(Abend { code: AbendCode::user(4038), message, pos, file: None });
}
let _ = writeln!(unit.err, "ironwork: {pos}: {message}");
Ok(())
}