[libc-commits] [libc] ba7e1cd - [libc] add fprintf and file_writer

Michael Jones via libc-commits libc-commits at lists.llvm.org
Tue May 31 13:59:22 PDT 2022


Author: Michael Jones
Date: 2022-05-31T13:59:19-07:00
New Revision: ba7e1cddda621adb90175e060a3e2ad8bdef35f8

URL: https://github.com/llvm/llvm-project/commit/ba7e1cddda621adb90175e060a3e2ad8bdef35f8
DIFF: https://github.com/llvm/llvm-project/commit/ba7e1cddda621adb90175e060a3e2ad8bdef35f8.diff

LOG: [libc] add fprintf and file_writer

This patch adds the file_writer header, which just provides a wrapper
for File->write, as well as fprintf to use it. There are no unit tests
for file_writer since it's too simple to need them, but fprintf does
have a simple test of writing to a file.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D125939

Added: 
    libc/src/stdio/fprintf.cpp
    libc/src/stdio/fprintf.h
    libc/src/stdio/printf_core/file_writer.h
    libc/test/src/stdio/fprintf_test.cpp

Modified: 
    libc/config/linux/x86_64/entrypoints.txt
    libc/src/stdio/CMakeLists.txt
    libc/src/stdio/printf_core/CMakeLists.txt
    libc/test/src/stdio/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 300d94761f701..28607d615edcb 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -276,6 +276,7 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.stdio.fwrite_unlocked
     libc.src.stdio.sprintf
     libc.src.stdio.snprintf
+    libc.src.stdio.fprintf
     libc.src.stdio.stderr
     libc.src.stdio.stdout
 

diff  --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index f4684c6b371f4..16fb58fb15b88 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -250,3 +250,16 @@ add_entrypoint_object(
     libc.src.stdio.printf_core.string_writer
     libc.src.stdio.printf_core.writer
 )
+
+add_entrypoint_object(
+  fprintf
+  SRCS
+    fprintf.cpp
+  HDRS
+    fprintf.h
+  DEPENDS
+    libc.include.stdio
+    libc.src.stdio.printf_core.printf_main
+    libc.src.stdio.printf_core.file_writer
+    libc.src.stdio.printf_core.writer
+)

