From af577e7a140b8d2bba76ff9126c9c997f8819a0f Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Wed, 1 Jan 2025 17:17:44 +0100 Subject: [PATCH] printf: support for extract chars Should fix tests/printf/printf-mb.sh --- .../src/lib/features/format/argument.rs | 20 +++++++++++++------ tests/by-util/test_printf.rs | 17 +++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/uucore/src/lib/features/format/argument.rs b/src/uucore/src/lib/features/format/argument.rs index 0441a5796..48d7f8f93 100644 --- a/src/uucore/src/lib/features/format/argument.rs +++ b/src/uucore/src/lib/features/format/argument.rs @@ -60,13 +60,21 @@ impl<'a, T: Iterator> ArgumentIter<'a> for T { FormatArgument::UnsignedInt(n) => *n, FormatArgument::Unparsed(s) => { // Check if the string is a character literal enclosed in quotes - if s.starts_with(['"', '\'']) && s.len() > 2 { - // Extract the content between the quotes safely - let chars: Vec = - s.trim_matches(|c| c == '"' || c == '\'').chars().collect(); - if chars.len() == 1 { - return chars[0] as u64; // Return the Unicode code point + if s.starts_with(['"', '\'']) { + // Extract the content between the quotes safely using chars + let mut chars = s.trim_matches(|c| c == '"' || c == '\'').chars(); + if let Some(first_char) = chars.next() { + if chars.clone().count() > 0 { + // Emit a warning if there are additional characters + let remaining: String = chars.collect(); + show_warning!( + "{}: character(s) following character constant have been ignored", + remaining + ); + } + return first_char as u64; // Use only the first character } + return 0; // Empty quotes } extract_value(u64::extended_parse(s), s) } diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index ca600f937..2b53c10a2 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -1291,10 +1291,25 @@ fn float_arg_with_whitespace() { #[test] fn mb_input() { - for format in ["\"á", "\'á"] { + for format in ["\"á", "\'á", "'\u{e1}"] { new_ucmd!() .args(&["%04x\n", format]) .succeeds() .stdout_only("00e1\n"); } + + let cases = vec![ + ("\"á=", "="), + ("\'á-", "-"), + ("\'á=-==", "=-=="), + ("'\u{e1}++", "++"), + ]; + + for (format, expected) in cases { + new_ucmd!() + .args(&["%04x\n", format]) + .succeeds() + .stdout_is("00e1\n") + .stderr_is(format!("printf: warning: {expected}: character(s) following character constant have been ignored\n")); + } }