• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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