From 0e766c6b53dd699f1c877ba36c322f3d052461d4 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Thu, 8 Mar 2018 20:17:45 -0700
Subject: [PATCH] Implement atof

---
 Cargo.lock              |  1 +
 src/stdio/src/printf.rs | 15 +++++++++------
 src/stdlib/Cargo.toml   |  1 +
 src/stdlib/src/lib.rs   | 23 +++++++++++++++++++----
 tests/.gitignore        |  1 +
 tests/Makefile          |  1 +
 tests/atof.c            |  8 ++++++++
 7 files changed, 40 insertions(+), 10 deletions(-)
 create mode 100644 tests/atof.c

diff --git a/Cargo.lock b/Cargo.lock
index 6e07d9119..91daf313a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -465,6 +465,7 @@ version = "0.1.0"
 dependencies = [
  "cbindgen 0.5.0",
  "ctype 0.1.0",
+ "errno 0.1.0",
  "platform 0.1.0",
  "ralloc 1.0.0",
 ]
diff --git a/src/stdio/src/printf.rs b/src/stdio/src/printf.rs
index d1ce976cb..6d9ec1f89 100644
--- a/src/stdio/src/printf.rs
+++ b/src/stdio/src/printf.rs
@@ -1,13 +1,9 @@
-use core::fmt;
+use core::{fmt, mem, slice, str};
 
 use platform::types::*;
 use vl::VaList;
 
 pub unsafe fn printf<W: fmt::Write>(mut w: W, format: *const c_char, mut ap: VaList) -> c_int {
-    use core::fmt::Write;
-    use core::slice;
-    use core::str;
-
     extern "C" {
         fn strlen(s: *const c_char) -> size_t;
     }
@@ -38,7 +34,14 @@ pub unsafe fn printf<W: fmt::Write>(mut w: W, format: *const c_char, mut ap: VaL
                     w.write_fmt(format_args!("{}", a));
 
                     found_percent = false;
-                }
+                },
+                'f' | 'F' => {
+                    let a: f64 = mem::transmute(ap.get::<u64>());
+
+                    w.write_fmt(format_args!("{}", a));
+
+                    found_percent = false;
+                },
                 'n' => {
                     let _a = ap.get::<c_int>();
 
diff --git a/src/stdlib/Cargo.toml b/src/stdlib/Cargo.toml
index 4a2fb9f88..97f5d4418 100644
--- a/src/stdlib/Cargo.toml
+++ b/src/stdlib/Cargo.toml
@@ -11,3 +11,4 @@ cbindgen = { path = "../../cbindgen" }
 platform = { path = "../platform" }
 ralloc = { path = "../../ralloc", default-features = false }
 ctype = { path = "../ctype" }
+errno = { path = "../errno" }
diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs
index fd25f5b73..1bc1ff4e4 100644
--- a/src/stdlib/src/lib.rs
+++ b/src/stdlib/src/lib.rs
@@ -5,9 +5,13 @@
 #![feature(global_allocator)]
 
 extern crate ctype;
+extern crate errno;
 extern crate platform;
 extern crate ralloc;
 
+use core::{ptr, str};
+
+use errno::*;
 use platform::types::*;
 
 #[global_allocator]
@@ -52,8 +56,8 @@ pub unsafe extern "C" fn atexit(func: Option<extern "C" fn()>) -> c_int {
 }
 
 #[no_mangle]
-pub extern "C" fn atof(s: *const c_char) -> c_double {
-    unimplemented!();
+pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
+    strtod(s, ptr::null_mut())
 }
 
 macro_rules! dec_num_from_ascii {
@@ -396,8 +400,19 @@ pub extern "C" fn srandom(seed: c_uint) {
 }
 
 #[no_mangle]
-pub extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
-    unimplemented!();
+pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
+    //TODO: endptr
+
+    use core::str::FromStr;
+
+    let s_str = str::from_utf8_unchecked(platform::c_str(s));
+    match f64::from_str(s_str) {
+        Ok(ok) => ok as c_double,
+        Err(_err) => {
+            platform::errno = EINVAL;
+            0.0
+        }
+    }
 }
 
 #[no_mangle]
diff --git a/tests/.gitignore b/tests/.gitignore
index 81c3450f8..073101f0f 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,5 +1,6 @@
 /alloc
 /args
+/atof
 /atoi
 /brk
 /chdir
diff --git a/tests/Makefile b/tests/Makefile
index 03c2a97cc..1d03ad22b 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,5 +1,6 @@
 BINS=\
 	alloc \
+	atof \
 	atoi \
 	brk \
 	args \
diff --git a/tests/atof.c b/tests/atof.c
new file mode 100644
index 000000000..b6668aab8
--- /dev/null
+++ b/tests/atof.c
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+    double d = atof("1.0");
+    printf("%f\n", d);
+    return 0;
+}
-- 
GitLab