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