From c7d94ae4d7ea2ab885c9cd881d1f10658ccfa8bf Mon Sep 17 00:00:00 2001 From: GrayJack Date: Sat, 22 Mar 2025 20:15:56 -0300 Subject: [PATCH] feat(c23): Implement `%b` and `%B` format --- src/header/stdio/printf.rs | 23 +++++++++++-------- .../expected/bins_dynamic/stdio/printf.stdout | 6 +++++ .../expected/bins_static/stdio/printf.stdout | 6 +++++ tests/stdio/printf.c | 6 +++++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/header/stdio/printf.rs b/src/header/stdio/printf.rs index 324be2cfcf..6faf477507 100644 --- a/src/header/stdio/printf.rs +++ b/src/header/stdio/printf.rs @@ -4,7 +4,7 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::{char, cmp, f64, ffi::VaList, fmt, num::FpCategory, ops::Range, slice}; +use core::{cmp, ffi::VaList, fmt, num::FpCategory, ops::Range, slice}; use crate::{ header::errno::EILSEQ, @@ -313,13 +313,14 @@ unsafe fn pop_int(format: &mut *const u8) -> Option { unsafe fn fmt_int(fmt: u8, i: I) -> String where - I: fmt::Display + fmt::Octal + fmt::LowerHex + fmt::UpperHex, + I: fmt::Display + fmt::Octal + fmt::LowerHex + fmt::UpperHex + fmt::Binary, { match fmt { b'o' => format!("{:o}", i), b'u' => i.to_string(), b'x' => format!("{:x}", i), b'X' => format!("{:X}", i), + b'b' | b'B' => format!("{:b}", i), _ => panic!( "fmt_int should never be called with the fmt {:?}", fmt as char @@ -579,7 +580,7 @@ impl Iterator for PrintfIter { let fmtkind = match fmt { b'%' => FmtKind::Percent, b'd' | b'i' => FmtKind::Signed, - b'o' | b'u' | b'x' | b'X' => FmtKind::Unsigned, + b'o' | b'u' | b'x' | b'X' | b'b' | b'B' => FmtKind::Unsigned, b'e' | b'E' => FmtKind::Scientific, b'f' | b'F' => FmtKind::Decimal, b'g' | b'G' => FmtKind::AnyNotation, @@ -685,8 +686,8 @@ unsafe fn inner_printf(w: W, format: *const c_char, mut ap: VaList) -> let fmt = arg.fmt; let fmtkind = arg.fmtkind; let fmtcase = match fmt { - b'x' | b'f' | b'e' | b'g' => Some(FmtCase::Lower), - b'X' | b'F' | b'E' | b'G' => Some(FmtCase::Upper), + b'x' | b'b' | b'f' | b'e' | b'g' => Some(FmtCase::Lower), + b'X' | b'B' | b'F' | b'E' | b'G' => Some(FmtCase::Upper), _ => None, }; @@ -780,7 +781,7 @@ unsafe fn inner_printf(w: W, format: *const c_char, mut ap: VaList) -> + if alternate && string != "0" { match fmt { b'o' if no_precision => 1, - b'x' | b'X' => 2, + b'x' | b'X' | b'b' | b'B' => 2, _ => 0, } } else { @@ -792,9 +793,11 @@ unsafe fn inner_printf(w: W, format: *const c_char, mut ap: VaList) -> if alternate && string != "0" { match fmt { - b'o' if no_precision => w.write_all(&[b'0'])?, - b'x' => w.write_all(&[b'0', b'x'])?, - b'X' => w.write_all(&[b'0', b'X'])?, + b'o' if no_precision => w.write_all(b"0")?, + b'x' => w.write_all(b"0x")?, + b'X' => w.write_all(b"0X")?, + b'b' => w.write_all(b"0b")?, + b'B' => w.write_all(b"0B")?, _ => (), } } @@ -1136,7 +1139,7 @@ unsafe fn inner_printf(w: W, format: *const c_char, mut ap: VaList) -> /// characters written. /// - The alternative representation includes a leading `0X`. /// - The types are the same as `u`. -/// - `b` | `B` (C23 ※): Writes the binary representation of a unsigned integer. +/// - `b` | `B` (C23): Writes the binary representation of a unsigned integer. /// - The [precision] specifies the minimal number to appear (defaults to `1`). /// - If the precision is zero and the value to be written is also zero, the result is no /// characters written. diff --git a/tests/expected/bins_dynamic/stdio/printf.stdout b/tests/expected/bins_dynamic/stdio/printf.stdout index 75c6a49414..8e28c396b1 100644 --- a/tests/expected/bins_dynamic/stdio/printf.stdout +++ b/tests/expected/bins_dynamic/stdio/printf.stdout @@ -66,3 +66,9 @@ Testing asprintf... printed: test string, value: 11 printed: test string 2, value: 13 printed: test string 2, value: 13 + +C23: +Binary %b: 100 +Binary %b alternate: 0b100 +Binary %B: 100 +Binary %B alternate: 0B100 diff --git a/tests/expected/bins_static/stdio/printf.stdout b/tests/expected/bins_static/stdio/printf.stdout index 75c6a49414..8e28c396b1 100644 --- a/tests/expected/bins_static/stdio/printf.stdout +++ b/tests/expected/bins_static/stdio/printf.stdout @@ -66,3 +66,9 @@ Testing asprintf... printed: test string, value: 11 printed: test string 2, value: 13 printed: test string 2, value: 13 + +C23: +Binary %b: 100 +Binary %b alternate: 0b100 +Binary %B: 100 +Binary %B alternate: 0B100 diff --git a/tests/stdio/printf.c b/tests/stdio/printf.c index 073a609ca4..fb0c1478b7 100644 --- a/tests/stdio/printf.c +++ b/tests/stdio/printf.c @@ -90,4 +90,10 @@ int main(void) { res = asprintf(&s, "test %s %d", "string", 2); printf("printed: %s, value: %d\n", s, res); free(s); + + puts("\nC23:"); + printf("Binary %%b: %b\n", 4); + printf("Binary %%b alternate: %#b\n", 4); + printf("Binary %%B: %B\n", 4); + printf("Binary %%B alternate: %#B\n", 4); }