From a79d0d8fca82091f4b4b45d6f6aae47e935eb536 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 | 21 +++++++++++++------ tests/by-util/test_printf.rs | 17 ++++++++++++++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/uucore/src/lib/features/format/argument.rs b/src/uucore/src/lib/features/format/argument.rs index b2b83af74ab..400cc7b95d9 100644 --- a/src/uucore/src/lib/features/format/argument.rs +++ b/src/uucore/src/lib/features/format/argument.rs @@ -49,6 +49,7 @@ impl<'a, T: Iterator> ArgumentIter<'a> for T { _ => b'\0', } } + fn get_u64(&mut self) -> u64 { let Some(next) = self.next() else { return 0; @@ -57,13 +58,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(ParsedNumber::parse_u64(s), s) } diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 3dd0ccbc211..917487e308c 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -869,12 +869,27 @@ fn float_switch_switch_decimal_scientific() { #[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")); + } } #[test]