123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- #[macro_export]
- macro_rules! c_str {
- ($lit:expr) => {
- #[allow(unused_unsafe)]
- unsafe {
- $crate::c_str::CStr::from_bytes_with_nul_unchecked(concat!($lit, "\0").as_bytes())
- }
- };
- }
- /// Print to stdout
- #[macro_export]
- macro_rules! print {
- ($($arg:tt)*) => ({
- use core::fmt::Write;
- let _ = write!($crate::platform::FileWriter(1), $($arg)*);
- });
- }
- /// Print with new line to stdout
- #[macro_export]
- macro_rules! println {
- () => (print!("\n"));
- ($fmt:expr) => (print!(concat!($fmt, "\n")));
- ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
- }
- /// Print to stderr
- #[macro_export]
- macro_rules! eprint {
- ($($arg:tt)*) => ({
- use core::fmt::Write;
- let _ = write!($crate::platform::FileWriter(2), $($arg)*);
- });
- }
- /// Print with new line to stderr
- #[macro_export]
- macro_rules! eprintln {
- () => (eprint!("\n"));
- ($fmt:expr) => (eprint!(concat!($fmt, "\n")));
- ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
- }
- /// Lifted from libstd
- #[macro_export]
- macro_rules! dbg {
- () => {
- eprintln!("[{}:{}]", file!(), line!());
- };
- ($val:expr) => {
- // Use of `match` here is intentional because it affects the lifetimes
- // of temporaries - https://stackoverflow.com/a/48732525/1063961
- match $val {
- tmp => {
- eprintln!(
- "[{}:{}] {} = {:#?}",
- file!(),
- line!(),
- stringify!($val),
- &tmp
- );
- tmp
- }
- }
- };
- }
- #[macro_export]
- #[cfg(not(feature = "trace"))]
- macro_rules! trace {
- ($($arg:tt)*) => {};
- }
- #[macro_export]
- #[cfg(feature = "trace")]
- macro_rules! trace {
- ($($arg:tt)*) => ({
- use $crate::{Pal, Sys};
- eprintln!($($arg)*);
- });
- }
- #[macro_export]
- #[cfg(not(feature = "trace"))]
- macro_rules! trace_expr {
- ($expr:expr, $($arg:tt)*) => {
- $expr
- };
- }
- #[macro_export]
- #[cfg(feature = "trace")]
- macro_rules! trace_expr {
- ($expr:expr, $($arg:tt)*) => ({
- use $crate::header::errno::STR_ERROR;
- use $crate::platform;
- trace!("{}", format_args!($($arg)*));
- #[allow(unused_unsafe)]
- let trace_old_errno = unsafe { platform::errno };
- #[allow(unused_unsafe)]
- unsafe { platform::errno = 0; }
- let ret = $expr;
- #[allow(unused_unsafe)]
- let trace_errno = unsafe { platform::errno } as isize;
- if trace_errno == 0 {
- #[allow(unused_unsafe)]
- unsafe { platform::errno = trace_old_errno; }
- }
- let trace_strerror = if trace_errno >= 0 && trace_errno < STR_ERROR.len() as isize {
- STR_ERROR[trace_errno as usize]
- } else {
- "Unknown error"
- };
- trace!("{} = {} ({}, {})", format_args!($($arg)*), ret, trace_errno, trace_strerror);
- ret
- });
- }
- #[macro_export]
- macro_rules! strto_impl {
- (
- $rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident
- ) => {{
- // ensure these are constants
- const CHECK_SIGN: bool = $signed;
- const MAX_VAL: $rettype = $maxval;
- const MIN_VAL: $rettype = $minval;
- let set_endptr = |idx: isize| {
- if !$endptr.is_null() {
- // This is stupid, but apparently strto* functions want
- // const input but mut output, yet the man page says
- // "stores the address of the first invalid character in *endptr"
- // so obviously it doesn't want us to clone it.
- *$endptr = $s.offset(idx) as *mut _;
- }
- };
- let invalid_input = || {
- platform::errno = EINVAL;
- set_endptr(0);
- };
- // only valid bases are 2 through 36
- if $base != 0 && ($base < 2 || $base > 36) {
- invalid_input();
- return 0;
- }
- let mut idx = 0;
- // skip any whitespace at the beginning of the string
- while ctype::isspace(*$s.offset(idx) as c_int) != 0 {
- idx += 1;
- }
- // check for +/-
- let positive = match is_positive(*$s.offset(idx)) {
- Some((pos, i)) => {
- idx += i;
- pos
- }
- None => {
- invalid_input();
- return 0;
- }
- };
- // convert the string to a number
- let num_str = $s.offset(idx);
- let res = match $base {
- 0 => detect_base(num_str)
- .and_then(|($base, i)| convert_integer(num_str.offset(i), $base)),
- 8 => convert_octal(num_str),
- 16 => convert_hex(num_str),
- _ => convert_integer(num_str, $base),
- };
- // check for error parsing octal/hex prefix
- // also check to ensure a number was indeed parsed
- let (num, i, overflow) = match res {
- Some(res) => res,
- None => {
- invalid_input();
- return 0;
- }
- };
- idx += i;
- let overflow = if CHECK_SIGN {
- overflow || (num as c_long).is_negative()
- } else {
- overflow
- };
- // account for the sign
- let num = num as $rettype;
- let num = if overflow {
- platform::errno = ERANGE;
- if CHECK_SIGN {
- if positive {
- MAX_VAL
- } else {
- MIN_VAL
- }
- } else {
- MAX_VAL
- }
- } else {
- if positive {
- num
- } else {
- // not using -num to keep the compiler happy
- num.overflowing_neg().0
- }
- };
- set_endptr(idx);
- num
- }};
- }
- #[macro_export]
- macro_rules! strto_float_impl {
- ($type:ident, $s:expr, $endptr:expr) => {{
- let mut s = $s;
- let endptr = $endptr;
- // TODO: Handle named floats: NaN, Inf...
- while ctype::isspace(*s as c_int) != 0 {
- s = s.offset(1);
- }
- let mut result: $type = 0.0;
- let mut radix = 10;
- let result_sign = match *s as u8 {
- b'-' => {
- s = s.offset(1);
- -1.0
- }
- b'+' => {
- s = s.offset(1);
- 1.0
- }
- _ => 1.0,
- };
- if *s as u8 == b'0' && *s.offset(1) as u8 == b'x' {
- s = s.offset(2);
- radix = 16;
- }
- while let Some(digit) = (*s as u8 as char).to_digit(radix) {
- result *= radix as $type;
- result += digit as $type;
- s = s.offset(1);
- }
- if *s as u8 == b'.' {
- s = s.offset(1);
- let mut i = 1.0;
- while let Some(digit) = (*s as u8 as char).to_digit(radix) {
- i *= radix as $type;
- result += digit as $type / i;
- s = s.offset(1);
- }
- }
- let s_before_exponent = s;
- let exponent = match (*s as u8, radix) {
- (b'e' | b'E', 10) | (b'p' | b'P', 16) => {
- s = s.offset(1);
- let is_exponent_positive = match *s as u8 {
- b'-' => {
- s = s.offset(1);
- false
- }
- b'+' => {
- s = s.offset(1);
- true
- }
- _ => true,
- };
- // Exponent digits are always in base 10.
- if (*s as u8 as char).is_digit(10) {
- let mut exponent_value = 0;
- while let Some(digit) = (*s as u8 as char).to_digit(10) {
- exponent_value *= 10;
- exponent_value += digit;
- s = s.offset(1);
- }
- let exponent_base = match radix {
- 10 => 10u128,
- 16 => 2u128,
- _ => unreachable!(),
- };
- if is_exponent_positive {
- Some(exponent_base.pow(exponent_value) as $type)
- } else {
- Some(1.0 / (exponent_base.pow(exponent_value) as $type))
- }
- } else {
- // Exponent had no valid digits after 'e'/'p' and '+'/'-', rollback
- s = s_before_exponent;
- None
- }
- }
- _ => None,
- };
- if !endptr.is_null() {
- // This is stupid, but apparently strto* functions want
- // const input but mut output, yet the man page says
- // "stores the address of the first invalid character in *endptr"
- // so obviously it doesn't want us to clone it.
- *endptr = s as *mut _;
- }
- if let Some(exponent) = exponent {
- result_sign * result * exponent
- } else {
- result_sign * result
- }
- }};
- }
|