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(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) |
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 | |