[libc-commits] [libc] edf964e - [libc] add scanf pointer conversion
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Wed Jan 25 15:29:32 PST 2023
Author: Michael Jones
Date: 2023-01-25T15:29:25-08:00
New Revision: edf964e0ddfb98cf4ac849fa87bcc58a4d86a89e
URL: https://github.com/llvm/llvm-project/commit/edf964e0ddfb98cf4ac849fa87bcc58a4d86a89e
DIFF: https://github.com/llvm/llvm-project/commit/edf964e0ddfb98cf4ac849fa87bcc58a4d86a89e.diff
LOG: [libc] add scanf pointer conversion
This patch adds the last conversion for scanf, %p. It is set up to match
the %p implementation in our printf.
Reviewed By: sivachandra, lntue
Differential Revision: https://reviews.llvm.org/D142510
Added:
libc/src/stdio/scanf_core/ptr_converter.cpp
libc/src/stdio/scanf_core/ptr_converter.h
Modified:
libc/src/stdio/scanf_core/CMakeLists.txt
libc/src/stdio/scanf_core/converter.cpp
libc/src/stdio/scanf_core/converter_utils.h
libc/src/stdio/scanf_core/int_converter.cpp
libc/test/src/stdio/sscanf_test.cpp
Removed:
################################################################################
diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt
index d0eaa1a44012e..9f6cb9c386eb2 100644
--- a/libc/src/stdio/scanf_core/CMakeLists.txt
+++ b/libc/src/stdio/scanf_core/CMakeLists.txt
@@ -80,6 +80,7 @@ add_object_library(
string_converter.cpp
int_converter.cpp
float_converter.cpp
+ ptr_converter.cpp
HDRS
converter.h
converter_utils.h
@@ -87,6 +88,7 @@ add_object_library(
string_converter.h
float_converter.h
current_pos_converter.h
+ ptr_converter.h
DEPENDS
.reader
.core_structs
diff --git a/libc/src/stdio/scanf_core/converter.cpp b/libc/src/stdio/scanf_core/converter.cpp
index 053e215b4d983..994a160e764d8 100644
--- a/libc/src/stdio/scanf_core/converter.cpp
+++ b/libc/src/stdio/scanf_core/converter.cpp
@@ -17,6 +17,7 @@
#endif // LLVM_LIBC_SCANF_DISABLE_FLOAT
#include "src/stdio/scanf_core/current_pos_converter.h"
#include "src/stdio/scanf_core/int_converter.h"
+#include "src/stdio/scanf_core/ptr_converter.h"
#include "src/stdio/scanf_core/string_converter.h"
#include <stddef.h>
@@ -63,11 +64,11 @@ int convert(Reader *reader, const FormatSection &to_conv) {
#endif // LLVM_LIBC_SCANF_DISABLE_FLOAT
case 'n':
return convert_current_pos(reader, to_conv);
- // case 'p':
- // ret_val = raw_match(reader, " ");
- // if (ret_val != READ_OK)
- // return ret_val;
- // return convert_pointer(reader, to_conv);
+ case 'p':
+ ret_val = raw_match(reader, " ");
+ if (ret_val != READ_OK)
+ return ret_val;
+ return convert_pointer(reader, to_conv);
default:
return raw_match(reader, to_conv.raw_string);
}
diff --git a/libc/src/stdio/scanf_core/converter_utils.h b/libc/src/stdio/scanf_core/converter_utils.h
index 07ac9c7407ed3..966725662dd1d 100644
--- a/libc/src/stdio/scanf_core/converter_utils.h
+++ b/libc/src/stdio/scanf_core/converter_utils.h
@@ -35,8 +35,14 @@ LIBC_INLINE void write_int_with_length(uintmax_t output_val,
if ((to_conv.flags & NO_WRITE) != 0) {
return;
}
- LengthModifier lm = to_conv.length_modifier;
void *output_ptr = to_conv.output_ptr;
+ // The %p conversion uses this function, and is always void*.
+ if (to_conv.conv_name == 'p') {
+ *reinterpret_cast<void **>(output_ptr) =
+ reinterpret_cast<void *>(output_val);
+ return;
+ }
+ LengthModifier lm = to_conv.length_modifier;
switch (lm) {
case (LengthModifier::hh):
*reinterpret_cast<unsigned char *>(output_ptr) =
diff --git a/libc/src/stdio/scanf_core/int_converter.cpp b/libc/src/stdio/scanf_core/int_converter.cpp
index ce23f5d3fed8d..6370c98e0f160 100644
--- a/libc/src/stdio/scanf_core/int_converter.cpp
+++ b/libc/src/stdio/scanf_core/int_converter.cpp
@@ -79,7 +79,7 @@ int convert_int(Reader *reader, const FormatSection &to_conv) {
is_signed = true;
} else if (to_conv.conv_name == 'o') {
base = 8;
- } else if (to_lower(to_conv.conv_name) == 'x') {
+ } else if (to_lower(to_conv.conv_name) == 'x' || to_conv.conv_name == 'p') {
base = 16;
} else if (to_conv.conv_name == 'd') {
base = 10;
diff --git a/libc/src/stdio/scanf_core/ptr_converter.cpp b/libc/src/stdio/scanf_core/ptr_converter.cpp
new file mode 100644
index 0000000000000..31d6476a2da1b
--- /dev/null
+++ b/libc/src/stdio/scanf_core/ptr_converter.cpp
@@ -0,0 +1,43 @@
+//===-- Int type specifier converters for scanf -----------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/scanf_core/ptr_converter.h"
+
+#include "src/stdio/scanf_core/converter_utils.h"
+#include "src/stdio/scanf_core/core_structs.h"
+#include "src/stdio/scanf_core/int_converter.h"
+#include "src/stdio/scanf_core/reader.h"
+
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+int convert_pointer(Reader *reader, const FormatSection &to_conv) {
+ static const char nullptr_string[] = "(nullptr)";
+
+ // Check if it's exactly the nullptr string, if so then it's a nullptr.
+ char cur_char = reader->getc();
+ size_t i = 0;
+ for (; i < sizeof(nullptr_string) && to_lower(cur_char) == nullptr_string[i];
+ ++i) {
+ cur_char = reader->getc();
+ }
+ if (i == (sizeof(nullptr_string) - 1)) {
+ *reinterpret_cast<void **>(to_conv.output_ptr) = nullptr;
+ return READ_OK;
+ } else if (i > 0) {
+ return MATCHING_FAILURE;
+ }
+
+ reader->ungetc(cur_char);
+
+ // Else treat it as a hex int
+ return convert_int(reader, to_conv);
+}
+} // namespace scanf_core
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/scanf_core/ptr_converter.h b/libc/src/stdio/scanf_core/ptr_converter.h
new file mode 100644
index 0000000000000..642898c1db18f
--- /dev/null
+++ b/libc/src/stdio/scanf_core/ptr_converter.h
@@ -0,0 +1,25 @@
+//===-- Pointer specifier converter for scanf -------------------*- 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_SCANF_CORE_PTR_CONVERTER_H
+#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_PTR_CONVERTER_H
+
+#include "src/stdio/scanf_core/core_structs.h"
+#include "src/stdio/scanf_core/reader.h"
+
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+
+int convert_pointer(Reader *reader, const FormatSection &to_conv);
+
+} // namespace scanf_core
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_PTR_CONVERTER_H
diff --git a/libc/test/src/stdio/sscanf_test.cpp b/libc/test/src/stdio/sscanf_test.cpp
index 55671279e1b4d..64da77b377784 100644
--- a/libc/test/src/stdio/sscanf_test.cpp
+++ b/libc/test/src/stdio/sscanf_test.cpp
@@ -629,6 +629,45 @@ TEST(LlvmLibcSScanfTest, CurPosCombined) {
EXPECT_EQ(result, 320);
}
+TEST(LlvmLibcSScanfTest, PointerConvCombined) {
+ int ret_val;
+ void *result;
+
+ ret_val = __llvm_libc::sscanf("(nullptr)", "%p", &result);
+ EXPECT_EQ(ret_val, 1);
+ EXPECT_EQ(result, static_cast<void *>(nullptr));
+
+ ret_val = __llvm_libc::sscanf("(NuLlPtR)", "%p", &result);
+ EXPECT_EQ(ret_val, 1);
+ EXPECT_EQ(result, static_cast<void *>(nullptr));
+
+ ret_val = __llvm_libc::sscanf("(NULLPTR)", "%p", &result);
+ EXPECT_EQ(ret_val, 1);
+ EXPECT_EQ(result, static_cast<void *>(nullptr));
+
+ ret_val = __llvm_libc::sscanf("(null)", "%p", &result);
+ EXPECT_EQ(ret_val, 0);
+
+ ret_val = __llvm_libc::sscanf("(nullptr2", "%p", &result);
+ EXPECT_EQ(ret_val, 0);
+
+ ret_val = __llvm_libc::sscanf("0", "%p", &result);
+ EXPECT_EQ(ret_val, 1);
+ EXPECT_EQ(result, reinterpret_cast<void *>(0));
+
+ ret_val = __llvm_libc::sscanf("100", "%p", &result);
+ EXPECT_EQ(ret_val, 1);
+ EXPECT_EQ(result, reinterpret_cast<void *>(0x100));
+
+ ret_val = __llvm_libc::sscanf("-1", "%p", &result);
+ EXPECT_EQ(ret_val, 1);
+ EXPECT_EQ(result, reinterpret_cast<void *>(-1));
+
+ ret_val = __llvm_libc::sscanf("0xabcDEFG", "%p", &result);
+ EXPECT_EQ(ret_val, 1);
+ EXPECT_EQ(result, reinterpret_cast<void *>(0xabcdef));
+}
+
TEST(LlvmLibcSScanfTest, CombinedConv) {
int ret_val;
int result = 0;
More information about the libc-commits
mailing list