• 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 // 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