Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions pyre/pyre-interpreter/src/module/_locale/interp_locale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,20 +203,17 @@ pub fn register_module(ns: pyre_object::PyObjectRef) {
// `_w_copy_grouping` (`interp_locale.py:36-40`): every byte
// of the C grouping string up to its NUL is one group size
// (a `CHAR_MAX` element stays `127`), then a trailing `0`
// is appended to a non-empty list. Read the grouping
// straight from `localeconv()` because the host helper
// stops at the first `CHAR_MAX`, dropping it.
// is appended to a non-empty list. The bytes come from
// `rlocale::charp2str`, the same read `numeric_formatting`
// groups by, rather than from the host helper, which stops
// at the first `CHAR_MAX` and drops it. The trailing `0` is
// this function's own fixup and belongs to the app-level
// list, never to the grouping the formatter walks.
let grouping_of = |ptr: *const libc::c_char| -> Vec<i64> {
let mut v: Vec<i64> = Vec::new();
if !ptr.is_null() {
let mut cur = ptr;
unsafe {
while *cur != 0 {
v.push(*cur as u8 as i64);
cur = cur.add(1);
}
}
}
let mut v: Vec<i64> = super::rlocale::charp2str(ptr)
.into_iter()
.map(i64::from)
.collect();
if !v.is_empty() {
v.push(0);
}
Expand Down
2 changes: 2 additions & 0 deletions pyre/pyre-interpreter/src/module/_locale/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
//! Provides the 'C' locale defaults so locale.py's `from _locale import *`
//! succeeds and Lib/locale.py exposes working `localeconv` / `setlocale`.

pub mod rlocale;

crate::pyre_module_init!(interp_locale);
56 changes: 56 additions & 0 deletions pyre/pyre-interpreter/src/module/_locale/rlocale.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! rlocale — RPython: rpython/rlib/rlocale.py
//!
//! `numeric_formatting` is the entry point the number formatter draws its
//! locale from (`newformat.py:643-644`). It sits beside the `_locale` module
//! port so it shares the raw `localeconv()` walk with that module's own
//! `localeconv()`: the grouping `format(x, 'n')` groups by and the grouping
//! `locale.localeconv()` reports come out of the same read and cannot drift
//! apart.

/// Every byte of a NUL-terminated C string, `CHAR_MAX` included.
///
/// `rffi.charp2str` (`rlocale.py:175-177`) truncates at the NUL and at nothing
/// else, so a grouping terminator a locale spells as `CHAR_MAX` stays in the
/// result. `rustpython_host_env::locale`'s own reader stops at `CHAR_MAX` and
/// drops it, which would collapse the "stop" and "repeat the last group"
/// conventions onto the same vector.
#[cfg(all(unix, feature = "host_env", not(feature = "sandbox")))]
pub(super) fn charp2str(ptr: *const libc::c_char) -> Vec<u8> {
let mut out = Vec::new();
if !ptr.is_null() {
let mut cur = ptr;
unsafe {
while *cur != 0 {
out.push(*cur as u8);
cur = cur.add(1);
}
}
}
out
}

/// `rlocale.py:173-178 numeric_formatting`: the decimal point, thousands
/// separator and grouping string of the current locale, as the bytes
/// `localeconv()` reports them.
///
/// Off unix, without `host_env`, and under sandbox the C locale's values stand
/// in. Upstream declares `localeconv` `sandboxsafe=True` (`rlocale.py:167`,
/// `:180-182`) and reads the host locale even there; pyre compiles the call out
/// instead, because the sandbox build replaces `_locale`'s host entry points
/// with raising stubs and `format()` must not acquire a raising path.
pub(crate) fn numeric_formatting() -> (Vec<u8>, Vec<u8>, Vec<u8>) {
#[cfg(all(unix, feature = "host_env", not(feature = "sandbox")))]
{
let conv = unsafe { libc::localeconv() };
if !conv.is_null() {
return unsafe {
(
charp2str((*conv).decimal_point),
charp2str((*conv).thousands_sep),
charp2str((*conv).grouping),
)
};
}
}
(b".".to_vec(), Vec::new(), Vec::new())
}
Loading
Loading