1#![allow(unused_macros)]
2
3// vendored from the cfg-if crate to avoid breaking ctest
4macro_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
58macro_rules! stack {
59 ($t:ident) => {
60 cfg_if! {
61 if #[cfg(any(ossl110, libressl390))] {
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)
97macro_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