From 0934bcf13ebcfd02f422bba786307a6b0c515bfd Mon Sep 17 00:00:00 2001 From: Connor-GH Date: Mon, 19 Jan 2026 16:54:53 -0600 Subject: [PATCH] Implement strxfrm_l, strcoll_l, and strerror_l These implementations are effectively the same as the ones in musl. --- src/header/locale/mod.rs | 2 +- src/header/string/mod.rs | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/header/locale/mod.rs b/src/header/locale/mod.rs index 696b26995d..25b9ffb06d 100644 --- a/src/header/locale/mod.rs +++ b/src/header/locale/mod.rs @@ -36,7 +36,7 @@ pub const LC_GLOBAL_LOCALE: locale_t = -1isize as locale_t; static mut GLOBAL_LOCALE: *mut GlobalLocaleData = ptr::null_mut(); /// thread-wide locale, used by uselocale() and localeconv() #[thread_local] -static mut THREAD_LOCALE: *mut LocaleData = ptr::null_mut(); +pub(crate) static mut THREAD_LOCALE: *mut LocaleData = ptr::null_mut(); /// See . #[unsafe(no_mangle)] diff --git a/src/header/string/mod.rs b/src/header/string/mod.rs index a40d6160cc..e1c2c2478b 100644 --- a/src/header/string/mod.rs +++ b/src/header/string/mod.rs @@ -20,6 +20,8 @@ use crate::{ raw_cell::RawCell, }; +use super::locale::{THREAD_LOCALE, locale_t}; + /// See . /// /// # Safety @@ -292,14 +294,18 @@ pub unsafe extern "C" fn strcmp(s1: *const c_char, s2: *const c_char) -> c_int { unsafe { strncmp(s1, s2, usize::MAX) } } -/// See . +/// See . #[unsafe(no_mangle)] -pub unsafe extern "C" fn strcoll(s1: *const c_char, s2: *const c_char) -> c_int { +pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int { // relibc has no locale stuff (yet) unsafe { strcmp(s1, s2) } } -// TODO: strcoll_l +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn strcoll(s1: *const c_char, s2: *const c_char) -> c_int { + strcoll_l(s1, s2, THREAD_LOCALE as locale_t) +} /// See . #[unsafe(no_mangle)] @@ -352,9 +358,9 @@ pub unsafe extern "C" fn strdup(s1: *const c_char) -> *mut c_char { unsafe { strndup(s1, usize::MAX) } } -/// See . +/// See . #[unsafe(no_mangle)] -pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char { +pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char { use core::fmt::Write; static strerror_buf: RawCell<[u8; STRERROR_MAX]> = RawCell::new([0; STRERROR_MAX]); @@ -370,10 +376,14 @@ pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char { (unsafe { strerror_buf.unsafe_mut().as_mut_ptr() }) as *mut c_char } -// TODO: strerror_l - /// See . #[unsafe(no_mangle)] +pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char { + strerror_l(errnum, THREAD_LOCALE as locale_t) +} + +/// See . +#[unsafe(no_mangle)] pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int { let msg = unsafe { strerror(errnum) }; let len = unsafe { strlen(msg) }; @@ -640,9 +650,14 @@ pub unsafe extern "C" fn strtok_r( token } -/// See . +/// See . #[unsafe(no_mangle)] -pub unsafe extern "C" fn strxfrm(s1: *mut c_char, s2: *const c_char, n: size_t) -> size_t { +pub unsafe extern "C" fn strxfrm_l( + s1: *mut c_char, + s2: *const c_char, + n: size_t, + _loc: locale_t, +) -> size_t { // relibc has no locale stuff (yet) let len = unsafe { strlen(s2) }; if len < n { @@ -651,4 +666,8 @@ pub unsafe extern "C" fn strxfrm(s1: *mut c_char, s2: *const c_char, n: size_t) len } -// TODO: strxfrm_l +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn strxfrm(s1: *mut c_char, s2: *const c_char, n: size_t) -> size_t { + strxfrm_l(s1, s2, n, THREAD_LOCALE as locale_t) +}