1 /// A macro for defining #[cfg] if-else statements.
3 /// This is similar to the `if/elif` C preprocessor macro by allowing definition
4 /// of a cascade of `#[cfg]` cases, emitting the implementation which matches
7 /// This allows you to conveniently provide a long list #[cfg]'d blocks of code
8 /// without having to rewrite each clause multiple times.
9 #[allow(unused_macros)]
11 // match if/else chains with a final `else`
13 if #[cfg($($meta:meta),*)] { $($it:item)* }
20 $
( ( ($
($meta
),*) ($
($it
)*) ), )*
25 // match if/else chains lacking a final `else`
27 if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
29 else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
35 ( ($
($i_met
),*) ($
($i_it
)*) ),
36 $
( ( ($
($e_met
),*) ($
($e_it
)*) ), )*
41 // Internal and recursive macro to emit all the items
43 // Collects all the negated cfgs in a list at the beginning and after the
44 // semicolon is all the remaining items
45 (@
__items ($
($not
:meta
,)*) ; ) => {}
;
46 (@
__items ($
($not
:meta
,)*) ; ( ($
($m
:meta
),*) ($
($it
:item
)*) ),
48 // Emit all items within one block, applying an approprate #[cfg]. The
49 // #[cfg] will require all `$m` matchers specified and must also negate
50 // all previous matchers.
51 cfg_if
! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
53 // Recurse to emit all other items in `$rest`, and when we do so add all
54 // our `$m` matchers to the list of `$not` matchers as future emissions
55 // will have to negate everything we just matched as well.
56 cfg_if
! { @__items ($($not,)* $($m,)*) ; $($rest)* }
59 // Internal macro to Apply a cfg attribute to a list of items
60 (@__apply $m
:meta
, $
($it
:item
)*) => {
65 #[allow(unused_macros)]
67 ($
($
(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
68 s
!(it
: $
(#[$attr])* pub $t $i { $($field)* });
70 (it
: $
(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
71 compile_error
!("unions cannot derive extra traits, use s_no_extra_traits instead");
73 (it
: $
(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
76 #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
79 pub struct $i { $($field)* }
85 fn clone(&self) -> $i { *self }
90 #[allow(unused_macros)]
91 macro_rules
! s_no_extra_traits
{
92 ($
($
(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
93 s_no_extra_traits
!(it
: $
(#[$attr])* pub $t $i { $($field)* });
95 (it
: $
(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
97 if #[cfg(libc_union)] {
101 pub union $i { $($field)* }
104 impl ::Copy
for $i {}
105 impl ::Clone
for $i
{
106 fn clone(&self) -> $i { *self }
111 (it
: $
(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
115 pub struct $i { $($field)* }
117 impl ::Copy
for $i {}
118 impl ::Clone
for $i
{
119 fn clone(&self) -> $i { *self }
124 #[allow(unused_macros)]
126 ($
($
(#[$attr:meta])* pub enum $i:ident { $($field:tt)* })*) => ($(
128 #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
130 pub enum $i { $($field)* }
132 impl ::Copy
for $i {}
133 impl ::Clone
for $i
{
134 fn clone(&self) -> $i { *self }
139 #[allow(unused_macros)]
140 macro_rules
! s_paren
{
141 ($
($
(#[$attr:meta])* pub struct $i:ident ( $($field:tt)* ); )* ) => ($(
143 #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
145 pub struct $
i ( $
($field
)* );
147 impl ::Copy
for $i {}
148 impl ::Clone
for $i
{
149 fn clone(&self) -> $i { *self }
154 // This is a pretty horrible hack to allow us to conditionally mark
155 // some functions as 'const', without requiring users of this macro
156 // to care about the "const-extern-fn" feature.
158 // When 'const-extern-fn' is enabled, we emit the captured 'const' keyword
159 // in the expanded function.
161 // When 'const-extern-fn' is disabled, we always emit a plain 'pub unsafe extern fn'.
162 // Note that the expression matched by the macro is exactly the same - this allows
163 // users of this macro to work whether or not 'const-extern-fn' is enabled
165 // Unfortunately, we need to duplicate most of this macro between the 'cfg_if' blocks.
166 // This is because 'const unsafe extern fn' won't even parse on older compilers,
167 // so we need to avoid emitting it at all of 'const-extern-fn'.
169 // Specifically, moving the 'cfg_if' into the macro body will *not* work.
170 // Doing so would cause the '#[cfg(feature = "const-extern-fn")]' to be emiited
171 // into user code. The 'cfg' gate will not stop Rust from trying to parse the
172 // 'pub const unsafe extern fn', so users would get a compiler error even when
173 // the 'const-extern-fn' feature is disabled
175 // Note that users of this macro need to place 'const' in a weird position
176 // (after the closing ')' for the arguments, but before the return type).
177 // This was the only way I could satisfy the following two requirements:
178 // 1. Avoid ambuguity errors from 'macro_rules!' (which happen when writing '$foo:ident fn'
179 // 2. Allow users of this macro to mix 'pub fn foo' and 'pub const fn bar' within the same
182 if #[cfg(libc_const_extern_fn)] {
183 #[allow(unused_macros)]
185 ($
(pub $
({$constness:ident}
)* fn $i
:ident(
186 $
($arg
:ident
: $argty
:ty
),*
191 pub $
($constness
)* unsafe extern fn $
i($
($arg
: $argty
),*
198 #[allow(unused_macros)]
199 macro_rules
! safe_f
{
200 ($
(pub $
({$constness:ident}
)* fn $i
:ident(
201 $
($arg
:ident
: $argty
:ty
),*
206 pub $
($constness
)* extern fn $
i($
($arg
: $argty
),*
213 #[allow(unused_macros)]
214 macro_rules
! const_fn
{
215 ($
($
({$constness:ident}
)* fn $i
:ident(
216 $
($arg
:ident
: $argty
:ty
),*
221 $
($constness
)* fn $
i($
($arg
: $argty
),*
229 #[allow(unused_macros)]
231 ($
(pub $
({$constness:ident}
)* fn $i
:ident(
232 $
($arg
:ident
: $argty
:ty
),*
237 pub unsafe extern fn $
i($
($arg
: $argty
),*
244 #[allow(unused_macros)]
245 macro_rules
! safe_f
{
246 ($
(pub $
({$constness:ident}
)* fn $i
:ident(
247 $
($arg
:ident
: $argty
:ty
),*
252 pub extern fn $
i($
($arg
: $argty
),*
259 #[allow(unused_macros)]
260 macro_rules
! const_fn
{
261 ($
($
({$constness:ident}
)* fn $i
:ident(
262 $
($arg
:ident
: $argty
:ty
),*
267 fn $
i($
($arg
: $argty
),*
276 #[allow(unused_macros)]
277 macro_rules
! __item
{
283 #[allow(unused_macros)]
284 macro_rules
! align_const
{
286 pub const $name
:ident
: $t1
:ty
287 = $t2
:ident { $($field:tt)* }
;)*) => ($
(
290 pub const $name
: $t1
= $t2
{
293 #[cfg(not(libc_align))]
295 pub const $name
: $t1
= $t2
{
302 // This macro is used to deprecate items that should be accessed via the mach crate
303 #[allow(unused_macros)]
304 macro_rules
! deprecated_mach
{
305 (pub const $id
:ident
: $ty
:ty
= $expr
:expr
;) => {
308 note
= "Use the `mach` crate instead",
311 pub const $id
: $ty
= $expr
;
313 ($
(pub const $id
:ident
: $ty
:ty
= $expr
:expr
;)*) => {
316 pub const $id
: $ty
= $expr
;
320 (pub type $id
:ident
= $ty
:ty
;) => {
323 note
= "Use the `mach` crate instead",
328 ($
(pub type $id
:ident
= $ty
:ty
;)*) => {