macros.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. use core::ptr;
  2. use core::any::Any;
  3. /// This struct converts to `NULL` for raw pointers, and `-1` for signed
  4. /// integers.
  5. pub struct Fail;
  6. impl<T: Any> Into<*const T> for Fail {
  7. #[inline(always)]
  8. fn into(self) -> *const T {
  9. ptr::null()
  10. }
  11. }
  12. impl<T: Any> Into<*mut T> for Fail {
  13. #[inline(always)]
  14. fn into(self) -> *mut T {
  15. ptr::null_mut()
  16. }
  17. }
  18. macro_rules! int_fail {
  19. ($type:ty) => (
  20. impl Into<$type> for Fail {
  21. #[inline(always)]
  22. fn into(self) -> $type {
  23. -1
  24. }
  25. }
  26. )
  27. }
  28. int_fail!(i8);
  29. int_fail!(i16);
  30. int_fail!(i32);
  31. int_fail!(i64);
  32. int_fail!(isize);
  33. /// If `res` is `Err(..)`, set `errno` and return `-1` or `NULL`, otherwise
  34. /// unwrap.
  35. macro_rules! try_call {
  36. ($res:expr) => (
  37. match $res {
  38. Ok(val) => val,
  39. Err(err) => {
  40. *::__errno() = err.errno;
  41. return ::macros::Fail.into();
  42. }
  43. }
  44. );
  45. }
  46. /// Declares a libc function. The body should return syscall::Result, which
  47. /// is used to set errno on error with try_call!
  48. ///
  49. /// ```
  50. /// libc_fn!(foo(arg: c_int) -> c_int) {
  51. /// Ok(arg)
  52. /// }
  53. /// ```
  54. ///
  55. /// The `unsafe` keyword can be added to make the function unsafe:
  56. ///
  57. /// ```
  58. /// libc_fn!(unsafe foo(arg: c_int) -> c_int) {
  59. /// Ok(arg)
  60. /// }
  61. /// ```
  62. macro_rules! libc_fn {
  63. // The next 2 cases handle Result return values, and convert to errno+return
  64. // Call with arguments and return value
  65. ($name:ident($($aname:ident : $atype:ty),*) -> Result<$rtype:ty> $content:block) => {
  66. #[no_mangle]
  67. pub extern "C" fn $name($($aname: $atype,)*) -> $rtype {
  68. #[inline(always)]
  69. fn inner($($aname: $atype,)*) -> ::syscall::Result<$rtype> {
  70. $content
  71. }
  72. unsafe { try_call!(inner($($aname,)*)) }
  73. }
  74. };
  75. // Call with `unsafe` keyword (and arguments, return value)
  76. (unsafe $name:ident($($aname:ident : $atype:ty),*) -> Result<$rtype:ty> $content:block) => {
  77. #[no_mangle]
  78. pub unsafe extern "C" fn $name($($aname: $atype,)*) -> $rtype {
  79. #[inline(always)]
  80. unsafe fn inner($($aname: $atype,)*) -> ::syscall::Result<$rtype> {
  81. $content
  82. }
  83. try_call!(inner($($aname,)*))
  84. }
  85. };
  86. // The next 2 cases handle non-Result return values
  87. ($name:ident($($aname:ident : $atype:ty),*) -> $rtype:ty $content:block) => {
  88. #[no_mangle]
  89. pub extern "C" fn $name($($aname: $atype,)*) -> $rtype {
  90. $content
  91. }
  92. };
  93. (unsafe $name:ident($($aname:ident : $atype:ty),*) -> $rtype:ty $content:block) => {
  94. #[no_mangle]
  95. pub unsafe extern "C" fn $name($($aname: $atype,)*) -> $rtype {
  96. $content
  97. }
  98. };
  99. // The next 2 cases handle calls with no return value
  100. ($name:ident($($aname:ident : $atype:ty),*) $content:block) => {
  101. #[no_mangle]
  102. pub extern "C" fn $name($($aname: $atype,)*) {
  103. $content
  104. }
  105. };
  106. (unsafe $name:ident($($aname:ident : $atype:ty),*) $content:block) => {
  107. #[no_mangle]
  108. pub unsafe extern "C" fn $name($($aname: $atype,)*) {
  109. $content
  110. }
  111. };
  112. }