openssl_sys/
macros.rs

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}