macros.rs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #[macro_export]
  2. macro_rules! c_str {
  3. ($lit:expr) => {
  4. #[allow(unused_unsafe)]
  5. unsafe {
  6. $crate::c_str::CStr::from_bytes_with_nul_unchecked(concat!($lit, "\0").as_bytes())
  7. }
  8. };
  9. }
  10. /// Print to stdout
  11. #[macro_export]
  12. macro_rules! print {
  13. ($($arg:tt)*) => ({
  14. use core::fmt::Write;
  15. let _ = write!($crate::platform::FileWriter(1), $($arg)*);
  16. });
  17. }
  18. /// Print with new line to stdout
  19. #[macro_export]
  20. macro_rules! println {
  21. () => (print!("\n"));
  22. ($fmt:expr) => (print!(concat!($fmt, "\n")));
  23. ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
  24. }
  25. /// Print to stderr
  26. #[macro_export]
  27. macro_rules! eprint {
  28. ($($arg:tt)*) => ({
  29. use core::fmt::Write;
  30. let _ = write!($crate::platform::FileWriter(2), $($arg)*);
  31. });
  32. }
  33. /// Print with new line to stderr
  34. #[macro_export]
  35. macro_rules! eprintln {
  36. () => (eprint!("\n"));
  37. ($fmt:expr) => (eprint!(concat!($fmt, "\n")));
  38. ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
  39. }
  40. #[macro_export]
  41. #[cfg(not(feature = "trace"))]
  42. macro_rules! trace {
  43. ($($arg:tt)*) => {};
  44. }
  45. #[macro_export]
  46. #[cfg(feature = "trace")]
  47. macro_rules! trace {
  48. ($($arg:tt)*) => ({
  49. use $crate::{Pal, Sys};
  50. eprintln!($($arg)*);
  51. Sys::fsync(2);
  52. });
  53. }
  54. #[macro_export]
  55. #[cfg(not(feature = "trace"))]
  56. macro_rules! trace_expr {
  57. ($expr:expr, $($arg:tt)*) => {
  58. $expr
  59. };
  60. }
  61. #[macro_export]
  62. #[cfg(feature = "trace")]
  63. macro_rules! trace_expr {
  64. ($expr:expr, $($arg:tt)*) => ({
  65. use $crate::header::errno::STR_ERROR;
  66. use $crate::platform;
  67. trace!("{}", format_args!($($arg)*));
  68. #[allow(unused_unsafe)]
  69. let trace_old_errno = unsafe { platform::errno };
  70. #[allow(unused_unsafe)]
  71. unsafe { platform::errno = 0; }
  72. let ret = $expr;
  73. #[allow(unused_unsafe)]
  74. let trace_errno = unsafe { platform::errno } as isize;
  75. if trace_errno == 0 {
  76. #[allow(unused_unsafe)]
  77. unsafe { platform::errno = trace_old_errno; }
  78. }
  79. let trace_strerror = if trace_errno >= 0 && trace_errno < STR_ERROR.len() as isize {
  80. STR_ERROR[trace_errno as usize]
  81. } else {
  82. "Unknown error"
  83. };
  84. trace!("{} = {} ({}, {})", format_args!($($arg)*), ret, trace_errno, trace_strerror);
  85. ret
  86. });
  87. }
  88. #[macro_export]
  89. macro_rules! strto_impl {
  90. (
  91. $rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident
  92. ) => {{
  93. // ensure these are constants
  94. const CHECK_SIGN: bool = $signed;
  95. const MAX_VAL: $rettype = $maxval;
  96. const MIN_VAL: $rettype = $minval;
  97. let set_endptr = |idx: isize| {
  98. if !$endptr.is_null() {
  99. // This is stupid, but apparently strto* functions want
  100. // const input but mut output, yet the man page says
  101. // "stores the address of the first invalid character in *endptr"
  102. // so obviously it doesn't want us to clone it.
  103. *$endptr = $s.offset(idx) as *mut _;
  104. }
  105. };
  106. let invalid_input = || {
  107. platform::errno = EINVAL;
  108. set_endptr(0);
  109. };
  110. // only valid bases are 2 through 36
  111. if $base != 0 && ($base < 2 || $base > 36) {
  112. invalid_input();
  113. return 0;
  114. }
  115. let mut idx = 0;
  116. // skip any whitespace at the beginning of the string
  117. while ctype::isspace(*$s.offset(idx) as c_int) != 0 {
  118. idx += 1;
  119. }
  120. // check for +/-
  121. let positive = match is_positive(*$s.offset(idx)) {
  122. Some((pos, i)) => {
  123. idx += i;
  124. pos
  125. }
  126. None => {
  127. invalid_input();
  128. return 0;
  129. }
  130. };
  131. // convert the string to a number
  132. let num_str = $s.offset(idx);
  133. let res = match $base {
  134. 0 => detect_base(num_str)
  135. .and_then(|($base, i)| convert_integer(num_str.offset(i), $base)),
  136. 8 => convert_octal(num_str),
  137. 16 => convert_hex(num_str),
  138. _ => convert_integer(num_str, $base),
  139. };
  140. // check for error parsing octal/hex prefix
  141. // also check to ensure a number was indeed parsed
  142. let (num, i, overflow) = match res {
  143. Some(res) => res,
  144. None => {
  145. invalid_input();
  146. return 0;
  147. }
  148. };
  149. idx += i;
  150. let overflow = if CHECK_SIGN {
  151. overflow || (num as c_long).is_negative()
  152. } else {
  153. overflow
  154. };
  155. // account for the sign
  156. let num = num as $rettype;
  157. let num = if overflow {
  158. platform::errno = ERANGE;
  159. if CHECK_SIGN {
  160. if positive {
  161. MAX_VAL
  162. } else {
  163. MIN_VAL
  164. }
  165. } else {
  166. MAX_VAL
  167. }
  168. } else {
  169. if positive {
  170. num
  171. } else {
  172. // not using -num to keep the compiler happy
  173. num.overflowing_neg().0
  174. }
  175. };
  176. set_endptr(idx);
  177. num
  178. }};
  179. }
  180. #[macro_export]
  181. macro_rules! strto_float_impl {
  182. ($type:ident, $s:expr, $endptr:expr) => {{
  183. let mut s = $s;
  184. let endptr = $endptr;
  185. while ctype::isspace(*s as c_int) != 0 {
  186. s = s.offset(1);
  187. }
  188. let mut result: $type = 0.0;
  189. let mut radix = 10;
  190. let negative = match *s as u8 {
  191. b'-' => {
  192. s = s.offset(1);
  193. true
  194. }
  195. b'+' => {
  196. s = s.offset(1);
  197. false
  198. }
  199. _ => false,
  200. };
  201. if *s as u8 == b'0' && *s.offset(1) as u8 == b'x' {
  202. s = s.offset(2);
  203. radix = 16;
  204. }
  205. while let Some(digit) = (*s as u8 as char).to_digit(radix) {
  206. result *= radix as $type;
  207. result += digit as $type;
  208. s = s.offset(1);
  209. }
  210. if *s as u8 == b'.' {
  211. s = s.offset(1);
  212. let mut i = 1.0;
  213. while let Some(digit) = (*s as u8 as char).to_digit(radix) {
  214. i *= radix as $type;
  215. result += digit as $type / i;
  216. s = s.offset(1);
  217. }
  218. }
  219. if !endptr.is_null() {
  220. // This is stupid, but apparently strto* functions want
  221. // const input but mut output, yet the man page says
  222. // "stores the address of the first invalid character in *endptr"
  223. // so obviously it doesn't want us to clone it.
  224. *endptr = s as *mut _;
  225. }
  226. if negative {
  227. -result
  228. } else {
  229. result
  230. }
  231. }};
  232. }