From 528cab55c1b5dc3dc3eb7477464598ab6bd7cc9b Mon Sep 17 00:00:00 2001 From: luizgfc Date: Fri, 29 Aug 2025 18:34:07 -0300 Subject: [PATCH] core/printf: %o substitution type implementation --- core/functions/printf.rs | 47 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/core/functions/printf.rs b/core/functions/printf.rs index 030ca7192..00c504a6e 100644 --- a/core/functions/printf.rs +++ b/core/functions/printf.rs @@ -34,7 +34,7 @@ fn get_exponential_formatted_str(number: &f64, uppercase: bool) -> crate::Result } } -// TODO: Support %!.3s, %o. flags: - + 0 ! , +// TODO: Support %!.3s. flags: - + 0 ! , #[inline(always)] pub fn exec_printf(values: &[Register]) -> crate::Result { if values.is_empty() { @@ -210,6 +210,18 @@ pub fn exec_printf(values: &[Register]) -> crate::Result { } args_index += 1; } + Some('o') => { + if args_index >= values.len() { + return Err(LimboError::InvalidArgument("not enough arguments".into())); + } + let value = &values[args_index].get_value(); + match value { + Value::Float(f) => result.push_str(&format!("{:o}", *f as i64)), + Value::Integer(i) => result.push_str(&format!("{i:o}")), + _ => result.push('0'), + } + args_index += 1; + } None => { return Err(LimboError::InvalidArgument( "incomplete format specifier".into(), @@ -503,6 +515,39 @@ mod tests { } } + #[test] + fn test_printf_octal_formatting() { + let test_cases = vec![ + // Simple number + (vec![text("octal: %o"), integer(4)], text("octal: 4")), + // Bigger Number + ( + vec![text("octal: %o"), integer(15565303546)], + text("octal: 163760727372"), + ), + // Negative + ( + vec![text("octal: %o"), integer(-15565303546)], + text("octal: 1777777777614017050406"), + ), + // Float + (vec![text("octal: %o"), float(42.5)], text("octal: 52")), + // Negative Float + ( + vec![text("octal: %o"), float(-42.5)], + text("octal: 1777777777777777777726"), + ), + // Text + (vec![text("octal: %o"), text("42")], text("octal: 0")), + // Empty Text + (vec![text("octal: %o"), text("")], text("octal: 0")), + ]; + + for (input, expected) in test_cases { + assert_eq!(exec_printf(&input).unwrap(), *expected.get_value()); + } + } + #[test] fn test_printf_mixed_formatting() { let test_cases = vec![