diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs index 02750d14422e4778776340fe52fc0c56f34acaa1..a4b5fa6ffa1c33943ca044de5ecd47485e3fe6c0 100644 --- a/src/header/stdlib/mod.rs +++ b/src/header/stdlib/mod.rs @@ -675,61 +675,12 @@ pub extern "C" fn srandom(seed: c_uint) { } #[no_mangle] -pub unsafe extern "C" fn strtod(mut s: *const c_char, endptr: *mut *mut c_char) -> c_double { - while ctype::isspace(*s as c_int) != 0 { - s = s.offset(1); - } - - let mut result = 0.0; - let mut radix = 10; - - let negative = match *s as u8 { - b'-' => { - s = s.offset(1); - true - } - b'+' => { - s = s.offset(1); - false - } - _ => false, - }; - - 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 c_double; - result += digit as c_double; - 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 c_double; - result += digit as c_double / i; - s = s.offset(1); - } - } - - 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 negative { - -result - } else { - result - } +pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double { + strto_float_impl!(c_double, s, endptr) +} +#[no_mangle] +pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> c_float { + strto_float_impl!(c_float, s, endptr) } pub fn is_positive(ch: c_char) -> Option<(bool, isize)> { diff --git a/src/macros.rs b/src/macros.rs index 6a3b790e4085b88022fdf20ba8ee3d5eb879c2df..31e415c3c3cacc5cd542153a0fa5c2ec39b8a93a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -190,3 +190,65 @@ macro_rules! strto_impl { num }}; } +#[macro_export] +macro_rules! strto_float_impl { + ($type:ident, $s:expr, $endptr:expr) => {{ + let mut s = $s; + let endptr = $endptr; + + while ctype::isspace(*s as c_int) != 0 { + s = s.offset(1); + } + + let mut result: $type = 0.0; + let mut radix = 10; + + let negative = match *s as u8 { + b'-' => { + s = s.offset(1); + true + } + b'+' => { + s = s.offset(1); + false + } + _ => false, + }; + + 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); + } + } + + 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 negative { + -result + } else { + result + } + }} +}