• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /// The `libc_bitflags!` macro helps with a common use case of defining a public bitflags type
2 /// with values from the libc crate. It is used the same way as the `bitflags!` macro, except
3 /// that only the name of the flag value has to be given.
4 ///
5 /// The `libc` crate must be in scope with the name `libc`.
6 ///
7 /// # Example
8 /// ```
9 /// libc_bitflags!{
10 ///     pub struct ProtFlags: libc::c_int {
11 ///         PROT_NONE;
12 ///         PROT_READ;
13 ///         /// PROT_WRITE enables write protect
14 ///         PROT_WRITE;
15 ///         PROT_EXEC;
16 ///         #[cfg(any(target_os = "linux", target_os = "android"))]
17 ///         PROT_GROWSDOWN;
18 ///         #[cfg(any(target_os = "linux", target_os = "android"))]
19 ///         PROT_GROWSUP;
20 ///     }
21 /// }
22 /// ```
23 ///
24 /// Example with casting, due to a mistake in libc. In this example, the
25 /// various flags have different types, so we cast the broken ones to the right
26 /// type.
27 ///
28 /// ```
29 /// libc_bitflags!{
30 ///     pub struct SaFlags: libc::c_ulong {
31 ///         SA_NOCLDSTOP as libc::c_ulong;
32 ///         SA_NOCLDWAIT;
33 ///         SA_NODEFER as libc::c_ulong;
34 ///         SA_ONSTACK;
35 ///         SA_RESETHAND as libc::c_ulong;
36 ///         SA_RESTART as libc::c_ulong;
37 ///         SA_SIGINFO;
38 ///     }
39 /// }
40 /// ```
41 macro_rules! libc_bitflags {
42     (
43         $(#[$outer:meta])*
44         pub struct $BitFlags:ident: $T:ty {
45             $(
46                 $(#[$inner:ident $($args:tt)*])*
47                 $Flag:ident $(as $cast:ty)*;
48             )+
49         }
50     ) => {
51         ::bitflags::bitflags! {
52             $(#[$outer])*
53             pub struct $BitFlags: $T {
54                 $(
55                     $(#[$inner $($args)*])*
56                     const $Flag = libc::$Flag $(as $cast)*;
57                 )+
58             }
59         }
60     };
61 }
62 
63 /// The `libc_enum!` macro helps with a common use case of defining an enum exclusively using
64 /// values from the `libc` crate. This macro supports both `pub` and private `enum`s.
65 ///
66 /// The `libc` crate must be in scope with the name `libc`.
67 ///
68 /// # Example
69 /// ```
70 /// libc_enum!{
71 ///     pub enum ProtFlags {
72 ///         PROT_NONE,
73 ///         PROT_READ,
74 ///         PROT_WRITE,
75 ///         PROT_EXEC,
76 ///         #[cfg(any(target_os = "linux", target_os = "android"))]
77 ///         PROT_GROWSDOWN,
78 ///         #[cfg(any(target_os = "linux", target_os = "android"))]
79 ///         PROT_GROWSUP,
80 ///     }
81 /// }
82 /// ```
83 macro_rules! libc_enum {
84     // Exit rule.
85     (@make_enum
86         {
87             $v:vis
88             name: $BitFlags:ident,
89             attrs: [$($attrs:tt)*],
90             entries: [$($entries:tt)*],
91         }
92     ) => {
93         $($attrs)*
94         #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
95         $v enum $BitFlags {
96             $($entries)*
97         }
98     };
99 
100     // Done accumulating.
101     (@accumulate_entries
102         {
103             $v:vis
104             name: $BitFlags:ident,
105             attrs: $attrs:tt,
106         },
107         $entries:tt;
108     ) => {
109         libc_enum! {
110             @make_enum
111             {
112                 $v
113                 name: $BitFlags,
114                 attrs: $attrs,
115                 entries: $entries,
116             }
117         }
118     };
119 
120     // Munch an attr.
121     (@accumulate_entries
122         $prefix:tt,
123         [$($entries:tt)*];
124         #[$attr:meta] $($tail:tt)*
125     ) => {
126         libc_enum! {
127             @accumulate_entries
128             $prefix,
129             [
130                 $($entries)*
131                 #[$attr]
132             ];
133             $($tail)*
134         }
135     };
136 
137     // Munch last ident if not followed by a comma.
138     (@accumulate_entries
139         $prefix:tt,
140         [$($entries:tt)*];
141         $entry:ident
142     ) => {
143         libc_enum! {
144             @accumulate_entries
145             $prefix,
146             [
147                 $($entries)*
148                 $entry = libc::$entry,
149             ];
150         }
151     };
152 
153     // Munch an ident; covers terminating comma case.
154     (@accumulate_entries
155         $prefix:tt,
156         [$($entries:tt)*];
157         $entry:ident, $($tail:tt)*
158     ) => {
159         libc_enum! {
160             @accumulate_entries
161             $prefix,
162             [
163                 $($entries)*
164                 $entry = libc::$entry,
165             ];
166             $($tail)*
167         }
168     };
169 
170     // Munch an ident and cast it to the given type; covers terminating comma.
171     (@accumulate_entries
172         $prefix:tt,
173         [$($entries:tt)*];
174         $entry:ident as $ty:ty, $($tail:tt)*
175     ) => {
176         libc_enum! {
177             @accumulate_entries
178             $prefix,
179             [
180                 $($entries)*
181                 $entry = libc::$entry as $ty,
182             ];
183             $($tail)*
184         }
185     };
186 
187     // Entry rule.
188     (
189         $(#[$attr:meta])*
190         $v:vis enum $BitFlags:ident {
191             $($vals:tt)*
192         }
193     ) => {
194         libc_enum! {
195             @accumulate_entries
196             {
197                 $v
198                 name: $BitFlags,
199                 attrs: [$(#[$attr])*],
200             },
201             [];
202             $($vals)*
203         }
204     };
205 }
206 
207 /// A Rust version of the familiar C `offset_of` macro.  It returns the byte
208 /// offset of `field` within struct `ty`
209 #[cfg(not(target_os = "redox"))]
210 macro_rules! offset_of {
211     ($ty:ty, $field:ident) => {{
212         // Safe because we don't actually read from the dereferenced pointer
213         #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
214         unsafe {
215             &(*(ptr::null() as *const $ty)).$field as *const _ as usize
216         }
217     }}
218 }
219