use std::io;
use super::super::Core;
use super::history::Halted;
use super::packet::Connection;
use super::threads::{Reason, stop_reply};
use super::{Asked, Debugger, Held};
use crate::emulator::HaltReason;
const REFUSED_RUNNING: &[&str] = &["g", "G", "p", "P", "M", "X", "vFlash", "qRcmd,", "bs", "bc"];
impl Debugger<'_> {
pub(super) fn non_stop(&self) -> bool {
self.negotiated().non_stop
}
pub(super) fn refused_running(&self, packet: &str) -> bool {
let from_an_address = match packet.as_bytes().first() {
Some(b'c' | b's') => packet.len() > 1,
Some(b'C' | b'S') => packet.contains(';'),
_ => false,
};
self.non_stop()
&& self.core != Held::Halted
&& (from_an_address
|| REFUSED_RUNNING
.iter()
.any(|start| packet.starts_with(start)))
}
pub(super) fn set_non_stop(&mut self, core: &mut Core, on: bool) -> Asked {
self.threads.only_core(on);
if !on && self.core != Held::Halted {
self.hold(core, Reason::Halt, Halted::By(HaltReason::Requested));
}
if let Some(connection) = self.connection.as_mut() {
connection.negotiated.non_stop = on;
connection.telling = false;
}
Asked::Reply("OK".to_owned())
}
pub(super) fn tell(&mut self, stop: &str) -> io::Result<()> {
let connection = self.connection()?;
connection.telling = true;
connection.notify(&format!("Stop:{stop}"))
}
pub(super) fn telling(&self) -> bool {
self.connection
.as_ref()
.is_some_and(|connection| connection.telling)
}
pub(super) fn exit_taken(&mut self) {
for _ in 0..4 {
let Ok(packet) = self.connection().and_then(Connection::next_packet) else {
return;
};
let answer = if packet == "vStopped" { "OK" } else { "E01" };
if self
.connection()
.and_then(|connection| connection.send(answer))
.is_err()
|| packet == "vStopped"
{
return;
}
}
}
pub(super) fn told(&mut self) -> Asked {
if let Some(connection) = self.connection.as_mut() {
connection.telling = false;
}
Asked::Reply("OK".to_owned())
}
pub(super) fn stops_again(&mut self) -> Asked {
let held = self.core == Held::Halted;
let stop = held.then(|| stop_reply(self.stopped, self.negotiated()));
if let Some(connection) = self.connection.as_mut() {
connection.telling = held;
}
Asked::Reply(stop.unwrap_or_else(|| "OK".to_owned()))
}
pub(super) fn stop(&mut self, core: &mut Core, reason: Reason) -> io::Result<()> {
self.connection()?.send("OK")?;
if self.core == Held::Halted {
return Ok(());
}
self.halt_core(core, reason)
}
}