use crate::stack::{Stack, pop, push};
use crate::value::Value;
#[cfg(unix)]
use std::sync::atomic::Ordering;
#[cfg(unix)]
use super::{MAX_SIGNAL, SIGNAL_FLAGS};
#[cfg(unix)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_trap(stack: Stack) -> Stack {
unsafe {
let (stack, sig_val) = pop(stack);
let sig_num = match sig_val {
Value::Int(n) => {
if n < 0 || n as usize >= MAX_SIGNAL {
panic!("signal.trap: invalid signal number {}", n);
}
n as libc::c_int
}
_ => panic!(
"signal.trap: expected Int (signal number), got {:?}",
sig_val
),
};
if let Err(e) = super::handlers::install_signal_handler(sig_num) {
panic!(
"signal.trap: failed to install handler for signal {}: {}",
sig_num, e
);
}
stack
}
}
#[cfg(unix)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_received(stack: Stack) -> Stack {
unsafe {
let (stack, sig_val) = pop(stack);
let sig_num = match sig_val {
Value::Int(n) => {
if n < 0 || n as usize >= MAX_SIGNAL {
panic!("signal.received?: invalid signal number {}", n);
}
n as usize
}
_ => panic!(
"signal.received?: expected Int (signal number), got {:?}",
sig_val
),
};
let was_set = SIGNAL_FLAGS[sig_num].swap(false, Ordering::Acquire);
push(stack, Value::Bool(was_set))
}
}
#[cfg(unix)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_pending(stack: Stack) -> Stack {
unsafe {
let (stack, sig_val) = pop(stack);
let sig_num = match sig_val {
Value::Int(n) => {
if n < 0 || n as usize >= MAX_SIGNAL {
panic!("signal.pending?: invalid signal number {}", n);
}
n as usize
}
_ => panic!(
"signal.pending?: expected Int (signal number), got {:?}",
sig_val
),
};
let is_set = SIGNAL_FLAGS[sig_num].load(Ordering::Acquire);
push(stack, Value::Bool(is_set))
}
}
#[cfg(unix)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_default(stack: Stack) -> Stack {
unsafe {
let (stack, sig_val) = pop(stack);
let sig_num = match sig_val {
Value::Int(n) => {
if n < 0 || n as usize >= MAX_SIGNAL {
panic!("signal.default: invalid signal number {}", n);
}
n as libc::c_int
}
_ => panic!(
"signal.default: expected Int (signal number), got {:?}",
sig_val
),
};
if let Err(e) = super::handlers::restore_default_handler(sig_num) {
panic!(
"signal.default: failed to restore default handler for signal {}: {}",
sig_num, e
);
}
stack
}
}
#[cfg(unix)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_ignore(stack: Stack) -> Stack {
unsafe {
let (stack, sig_val) = pop(stack);
let sig_num = match sig_val {
Value::Int(n) => {
if n < 0 || n as usize >= MAX_SIGNAL {
panic!("signal.ignore: invalid signal number {}", n);
}
n as libc::c_int
}
_ => panic!(
"signal.ignore: expected Int (signal number), got {:?}",
sig_val
),
};
if let Err(e) = super::handlers::ignore_signal(sig_num) {
panic!("signal.ignore: failed to ignore signal {}: {}", sig_num, e);
}
stack
}
}
#[cfg(unix)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_clear(stack: Stack) -> Stack {
unsafe {
let (stack, sig_val) = pop(stack);
let sig_num = match sig_val {
Value::Int(n) => {
if n < 0 || n as usize >= MAX_SIGNAL {
panic!("signal.clear: invalid signal number {}", n);
}
n as usize
}
_ => panic!(
"signal.clear: expected Int (signal number), got {:?}",
sig_val
),
};
SIGNAL_FLAGS[sig_num].store(false, Ordering::Release);
stack
}
}
#[cfg(not(unix))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_trap(stack: Stack) -> Stack {
let (stack, _) = unsafe { pop(stack) };
stack
}
#[cfg(not(unix))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_default(stack: Stack) -> Stack {
let (stack, _) = unsafe { pop(stack) };
stack
}
#[cfg(not(unix))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_ignore(stack: Stack) -> Stack {
let (stack, _) = unsafe { pop(stack) };
stack
}
#[cfg(not(unix))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_received(stack: Stack) -> Stack {
let (stack, _) = unsafe { pop(stack) };
unsafe { push(stack, Value::Bool(false)) }
}
#[cfg(not(unix))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_pending(stack: Stack) -> Stack {
let (stack, _) = unsafe { pop(stack) };
unsafe { push(stack, Value::Bool(false)) }
}
#[cfg(not(unix))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_signal_clear(stack: Stack) -> Stack {
let (stack, _) = unsafe { pop(stack) };
stack
}