1 #![allow(unused_macros)] 2 3 // vendored from the cfg-if crate to avoid breaking ctest 4 macro_rules! cfg_if { 5 // match if/else chains with a final `else` 6 ($( 7 if #[cfg($($meta:meta),*)] { $($it:item)* } 8 ) else * else { 9 $($it2:item)* 10 }) => { 11 cfg_if! { 12 @__items 13 () ; 14 $( ( ($($meta),*) ($($it)*) ), )* 15 ( () ($($it2)*) ), 16 } 17 }; 18 19 // match if/else chains lacking a final `else` 20 ( 21 if #[cfg($($i_met:meta),*)] { $($i_it:item)* } 22 $( 23 else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } 24 )* 25 ) => { 26 cfg_if! { 27 @__items 28 () ; 29 ( ($($i_met),*) ($($i_it)*) ), 30 $( ( ($($e_met),*) ($($e_it)*) ), )* 31 ( () () ), 32 } 33 }; 34 35 // Internal and recursive macro to emit all the items 36 // 37 // Collects all the negated cfgs in a list at the beginning and after the 38 // semicolon is all the remaining items 39 (@__items ($($not:meta,)*) ; ) => {}; 40 (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { 41 // Emit all items within one block, applying an appropriate #[cfg]. The 42 // #[cfg] will require all `$m` matchers specified and must also negate 43 // all previous matchers. 44 cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } 45 46 // Recurse to emit all other items in `$rest`, and when we do so add all 47 // our `$m` matchers to the list of `$not` matchers as future emissions 48 // will have to negate everything we just matched as well. 49 cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } 50 }; 51 52 // Internal macro to Apply a cfg attribute to a list of items 53 (@__apply $m:meta, $($it:item)*) => { 54 $(#[$m] $it)* 55 }; 56 } 57 58 macro_rules! stack { 59 ($t:ident) => { 60 cfg_if! { 61 if #[cfg(ossl110)] { 62 pub enum $t {} 63 } else { 64 #[repr(C)] 65 pub struct $t { 66 pub stack: $crate::_STACK, 67 } 68 } 69 } 70 }; 71 } 72 73 // openssl changes `*mut` to `*const` in certain parameters in certain versions; 74 // in C this is ABI and (mostly) API compatible. 75 // 76 // We need to handle this explicitly, and this macro helps annotate which 77 // parameter got converted in which version. 78 // 79 // Input is: 80 // extern "C" { 81 // #[attributes...] 82 // pub fn name(args) -> rettype; // `-> rettype` optional 83 // // more functions... 84 // } 85 // 86 // This macro replaces `#[const_ptr_if(...)]` in types with `*const` or `*mut` 87 // (depending on the inner cfg flags) 88 // 89 // Walks through all argument and return types, but only finds inner types of 90 // `*const` and `*mut`; doesn't walk arrays or generics. 91 // 92 // NOTE: can't abstract `pub` as `$fn_vis:vis`, as ctest macro handling doesn't 93 // support it (old syntax crate). But we really only need `pub` anyway. 94 // 95 // NOTE: ctest seams to simply ignore macros it can't expand (whatever the 96 // reason) 97 macro_rules! const_ptr_api { 98 // ---------------------------------------------------------------- 99 // (partialarg): partial argument, waiting for "final" argument type 100 // MAGIC PART 1: hande conditional const ptr in argument type 101 ( (partialarg) 102 { $(#[$fn_attr:meta])* pub fn $fn_name:ident } 103 $args_packed:tt 104 [ $($part_arg:tt)* ] 105 [ #[const_ptr_if( $($cfg:tt)* )] $($arg_rem:tt)* ] 106 $ret_packed:tt 107 ) => { 108 const_ptr_api!( (partialarg) { #[cfg($($cfg)*)] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_arg)* *const ] [ $($arg_rem)* ] $ret_packed ); 109 const_ptr_api!( (partialarg) { #[cfg(not($($cfg)*))] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_arg)* *mut ] [ $($arg_rem)* ] $ret_packed ); 110 }; 111 // continue partial argument with `*mut` pointer (might need special const handling in inner type) 112 ( (partialarg) 113 $def_packed:tt 114 $args_packed:tt 115 [ $($part_arg:tt)* ] 116 [ *mut $($arg_rem:tt)* ] 117 $ret_packed:tt 118 ) => { 119 const_ptr_api!( (partialarg) $def_packed $args_packed [ $($part_arg)* *mut ] [ $($arg_rem)* ] $ret_packed ); 120 }; 121 // continue partial argument with `*const` pointer (might need special const handling in inner type) 122 ( (partialarg) 123 $def_packed:tt 124 $args_packed:tt 125 [ $($part_arg:tt)* ] 126 [ *const $($arg_rem:tt)* ] 127 $ret_packed:tt 128 ) => { 129 const_ptr_api!( (partialarg) $def_packed $args_packed [ $($part_arg)* *const ] [ $($arg_rem)* ] $ret_packed ); 130 }; 131 // finish partial argument with trailing comma 132 ( (partialarg) 133 $def_packed:tt 134 { $($args_tt:tt)* } 135 [ $($part_arg:tt)* ] 136 [ $arg_ty:ty, $($arg_rem:tt)* ] 137 $ret_packed:tt 138 ) => { 139 const_ptr_api!( (parseargs) $def_packed { $($args_tt)* { $($part_arg)* $arg_ty } } [ $($arg_rem)* ] $ret_packed ); 140 }; 141 // finish final partial argument (no trailing comma) 142 ( (partialarg) 143 $def_packed:tt 144 { $($args_tt:tt)* } 145 [ $($part_arg:tt)* ] 146 [ $arg_ty:ty ] 147 $ret_packed:tt 148 ) => { 149 const_ptr_api!( (parseargs) $def_packed { $($args_tt)* { $($part_arg)* $arg_ty } } [ ] $ret_packed ); 150 }; 151 152 // ---------------------------------------------------------------- 153 // (parseargs): parsing arguments 154 // start next argument 155 ( (parseargs) 156 $def_packed:tt 157 $args_packed:tt 158 [ $arg_name:ident : $($arg_rem:tt)* ] 159 $ret_packed:tt 160 ) => { 161 const_ptr_api!( (partialarg) $def_packed $args_packed [ $arg_name: ] [ $($arg_rem)* ] $ret_packed ); 162 }; 163 // end of arguments, there is a return type; start parsing it 164 ( (parseargs) 165 $def_packed:tt 166 $args_packed:tt 167 [ ] 168 [ -> $($rem:tt)* ] 169 ) => { 170 const_ptr_api!( (partialret) $def_packed $args_packed [] [ $($rem)* ] ); 171 }; 172 // end of arguments, no return type 173 ( (parseargs) 174 $def_packed:tt 175 $args_packed:tt 176 [ ] 177 [ ] 178 ) => { 179 const_ptr_api!( (generate) $def_packed $args_packed { () } ); 180 }; 181 182 // ---------------------------------------------------------------- 183 // (partialret): have partial return type, waiting for final return type 184 // MAGIC PART 2: hande conditional const ptr in return type 185 ( (partialret) 186 { $(#[$fn_attr:meta])* pub fn $fn_name:ident } 187 $args_packed:tt 188 [ $($part_ret:tt)* ] 189 [ #[const_ptr_if( $($cfg:tt)* )] $($rem:tt)* ] 190 ) => { 191 const_ptr_api!( (partialret) { #[cfg($($cfg)*)] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_ret)* *const ] [ $($rem)* ] ); 192 const_ptr_api!( (partialret) { #[cfg(not($($cfg)*))] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_ret)* *mut ] [ $($rem)* ] ); 193 }; 194 // `* mut` part in return type; continue parsing to find inner conditional const ptr 195 ( (partialret) 196 $def_packed:tt 197 $args_packed:tt 198 [ $($part_ret:tt)* ] 199 [ *mut $($rem:tt)* ] 200 ) => { 201 const_ptr_api!( (partialret) $def_packed $args_packed [ $($part_ret)* *mut ] [ $($rem)* ] ); 202 }; 203 // `* const` part in return type; continue parsing to find inner conditional const ptr 204 ( (partialret) 205 $def_packed:tt 206 $args_packed:tt 207 [ $($part_ret:tt)* ] 208 [ *const $($rem:tt)* ] 209 ) => { 210 const_ptr_api!( (partialret) $def_packed $args_packed [ $($part_ret)* *const ] [ $($rem)* ] ); 211 }; 212 // final part of return type 213 ( (partialret) 214 $def_packed:tt 215 $args_packed:tt 216 [ $($part_ret:tt)* ] 217 [ $ret_ty:ty ] 218 ) => { 219 const_ptr_api!( (generate) $def_packed $args_packed { $($part_ret)* $ret_ty } ); 220 }; 221 222 // ---------------------------------------------------------------- 223 // generate 224 ( (generate) 225 { $(#[$fn_attr:meta])* pub fn $fn_name:ident } 226 { $({ $arg_name:ident: $($arg_ty:tt)* })* } 227 { $ret_ty:ty } 228 ) => { 229 extern "C" { 230 $(#[$fn_attr])* 231 pub fn $fn_name( $( 232 $arg_name: $($arg_ty)* 233 ),* ) -> $ret_ty; 234 } 235 }; 236 237 // ---------------------------------------------------------------- 238 // (fn): gather tokens for return type until ";" 239 // found end; start parsing current function, and parse remaining functions 240 ( (fn) 241 $def_packed:tt 242 $arg_tts_packed:tt 243 $ret_packed:tt 244 [ ; $($rem:tt)* ] 245 ) => { 246 const_ptr_api!( (parseargs) $def_packed {} $arg_tts_packed $ret_packed ); 247 const_ptr_api!( (extern) [ $($rem)* ] ); 248 }; 249 // not ";" - all other tokens are part of the return type. 250 // don't expand return type yet; otherwise we'd have to remember in which branch `rem` needs 251 // to be used to parse further functions. 252 ( (fn) 253 $def_packed:tt 254 $arg_tts_packed:tt 255 [ $($ret_tt:tt)* ] 256 [ $tt:tt $($rem:tt)* ] 257 ) => { 258 const_ptr_api!( (fn) $def_packed $arg_tts_packed [ $($ret_tt)* $tt ] [ $($rem)* ] ); 259 }; 260 261 // ---------------------------------------------------------------- 262 // (extern): in extern block, find next function 263 // try to split into functions as fast as possible to reduce recursion depth 264 ( (extern) [ 265 $(#[$fn_attr:meta])* 266 pub fn $fn_name:ident( $($arg_rem:tt)* ) $($rem:tt)* 267 ] ) => { 268 const_ptr_api!( (fn) 269 { $(#[$fn_attr])* pub fn $fn_name } [ $($arg_rem)* ] [] [ $($rem)* ] 270 ); 271 }; 272 // end of extern block 273 ( (extern) [] ) => {}; 274 275 // ---------------------------------------------------------------- 276 // macro start; find extern block 277 ( extern "C" { $($rem:tt)* } ) => { 278 const_ptr_api!( (extern) [ $($rem)* ] ); 279 }; 280 } 281