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 #[cfg(const_fn)] 74 macro_rules! const_fn { 75 ($(pub const fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty $b:block)*) => { 76 $( 77 pub const fn $name($($arg: $t),*) -> $ret $b 78 )* 79 } 80 } 81 82 #[cfg(not(const_fn))] 83 macro_rules! const_fn { 84 ($(pub const fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty $b:block)*) => { 85 $( 86 pub fn $name($($arg: $t),*) -> $ret $b 87 )* 88 } 89 } 90 91 // openssl changes `*mut` to `*const` in certain parameters in certain versions; 92 // in C this is ABI and (mostly) API compatible. 93 // 94 // We need to handle this explicitly, and this macro helps annotate which 95 // parameter got converted in which version. 96 // 97 // Input is: 98 // extern "C" { 99 // #[attributes...] 100 // pub fn name(args) -> rettype; // `-> rettype` optional 101 // // more functions... 102 // } 103 // 104 // This macro replaces `#[const_ptr_if(...)]` in types with `*const` or `*mut` 105 // (depending on the inner cfg flags) 106 // 107 // Walks through all argument and return types, but only finds inner types of 108 // `*const` and `*mut`; doesn't walk arrays or generics. 109 // 110 // NOTE: can't abstract `pub` as `$fn_vis:vis`, as ctest macro handling doesn't 111 // support it (old syntax crate). But we really only need `pub` anyway. 112 // 113 // NOTE: ctest seams to simply ignore macros it can't expand (whatever the 114 // reason) 115 macro_rules! const_ptr_api { 116 // ---------------------------------------------------------------- 117 // (partialarg): partial argument, waiting for "final" argument type 118 // MAGIC PART 1: hande conditional const ptr in argument type 119 ( (partialarg) 120 { $(#[$fn_attr:meta])* pub fn $fn_name:ident } 121 $args_packed:tt 122 [ $($part_arg:tt)* ] 123 [ #[const_ptr_if( $($cfg:tt)* )] $($arg_rem:tt)* ] 124 $ret_packed:tt 125 ) => { 126 const_ptr_api!( (partialarg) { #[cfg($($cfg)*)] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_arg)* *const ] [ $($arg_rem)* ] $ret_packed ); 127 const_ptr_api!( (partialarg) { #[cfg(not($($cfg)*))] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_arg)* *mut ] [ $($arg_rem)* ] $ret_packed ); 128 }; 129 // continue partial argument with `*mut` pointer (might need special const handling in inner type) 130 ( (partialarg) 131 $def_packed:tt 132 $args_packed:tt 133 [ $($part_arg:tt)* ] 134 [ *mut $($arg_rem:tt)* ] 135 $ret_packed:tt 136 ) => { 137 const_ptr_api!( (partialarg) $def_packed $args_packed [ $($part_arg)* *mut ] [ $($arg_rem)* ] $ret_packed ); 138 }; 139 // continue partial argument with `*const` pointer (might need special const handling in inner type) 140 ( (partialarg) 141 $def_packed:tt 142 $args_packed:tt 143 [ $($part_arg:tt)* ] 144 [ *const $($arg_rem:tt)* ] 145 $ret_packed:tt 146 ) => { 147 const_ptr_api!( (partialarg) $def_packed $args_packed [ $($part_arg)* *const ] [ $($arg_rem)* ] $ret_packed ); 148 }; 149 // finish partial argument with trailing comma 150 ( (partialarg) 151 $def_packed:tt 152 { $($args_tt:tt)* } 153 [ $($part_arg:tt)* ] 154 [ $arg_ty:ty, $($arg_rem:tt)* ] 155 $ret_packed:tt 156 ) => { 157 const_ptr_api!( (parseargs) $def_packed { $($args_tt)* { $($part_arg)* $arg_ty } } [ $($arg_rem)* ] $ret_packed ); 158 }; 159 // finish final partial argument (no trailing comma) 160 ( (partialarg) 161 $def_packed:tt 162 { $($args_tt:tt)* } 163 [ $($part_arg:tt)* ] 164 [ $arg_ty:ty ] 165 $ret_packed:tt 166 ) => { 167 const_ptr_api!( (parseargs) $def_packed { $($args_tt)* { $($part_arg)* $arg_ty } } [ ] $ret_packed ); 168 }; 169 170 // ---------------------------------------------------------------- 171 // (parseargs): parsing arguments 172 // start next argument 173 ( (parseargs) 174 $def_packed:tt 175 $args_packed:tt 176 [ $arg_name:ident : $($arg_rem:tt)* ] 177 $ret_packed:tt 178 ) => { 179 const_ptr_api!( (partialarg) $def_packed $args_packed [ $arg_name: ] [ $($arg_rem)* ] $ret_packed ); 180 }; 181 // end of arguments, there is a return type; start parsing it 182 ( (parseargs) 183 $def_packed:tt 184 $args_packed:tt 185 [ ] 186 [ -> $($rem:tt)* ] 187 ) => { 188 const_ptr_api!( (partialret) $def_packed $args_packed [] [ $($rem)* ] ); 189 }; 190 // end of arguments, no return type 191 ( (parseargs) 192 $def_packed:tt 193 $args_packed:tt 194 [ ] 195 [ ] 196 ) => { 197 const_ptr_api!( (generate) $def_packed $args_packed { () } ); 198 }; 199 200 // ---------------------------------------------------------------- 201 // (partialret): have partial return type, waiting for final return type 202 // MAGIC PART 2: hande conditional const ptr in return type 203 ( (partialret) 204 { $(#[$fn_attr:meta])* pub fn $fn_name:ident } 205 $args_packed:tt 206 [ $($part_ret:tt)* ] 207 [ #[const_ptr_if( $($cfg:tt)* )] $($rem:tt)* ] 208 ) => { 209 const_ptr_api!( (partialret) { #[cfg($($cfg)*)] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_ret)* *const ] [ $($rem)* ] ); 210 const_ptr_api!( (partialret) { #[cfg(not($($cfg)*))] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_ret)* *mut ] [ $($rem)* ] ); 211 }; 212 // `* mut` part in return type; continue parsing to find inner conditional const ptr 213 ( (partialret) 214 $def_packed:tt 215 $args_packed:tt 216 [ $($part_ret:tt)* ] 217 [ *mut $($rem:tt)* ] 218 ) => { 219 const_ptr_api!( (partialret) $def_packed $args_packed [ $($part_ret)* *mut ] [ $($rem)* ] ); 220 }; 221 // `* const` part in return type; continue parsing to find inner conditional const ptr 222 ( (partialret) 223 $def_packed:tt 224 $args_packed:tt 225 [ $($part_ret:tt)* ] 226 [ *const $($rem:tt)* ] 227 ) => { 228 const_ptr_api!( (partialret) $def_packed $args_packed [ $($part_ret)* *const ] [ $($rem)* ] ); 229 }; 230 // final part of return type 231 ( (partialret) 232 $def_packed:tt 233 $args_packed:tt 234 [ $($part_ret:tt)* ] 235 [ $ret_ty:ty ] 236 ) => { 237 const_ptr_api!( (generate) $def_packed $args_packed { $($part_ret)* $ret_ty } ); 238 }; 239 240 // ---------------------------------------------------------------- 241 // generate 242 ( (generate) 243 { $(#[$fn_attr:meta])* pub fn $fn_name:ident } 244 { $({ $arg_name:ident: $($arg_ty:tt)* })* } 245 { $ret_ty:ty } 246 ) => { 247 extern "C" { 248 $(#[$fn_attr])* 249 pub fn $fn_name( $( 250 $arg_name: $($arg_ty)* 251 ),* ) -> $ret_ty; 252 } 253 }; 254 255 // ---------------------------------------------------------------- 256 // (fn): gather tokens for return type until ";" 257 // found end; start parsing current function, and parse remaining functions 258 ( (fn) 259 $def_packed:tt 260 $arg_tts_packed:tt 261 $ret_packed:tt 262 [ ; $($rem:tt)* ] 263 ) => { 264 const_ptr_api!( (parseargs) $def_packed {} $arg_tts_packed $ret_packed ); 265 const_ptr_api!( (extern) [ $($rem)* ] ); 266 }; 267 // not ";" - all other tokens are part of the return type. 268 // don't expand return type yet; otherwise we'd have to remember in which branch `rem` needs 269 // to be used to parse further functions. 270 ( (fn) 271 $def_packed:tt 272 $arg_tts_packed:tt 273 [ $($ret_tt:tt)* ] 274 [ $tt:tt $($rem:tt)* ] 275 ) => { 276 const_ptr_api!( (fn) $def_packed $arg_tts_packed [ $($ret_tt)* $tt ] [ $($rem)* ] ); 277 }; 278 279 // ---------------------------------------------------------------- 280 // (extern): in extern block, find next function 281 // try to split into functions as fast as possible to reduce recursion depth 282 ( (extern) [ 283 $(#[$fn_attr:meta])* 284 pub fn $fn_name:ident( $($arg_rem:tt)* ) $($rem:tt)* 285 ] ) => { 286 const_ptr_api!( (fn) 287 { $(#[$fn_attr])* pub fn $fn_name } [ $($arg_rem)* ] [] [ $($rem)* ] 288 ); 289 }; 290 // end of extern block 291 ( (extern) [] ) => {}; 292 293 // ---------------------------------------------------------------- 294 // macro start; find extern block 295 ( extern "C" { $($rem:tt)* } ) => { 296 const_ptr_api!( (extern) [ $($rem)* ] ); 297 }; 298 } 299