From 9642d2ab027f4f07494d8a63c44cb7ec318df0fc Mon Sep 17 00:00:00 2001
From: Darley Barreto <darleybarreto@gmail.com>
Date: Mon, 22 May 2023 16:01:04 +0000
Subject: [PATCH] Adding some wcst* functions

---
 src/header/inttypes/mod.rs                    | 24 +-----
 src/header/wchar/mod.rs                       | 76 ++++++++++++++++++-
 tests/Makefile                                |  2 +
 .../bins_static/wchar/wcstoimax.stderr        |  0
 .../bins_static/wchar/wcstoimax.stdout        |  6 ++
 .../expected/bins_static/wchar/wcstol.stdout  |  2 +-
 .../bins_static/wchar/wcstoumax.stderr        |  0
 .../bins_static/wchar/wcstoumax.stdout        |  3 +
 tests/wchar/wcstoimax.c                       | 13 ++++
 tests/wchar/wcstoumax.c                       | 15 ++++
 10 files changed, 116 insertions(+), 25 deletions(-)
 create mode 100644 tests/expected/bins_static/wchar/wcstoimax.stderr
 create mode 100644 tests/expected/bins_static/wchar/wcstoimax.stdout
 create mode 100644 tests/expected/bins_static/wchar/wcstoumax.stderr
 create mode 100644 tests/expected/bins_static/wchar/wcstoumax.stdout
 create mode 100644 tests/wchar/wcstoimax.c
 create mode 100644 tests/wchar/wcstoumax.c

diff --git a/src/header/inttypes/mod.rs b/src/header/inttypes/mod.rs
index 52ec258c7..089ac5e7c 100644
--- a/src/header/inttypes/mod.rs
+++ b/src/header/inttypes/mod.rs
@@ -1,5 +1,7 @@
+use core::{convert::TryInto, ptr};
+
 use crate::{
-    header::{ctype, errno::*, stdlib::*},
+    header::{ctype, errno::*, stdlib::*, wctype::iswspace},
     platform::{self, types::*},
 };
 
@@ -56,23 +58,3 @@ pub unsafe extern "C" fn strtoumax(
         base
     )
 }
