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

5 months ago
  1. use libc::{
  2. c_void,
  3. size_t,
  4. };
  5. /// How to free the memory allocated by the callback.
  6. pub type Free = unsafe extern "C" fn(*mut c_void);
  7. /// How to free the memory allocated by the callback.
  8. pub type Malloc = unsafe extern "C" fn(size_t) -> *mut c_void;
  9. // Wraps an ffi function.
  10. //
  11. // This wrapper allows the function to return a Result. The Ok
  12. // variant should be (). It may be something else. In that case, the
  13. // value is simply discarded. The Error variant must be convertable
  14. // to a `crate::ErrorCode` using `Into`.
  15. macro_rules! ffi {
  16. (fn $f:ident( $( $v:ident: $t:ty ),* ) -> $rt:ty $body:block ) => {
  17. // The wrapper. It calls $f and turns the result into an
  18. // error code.
  19. #[no_mangle] pub extern "C"
  20. fn $f($($v: $t,)*) -> crate::ErrorCode {
  21. tracer!(*crate::TRACE, stringify!($f));
  22. // The actual function.
  23. fn inner($($v: $t,)*) -> $rt { $body };
  24. t!("entered");
  25. // We use AssertUnwindSafe. This is safe, because if we
  26. // catch a panic, we abort. If we turn the panic into an
  27. // error, then we need to reexamine this assumption.
  28. let r = std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| {
  29. match inner($($v,)*) {
  30. Ok(_) => {
  31. t!("-> success");
  32. ErrorCode::from(crate::Error::StatusOk)
  33. }
  34. Err(err) => {
  35. t!("-> error: {}{}",
  36. err,
  37. {
  38. use std::error::Error;
  39. let mut causes = String::new();
  40. let mut cause = err.source();
  41. while let Some(e) = cause {
  42. causes.push_str("\n because: ");
  43. causes.push_str(&e.to_string());
  44. cause = e.source();
  45. }
  46. causes
  47. });
  48. ErrorCode::from(err)
  49. }
  50. }
  51. }));
  52. match r {
  53. Ok(code) => code,
  54. Err(_) => {
  55. t!("-> panic!");
  56. unsafe { ::libc::abort() };
  57. }
  58. }
  59. }
  60. }
  61. }
  62. // Creates a stub for a ffi, which returns an error.
  63. #[allow(unused_macros)]
  64. macro_rules! stub {
  65. ($f:ident) => {
  66. #[no_mangle] pub extern "C"
  67. fn $f() -> crate::ErrorCode {
  68. tracer!(*crate::TRACE, stringify!($f));
  69. t!("{} is a stub\n", stringify!($f));
  70. crate::Error::UnknownError(
  71. anyhow::anyhow!("Function not implemented"),
  72. stringify!($f).into()).into()
  73. }
  74. };
  75. }