diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt index b8d09c9bb8a8b..ba3e41ce3e5a8 100644 --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt @@ -86,6 +86,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.errno.errno # stdio.h entrypoints + libc.src.stdio.feof + libc.src.stdio.ferror + libc.src.stdio.clearerr libc.src.stdio.puts libc.src.stdio.fopen libc.src.stdio.fclose @@ -95,6 +98,10 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdio.fputc libc.src.stdio.putc libc.src.stdio.putchar + libc.src.stdio.fgets + libc.src.stdio.fgetc + libc.src.stdio.getc + libc.src.stdio.getchar libc.src.stdio.stdin libc.src.stdio.stdout libc.src.stdio.stderr diff --git a/libc/docs/gpu/support.rst b/libc/docs/gpu/support.rst index 6d73addb28d05..a19fca59270af 100644 --- a/libc/docs/gpu/support.rst +++ b/libc/docs/gpu/support.rst @@ -126,6 +126,13 @@ stdio.h ============= ========= ============ Function Name Available RPC Required ============= ========= ============ +feof |check| |check| +ferror |check| |check| +clearerr |check| |check| +fgetc |check| |check| +fgets |check| |check| +getc |check| |check| +getchar |check| |check| puts |check| |check| fputs |check| |check| fputc |check| |check| diff --git a/libc/include/llvm-libc-types/rpc_opcodes_t.h b/libc/include/llvm-libc-types/rpc_opcodes_t.h index 3916c0ad95389..2c1c89779568a 100644 --- a/libc/include/llvm-libc-types/rpc_opcodes_t.h +++ b/libc/include/llvm-libc-types/rpc_opcodes_t.h @@ -23,6 +23,9 @@ typedef enum : unsigned short { RPC_FREE = 10, RPC_HOST_CALL = 11, RPC_ABORT = 12, + RPC_FEOF = 13, + RPC_FERROR = 14, + RPC_CLEARERR = 15, } rpc_opcode_t; #endif // __LLVM_LIBC_TYPES_RPC_OPCODE_H__ diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt index de28b5c02071b..db1129cfd7e90 100644 --- a/libc/src/stdio/CMakeLists.txt +++ b/libc/src/stdio/CMakeLists.txt @@ -29,169 +29,6 @@ endif() add_subdirectory(printf_core) add_subdirectory(scanf_core) -add_entrypoint_object( - clearerr - SRCS - clearerr.cpp - HDRS - clearerr.h - DEPENDS - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - clearerr_unlocked - SRCS - clearerr_unlocked.cpp - HDRS - clearerr_unlocked.h - DEPENDS - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - feof - SRCS - feof.cpp - HDRS - feof.h - DEPENDS - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - feof_unlocked - SRCS - feof_unlocked.cpp - HDRS - feof_unlocked.h - DEPENDS - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - ferror - SRCS - ferror.cpp - HDRS - ferror.h - DEPENDS - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - ferror_unlocked - SRCS - ferror_unlocked.cpp - HDRS - ferror_unlocked.h - DEPENDS - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - fgetc - SRCS - fgetc.cpp - HDRS - fgetc.h - DEPENDS - libc.src.errno.errno - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - fgetc_unlocked - SRCS - fgetc_unlocked.cpp - HDRS - fgetc_unlocked.h - DEPENDS - libc.src.errno.errno - 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.src.errno.errno - 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.src.errno.errno - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - getchar - SRCS - getchar.cpp - HDRS - getchar.h - DEPENDS - libc.src.errno.errno - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - getchar_unlocked - SRCS - getc_unlocked.cpp - HDRS - getc_unlocked.h - DEPENDS - libc.src.errno.errno - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - -add_entrypoint_object( - fgets - SRCS - fgets.cpp - HDRS - fgets.h - DEPENDS - libc.src.errno.errno - libc.include.stdio - libc.src.__support.File.file - libc.src.__support.File.platform_file -) - add_entrypoint_object( fflush SRCS @@ -470,6 +307,9 @@ add_entrypoint_object( ) # These entrypoints have multiple potential implementations. +add_stdio_entrypoint_object(feof) +add_stdio_entrypoint_object(ferror) +add_stdio_entrypoint_object(clearerr) add_stdio_entrypoint_object(fopen) add_stdio_entrypoint_object(fclose) add_stdio_entrypoint_object(fread_unlocked) @@ -481,6 +321,13 @@ add_stdio_entrypoint_object(fwrite) add_stdio_entrypoint_object(fputc) add_stdio_entrypoint_object(putc) add_stdio_entrypoint_object(putchar) +add_stdio_entrypoint_object(fgetc) +add_stdio_entrypoint_object(fgetc_unlocked) +add_stdio_entrypoint_object(getc) +add_stdio_entrypoint_object(getc_unlocked) +add_stdio_entrypoint_object(getchar) +add_stdio_entrypoint_object(getchar_unlocked) +add_stdio_entrypoint_object(fgets) add_stdio_entrypoint_object(stdin) add_stdio_entrypoint_object(stdout) add_stdio_entrypoint_object(stderr) diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt index e40e2cc9e04d3..b7a9b9b5747e2 100644 --- a/libc/src/stdio/generic/CMakeLists.txt +++ b/libc/src/stdio/generic/CMakeLists.txt @@ -1,3 +1,75 @@ +add_entrypoint_object( + clearerr + SRCS + clearerr.cpp + HDRS + ../clearerr.h + DEPENDS + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + clearerr_unlocked + SRCS + clearerr_unlocked.cpp + HDRS + ../clearerr_unlocked.h + DEPENDS + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + feof + SRCS + feof.cpp + HDRS + ../feof.h + DEPENDS + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + feof_unlocked + SRCS + feof_unlocked.cpp + HDRS + ../feof_unlocked.h + DEPENDS + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + ferror + SRCS + ferror.cpp + HDRS + ../ferror.h + DEPENDS + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + ferror_unlocked + SRCS + ferror_unlocked.cpp + HDRS + ../ferror_unlocked.h + DEPENDS + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + add_entrypoint_object( fopen SRCS @@ -140,6 +212,97 @@ add_entrypoint_object( libc.src.__support.File.platform_file ) +add_entrypoint_object( + fgetc + SRCS + fgetc.cpp + HDRS + ../fgetc.h + DEPENDS + libc.src.errno.errno + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + fgetc_unlocked + SRCS + fgetc_unlocked.cpp + HDRS + ../fgetc_unlocked.h + DEPENDS + libc.src.errno.errno + 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.src.errno.errno + 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.src.errno.errno + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + getchar + SRCS + getchar.cpp + HDRS + ../getchar.h + DEPENDS + libc.src.errno.errno + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + getchar_unlocked + SRCS + getc_unlocked.cpp + HDRS + ../getc_unlocked.h + DEPENDS + libc.src.errno.errno + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + fgets + SRCS + fgets.cpp + HDRS + ../fgets.h + DEPENDS + libc.src.errno.errno + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + add_entrypoint_object( stdin SRCS diff --git a/libc/src/stdio/clearerr.cpp b/libc/src/stdio/generic/clearerr.cpp similarity index 100% rename from libc/src/stdio/clearerr.cpp rename to libc/src/stdio/generic/clearerr.cpp diff --git a/libc/src/stdio/clearerr_unlocked.cpp b/libc/src/stdio/generic/clearerr_unlocked.cpp similarity index 100% rename from libc/src/stdio/clearerr_unlocked.cpp rename to libc/src/stdio/generic/clearerr_unlocked.cpp diff --git a/libc/src/stdio/feof.cpp b/libc/src/stdio/generic/feof.cpp similarity index 100% rename from libc/src/stdio/feof.cpp rename to libc/src/stdio/generic/feof.cpp diff --git a/libc/src/stdio/feof_unlocked.cpp b/libc/src/stdio/generic/feof_unlocked.cpp similarity index 100% rename from libc/src/stdio/feof_unlocked.cpp rename to libc/src/stdio/generic/feof_unlocked.cpp diff --git a/libc/src/stdio/ferror.cpp b/libc/src/stdio/generic/ferror.cpp similarity index 100% rename from libc/src/stdio/ferror.cpp rename to libc/src/stdio/generic/ferror.cpp diff --git a/libc/src/stdio/ferror_unlocked.cpp b/libc/src/stdio/generic/ferror_unlocked.cpp similarity index 100% rename from libc/src/stdio/ferror_unlocked.cpp rename to libc/src/stdio/generic/ferror_unlocked.cpp diff --git a/libc/src/stdio/fgetc.cpp b/libc/src/stdio/generic/fgetc.cpp similarity index 100% rename from libc/src/stdio/fgetc.cpp rename to libc/src/stdio/generic/fgetc.cpp diff --git a/libc/src/stdio/fgetc_unlocked.cpp b/libc/src/stdio/generic/fgetc_unlocked.cpp similarity index 100% rename from libc/src/stdio/fgetc_unlocked.cpp rename to libc/src/stdio/generic/fgetc_unlocked.cpp diff --git a/libc/src/stdio/fgets.cpp b/libc/src/stdio/generic/fgets.cpp similarity index 100% rename from libc/src/stdio/fgets.cpp rename to libc/src/stdio/generic/fgets.cpp diff --git a/libc/src/stdio/getc.cpp b/libc/src/stdio/generic/getc.cpp similarity index 100% rename from libc/src/stdio/getc.cpp rename to libc/src/stdio/generic/getc.cpp diff --git a/libc/src/stdio/getc_unlocked.cpp b/libc/src/stdio/generic/getc_unlocked.cpp similarity index 100% rename from libc/src/stdio/getc_unlocked.cpp rename to libc/src/stdio/generic/getc_unlocked.cpp diff --git a/libc/src/stdio/getchar.cpp b/libc/src/stdio/generic/getchar.cpp similarity index 100% rename from libc/src/stdio/getchar.cpp rename to libc/src/stdio/generic/getchar.cpp diff --git a/libc/src/stdio/getchar_unlocked.cpp b/libc/src/stdio/generic/getchar_unlocked.cpp similarity index 100% rename from libc/src/stdio/getchar_unlocked.cpp rename to libc/src/stdio/generic/getchar_unlocked.cpp diff --git a/libc/src/stdio/gpu/CMakeLists.txt b/libc/src/stdio/gpu/CMakeLists.txt index d35b1925c6a47..c47176621144e 100644 --- a/libc/src/stdio/gpu/CMakeLists.txt +++ b/libc/src/stdio/gpu/CMakeLists.txt @@ -3,12 +3,46 @@ add_header_library( HDRS file.h DEPENDS + libc.src.__support.RPC.rpc_client libc.src.__support.common .stdin .stdout .stderr ) +add_entrypoint_object( + feof + SRCS + feof.cpp + HDRS + ../feof.h + DEPENDS + libc.include.stdio + libc.src.__support.RPC.rpc_client +) + +add_entrypoint_object( + ferror + SRCS + ferror.cpp + HDRS + ../ferror.h + DEPENDS + libc.include.stdio + libc.src.__support.RPC.rpc_client +) + +add_entrypoint_object( + clearerr + SRCS + clearerr.cpp + HDRS + ../clearerr.h + DEPENDS + libc.include.stdio + libc.src.__support.RPC.rpc_client +) + add_entrypoint_object( fopen SRCS @@ -105,6 +139,85 @@ add_entrypoint_object( .gpu_file ) +add_entrypoint_object( + fgetc + SRCS + fgetc.cpp + HDRS + ../fgetc.h + DEPENDS + libc.include.stdio + .gpu_file +) + +add_entrypoint_object( + fgetc_unlocked + SRCS + fgetc_unlocked.cpp + HDRS + ../fgetc_unlocked.h + DEPENDS + libc.include.stdio + .gpu_file +) + +add_entrypoint_object( + getc + SRCS + getc.cpp + HDRS + ../getc.h + DEPENDS + libc.include.stdio + .gpu_file +) + +add_entrypoint_object( + getc_unlocked + SRCS + getc_unlocked.cpp + HDRS + ../getc_unlocked.h + DEPENDS + libc.include.stdio + .gpu_file +) + +add_entrypoint_object( + getchar + SRCS + getchar.cpp + HDRS + ../getchar.h + DEPENDS + libc.include.stdio + .gpu_file +) + +add_entrypoint_object( + getchar_unlocked + SRCS + getc_unlocked.cpp + HDRS + ../getc_unlocked.h + DEPENDS + libc.include.stdio + .gpu_file +) + +add_entrypoint_object( + fgets + SRCS + fgets.cpp + HDRS + ../fgets.h + DEPENDS + libc.include.stdio + .gpu_file + .feof + .ferror +) + add_entrypoint_object( stdin SRCS diff --git a/libc/src/stdio/gpu/clearerr.cpp b/libc/src/stdio/gpu/clearerr.cpp new file mode 100644 index 0000000000000..dc7a3729aa789 --- /dev/null +++ b/libc/src/stdio/gpu/clearerr.cpp @@ -0,0 +1,24 @@ +//===-- Implementation of clearerr ----------------------------------------===// +// +// 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/clearerr.h" +#include "file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(void, clearerr, (::FILE * stream)) { + rpc::Client::Port port = rpc::client.open(); + port.send_and_recv( + [=](rpc::Buffer *buffer) { buffer->data[0] = file::from_stream(stream); }, + [&](rpc::Buffer *) {}); + port.close(); +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/feof.cpp b/libc/src/stdio/gpu/feof.cpp new file mode 100644 index 0000000000000..27d27a445812c --- /dev/null +++ b/libc/src/stdio/gpu/feof.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of feof --------------------------------------------===// +// +// 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/feof.h" +#include "file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, feof, (::FILE * stream)) { + int ret; + rpc::Client::Port port = rpc::client.open(); + port.send_and_recv( + [=](rpc::Buffer *buffer) { buffer->data[0] = file::from_stream(stream); }, + [&](rpc::Buffer *buffer) { ret = static_cast(buffer->data[0]); }); + port.close(); + return ret; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/ferror.cpp b/libc/src/stdio/gpu/ferror.cpp new file mode 100644 index 0000000000000..e4bd631f392d4 --- /dev/null +++ b/libc/src/stdio/gpu/ferror.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of ferror ------------------------------------------===// +// +// 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/ferror.h" +#include "file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, ferror, (::FILE * stream)) { + int ret; + rpc::Client::Port port = rpc::client.open(); + port.send_and_recv( + [=](rpc::Buffer *buffer) { buffer->data[0] = file::from_stream(stream); }, + [&](rpc::Buffer *buffer) { ret = static_cast(buffer->data[0]); }); + port.close(); + return ret; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/fgetc.cpp b/libc/src/stdio/gpu/fgetc.cpp new file mode 100644 index 0000000000000..ff4ef27ccb88e --- /dev/null +++ b/libc/src/stdio/gpu/fgetc.cpp @@ -0,0 +1,25 @@ +//===-- GPU implementation of 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/fgetc.h" +#include "file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, fgetc, (::FILE * stream)) { + unsigned char c; + size_t r = file::read(stream, &c, 1); + + if (r != 1) + return EOF; + return c; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/fgets.cpp b/libc/src/stdio/gpu/fgets.cpp new file mode 100644 index 0000000000000..df00451e2a970 --- /dev/null +++ b/libc/src/stdio/gpu/fgets.cpp @@ -0,0 +1,46 @@ +//===-- GPU implementation of fgets ---------------------------------------===// +// +// 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/fgets.h" +#include "file.h" +#include "src/stdio/feof.h" +#include "src/stdio/ferror.h" + +#include +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(char *, fgets, + (char *__restrict str, int count, + ::FILE *__restrict stream)) { + if (count < 1) + return nullptr; + + // This implementation is very slow as it makes multiple RPC calls. + unsigned char c = '\0'; + int i = 0; + for (; i < count - 1 && c != '\n'; ++i) { + auto r = file::read(stream, &c, 1); + if (r != 1) + break; + + str[i] = c; + } + + bool has_error = __llvm_libc::ferror(stream); + bool has_eof = __llvm_libc::feof(stream); + + if (has_error || (i == 0 && has_eof)) + return nullptr; + + str[i] = '\0'; + return str; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/file.h b/libc/src/stdio/gpu/file.h index 77817e070680e..42395a6d4287c 100644 --- a/libc/src/stdio/gpu/file.h +++ b/libc/src/stdio/gpu/file.h @@ -65,5 +65,38 @@ LIBC_INLINE uint64_t read(::FILE *f, void *data, size_t size) { return read_from_stream(f, data, size); } +enum Stream { + File = 0, + Stdin = 1, + Stdout = 2, + Stderr = 3, +}; + +// When copying between the client and server we need to indicate if this is one +// of the special streams. We do this by enocding the low order bits of the +// pointer to indicate if we need to use the host's standard stream. +LIBC_INLINE uintptr_t from_stream(::FILE *f) { + if (f == stdin) + return reinterpret_cast(f) | Stdin; + if (f == stdout) + return reinterpret_cast(f) | Stdout; + if (f == stderr) + return reinterpret_cast(f) | Stderr; + return reinterpret_cast(f); +} + +// Get the associated stream out of an encoded number. +LIBC_INLINE ::FILE *to_stream(uintptr_t f) { + ::FILE *stream = reinterpret_cast(f & ~0x3ull); + Stream type = static_cast(f & 0x3ull); + if (type == Stdin) + return stdin; + if (type == Stdout) + return stdout; + if (type == Stderr) + return stderr; + return stream; +} + } // namespace file } // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/getc.cpp b/libc/src/stdio/gpu/getc.cpp new file mode 100644 index 0000000000000..a2272221d6b7b --- /dev/null +++ b/libc/src/stdio/gpu/getc.cpp @@ -0,0 +1,25 @@ +//===-- GPU 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 "file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, getc, (::FILE * stream)) { + unsigned char c; + size_t r = file::read(stream, &c, 1); + + if (r != 1) + return EOF; + return c; +} + +} // namespace __llvm_libc diff --git a/libc/src/stdio/gpu/getchar.cpp b/libc/src/stdio/gpu/getchar.cpp new file mode 100644 index 0000000000000..a7a6e6c55c13e --- /dev/null +++ b/libc/src/stdio/gpu/getchar.cpp @@ -0,0 +1,25 @@ +//===-- GPU implementation of getchar -------------------------------------===// +// +// 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/getchar.h" +#include "file.h" + +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, getchar, ()) { + unsigned char c; + size_t r = file::read(stdin, &c, 1); + + if (r != 1) + return EOF; + return c; +} + +} // namespace __llvm_libc diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt index 6090dc1f46c87..e042a8bd8be68 100644 --- a/libc/test/src/stdio/CMakeLists.txt +++ b/libc/test/src/stdio/CMakeLists.txt @@ -298,7 +298,7 @@ add_libc_test( libc.src.stdio.fopen ) -add_libc_unittest( +add_libc_test( putc_test SUITE libc_stdio_unittests @@ -330,7 +330,7 @@ if(${LIBC_TARGET_OS} STREQUAL "linux") ) endif() -add_libc_unittest( +add_libc_test( fgetc_test SUITE libc_stdio_unittests @@ -370,7 +370,7 @@ add_libc_unittest( libc.src.stdio.getc_unlocked ) -add_libc_unittest( +add_libc_test( fgets_test SUITE libc_stdio_unittests diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 22e937f0595c6..c98b9fa46ce05 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -9,6 +9,7 @@ #include "rpc_server.h" #include "src/__support/RPC/rpc.h" +#include "src/stdio/gpu/file.h" #include #include #include @@ -164,6 +165,24 @@ struct Server { }); break; } + case RPC_FEOF: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = feof(file::to_stream(buffer->data[0])); + }); + break; + } + case RPC_FERROR: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = ferror(file::to_stream(buffer->data[0])); + }); + break; + } + case RPC_CLEARERR: { + port->recv_and_send([](rpc::Buffer *buffer) { + clearerr(file::to_stream(buffer->data[0])); + }); + break; + } case RPC_NOOP: { port->recv([](rpc::Buffer *) {}); break;