From 70f9dad334b5d540731d53d44635bf57eab73de2 Mon Sep 17 00:00:00 2001 From: auronandace Date: Tue, 17 Mar 2026 16:46:09 +0000 Subject: [PATCH 1/4] move macros from wchar to macros --- src/header/wchar/mod.rs | 84 ---------------------------------------- src/macros.rs | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index 08edbf3374..d41213b18c 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -759,14 +759,6 @@ pub unsafe extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mu } } -macro_rules! skipws { - ($ptr:expr) => { - while isspace(unsafe { *$ptr }) != 0 { - $ptr = unsafe { $ptr.add(1) }; - } - }; -} - /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcstod(mut ptr: *const wchar_t, end: *mut *mut wchar_t) -> c_double { @@ -845,82 +837,6 @@ pub unsafe extern "C" fn wcstok( wcs } -macro_rules! strtou_impl { - ($type:ident, $ptr:expr, $base:expr) => { - strtou_impl!($type, $ptr, $base, false) - }; - ($type:ident, $ptr:expr, $base:expr, $negative:expr) => {{ - let mut base = $base; - - if (base == 16 || base == 0) - && unsafe { *$ptr } == '0' as wchar_t - && (unsafe { *$ptr.add(1) } == 'x' as wchar_t - || unsafe { *$ptr.add(1) } == 'X' as wchar_t) - { - $ptr = unsafe { $ptr.add(2) }; - base = 16; - } - - if base == 0 { - base = if unsafe { *$ptr } == '0' as wchar_t { - 8 - } else { - 10 - }; - }; - - let mut result: $type = 0; - while let Some(digit) = - char::from_u32(unsafe { *$ptr } as u32).and_then(|c| c.to_digit(base as u32)) - { - let new = result.checked_mul(base as $type).and_then(|result| { - if $negative { - #[cfg(target_arch = "x86")] - { - result.checked_sub( - $type::try_from(digit).expect("single digit never overflows"), - ) - } - #[cfg(not(target_arch = "x86"))] - { - result.checked_sub($type::from(digit)) - } - } else { - #[cfg(target_arch = "x86")] - { - result.checked_add( - $type::try_from(digit).expect("single digit never overflows"), - ) - } - #[cfg(not(target_arch = "x86"))] - { - result.checked_add($type::from(digit)) - } - } - }); - result = match new { - Some(new) => new, - None => { - platform::ERRNO.set(ERANGE); - return !0; - } - }; - - $ptr = unsafe { $ptr.add(1) }; - } - result - }}; -} -macro_rules! strto_impl { - ($type:ident, $ptr:expr, $base:expr) => {{ - let negative = unsafe { *$ptr } == '-' as wchar_t; - if negative { - $ptr = unsafe { $ptr.add(1) }; - } - strtou_impl!($type, $ptr, $base, negative) - }}; -} - /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcstol( diff --git a/src/macros.rs b/src/macros.rs index 51440365e2..1b718eb8b2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -117,8 +117,86 @@ macro_rules! trace_expr { }); } +#[macro_export] +macro_rules! skipws { + ($ptr:expr) => { + while isspace(unsafe { *$ptr }) != 0 { + $ptr = unsafe { $ptr.add(1) }; + } + }; +} + +#[macro_export] +macro_rules! strtou_impl { + ($type:ident, $ptr:expr, $base:expr) => { + strtou_impl!($type, $ptr, $base, false) + }; + ($type:ident, $ptr:expr, $base:expr, $negative:expr) => {{ + let mut base = $base; + + if (base == 16 || base == 0) + && unsafe { *$ptr } == '0' as wchar_t + && (unsafe { *$ptr.add(1) } == 'x' as wchar_t + || unsafe { *$ptr.add(1) } == 'X' as wchar_t) + { + $ptr = unsafe { $ptr.add(2) }; + base = 16; + } + + if base == 0 { + base = if unsafe { *$ptr } == '0' as wchar_t { + 8 + } else { + 10 + }; + }; + + let mut result: $type = 0; + while let Some(digit) = + char::from_u32(unsafe { *$ptr } as u32).and_then(|c| c.to_digit(base as u32)) + { + let new = result.checked_mul(base as $type).and_then(|result| { + if $negative { + #[cfg(target_arch = "x86")] + { + result.checked_sub( + $type::try_from(digit).expect("single digit never overflows"), + ) + } + #[cfg(not(target_arch = "x86"))] + { + result.checked_sub($type::from(digit)) + } + } else { + #[cfg(target_arch = "x86")] + { + result.checked_add( + $type::try_from(digit).expect("single digit never overflows"), + ) + } + #[cfg(not(target_arch = "x86"))] + { + result.checked_add($type::from(digit)) + } + } + }); + result = match new { + Some(new) => new, + None => { + platform::ERRNO.set(ERANGE); + return !0; + } + }; + + $ptr = unsafe { $ptr.add(1) }; + } + result + }}; +} + #[macro_export] macro_rules! strto_impl { + // this variant is used by inttypes and stdlib ( $rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident ) => {{ @@ -219,6 +297,14 @@ macro_rules! strto_impl { num }}; + // this variant is used by wchar (also wcstoimax and wcstoumax from inttypes) + ($type:ident, $ptr:expr, $base:expr) => {{ + let negative = unsafe { *$ptr } == '-' as wchar_t; + if negative { + $ptr = unsafe { $ptr.add(1) }; + } + strtou_impl!($type, $ptr, $base, negative) + }}; } #[macro_export] From 84c9038a1165780f1086010ab1bda5a92bca21da Mon Sep 17 00:00:00 2001 From: auronandace Date: Tue, 17 Mar 2026 16:53:48 +0000 Subject: [PATCH 2/4] move wcstoimax and wcstoumax from wchar to inttypes --- src/header/inttypes/mod.rs | 34 +++++++++++++++++++++++++++++++--- src/header/wchar/mod.rs | 32 +------------------------------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/header/inttypes/mod.rs b/src/header/inttypes/mod.rs index d4abdc9b9d..725aae8be7 100644 --- a/src/header/inttypes/mod.rs +++ b/src/header/inttypes/mod.rs @@ -3,10 +3,10 @@ //! See . use crate::{ - header::{ctype, errno::*, stdlib::*}, + header::{ctype::{self, isspace}, errno::*, stdlib::*}, platform::{ self, - types::{c_char, c_int, c_long, intmax_t, uintmax_t}, + types::{c_char, c_int, c_long, intmax_t, uintmax_t, wchar_t}, }, }; @@ -68,4 +68,32 @@ pub unsafe extern "C" fn strtoumax( ) } -// wcstoimax(), wcstoumax() currently defined in header::wchar? +/// See . +#[unsafe(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() { + unsafe { *end = ptr.cast_mut() }; + } + result +} + +/// See . +#[unsafe(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() { + unsafe { *end = ptr.cast_mut() }; + } + result +} diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index d41213b18c..304c9940f8 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -21,7 +21,7 @@ use crate::{ self, ERRNO, types::{ c_char, c_double, c_int, c_long, c_longlong, c_uchar, c_ulong, c_ulonglong, c_void, - intmax_t, size_t, uintmax_t, wchar_t, wint_t, + size_t, wchar_t, wint_t, }, }, }; @@ -867,21 +867,6 @@ pub unsafe extern "C" fn wcstoll( result } -/// See . -#[unsafe(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() { - unsafe { *end = ptr.cast_mut() }; - } - result -} - /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcstoul( @@ -912,21 +897,6 @@ pub unsafe extern "C" fn wcstoull( result } -/// See . -#[unsafe(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() { - unsafe { *end = ptr.cast_mut() }; - } - result -} - /// See . /// /// Marked legacy in issue 6. From b252a794e0ce079c69363e733501c3029fa5a657 Mon Sep 17 00:00:00 2001 From: auronandace Date: Tue, 17 Mar 2026 17:11:42 +0000 Subject: [PATCH 3/4] verify inttypes header includes --- src/header/inttypes/cbindgen.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/header/inttypes/cbindgen.toml b/src/header/inttypes/cbindgen.toml index f923cb6804..28710c9e1c 100644 --- a/src/header/inttypes/cbindgen.toml +++ b/src/header/inttypes/cbindgen.toml @@ -1,4 +1,11 @@ -sys_includes = ["stdint.h", "wchar.h"] +# POSIX header spec: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/inttypes.h.html +# +# Spec quotations relating to includes: +# - "The header shall include the header." +# - "wchar_t As described in ." +# +# bits/wchar.h brings in both stdint.h and stddef.h +sys_includes = ["bits/wchar.h"] include_guard = "_RELIBC_INTTYPES_H" trailer = "#include " language = "C" From c79315ed0684d04817a5bfd86694a6e93557ae75 Mon Sep 17 00:00:00 2001 From: auronandace Date: Tue, 17 Mar 2026 17:13:19 +0000 Subject: [PATCH 4/4] cargo fmt --- src/header/inttypes/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/header/inttypes/mod.rs b/src/header/inttypes/mod.rs index 725aae8be7..bf3c355381 100644 --- a/src/header/inttypes/mod.rs +++ b/src/header/inttypes/mod.rs @@ -3,7 +3,11 @@ //! See . use crate::{ - header::{ctype::{self, isspace}, errno::*, stdlib::*}, + header::{ + ctype::{self, isspace}, + errno::*, + stdlib::*, + }, platform::{ self, types::{c_char, c_int, c_long, intmax_t, uintmax_t, wchar_t},