diff  --git a/libc/src/stdio/fprintf.cpp b/libc/src/stdio/fprintf.cpp
new file mode 100644
index 0000000000000..21451f5d5f5b0
--- /dev/null
+++ b/libc/src/stdio/fprintf.cpp
@@ -0,0 +1,40 @@
+//===-- Implementation of fprintf -------------------------------*- 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/fprintf.h"
+
+#include "src/__support/arg_list.h"
+#include "src/stdio/ferror.h"
+#include "src/stdio/printf_core/file_writer.h"
+#include "src/stdio/printf_core/printf_main.h"
+#include "src/stdio/printf_core/writer.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fprintf,
+                   (::FILE *__restrict stream, const char *__restrict format,
+                    ...)) {
+  va_list vlist;
+  va_start(vlist, format);
+  internal::ArgList args(vlist); // This holder class allows for easier copying
+                                 // and pointer semantics, as well as handling
+                                 // destruction automatically.
+  va_end(vlist);
+  printf_core::Writer writer(reinterpret_cast<void *>(stream),
+                             printf_core::write_to_file);
+
+  int ret_val = printf_core::printf_main(&writer, format, args);
+  if (__llvm_libc::ferror(stream))
+    return -1;
+  return ret_val;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/stdio/fprintf.h b/libc/src/stdio/fprintf.h
new file mode 100644
index 0000000000000..caac3e88ee4fe
--- /dev/null
+++ b/libc/src/stdio/fprintf.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of fprintf ------------------------*- 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_FPRINTF_H
+#define LLVM_LIBC_SRC_STDIO_FPRINTF_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+int fprintf(::FILE *__restrict stream, const char *__restrict format, ...);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FPRINTF_H

diff  --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt
index 7c9853ee33708..7a1e46907753e 100644
--- a/libc/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/src/stdio/printf_core/CMakeLists.txt
@@ -28,6 +28,14 @@ add_header_library(
     libc.src.string.memory_utils.memcpy_implementation
 )
 
+add_header_library(
+  file_writer
+  HDRS
+    file_writer.h
+  DEPENDS
+    libc.src.__support.File.file
+)
+
 add_object_library(
   writer
   SRCS

diff  --git a/libc/src/stdio/printf_core/file_writer.h b/libc/src/stdio/printf_core/file_writer.h
new file mode 100644
index 0000000000000..10fea82d83098
--- /dev/null
+++ b/libc/src/stdio/printf_core/file_writer.h
@@ -0,0 +1,29 @@
+//===-- FILE Writer class 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_FILE_WRITER_H
+#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FILE_WRITER_H
+
+#include "src/__support/File/file.h"
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace printf_core {
+
+// write_to_file treats raw_pointer as a File and calls its write
+// function.
+void write_to_file(void *raw_pointer, const char *__restrict to_write,
+                   size_t len) {
+  __llvm_libc::File *file = reinterpret_cast<__llvm_libc::File *>(raw_pointer);
+  file->write(to_write, len);
+}
+
+} // namespace printf_core
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FILE_WRITER_H

diff  --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index 331b90f32162b..e0e7357620a7c 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -83,6 +83,20 @@ add_libc_unittest(
     libc.src.stdio.snprintf
 )
 
+add_libc_unittest(
+  fprintf_test
+  SUITE
+    libc_stdio_unittests
+  SRCS
+    fprintf_test.cpp
+  DEPENDS
+    libc.src.stdio.fprintf
+    libc.src.stdio.fclose
+    libc.src.stdio.ferror
+    libc.src.stdio.fopen
+    libc.src.stdio.fread
+)
+
 add_subdirectory(printf_core)
 
 add_subdirectory(testdata)

diff  --git a/libc/test/src/stdio/fprintf_test.cpp b/libc/test/src/stdio/fprintf_test.cpp
new file mode 100644
index 0000000000000..c7bf2cc1525d2
--- /dev/null
+++ b/libc/test/src/stdio/fprintf_test.cpp
@@ -0,0 +1,68 @@
+//===-- Unittests for fprintf ---------------------------------------------===//
+//
+// 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/fclose.h"
+#include "src/stdio/ferror.h"
+#include "src/stdio/fopen.h"
+#include "src/stdio/fread.h"
+
+#include "src/stdio/fprintf.h"
+
+#include "utils/UnitTest/Test.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+TEST(LlvmLibcFPrintfTest, WriteToFile) {
+  constexpr char FILENAME[] = "testdata/fprintf_output.test";
+  ::FILE *file = __llvm_libc::fopen(FILENAME, "w");
+  ASSERT_FALSE(file == nullptr);
+
+  int written;
+
+  constexpr char simple[] = "A simple string with no conversions.\n";
+  written = __llvm_libc::fprintf(file, simple);
+  EXPECT_EQ(written, 37);
+
+  constexpr char numbers[] = "1234567890\n";
+  written = __llvm_libc::fprintf(file, "%s", numbers);
+  EXPECT_EQ(written, 11);
+
+  constexpr char format_more[] = "%s and more\n";
+  constexpr char short_numbers[] = "1234";
+  written = __llvm_libc::fprintf(file, format_more, short_numbers);
+  EXPECT_EQ(written, 14);
+
+  ASSERT_EQ(0, __llvm_libc::fclose(file));
+
+  file = __llvm_libc::fopen(FILENAME, "r");
+  ASSERT_FALSE(file == nullptr);
+
+  char data[50];
+  ASSERT_EQ(__llvm_libc::fread(data, 1, sizeof(simple) - 1, file),
+            sizeof(simple) - 1);
+  data[sizeof(simple) - 1] = '\0';
+  ASSERT_STREQ(data, simple);
+  ASSERT_EQ(__llvm_libc::fread(data, 1, sizeof(numbers) - 1, file),
+            sizeof(numbers) - 1);
+  data[sizeof(numbers) - 1] = '\0';
+  ASSERT_STREQ(data, numbers);
+  ASSERT_EQ(__llvm_libc::fread(
+                data, 1, sizeof(format_more) + sizeof(short_numbers) - 4, file),
+            sizeof(format_more) + sizeof(short_numbers) - 4);
+  data[sizeof(format_more) + sizeof(short_numbers) - 4] = '\0';
+  ASSERT_STREQ(data, "1234 and more\n");
+
+  ASSERT_EQ(__llvm_libc::ferror(file), 0);
+
+  written =
+      __llvm_libc::fprintf(file, "Writing to a read only file should fail.");
+  EXPECT_EQ(written, -1);
+
+  ASSERT_EQ(__llvm_libc::fclose(file), 0);
+}


        


More information about the libc-commits mailing list