Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2022-11-06 09:25:15 +0300
committerSiva Chandra Reddy <sivachandra@google.com>2022-11-08 00:47:29 +0300
commit6a6101958a9ef3dd076f3c65b5d7b200314c0a8c (patch)
tree47e897d2d133c10447a79cb61fa00158aae22bf7 /libc
parent4fa00ce15c842aa8be495759723e2e2450591380 (diff)
[libc] Add implementation of getc, getc_unlocked and fgetc_unlocked.
Reviewed By: michaelrj Differential Revision: https://reviews.llvm.org/D137507
Diffstat (limited to 'libc')
-rw-r--r--libc/config/linux/x86_64/entrypoints.txt3
-rw-r--r--libc/spec/gnu_ext.td5
-rw-r--r--libc/spec/posix.td5
-rw-r--r--libc/spec/stdc.td5
-rw-r--r--libc/src/stdio/CMakeLists.txt36
-rw-r--r--libc/src/stdio/fgetc_unlocked.cpp25
-rw-r--r--libc/src/stdio/fgetc_unlocked.h20
-rw-r--r--libc/src/stdio/getc.cpp24
-rw-r--r--libc/src/stdio/getc.h20
-rw-r--r--libc/src/stdio/getc_unlocked.cpp25
-rw-r--r--libc/src/stdio/getc_unlocked.h20
-rw-r--r--libc/test/src/stdio/CMakeLists.txt23
-rw-r--r--libc/test/src/stdio/fgetc_test.cpp66
-rw-r--r--libc/test/src/stdio/fgetc_unlocked_test.cpp67
14 files changed, 317 insertions, 27 deletions
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 8349af0e54e2..2544ff2a5e40 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -376,6 +376,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdio.ferror
libc.src.stdio.ferror_unlocked
libc.src.stdio.fgetc
+ libc.src.stdio.fgetc_unlocked
libc.src.stdio.fgets
libc.src.stdio.fflush
libc.src.stdio.fopen
@@ -390,6 +391,8 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdio.fwrite
libc.src.stdio.fwrite_unlocked
libc.src.stdio.fprintf
+ libc.src.stdio.getc
+ libc.src.stdio.getc_unlocked
libc.src.stdio.printf
libc.src.stdio.putc
libc.src.stdio.putchar
diff --git a/libc/spec/gnu_ext.td b/libc/spec/gnu_ext.td
index ebadbb6f12c4..239790bb9bdc 100644
--- a/libc/spec/gnu_ext.td
+++ b/libc/spec/gnu_ext.td
@@ -137,6 +137,11 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
ArgSpec<SizeTType>,
ArgSpec<FILERestrictedPtr>]
>,
+ FunctionSpec<
+ "fgetc_unlocked",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
]
>;
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 43b3319059c9..0333c6e47c4d 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -1011,6 +1011,11 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<VoidType>,
[ArgSpec<FILEPtr>]
>,
+ FunctionSpec<
+ "getc_unlocked",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
]
>;
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index bb3f9a1c701b..4d1295313e5a 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -569,6 +569,11 @@ def StdC : StandardSpec<"stdc"> {
[ArgSpec<FILEPtr>]
>,
FunctionSpec<
+ "getc",
+ RetValSpec<IntType>,
+ [ArgSpec<FILEPtr>]
+ >,
+ FunctionSpec<
"putc",
RetValSpec<IntType>,
[ArgSpec<IntType>,
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index f62b09599747..d4b39767473e 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -114,6 +114,42 @@ add_entrypoint_object(
)
add_entrypoint_object(
+ fgetc_unlocked
+ SRCS
+ fgetc_unlocked.cpp
+ HDRS
+ fgetc_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ getc
+ SRCS
+ getc.cpp
+ HDRS
+ getc.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
+ getc_unlocked
+ SRCS
+ getc_unlocked.cpp
+ HDRS
+ getc_unlocked.h
+ DEPENDS
+ libc.include.stdio
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+)
+
+add_entrypoint_object(
fgets
SRCS
fgets.cpp
diff --git a/libc/src/stdio/fgetc_unlocked.cpp b/libc/src/stdio/fgetc_unlocked.cpp
new file mode 100644
index 000000000000..d61493b5bba1
--- /dev/null
+++ b/libc/src/stdio/fgetc_unlocked.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of fgetc_unlocked ----------------------------------===//
+//
+// 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/fgetc_unlocked.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fgetc_unlocked, (::FILE * stream)) {
+ unsigned char c;
+ size_t r =
+ reinterpret_cast<__llvm_libc::File *>(stream)->read_unlocked(&c, 1);
+ if (r != 1)
+ return EOF;
+ return c;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/fgetc_unlocked.h b/libc/src/stdio/fgetc_unlocked.h
new file mode 100644
index 000000000000..e374a6d0f6ce
--- /dev/null
+++ b/libc/src/stdio/fgetc_unlocked.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of fgetc_unlocked -----------------*- 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_FGETC_UNLOCKED_H
+#define LLVM_LIBC_SRC_STDIO_FGETC_UNLOCKED_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+int fgetc_unlocked(::FILE *f);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_FGETC_UNLOCKED_H
diff --git a/libc/src/stdio/getc.cpp b/libc/src/stdio/getc.cpp
new file mode 100644
index 000000000000..406e83f2b362
--- /dev/null
+++ b/libc/src/stdio/getc.cpp
@@ -0,0 +1,24 @@
+//===-- Implementation of getc --------------------------------------------===//
+//
+// 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/getc.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, getc, (::FILE * stream)) {
+ unsigned char c;
+ size_t r = reinterpret_cast<__llvm_libc::File *>(stream)->read(&c, 1);
+ if (r != 1)
+ return EOF;
+ return c;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/getc.h b/libc/src/stdio/getc.h
new file mode 100644
index 000000000000..b5de6a758580
--- /dev/null
+++ b/libc/src/stdio/getc.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of getc ---------------------------*- 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_GETC_H
+#define LLVM_LIBC_SRC_STDIO_GETC_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+int getc(::FILE *f);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_GETC_H
diff --git a/libc/src/stdio/getc_unlocked.cpp b/libc/src/stdio/getc_unlocked.cpp
new file mode 100644
index 000000000000..48adba5ff411
--- /dev/null
+++ b/libc/src/stdio/getc_unlocked.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of getc_unlocked ----------------------------------===//
+//
+// 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/getc_unlocked.h"
+#include "src/__support/File/file.h"
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, getc_unlocked, (::FILE * stream)) {
+ unsigned char c;
+ size_t r =
+ reinterpret_cast<__llvm_libc::File *>(stream)->read_unlocked(&c, 1);
+ if (r != 1)
+ return EOF;
+ return c;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/stdio/getc_unlocked.h b/libc/src/stdio/getc_unlocked.h
new file mode 100644
index 000000000000..b318dfc934e9
--- /dev/null
+++ b/libc/src/stdio/getc_unlocked.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of getc_unlocked ------------------*- 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_GETC_UNLOCKED_H
+#define LLVM_LIBC_SRC_STDIO_GETC_UNLOCKED_H
+
+#include <stdio.h>
+
+namespace __llvm_libc {
+
+int getc_unlocked(::FILE *f);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_GETC_UNLOCKED_H
diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index 7c76c1990a68..f27d7bba1c56 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -216,6 +216,29 @@ add_libc_unittest(
libc.src.stdio.fgetc
libc.src.stdio.fopen
libc.src.stdio.fwrite
+ libc.src.stdio.getc
+)
+
+add_libc_unittest(
+ fgetc_unlocked_test
+ SUITE
+ libc_stdio_unittests
+ SRCS
+ fgetc_unlocked_test.cpp
+ DEPENDS
+ libc.include.errno
+ libc.include.stdio
+ libc.src.stdio.fclose
+ libc.src.stdio.ferror
+ libc.src.stdio.ferror_unlocked
+ libc.src.stdio.feof
+ libc.src.stdio.feof_unlocked
+ libc.src.stdio.fgetc_unlocked
+ libc.src.stdio.flockfile
+ libc.src.stdio.fopen
+ libc.src.stdio.funlockfile
+ libc.src.stdio.fwrite
+ libc.src.stdio.getc_unlocked
)
add_libc_unittest(
diff --git a/libc/test/src/stdio/fgetc_test.cpp b/libc/test/src/stdio/fgetc_test.cpp
index 50d1780840de..5be141ecd202 100644
--- a/libc/test/src/stdio/fgetc_test.cpp
+++ b/libc/test/src/stdio/fgetc_test.cpp
@@ -13,38 +13,50 @@
#include "src/stdio/fgetc.h"
#include "src/stdio/fopen.h"
#include "src/stdio/fwrite.h"
+#include "src/stdio/getc.h"
#include "utils/UnitTest/Test.h"
#include <errno.h>
#include <stdio.h>
-TEST(LlvmLibcFGetCTest, WriteAndReadCharacters) {
- constexpr char FILENAME[] = "testdata/fgetc.test";
- ::FILE *file = __llvm_libc::fopen(FILENAME, "w");
- ASSERT_FALSE(file == nullptr);
- constexpr char CONTENT[] = "123456789";
- constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
- ASSERT_EQ(WRITE_SIZE, __llvm_libc::fwrite(CONTENT, 1, WRITE_SIZE, file));
- // This is a write-only file so reads should fail.
- ASSERT_EQ(__llvm_libc::fgetc(file), EOF);
- // This is an error and not a real EOF.
- ASSERT_EQ(__llvm_libc::feof(file), 0);
- ASSERT_NE(__llvm_libc::ferror(file), 0);
- errno = 0;
-
- ASSERT_EQ(0, __llvm_libc::fclose(file));
-
- file = __llvm_libc::fopen(FILENAME, "r");
- ASSERT_FALSE(file == nullptr);
-
- for (size_t i = 0; i < WRITE_SIZE; ++i) {
- int c = __llvm_libc::fgetc(file);
- ASSERT_EQ(c, int('1' + i));
+class LlvmLibcGetcTest : public __llvm_libc::testing::Test {
+public:
+ using GetcFunc = int(FILE *);
+ void test_with_func(GetcFunc *func, const char *filename) {
+ ::FILE *file = __llvm_libc::fopen(filename, "w");
+ ASSERT_FALSE(file == nullptr);
+ constexpr char CONTENT[] = "123456789";
+ constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
+ ASSERT_EQ(WRITE_SIZE, __llvm_libc::fwrite(CONTENT, 1, WRITE_SIZE, file));
+ // This is a write-only file so reads should fail.
+ ASSERT_EQ(func(file), EOF);
+ // This is an error and not a real EOF.
+ ASSERT_EQ(__llvm_libc::feof(file), 0);
+ ASSERT_NE(__llvm_libc::ferror(file), 0);
+ errno = 0;
+
+ ASSERT_EQ(0, __llvm_libc::fclose(file));
+
+ file = __llvm_libc::fopen(filename, "r");
+ ASSERT_FALSE(file == nullptr);
+
+ for (size_t i = 0; i < WRITE_SIZE; ++i) {
+ int c = func(file);
+ ASSERT_EQ(c, int('1' + i));
+ }
+ // Reading more should return EOF but not set error.
+ ASSERT_EQ(func(file), EOF);
+ ASSERT_NE(__llvm_libc::feof(file), 0);
+ ASSERT_EQ(__llvm_libc::ferror(file), 0);
+
+ ASSERT_EQ(0, __llvm_libc::fclose(file));
}
- // Reading more should return EOF but not set error.
- ASSERT_EQ(__llvm_libc::fgetc(file), EOF);
- ASSERT_NE(__llvm_libc::feof(file), 0);
- ASSERT_EQ(__llvm_libc::ferror(file), 0);
+};
+
+TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithFgetc) {
+ test_with_func(&__llvm_libc::fgetc, "testdata/fgetc.test");
+}
- ASSERT_EQ(0, __llvm_libc::fclose(file));
+TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithGetc) {
+ test_with_func(&__llvm_libc::getc, "testdata/getc.test");
}
diff --git a/libc/test/src/stdio/fgetc_unlocked_test.cpp b/libc/test/src/stdio/fgetc_unlocked_test.cpp
new file mode 100644
index 000000000000..2687b2231afd
--- /dev/null
+++ b/libc/test/src/stdio/fgetc_unlocked_test.cpp
@@ -0,0 +1,67 @@
+//===-- Unittests for fgetc -----------------------------------------------===//
+//
+// 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/feof.h"
+#include "src/stdio/feof_unlocked.h"
+#include "src/stdio/ferror.h"
+#include "src/stdio/ferror_unlocked.h"
+#include "src/stdio/fgetc_unlocked.h"
+#include "src/stdio/flockfile.h"
+#include "src/stdio/fopen.h"
+#include "src/stdio/funlockfile.h"
+#include "src/stdio/fwrite.h"
+#include "src/stdio/getc_unlocked.h"
+#include "utils/UnitTest/Test.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+class LlvmLibcGetcTest : public __llvm_libc::testing::Test {
+public:
+ using GetcFunc = int(FILE *);
+ void test_with_func(GetcFunc *func, const char *filename) {
+ ::FILE *file = __llvm_libc::fopen(filename, "w");
+ ASSERT_FALSE(file == nullptr);
+ constexpr char CONTENT[] = "123456789";
+ constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
+ ASSERT_EQ(WRITE_SIZE, __llvm_libc::fwrite(CONTENT, 1, WRITE_SIZE, file));
+ // This is a write-only file so reads should fail.
+ ASSERT_EQ(func(file), EOF);
+ // This is an error and not a real EOF.
+ ASSERT_EQ(__llvm_libc::feof(file), 0);
+ ASSERT_NE(__llvm_libc::ferror(file), 0);
+ errno = 0;
+
+ ASSERT_EQ(0, __llvm_libc::fclose(file));
+
+ file = __llvm_libc::fopen(filename, "r");
+ ASSERT_FALSE(file == nullptr);
+
+ __llvm_libc::flockfile(file);
+ for (size_t i = 0; i < WRITE_SIZE; ++i) {
+ int c = func(file);
+ ASSERT_EQ(c, int('1' + i));
+ }
+ // Reading more should return EOF but not set error.
+ ASSERT_EQ(func(file), EOF);
+ ASSERT_NE(__llvm_libc::feof_unlocked(file), 0);
+ ASSERT_EQ(__llvm_libc::ferror_unlocked(file), 0);
+
+ __llvm_libc::funlockfile(file);
+ ASSERT_EQ(0, __llvm_libc::fclose(file));
+ }
+};
+
+TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithFgetcUnlocked) {
+ test_with_func(&__llvm_libc::fgetc_unlocked, "testdata/fgetc_unlocked.test");
+}
+
+TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithGetcUnlocked) {
+ test_with_func(&__llvm_libc::getc_unlocked, "testdata/getc_unlocked.test");
+}