diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt index 90d0a7a9adc6a..637be4f19d5b7 100644 --- a/libc/config/baremetal/aarch64/entrypoints.txt +++ b/libc/config/baremetal/aarch64/entrypoints.txt @@ -124,8 +124,6 @@ set(TARGET_LIBC_ENTRYPOINTS # stdio.h entrypoints libc.src.stdio.asprintf - libc.src.stdio.fopencookie - libc.src.stdio.fprintf libc.src.stdio.getchar libc.src.stdio.printf libc.src.stdio.putchar diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index d838a485b6c89..19aedb0a8677d 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -124,8 +124,6 @@ set(TARGET_LIBC_ENTRYPOINTS # stdio.h entrypoints libc.src.stdio.asprintf - libc.src.stdio.fopencookie - libc.src.stdio.fprintf libc.src.stdio.getchar libc.src.stdio.printf libc.src.stdio.putchar diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index db65d6115cdbb..cfbb598cbe4bf 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -124,8 +124,6 @@ set(TARGET_LIBC_ENTRYPOINTS # stdio.h entrypoints libc.src.stdio.asprintf - libc.src.stdio.fopencookie - libc.src.stdio.fprintf libc.src.stdio.getchar libc.src.stdio.printf libc.src.stdio.putchar diff --git a/libc/src/__support/File/CMakeLists.txt b/libc/src/__support/File/CMakeLists.txt index bcc6cef2163a1..253243ff40ded 100644 --- a/libc/src/__support/File/CMakeLists.txt +++ b/libc/src/__support/File/CMakeLists.txt @@ -22,18 +22,6 @@ add_object_library( libc.src.__support.error_or ) -add_header_library( - cookie_file - HDRS - cookie_file.h - DEPENDS - .file - libc.hdr.errno_macros - libc.hdr.types.cookie_io_functions_t - libc.hdr.types.off_t - libc.src.__support.CPP.new -) - add_object_library( dir SRCS @@ -53,11 +41,7 @@ endif() add_subdirectory(${LIBC_TARGET_OS}) -if(LIBC_TARGET_OS_IS_BAREMETAL) - set(target_file libc.src.__support.File.cookie_file) -else() - set(target_file libc.src.__support.File.${LIBC_TARGET_OS}.file) -endif() +set(target_file libc.src.__support.File.${LIBC_TARGET_OS}.file) set(target_stdout libc.src.__support.File.${LIBC_TARGET_OS}.stdout) set(target_stderr libc.src.__support.File.${LIBC_TARGET_OS}.stderr) set(target_stdin libc.src.__support.File.${LIBC_TARGET_OS}.stdin) diff --git a/libc/src/__support/File/baremetal/CMakeLists.txt b/libc/src/__support/File/baremetal/CMakeLists.txt deleted file mode 100644 index a789948368f02..0000000000000 --- a/libc/src/__support/File/baremetal/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -add_object_library( - stdout - SRCS - stdout.cpp - DEPENDS - libc.hdr.stdio_macros - libc.src.__support.File.cookie_file - libc.src.__support.File.file - libc.src.__support.OSUtil.osutil -) - -add_object_library( - stdin - SRCS - stdin.cpp - DEPENDS - libc.hdr.stdio_macros - libc.src.__support.File.cookie_file - libc.src.__support.File.file - libc.src.__support.OSUtil.osutil -) - -add_object_library( - stderr - SRCS - stderr.cpp - DEPENDS - libc.hdr.stdio_macros - libc.src.__support.File.cookie_file - libc.src.__support.File.file - libc.src.__support.OSUtil.osutil -) diff --git a/libc/src/__support/File/baremetal/stderr.cpp b/libc/src/__support/File/baremetal/stderr.cpp deleted file mode 100644 index 0a67771f034aa..0000000000000 --- a/libc/src/__support/File/baremetal/stderr.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===--- Definition of baremetal stderr -----------------------------------===// -// -// 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 "hdr/stdio_macros.h" -#include "src/__support/File/cookie_file.h" -#include "src/__support/File/file.h" -#include "src/__support/OSUtil/baremetal/io.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -cookie_io_functions_t io_func = {.read = nullptr, - .write = __llvm_libc_stdio_write, - .seek = nullptr, - .close = nullptr}; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wglobal-constructors" -// Buffering is implementation defined. Therefore to save RAM, we use no -// buffering -static CookieFile StdErr(&__llvm_libc_stderr_cookie, io_func, nullptr, 0, - _IONBF, File::mode_flags("w")); -#pragma clang diagnostic pop -File *stderr = &StdErr; - -} // namespace LIBC_NAMESPACE_DECL - -extern "C" { -FILE *stderr = reinterpret_cast(&LIBC_NAMESPACE::StdErr); -} diff --git a/libc/src/__support/File/baremetal/stdin.cpp b/libc/src/__support/File/baremetal/stdin.cpp deleted file mode 100644 index 569d924749eec..0000000000000 --- a/libc/src/__support/File/baremetal/stdin.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===--- Definition of baremetal stdin ------------------------------------===// -// -// 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 "hdr/stdio_macros.h" -#include "src/__support/File/cookie_file.h" -#include "src/__support/File/file.h" -#include "src/__support/OSUtil/baremetal/io.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -cookie_io_functions_t io_func = {.read = __llvm_libc_stdio_read, - .write = nullptr, - .seek = nullptr, - .close = nullptr}; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wglobal-constructors" -// Buffering is implementation defined. Therefore to save RAM, we use no -// buffering -static CookieFile StdIn(&__llvm_libc_stdin_cookie, io_func, nullptr, 0, _IONBF, - File::mode_flags("r")); -#pragma clang diagnostic pop -File *stdin = &StdIn; - -} // namespace LIBC_NAMESPACE_DECL - -extern "C" { -FILE *stdin = reinterpret_cast(&LIBC_NAMESPACE::StdIn); -} diff --git a/libc/src/__support/File/baremetal/stdout.cpp b/libc/src/__support/File/baremetal/stdout.cpp deleted file mode 100644 index ee8535c0d7643..0000000000000 --- a/libc/src/__support/File/baremetal/stdout.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===--- Definition of baremetal stdout -----------------------------------===// -// -// 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 "hdr/stdio_macros.h" -#include "src/__support/File/cookie_file.h" -#include "src/__support/File/file.h" -#include "src/__support/OSUtil/baremetal/io.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -cookie_io_functions_t io_func = {.read = nullptr, - .write = __llvm_libc_stdio_write, - .seek = nullptr, - .close = nullptr}; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wglobal-constructors" -// Buffering is implementation defined. Therefore to save RAM, we use no -// buffering -static CookieFile StdOut(&__llvm_libc_stdout_cookie, io_func, nullptr, 0, - _IONBF, File::mode_flags("w")); -#pragma clang diagnostic pop -File *stdout = &StdOut; - -} // namespace LIBC_NAMESPACE_DECL - -extern "C" { -FILE *stdout = reinterpret_cast(&LIBC_NAMESPACE::StdOut); -} diff --git a/libc/src/__support/File/cookie_file.h b/libc/src/__support/File/cookie_file.h deleted file mode 100644 index 8fc13b047b292..0000000000000 --- a/libc/src/__support/File/cookie_file.h +++ /dev/null @@ -1,80 +0,0 @@ -//===--- A platform independent cookie file class -------------------------===// -// -// 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 "hdr/errno_macros.h" -#include "hdr/types/cookie_io_functions_t.h" -#include "hdr/types/off_t.h" -#include "src/__support/CPP/new.h" -#include "src/__support/File/file.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -class CookieFile : public LIBC_NAMESPACE::File { - void *cookie; - cookie_io_functions_t ops; - - LIBC_INLINE static FileIOResult cookie_write(File *f, const void *data, - size_t size); - LIBC_INLINE static FileIOResult cookie_read(File *f, void *data, size_t size); - LIBC_INLINE static ErrorOr cookie_seek(File *f, off_t offset, - int whence); - LIBC_INLINE static int cookie_close(File *f); - -public: - LIBC_INLINE CookieFile(void *c, cookie_io_functions_t cops, uint8_t *buffer, - size_t bufsize, int buffer_mode, File::ModeFlags mode) - : File(&cookie_write, &cookie_read, &CookieFile::cookie_seek, - &cookie_close, buffer, bufsize, buffer_mode, - true /* File owns buffer */, mode), - cookie(c), ops(cops) {} -}; - -LIBC_INLINE FileIOResult CookieFile::cookie_write(File *f, const void *data, - size_t size) { - auto cookie_file = reinterpret_cast(f); - if (cookie_file->ops.write == nullptr) - return 0; - return static_cast(cookie_file->ops.write( - cookie_file->cookie, reinterpret_cast(data), size)); -} - -LIBC_INLINE FileIOResult CookieFile::cookie_read(File *f, void *data, - size_t size) { - auto cookie_file = reinterpret_cast(f); - if (cookie_file->ops.read == nullptr) - return 0; - return static_cast(cookie_file->ops.read( - cookie_file->cookie, reinterpret_cast(data), size)); -} - -LIBC_INLINE ErrorOr CookieFile::cookie_seek(File *f, off_t offset, - int whence) { - auto cookie_file = reinterpret_cast(f); - if (cookie_file->ops.seek == nullptr) { - return Error(EINVAL); - } - off64_t offset64 = offset; - int result = cookie_file->ops.seek(cookie_file->cookie, &offset64, whence); - if (result == 0) - return offset64; - return -1; -} - -LIBC_INLINE int CookieFile::cookie_close(File *f) { - auto cookie_file = reinterpret_cast(f); - if (cookie_file->ops.close == nullptr) - return 0; - int retval = cookie_file->ops.close(cookie_file->cookie); - if (retval != 0) - return retval; - delete cookie_file; - return 0; -} - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/baremetal/io.cpp b/libc/src/__support/OSUtil/baremetal/io.cpp index 6b475209d421c..2a9ef6bfa6579 100644 --- a/libc/src/__support/OSUtil/baremetal/io.cpp +++ b/libc/src/__support/OSUtil/baremetal/io.cpp @@ -13,6 +13,45 @@ namespace LIBC_NAMESPACE_DECL { +// These are intended to be provided by the vendor. +// +// The signature of these types and functions intentionally match `fopencookie` +// which allows the following: +// +// ``` +// struct __llvm_libc_stdio_cookie { ... }; +// ... +// struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie; +// cookie_io_functions_t stdin_func = { .read = __llvm_libc_stdio_read }; +// FILE *stdin = fopencookie(&__llvm_libc_stdin_cookie, "r", stdin_func); +// ... +// struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie; +// cookie_io_functions_t stdout_func = { .write = __llvm_libc_stdio_write }; +// FILE *stdout = fopencookie(&__llvm_libc_stdout_cookie, "w", stdout_func); +// ... +// struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie; +// cookie_io_functions_t stderr_func = { .write = __llvm_libc_stdio_write }; +// FILE *stderr = fopencookie(&__llvm_libc_stderr_cookie, "w", stderr_func); +// ``` +// +// At the same time, implementation of functions like `printf` and `scanf` can +// use `__llvm_libc_stdio_read` and `__llvm_libc_stdio_write` directly to avoid +// the extra indirection. +// +// All three symbols `__llvm_libc_stdin_cookie`, `__llvm_libc_stdout_cookie`, +// and `__llvm_libc_stderr_cookie` must be provided, even if they don't point +// at anything. + +struct __llvm_libc_stdio_cookie; + +extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie; +extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie; +extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie; + +extern "C" ssize_t __llvm_libc_stdio_read(void *cookie, char *buf, size_t size); +extern "C" ssize_t __llvm_libc_stdio_write(void *cookie, const char *buf, + size_t size); + ssize_t read_from_stdin(char *buf, size_t size) { return __llvm_libc_stdio_read(static_cast(&__llvm_libc_stdin_cookie), buf, size); diff --git a/libc/src/__support/OSUtil/baremetal/io.h b/libc/src/__support/OSUtil/baremetal/io.h index b6c5ffb21c1a8..aed34ec7e62e3 100644 --- a/libc/src/__support/OSUtil/baremetal/io.h +++ b/libc/src/__support/OSUtil/baremetal/io.h @@ -14,46 +14,8 @@ #include "src/__support/CPP/string_view.h" #include "src/__support/macros/config.h" -// These are intended to be provided by the vendor. -// -// The signature of these types and functions intentionally match `fopencookie` -// which allows the following: -// -// ``` -// struct __llvm_libc_stdio_cookie { ... }; -// ... -// struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie; -// cookie_io_functions_t stdin_func = { .read = __llvm_libc_stdio_read }; -// FILE *stdin = fopencookie(&__llvm_libc_stdin_cookie, "r", stdin_func); -// ... -// struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie; -// cookie_io_functions_t stdout_func = { .write = __llvm_libc_stdio_write }; -// FILE *stdout = fopencookie(&__llvm_libc_stdout_cookie, "w", stdout_func); -// ... -// struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie; -// cookie_io_functions_t stderr_func = { .write = __llvm_libc_stdio_write }; -// FILE *stderr = fopencookie(&__llvm_libc_stderr_cookie, "w", stderr_func); -// ``` -// -// At the same time, implementation of functions like `printf` and `scanf` can -// use `__llvm_libc_stdio_read` and `__llvm_libc_stdio_write` directly to avoid -// the extra indirection. -// -// All three symbols `__llvm_libc_stdin_cookie`, `__llvm_libc_stdout_cookie`, -// and `__llvm_libc_stderr_cookie` must be provided, even if they don't point -// at anything. namespace LIBC_NAMESPACE_DECL { -struct __llvm_libc_stdio_cookie; - -extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdin_cookie; -extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie; -extern "C" struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie; - -extern "C" ssize_t __llvm_libc_stdio_read(void *cookie, char *buf, size_t size); -extern "C" ssize_t __llvm_libc_stdio_write(void *cookie, const char *buf, - size_t size); - ssize_t read_from_stdin(char *buf, size_t size); void write_to_stderr(cpp::string_view msg); void write_to_stdout(cpp::string_view msg); diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt index 273619ae2a570..b0a6ef1e291b5 100644 --- a/libc/src/stdio/CMakeLists.txt +++ b/libc/src/stdio/CMakeLists.txt @@ -63,7 +63,6 @@ add_entrypoint_object( libc.hdr.types.cookie_io_functions_t libc.hdr.types.FILE libc.src.__support.CPP.new - libc.src.__support.File.cookie_file libc.src.__support.File.file ) diff --git a/libc/src/stdio/baremetal/CMakeLists.txt b/libc/src/stdio/baremetal/CMakeLists.txt index 65089274050bd..548938f885c94 100644 --- a/libc/src/stdio/baremetal/CMakeLists.txt +++ b/libc/src/stdio/baremetal/CMakeLists.txt @@ -1,3 +1,15 @@ +add_entrypoint_object( + getchar + SRCS + getchar.cpp + HDRS + ../getchar.h + DEPENDS + libc.hdr.stdio_macros + libc.src.__support.OSUtil.osutil + libc.src.__support.CPP.string_view +) + add_entrypoint_object( remove SRCS @@ -7,3 +19,87 @@ add_entrypoint_object( DEPENDS libc.include.stdio ) + +add_entrypoint_object( + printf + SRCS + printf.cpp + HDRS + ../printf.h + DEPENDS + libc.src.stdio.printf_core.printf_main + libc.src.stdio.printf_core.writer + libc.src.__support.arg_list + libc.src.__support.OSUtil.osutil +) + +add_entrypoint_object( + putchar + SRCS + putchar.cpp + HDRS + ../putchar.h + DEPENDS + libc.src.__support.OSUtil.osutil + libc.src.__support.CPP.string_view +) + +add_entrypoint_object( + puts + SRCS + puts.cpp + HDRS + ../puts.h + DEPENDS + libc.src.__support.OSUtil.osutil + libc.src.__support.CPP.string_view +) + +add_header_library( + scanf_internal + HDRS + scanf_internal.h + DEPENDS + libc.src.stdio.scanf_core.reader + libc.src.__support.OSUtil.osutil +) + +add_entrypoint_object( + scanf + SRCS + scanf.cpp + HDRS + ../scanf.h + DEPENDS + .scanf_internal + libc.include.inttypes + libc.src.stdio.scanf_core.scanf_main + libc.src.__support.arg_list + libc.src.__support.OSUtil.osutil +) + +add_entrypoint_object( + vprintf + SRCS + vprintf.cpp + HDRS + ../vprintf.h + DEPENDS + libc.src.stdio.printf_core.printf_main + libc.src.stdio.printf_core.writer + libc.src.__support.arg_list + libc.src.__support.OSUtil.osutil +) + +add_entrypoint_object( + vscanf + SRCS + vscanf.cpp + HDRS + ../vscanf.h + DEPENDS + .scanf_internal + libc.src.stdio.scanf_core.scanf_main + libc.src.__support.arg_list + libc.src.__support.OSUtil.osutil +) diff --git a/libc/src/stdio/baremetal/printf.cpp b/libc/src/stdio/baremetal/printf.cpp new file mode 100644 index 0000000000000..7253c6549a4e4 --- /dev/null +++ b/libc/src/stdio/baremetal/printf.cpp @@ -0,0 +1,54 @@ +//===-- Implementation of printf for baremetal ------------------*- 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/printf.h" +#include "src/__support/OSUtil/io.h" +#include "src/__support/arg_list.h" +#include "src/__support/macros/config.h" +#include "src/stdio/printf_core/core_structs.h" +#include "src/stdio/printf_core/printf_main.h" +#include "src/stdio/printf_core/writer.h" + +#include +#include + +namespace LIBC_NAMESPACE_DECL { + +namespace { + +LIBC_INLINE int stdout_write_hook(cpp::string_view new_str, void *) { + write_to_stdout(new_str); + return printf_core::WRITE_OK; +} + +} // namespace + +LLVM_LIBC_FUNCTION(int, printf, (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); + static constexpr size_t BUFF_SIZE = 1024; + char buffer[BUFF_SIZE]; + + printf_core::WriteBuffer wb( + buffer, BUFF_SIZE, &stdout_write_hook, nullptr); + printf_core::Writer writer(wb); + + int retval = printf_core::printf_main(&writer, format, args); + + int flushval = wb.overflow_write(""); + if (flushval != printf_core::WRITE_OK) + retval = flushval; + + return retval; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/baremetal/putchar.cpp b/libc/src/stdio/baremetal/putchar.cpp new file mode 100644 index 0000000000000..ac21e6e783b01 --- /dev/null +++ b/libc/src/stdio/baremetal/putchar.cpp @@ -0,0 +1,24 @@ +//===-- Baremetal Implementation of putchar -------------------------------===// +// +// 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/putchar.h" +#include "src/__support/CPP/string_view.h" +#include "src/__support/OSUtil/io.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, putchar, (int c)) { + char uc = static_cast(c); + + write_to_stdout(cpp::string_view(&uc, 1)); + + return 0; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/baremetal/puts.cpp b/libc/src/stdio/baremetal/puts.cpp new file mode 100644 index 0000000000000..fcd3aa086b2bf --- /dev/null +++ b/libc/src/stdio/baremetal/puts.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of puts for baremetal-------------------------------===// +// +// 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/puts.h" +#include "src/__support/CPP/string_view.h" +#include "src/__support/OSUtil/io.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, puts, (const char *__restrict str)) { + cpp::string_view str_view(str); + + // TODO: Can we combine these to avoid needing two writes? + write_to_stdout(str_view); + write_to_stdout("\n"); + + return 0; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/baremetal/vprintf.cpp b/libc/src/stdio/baremetal/vprintf.cpp new file mode 100644 index 0000000000000..ab02533f14911 --- /dev/null +++ b/libc/src/stdio/baremetal/vprintf.cpp @@ -0,0 +1,52 @@ +//===-- Implementation of vprintf -------------------------------*- 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/vprintf.h" +#include "src/__support/OSUtil/io.h" +#include "src/__support/arg_list.h" +#include "src/__support/macros/config.h" +#include "src/stdio/printf_core/core_structs.h" +#include "src/stdio/printf_core/printf_main.h" +#include "src/stdio/printf_core/writer.h" + +#include +#include + +namespace LIBC_NAMESPACE_DECL { + +namespace { + +LIBC_INLINE int stdout_write_hook(cpp::string_view new_str, void *) { + write_to_stdout(new_str); + return printf_core::WRITE_OK; +} + +} // namespace + +LLVM_LIBC_FUNCTION(int, vprintf, + (const char *__restrict format, va_list vlist)) { + internal::ArgList args(vlist); // This holder class allows for easier copying + // and pointer semantics, as well as handling + // destruction automatically. + static constexpr size_t BUFF_SIZE = 1024; + char buffer[BUFF_SIZE]; + + printf_core::WriteBuffer wb( + buffer, BUFF_SIZE, &stdout_write_hook, nullptr); + printf_core::Writer writer(wb); + + int retval = printf_core::printf_main(&writer, format, args); + + int flushval = wb.overflow_write(""); + if (flushval != printf_core::WRITE_OK) + retval = flushval; + + return retval; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/fopencookie.cpp b/libc/src/stdio/fopencookie.cpp index 43a9acc5536c3..da8a132a4db6e 100644 --- a/libc/src/stdio/fopencookie.cpp +++ b/libc/src/stdio/fopencookie.cpp @@ -10,14 +10,76 @@ #include "hdr/stdio_macros.h" #include "hdr/types/FILE.h" #include "hdr/types/cookie_io_functions_t.h" +#include "hdr/types/off_t.h" #include "src/__support/CPP/new.h" -#include "src/__support/File/cookie_file.h" #include "src/__support/File/file.h" +#include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { +namespace { + +class CookieFile : public LIBC_NAMESPACE::File { + void *cookie; + cookie_io_functions_t ops; + + static FileIOResult cookie_write(File *f, const void *data, size_t size); + static FileIOResult cookie_read(File *f, void *data, size_t size); + static ErrorOr cookie_seek(File *f, off_t offset, int whence); + static int cookie_close(File *f); + +public: + CookieFile(void *c, cookie_io_functions_t cops, uint8_t *buffer, + size_t bufsize, File::ModeFlags mode) + : File(&cookie_write, &cookie_read, &CookieFile::cookie_seek, + &cookie_close, buffer, bufsize, 0 /* default buffering mode */, + true /* File owns buffer */, mode), + cookie(c), ops(cops) {} +}; + +FileIOResult CookieFile::cookie_write(File *f, const void *data, size_t size) { + auto cookie_file = reinterpret_cast(f); + if (cookie_file->ops.write == nullptr) + return 0; + return static_cast(cookie_file->ops.write( + cookie_file->cookie, reinterpret_cast(data), size)); +} + +FileIOResult CookieFile::cookie_read(File *f, void *data, size_t size) { + auto cookie_file = reinterpret_cast(f); + if (cookie_file->ops.read == nullptr) + return 0; + return static_cast(cookie_file->ops.read( + cookie_file->cookie, reinterpret_cast(data), size)); +} + +ErrorOr CookieFile::cookie_seek(File *f, off_t offset, int whence) { + auto cookie_file = reinterpret_cast(f); + if (cookie_file->ops.seek == nullptr) { + return Error(EINVAL); + } + off64_t offset64 = offset; + int result = cookie_file->ops.seek(cookie_file->cookie, &offset64, whence); + if (result == 0) + return offset64; + return -1; +} + +int CookieFile::cookie_close(File *f) { + auto cookie_file = reinterpret_cast(f); + if (cookie_file->ops.close == nullptr) + return 0; + int retval = cookie_file->ops.close(cookie_file->cookie); + if (retval != 0) + return retval; + delete cookie_file; + return 0; +} + +} // anonymous namespace + LLVM_LIBC_FUNCTION(::FILE *, fopencookie, (void *cookie, const char *mode, cookie_io_functions_t ops)) { @@ -29,9 +91,8 @@ LLVM_LIBC_FUNCTION(::FILE *, fopencookie, return nullptr; } AllocChecker ac; - auto *file = - new (ac) CookieFile(cookie, ops, buffer, File::DEFAULT_BUFFER_SIZE, - _IOFBF, File::mode_flags(mode)); + auto *file = new (ac) CookieFile( + cookie, ops, buffer, File::DEFAULT_BUFFER_SIZE, File::mode_flags(mode)); if (!ac) return nullptr; return reinterpret_cast<::FILE *>(file);