Merge branch 'printf-float-alternate-fix' into 'master'

printf: fix '%#.0e' to always print the radix character

See merge request redox-os/relibc!1177
This commit is contained in:
Jeremy Soller
2026-04-10 18:53:22 -06:00
+27 -8
View File
@@ -444,9 +444,23 @@ fn pad<W: Write>(
Ok(())
}
fn float_string(float: c_double, precision: usize, trim: bool) -> String {
fn float_string(float: c_double, precision: usize, trim: bool, alternate: bool) -> String {
// The Rust format! macro doesn't keep the dot on precision = 0 and alternate = true,
// so we have to perform a fix-up
//
// POSIX.1-2024 says "... if the precision is zero and no '#' flag is present,
// no radix character shall appear."
//
// This case is covered here.
let mut string = format!("{:.p$}", float, p = precision);
if trim && string.contains('.') {
//
// Additionally, it says "For a, A, e, E, f, F, g, and G conversion specifiers,
// the result shall always contain a radix character, even if no digits follow
// the radix character."
//
if alternate && precision == 0 {
string.push('.');
} else if trim && string.contains('.') {
let truncate = {
let slice = string.trim_end_matches('0');
let mut truncate = slice.len();
@@ -477,6 +491,7 @@ fn fmt_float_exp<W: Write>(
w: &mut W,
exp_fmt: char,
trim: bool,
alternate: bool,
precision: usize,
float: c_double,
exp: isize,
@@ -491,7 +506,7 @@ fn fmt_float_exp<W: Write>(
exp_len += 1;
}
let string = float_string(float, precision, trim);
let string = float_string(float, precision, trim, alternate);
let len = string.len() + 2 + 2.max(exp_len);
pad(w, !left, b' ', len..pad_space)?;
@@ -512,13 +527,14 @@ fn fmt_float_exp<W: Write>(
fn fmt_float_normal<W: Write>(
w: &mut W,
trim: bool,
alternate: bool,
precision: usize,
float: c_double,
left: bool,
pad_space: usize,
pad_zero: usize,
) -> io::Result<usize> {
let string = float_string(float, precision, trim);
let string = float_string(float, precision, trim, alternate);
pad(w, !left, b' ', string.len()..pad_space)?;
let bytes = if string.starts_with('-') {
@@ -968,7 +984,7 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
let precision = precision.unwrap_or(6);
fmt_float_exp(
w, fmt, false, precision, float, exp, left, pad_space, pad_zero,
w, fmt, false, alternate, precision, float, exp, left, pad_space, pad_zero,
)?;
} else {
fmt_float_nonfinite(w, float, fmtcase.unwrap(), left, pad_space, pad_zero)?;
@@ -985,7 +1001,9 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
if float.is_finite() {
let precision = precision.unwrap_or(6);
fmt_float_normal(w, false, precision, float, left, pad_space, pad_zero)?;
fmt_float_normal(
w, false, alternate, precision, float, left, pad_space, pad_zero,
)?;
} else {
fmt_float_nonfinite(w, float, fmtcase.unwrap(), left, pad_space, pad_zero)?;
}
@@ -1010,7 +1028,8 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
// because that's how x/floor(log10(x)) works
let precision = precision.saturating_sub(1);
fmt_float_exp(
w, exp_fmt, !alternate, precision, log, exp, left, pad_space, pad_zero,
w, exp_fmt, !alternate, alternate, precision, log, exp, left,
pad_space, pad_zero,
)?;
} else {
// Length of integral part will be the exponent of
@@ -1020,7 +1039,7 @@ pub(crate) unsafe fn inner_printf<T: c_str::Kind>(
let len = 1 + cmp::max(0, exp) as usize;
let precision = precision.saturating_sub(len);
fmt_float_normal(
w, !alternate, precision, float, left, pad_space, pad_zero,
w, !alternate, alternate, precision, float, left, pad_space, pad_zero,
)?;
}
} else {