-
-#[allow(unused)]
-// #[no_mangle]
-pub extern "C" fn wcstoimax(
-    nptr: *const wchar_t,
-    endptr: *mut *mut wchar_t,
-    base: c_int,
-) -> intmax_t {
-    unimplemented!();
-}
-
-#[allow(unused)]
-// #[no_mangle]
-pub extern "C" fn wcstoumax(
-    nptr: *const wchar_t,
-    endptr: *mut *mut wchar_t,
-    base: c_int,
-) -> uintmax_t {
-    unimplemented!();
-}
diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs
index cc8eb4f7b..28bbb1093 100644
--- a/src/header/wchar/mod.rs
+++ b/src/header/wchar/mod.rs
@@ -660,14 +660,28 @@ macro_rules! strtou_impl {
         strtou_impl!($type, $ptr, $base, false)
     };
     ($type:ident, $ptr:expr, $base:expr, $negative:expr) => {{
-        if $base == 16 && *$ptr == '0' as wchar_t && *$ptr.add(1) | 0x20 == 'x' as wchar_t {
+        let mut base = $base;
+        
+        if (base == 16 || base == 0)
+            && *$ptr == '0' as wchar_t
+            && (*$ptr.add(1) == 'x' as wchar_t || *$ptr.add(1) == 'X' as wchar_t)
+        {
             $ptr = $ptr.add(2);
+            base = 16;
         }
+        
+        if base == 0 {
+            base = if *$ptr == '0' as wchar_t {
+                8
+            } else {
+                10
+            };
+        };
 
         let mut result: $type = 0;
-        while let Some(digit) = char::from_u32(*$ptr as u32).and_then(|c| c.to_digit($base as u32))
+        while let Some(digit) = char::from_u32(*$ptr as u32).and_then(|c| c.to_digit(base as u32))
         {
-            let new = result.checked_mul($base as $type).and_then(|result| {
+            let new = result.checked_mul(base as $type).and_then(|result| {
                 if $negative {
                     result.checked_sub(digit as $type)
                 } else {
@@ -711,6 +725,34 @@ pub unsafe extern "C" fn wcstol(
     result
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn wcstoll(
+    mut ptr: *const wchar_t,
+    end: *mut *mut wchar_t,
+    base: c_int,
+) -> c_longlong {
+    skipws!(ptr);
+    let result = strto_impl!(c_longlong, ptr, base);
+    if !end.is_null() {
+        *end = ptr as *mut _;
+    }
+    result
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn wcstoimax(
+    mut ptr: *const wchar_t,
+    end: *mut *mut wchar_t,
+    base: c_int,
+) -> intmax_t {
+    skipws!(ptr);
+    let result = strto_impl!(intmax_t, ptr, base);
+    if !end.is_null() {
+        *end = ptr as *mut _;
+    }
+    result
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn wcstoul(
     mut ptr: *const wchar_t,
@@ -725,6 +767,34 @@ pub unsafe extern "C" fn wcstoul(
     result
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn wcstoull(
+    mut ptr: *const wchar_t,
+    end: *mut *mut wchar_t,
+    base: c_int,
+) -> c_ulonglong {
+    skipws!(ptr);
+    let result = strtou_impl!(c_ulonglong, ptr, base);
+    if !end.is_null() {
+        *end = ptr as *mut _;
+    }
+    result
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn wcstoumax(
+    mut ptr: *const wchar_t,
+    end: *mut *mut wchar_t,
+    base: c_int,
+) -> uintmax_t {
+    skipws!(ptr);
+    let result = strtou_impl!(uintmax_t, ptr, base);
+    if !end.is_null() {
+        *end = ptr as *mut _;
+    }
+    result
+}
+
 // #[no_mangle]
 pub extern "C" fn wcswcs(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
     unimplemented!();
diff --git a/tests/Makefile b/tests/Makefile
index bf1a04aa2..f6ccb321d 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -117,6 +117,8 @@ EXPECT_NAMES=\
 	wchar/wcstod \
 	wchar/wcstok \
 	wchar/wcstol \
+	wchar/wcstoimax \
+	wchar/wcstoumax \
 	wchar/wcscasecmp \
 	wchar/wcsncasecmp \
 	wchar/wcswidth \
diff --git a/tests/expected/bins_static/wchar/wcstoimax.stderr b/tests/expected/bins_static/wchar/wcstoimax.stderr
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/expected/bins_static/wchar/wcstoimax.stdout b/tests/expected/bins_static/wchar/wcstoimax.stdout
new file mode 100644
index 000000000..b9a14be84
--- /dev/null
+++ b/tests/expected/bins_static/wchar/wcstoimax.stdout
@@ -0,0 +1,6 @@
+-123
+255
+44027
+8
+10
+16
diff --git a/tests/expected/bins_static/wchar/wcstol.stdout b/tests/expected/bins_static/wchar/wcstol.stdout
index ec5ae5877..55aa50779 100644
--- a/tests/expected/bins_static/wchar/wcstol.stdout
+++ b/tests/expected/bins_static/wchar/wcstol.stdout
@@ -1 +1 @@
-The decimal equivalents are: 2001, 6340800, -3624224 and 0.
+The decimal equivalents are: 2001, 6340800, -3624224 and 7340031.
diff --git a/tests/expected/bins_static/wchar/wcstoumax.stderr b/tests/expected/bins_static/wchar/wcstoumax.stderr
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/expected/bins_static/wchar/wcstoumax.stdout b/tests/expected/bins_static/wchar/wcstoumax.stdout
new file mode 100644
index 000000000..8e372f758
--- /dev/null
+++ b/tests/expected/bins_static/wchar/wcstoumax.stdout
@@ -0,0 +1,3 @@
+nptr = `10110134932`
+wcstoumax = 10110134932
+Stopped scan at ``
diff --git a/tests/wchar/wcstoimax.c b/tests/wchar/wcstoimax.c
new file mode 100644
index 000000000..546314d06
--- /dev/null
+++ b/tests/wchar/wcstoimax.c
@@ -0,0 +1,13 @@
+#include <inttypes.h>
+#include <stdio.h>
+#include <wchar.h>
+
+int main(void) {
+    wchar_t* endptr;
+    wprintf(L"%ld\n", wcstoimax(L" -123junk", &endptr, 10)); /* base 10                    */
+    wprintf(L"%ld\n", wcstoimax(L"11111111", &endptr, 2));   /* base 2                     */
+    wprintf(L"%ld\n", wcstoimax(L"XyZ", &endptr, 36));       /* base 36                    */
+    wprintf(L"%ld\n", wcstoimax(L"010", &endptr, 0));        /* octal auto-detection       */
+    wprintf(L"%ld\n", wcstoimax(L"10", &endptr, 0));         /* decimal auto-detection     */
+    wprintf(L"%ld\n", wcstoimax(L"0x10", &endptr, 0));       /* hexadecimal auto-detection */
+}
\ No newline at end of file
diff --git a/tests/wchar/wcstoumax.c b/tests/wchar/wcstoumax.c
new file mode 100644
index 000000000..8f4c80b8a
--- /dev/null
+++ b/tests/wchar/wcstoumax.c
@@ -0,0 +1,15 @@
+#include <inttypes.h>      
+#include <stdio.h>
+#include <wchar.h>
+
+int main(void) {                                                    
+    wchar_t *nptr;                                    
+    wchar_t *endptr;                                  
+    uintmax_t  j;                                      
+    int base = 10;                                    
+    nptr = L"10110134932";                            
+    printf("nptr = `%ls`\n", nptr);                   
+    j = wcstoumax(nptr, &endptr, base);            
+    printf("wcstoumax = %ju\n", j);            
+    printf("Stopped scan at `%ls`\n", endptr);
+} 
\ No newline at end of file
-- 
GitLab