Don't use "readline" input functionality for the following builtins:

* peek_byte
* peek_char
* peek_code
* get_byte
* get_char
* get_code
* get_n_chars
This commit is contained in:
Peter Mikkelsen
2025-08-22 11:02:59 +02:00
parent 02b8a6010c
commit 39cf60bc05
2 changed files with 49 additions and 3 deletions

View File

@@ -2600,6 +2600,7 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn peek_byte(&mut self) -> CallResult { pub(crate) fn peek_byte(&mut self) -> CallResult {
let _guard = RawReadGuard::new();
let stub_gen = || functor_stub(atom!("peek_byte"), 2); let stub_gen = || functor_stub(atom!("peek_byte"), 2);
let mut stream = self.machine_st.get_stream_or_alias( let mut stream = self.machine_st.get_stream_or_alias(
@@ -2690,6 +2691,7 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn peek_char(&mut self) -> CallResult { pub(crate) fn peek_char(&mut self) -> CallResult {
let _guard = RawReadGuard::new();
let stub_gen = || functor_stub(atom!("peek_char"), 2); let stub_gen = || functor_stub(atom!("peek_char"), 2);
let mut stream = self.machine_st.get_stream_or_alias( let mut stream = self.machine_st.get_stream_or_alias(
@@ -2784,6 +2786,7 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn peek_code(&mut self) -> CallResult { pub(crate) fn peek_code(&mut self) -> CallResult {
let _guard = RawReadGuard::new();
let stub_gen = || functor_stub(atom!("peek_code"), 2); let stub_gen = || functor_stub(atom!("peek_code"), 2);
let mut stream = self.machine_st.get_stream_or_alias( let mut stream = self.machine_st.get_stream_or_alias(
@@ -3437,6 +3440,7 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn get_byte(&mut self) -> CallResult { pub(crate) fn get_byte(&mut self) -> CallResult {
let _guard = RawReadGuard::new();
let mut stream = self.machine_st.get_stream_or_alias( let mut stream = self.machine_st.get_stream_or_alias(
self.machine_st.registers[1], self.machine_st.registers[1],
&self.indices, &self.indices,
@@ -3521,6 +3525,7 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn get_char(&mut self) -> CallResult { pub(crate) fn get_char(&mut self) -> CallResult {
let _guard = RawReadGuard::new();
let mut stream = self.machine_st.get_stream_or_alias( let mut stream = self.machine_st.get_stream_or_alias(
self.machine_st.registers[1], self.machine_st.registers[1],
&self.indices, &self.indices,
@@ -3616,6 +3621,7 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn get_n_chars(&mut self) -> CallResult { pub(crate) fn get_n_chars(&mut self) -> CallResult {
let _guard = RawReadGuard::new();
let stream = self.machine_st.get_stream_or_alias( let stream = self.machine_st.get_stream_or_alias(
self.machine_st.registers[1], self.machine_st.registers[1],
&self.indices, &self.indices,
@@ -3688,6 +3694,7 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn get_code(&mut self) -> CallResult { pub(crate) fn get_code(&mut self) -> CallResult {
let _guard = RawReadGuard::new();
let mut stream = self.machine_st.get_stream_or_alias( let mut stream = self.machine_st.get_stream_or_alias(
self.machine_st.registers[1], self.machine_st.registers[1],
&self.indices, &self.indices,

View File

@@ -107,6 +107,30 @@ fn get_prompt() -> &'static str {
} }
} }
static mut RAW_READ: bool = false;
pub struct RawReadGuard;
impl RawReadGuard {
pub fn new() -> RawReadGuard {
unsafe {
if RAW_READ {
panic!("Nested RawReadGuards");
}
RAW_READ = true;
}
RawReadGuard
}
}
impl Drop for RawReadGuard {
fn drop(&mut self) {
unsafe {
RAW_READ = false;
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct ReadlineStream { pub struct ReadlineStream {
#[cfg(feature = "repl")] #[cfg(feature = "repl")]
@@ -172,7 +196,23 @@ impl ReadlineStream {
#[cfg(feature = "repl")] #[cfg(feature = "repl")]
fn call_readline(&mut self) -> std::io::Result<usize> { fn call_readline(&mut self) -> std::io::Result<usize> {
match self.rl.readline(get_prompt()) { let raw = unsafe { RAW_READ };
let text = if raw {
let mut buffer = String::new();
let stdin = std::io::stdin();
match stdin.read_line(&mut buffer) {
Ok(_) => Ok(buffer),
Err(e) => Err(e),
}
} else {
match self.rl.readline(get_prompt()) {
Ok(text) => Ok(text),
Err(ReadlineError::Eof) => Err(Error::from(ErrorKind::UnexpectedEof)),
Err(e) => Err(Error::new(ErrorKind::InvalidInput, e)),
}
};
match text {
Ok(text) => { Ok(text) => {
self.pending_input.reset_buffer(); self.pending_input.reset_buffer();
@@ -195,8 +235,7 @@ impl ReadlineStream {
Ok(self.pending_input.get_ref().get_ref().len()) Ok(self.pending_input.get_ref().get_ref().len())
} }
Err(ReadlineError::Eof) => Err(Error::from(ErrorKind::UnexpectedEof)), Err(e) => Err(e)
Err(e) => Err(Error::new(ErrorKind::InvalidInput, e)),
} }
} }