use super::*;
impl<'p> Machine<'p, '_, '_> {
pub(super) fn parmcheck_set(&mut self) {
if let Some((offset, len)) = self.layout.parmcheck {
let at = self.base + offset as usize;
self.unit.mem[at..at + len as usize].fill(0xAA);
}
}
pub(super) fn parmcheck_test(&mut self, c: &Call, addresses: &[Option<usize>], called: impl FnOnce(&Self) -> String) -> R<()> {
let Some((offset, len)) = self.layout.parmcheck else { return Ok(()) };
let at = self.base + offset as usize;
if self.unit.mem[at..at + len as usize].iter().all(|&b| b == 0xAA) {
return Ok(());
}
let parameter = c
.using
.iter()
.zip(addresses)
.filter_map(|(arg, address)| match (&arg.value, *address) {
(Some(Operand::Ref(r)), Some(a)) if (self.base..at).contains(&a) => Some((a, r.name.as_str())),
_ => None,
})
.max_by_key(|&(a, _)| a);
let beyond = parameter.map_or(String::new(), |(_, name)| format!(", beyond parameter {name}"));
let message = format!("PARMCHECK: {}, called at line {} of program {}, wrote past the end of WORKING-STORAGE{beyond}", called(self), c.pos.line, self.program.id);
if self.options.parmcheck.is_some_and(|p| p.abd) {
return Err(Abend { code: AbendCode::user(4038), message, pos: c.pos, file: None });
}
let _ = writeln!(self.unit.err, "ironwork: {}: {message}", c.pos);
Ok(())
}
}