macros.rs 6.4 KB

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