diff --git a/libc/src/stdio/printf_core/converter.cpp b/libc/src/stdio/printf_core/converter.cpp --- a/libc/src/stdio/printf_core/converter.cpp +++ b/libc/src/stdio/printf_core/converter.cpp @@ -61,7 +61,7 @@ case 'n': // return convert_write_int(writer, to_conv); case 'p': - // return convert_pointer(writer, to_conv); + return convert_pointer(writer, to_conv); default: return writer->write(to_conv.raw_string, to_conv.raw_len); } diff --git a/libc/src/stdio/printf_core/converter_atlas.h b/libc/src/stdio/printf_core/converter_atlas.h --- a/libc/src/stdio/printf_core/converter_atlas.h +++ b/libc/src/stdio/printf_core/converter_atlas.h @@ -36,5 +36,6 @@ // defines convert_write_int // defines convert_pointer +#include "src/stdio/printf_core/ptr_converter.h" #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_CONVERTER_ATLAS_H diff --git a/libc/src/stdio/printf_core/ptr_converter.h b/libc/src/stdio/printf_core/ptr_converter.h new file mode 100644 --- /dev/null +++ b/libc/src/stdio/printf_core/ptr_converter.h @@ -0,0 +1,39 @@ +//===-- Pointer Converter for printf ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PTR_CONVERTER_H +#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PTR_CONVERTER_H + +#include "src/stdio/printf_core/converter_utils.h" +#include "src/stdio/printf_core/core_structs.h" +#include "src/stdio/printf_core/hex_converter.h" +#include "src/stdio/printf_core/writer.h" + +namespace __llvm_libc { +namespace printf_core { + +int inline convert_pointer(Writer *writer, const FormatSection &to_conv) { + if (to_conv.conv_val_ptr == (void *)(nullptr)) { + const char ZERO_STR[] = "(nullptr)"; + // subtract 1 from sizeof to remove the null byte at the end. + RET_IF_RESULT_NEGATIVE(writer->write(ZERO_STR, sizeof(ZERO_STR) - 1)); + } else { + FormatSection hex_conv; + hex_conv.has_conv = true; + hex_conv.conv_name = 'x'; + hex_conv.flags = FormatFlags::ALTERNATE_FORM; + hex_conv.conv_val_raw = reinterpret_cast(to_conv.conv_val_ptr); + return convert_hex(writer, hex_conv); + } + return 0; +} + +} // namespace printf_core +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PTR_CONVERTER_H diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp --- a/libc/test/src/stdio/sprintf_test.cpp +++ b/libc/test/src/stdio/sprintf_test.cpp @@ -346,6 +346,22 @@ ASSERT_STREQ(buff, "007F 0x1000000000 002 "); } +TEST(LlvmLibcSPrintfTest, PointerConv) { + char buff[64]; + int written; + + written = __llvm_libc::sprintf(buff, "%p", nullptr); + EXPECT_EQ(written, 9); + ASSERT_STREQ(buff, "(nullptr)"); + + written = __llvm_libc::sprintf(buff, "%p", 0x1a2b3c4d); + EXPECT_EQ(written, 10); + ASSERT_STREQ(buff, "0x1a2b3c4d"); + + written = __llvm_libc::sprintf(buff, "%p", buff); + EXPECT_GT(written, 0); +} + #ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE TEST(LlvmLibcSPrintfTest, IndexModeParsing) { char buff[64];