A backend for the p≡p Engine built on Sequoia.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

83 lines
2.8 KiB

use libc::{
c_void,
size_t,
};
/// How to free the memory allocated by the callback.
pub type Free = unsafe extern "C" fn(*mut c_void);
/// How to free the memory allocated by the callback.
pub type Malloc = unsafe extern "C" fn(size_t) -> *mut c_void;
// Wraps an ffi function.
//
// This wrapper allows the function to return a Result. The Ok
// variant should be (). It may be something else. In that case, the
// value is simply discarded. The Error variant must be convertable
// to a `crate::ErrorCode` using `Into`.
macro_rules! ffi {
(fn $f:ident( $( $v:ident: $t:ty ),* ) -> $rt:ty $body:block ) => {
// The wrapper. It calls $f and turns the result into an
// error code.
#[no_mangle] pub extern "C"
fn $f($($v: $t,)*) -> crate::ErrorCode {
tracer!(*crate::TRACE, stringify!($f));
// The actual function.
fn inner($($v: $t,)*) -> $rt { $body };
t!("entered");
// We use AssertUnwindSafe. This is safe, because if we
// catch a panic, we abort. If we turn the panic into an
// error, then we need to reexamine this assumption.
let r = std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| {
match inner($($v,)*) {
Ok(_) => {
t!("-> success");
ErrorCode::from(crate::Error::StatusOk)
}
Err(err) => {
t!("-> error: {}{}",
err,
{
use std::error::Error;
let mut causes = String::new();
let mut cause = err.source();
while let Some(e) = cause {
causes.push_str("\n because: ");
causes.push_str(&e.to_string());
cause = e.source();
}
causes
});
ErrorCode::from(err)
}
}
}));
match r {
Ok(code) => code,
Err(_) => {
t!("-> panic!");
unsafe { ::libc::abort() };
}
}
}
}
}
// Creates a stub for a ffi, which returns an error.
#[allow(unused_macros)]
macro_rules! stub {
($f:ident) => {
#[no_mangle] pub extern "C"
fn $f() -> crate::ErrorCode {
tracer!(*crate::TRACE, stringify!($f));
t!("{} is a stub\n", stringify!($f));
crate::Error::UnknownError(
anyhow::anyhow!("Function not implemented"),
stringify!($f).into()).into()
}
};
}