[libc-commits] [libc] [libc] Support %lc in printf (PR #169301)
via libc-commits
libc-commits at lists.llvm.org
Mon Nov 24 01:26:43 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Shubh Pachchigar (shubhe25p)
<details>
<summary>Changes</summary>
Add %lc support to libc printf by utilizing wctomb internal function, also added relevant unit tests. Resolves #<!-- -->166598
---
Full diff: https://github.com/llvm/llvm-project/pull/169301.diff
3 Files Affected:
- (modified) libc/src/stdio/printf_core/char_converter.h (+19-3)
- (modified) libc/test/src/stdio/printf_core/CMakeLists.txt (+2)
- (modified) libc/test/src/stdio/printf_core/converter_test.cpp (+51)
``````````diff
diff --git a/libc/src/stdio/printf_core/char_converter.h b/libc/src/stdio/printf_core/char_converter.h
index fd2eb2553887a..58ade4fbf9a53 100644
--- a/libc/src/stdio/printf_core/char_converter.h
+++ b/libc/src/stdio/printf_core/char_converter.h
@@ -13,6 +13,7 @@
#include "src/stdio/printf_core/converter_utils.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/writer.h"
+#include "src/wchar/wctomb.h"
namespace LIBC_NAMESPACE_DECL {
namespace printf_core {
@@ -20,8 +21,10 @@ namespace printf_core {
template <WriteMode write_mode>
LIBC_INLINE int convert_char(Writer<write_mode> *writer,
const FormatSection &to_conv) {
- char c = static_cast<char>(to_conv.conv_val_raw);
-
+ char c;
+ wchar_t wc;
+ char mb_str[MB_LEN_MAX];
+ int ret = 0;
constexpr int STRING_LEN = 1;
size_t padding_spaces =
@@ -33,7 +36,20 @@ LIBC_INLINE int convert_char(Writer<write_mode> *writer,
RET_IF_RESULT_NEGATIVE(writer->write(' ', padding_spaces));
}
- RET_IF_RESULT_NEGATIVE(writer->write(c));
+ if (to_conv.length_modifier == LengthModifier::l) {
+ wc = static_cast<wchar_t>(to_conv.conv_val_raw);
+ ret = wctomb(mb_str, wc);
+ if (ret <= 0) {
+ return INT_CONVERSION_ERROR;
+ }
+ for (int i = 0; i < ret; ++i) {
+ RET_IF_RESULT_NEGATIVE(writer->write(mb_str[i]));
+ }
+ }
+ else {
+ c = static_cast<char>(to_conv.conv_val_raw);
+ RET_IF_RESULT_NEGATIVE(writer->write(c));
+ }
// If the padding is on the right side, write the spaces last.
if (padding_spaces > 0 &&
diff --git a/libc/test/src/stdio/printf_core/CMakeLists.txt b/libc/test/src/stdio/printf_core/CMakeLists.txt
index ff7ebbc4f5fd0..f075b8bd5ec52 100644
--- a/libc/test/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/test/src/stdio/printf_core/CMakeLists.txt
@@ -35,4 +35,6 @@ add_libc_unittest(
libc.src.stdio.printf_core.converter
libc.src.stdio.printf_core.writer
libc.src.stdio.printf_core.core_structs
+ libc.src.wchar.wctomb
+ libc.hdr.types.wchar_t
)
diff --git a/libc/test/src/stdio/printf_core/converter_test.cpp b/libc/test/src/stdio/printf_core/converter_test.cpp
index 2dae2a22c864c..2f7842fa97168 100644
--- a/libc/test/src/stdio/printf_core/converter_test.cpp
+++ b/libc/test/src/stdio/printf_core/converter_test.cpp
@@ -255,3 +255,54 @@ TEST_F(LlvmLibcPrintfConverterTest, OctConversion) {
ASSERT_STREQ(str, "1234");
ASSERT_EQ(writer.get_chars_written(), size_t{4});
}
+
+TEST_F(LlvmLibcPrintfConverterTest, WideCharConversion) {
+
+ LIBC_NAMESPACE::printf_core::FormatSection section;
+ section.has_conv = true;
+ section.raw_string = "%c";
+ section.conv_name = 'c';
+ section.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::l;
+ section.conv_val_raw = static_cast<wchar_t>(L'S');
+
+ LIBC_NAMESPACE::printf_core::convert(&writer, section);
+
+ wb.buff[wb.buff_cur] = '\0';
+
+ ASSERT_STREQ(str, "S");
+ ASSERT_EQ(writer.get_chars_written(), size_t{1});
+}
+
+TEST_F(LlvmLibcPrintfConverterTest, WideCharConversionLeftJustified) {
+ LIBC_NAMESPACE::printf_core::FormatSection left_justified_conv;
+ left_justified_conv.has_conv = true;
+ left_justified_conv.raw_string = "%-4c";
+ left_justified_conv.conv_name = 'c';
+ left_justified_conv.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::l;
+ left_justified_conv.flags =
+ LIBC_NAMESPACE::printf_core::FormatFlags::LEFT_JUSTIFIED;
+ left_justified_conv.min_width = 4;
+ left_justified_conv.conv_val_raw = static_cast<wchar_t>(L'S');
+
+ LIBC_NAMESPACE::printf_core::convert(&writer, left_justified_conv);
+ wb.buff[wb.buff_cur] = '\0';
+
+ ASSERT_STREQ(str, "S ");
+ ASSERT_EQ(writer.get_chars_written(), size_t{4});
+}
+
+TEST_F(LlvmLibcPrintfConverterTest, WideCharConversionRightJustified) {
+ LIBC_NAMESPACE::printf_core::FormatSection right_justified_conv;
+ right_justified_conv.has_conv = true;
+ right_justified_conv.raw_string = "%4c";
+ right_justified_conv.conv_name = 'c';
+ right_justified_conv.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::l;
+ right_justified_conv.min_width = 4;
+ right_justified_conv.conv_val_raw = static_cast<wchar_t>(L'S');
+
+ LIBC_NAMESPACE::printf_core::convert(&writer, right_justified_conv);
+ wb.buff[wb.buff_cur] = '\0';
+
+ ASSERT_STREQ(str, " S");
+ ASSERT_EQ(writer.get_chars_written(), size_t{4});
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/169301
More information about the libc-commits
mailing list