[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