diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -127,6 +127,9 @@ libc.src.stdio.snprintf libc.src.stdio.fprintf libc.src.stdio.printf + libc.src.stdio.sscanf + libc.src.stdio.scanf + libc.src.stdio.fscanf # sys/mman.h entrypoints libc.src.sys.mman.madvise @@ -433,9 +436,6 @@ libc.src.stdio.getc_unlocked libc.src.stdio.getchar libc.src.stdio.getchar_unlocked - libc.src.stdio.sscanf - libc.src.stdio.scanf - libc.src.stdio.fscanf libc.src.stdio.putc libc.src.stdio.putchar libc.src.stdio.puts diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt --- a/libc/src/stdio/CMakeLists.txt +++ b/libc/src/stdio/CMakeLists.txt @@ -460,6 +460,19 @@ libc.src.stdio.scanf_core.scanf_main ) +list(APPEND scanf_deps + libc.src.__support.arg_list + libc.src.stdio.scanf_core.vfscanf_internal +) +if(LLVM_LIBC_FULL_BUILD) + list(APPEND scanf_deps + libc.src.__support.File.file + libc.src.__support.File.platform_file + ) +else() + set(scanf_copts "-DLIBC_COPT_SCANF_USE_SYSTEM_FILE") +endif() + add_entrypoint_object( fscanf SRCS @@ -467,8 +480,9 @@ HDRS fscanf.h DEPENDS - libc.src.__support.arg_list - libc.src.stdio.scanf_core.vfscanf_internal + ${scanf_deps} + COMPILE_OPTIONS + ${scanf_copts} ) add_entrypoint_object( @@ -478,8 +492,9 @@ HDRS scanf.h DEPENDS - libc.src.__support.arg_list - libc.src.stdio.scanf_core.vfscanf_internal + ${scanf_deps} + COMPILE_OPTIONS + ${scanf_copts} ) add_entrypoint_object( @@ -538,8 +553,7 @@ HDRS fprintf.h DEPENDS - libc.src.__support.arg_list - libc.src.stdio.printf_core.vfprintf_internal + ${printf_deps} COMPILE_OPTIONS ${printf_copts} ) diff --git a/libc/src/stdio/fscanf.cpp b/libc/src/stdio/fscanf.cpp --- a/libc/src/stdio/fscanf.cpp +++ b/libc/src/stdio/fscanf.cpp @@ -15,6 +15,12 @@ #include #include +#ifndef LIBC_COPT_SCANF_USE_SYSTEM_FILE +using FileT = __llvm_libc::File; +#else // defined(LIBC_COPT_SCANF_USE_SYSTEM_FILE) +using FileT = ::FILE; +#endif // LIBC_COPT_SCANF_USE_SYSTEM_FILE + namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, fscanf, @@ -26,7 +32,8 @@ // and pointer semantics, as well as handling // destruction automatically. va_end(vlist); - int ret_val = scanf_core::vfscanf_internal(stream, format, args); + int ret_val = scanf_core::vfscanf_internal(reinterpret_cast(stream), + format, args); // This is done to avoid including stdio.h in the internals. On most systems // EOF is -1, so this will be transformed into just "return ret_val". return (ret_val == -1) ? EOF : ret_val; diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt --- a/libc/src/stdio/printf_core/CMakeLists.txt +++ b/libc/src/stdio/printf_core/CMakeLists.txt @@ -139,8 +139,6 @@ HDRS vfprintf_internal.h DEPENDS - libc.include.stdio - libc.src.__support.File.file libc.src.__support.arg_list libc.src.stdio.printf_core.printf_main libc.src.stdio.printf_core.file_writer diff --git a/libc/src/stdio/printf_core/vfprintf_internal.h b/libc/src/stdio/printf_core/vfprintf_internal.h --- a/libc/src/stdio/printf_core/vfprintf_internal.h +++ b/libc/src/stdio/printf_core/vfprintf_internal.h @@ -9,15 +9,12 @@ #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_VFPRINTF_INTERNAL_H #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_VFPRINTF_INTERNAL_H -#include "src/__support/File/file.h" #include "src/__support/arg_list.h" #include "src/__support/macros/attributes.h" // For LIBC_INLINE #include "src/stdio/printf_core/file_writer.h" #include "src/stdio/printf_core/printf_main.h" #include "src/stdio/printf_core/writer.h" -#include - namespace __llvm_libc { namespace printf_core { diff --git a/libc/src/stdio/scanf.cpp b/libc/src/stdio/scanf.cpp --- a/libc/src/stdio/scanf.cpp +++ b/libc/src/stdio/scanf.cpp @@ -8,13 +8,19 @@ #include "src/stdio/scanf.h" -#include "src/__support/File/file.h" #include "src/__support/arg_list.h" #include "src/stdio/scanf_core/vfscanf_internal.h" #include #include +#ifndef LIBC_COPT_SCANF_USE_SYSTEM_FILE +#include "src/__support/File/file.h" +#define SCANF_STDIN __llvm_libc::stdin +#else // LIBC_COPT_SCANF_USE_SYSTEM_FILE +#define SCANF_STDIN ::stdin +#endif // LIBC_COPT_SCANF_USE_SYSTEM_FILE + namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) { @@ -24,8 +30,7 @@ // and pointer semantics, as well as handling // destruction automatically. va_end(vlist); - int ret_val = scanf_core::vfscanf_internal( - reinterpret_cast<::FILE *>(__llvm_libc::stdin), format, args); + int ret_val = scanf_core::vfscanf_internal(SCANF_STDIN, format, args); // This is done to avoid including stdio.h in the internals. On most systems // EOF is -1, so this will be transformed into just "return ret_val". return (ret_val == -1) ? EOF : ret_val; diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt --- a/libc/src/stdio/scanf_core/CMakeLists.txt +++ b/libc/src/stdio/scanf_core/CMakeLists.txt @@ -24,9 +24,9 @@ libc.src.__support.CPP.string_view ) -if(NOT (TARGET libc.src.__support.File.file)) - # Not all platforms have a file implementation. If file is unvailable, - # then we must skip all the parts that need file. +if(NOT (TARGET libc.src.__support.File.file) AND LLVM_LIBC_FULL_BUILD) + # Not all platforms have a file implementation. If file is unvailable, and a + # full build is requested, then we must skip all file based printf sections. return() endif() @@ -52,13 +52,12 @@ string_reader.h ) -add_object_library( +add_header_library( file_reader - SRCS - file_reader.cpp HDRS file_reader.h DEPENDS + libc.include.stdio libc.src.__support.File.file ) @@ -101,10 +100,8 @@ libc.src.__support.str_to_float ) -add_object_library( +add_header_library( vfscanf_internal - SRCS - vfscanf_internal.cpp HDRS vfscanf_internal.h DEPENDS diff --git a/libc/src/stdio/scanf_core/converter.cpp b/libc/src/stdio/scanf_core/converter.cpp --- a/libc/src/stdio/scanf_core/converter.cpp +++ b/libc/src/stdio/scanf_core/converter.cpp @@ -94,7 +94,9 @@ } } } - reader->ungetc(cur_char); + if (!reader->ungetc(cur_char)) { + return UNGET_ERROR; + } return ret_val; } diff --git a/libc/src/stdio/scanf_core/core_structs.h b/libc/src/stdio/scanf_core/core_structs.h --- a/libc/src/stdio/scanf_core/core_structs.h +++ b/libc/src/stdio/scanf_core/core_structs.h @@ -85,6 +85,7 @@ FILE_STATUS_ERROR = -2, MATCHING_FAILURE = -3, ALLOCATION_FAILURE = -4, + UNGET_ERROR = -5, }; } // namespace scanf_core } // namespace __llvm_libc diff --git a/libc/src/stdio/scanf_core/file_reader.h b/libc/src/stdio/scanf_core/file_reader.h --- a/libc/src/stdio/scanf_core/file_reader.h +++ b/libc/src/stdio/scanf_core/file_reader.h @@ -17,22 +17,68 @@ namespace __llvm_libc { namespace scanf_core { -class FileReader { - __llvm_libc::File *file; +template class FileReader { + file_t *file; public: - FileReader(::FILE *init_file) { - file = reinterpret_cast<__llvm_libc::File *>(init_file); - file->lock(); - } + FileReader(file_t *init_file); - ~FileReader() { file->unlock(); } + ~FileReader(); char get_char(); - void unget_char(char c); - bool has_error() { return file->error_unlocked(); } + bool unget_char(char c); // Returns true on success, false on failure. + bool has_error(); }; +// The interface for using our internal file implementation. +template <> +LIBC_INLINE +FileReader<__llvm_libc::File>::FileReader(__llvm_libc::File *init_file) { + file = init_file; + file->lock(); +} +template <> LIBC_INLINE FileReader<__llvm_libc::File>::~FileReader() { + file->unlock(); +} + +template <> LIBC_INLINE char FileReader<__llvm_libc::File>::get_char() { + char tiny_buff = 0; + auto result = file->read_unlocked(&tiny_buff, 1); + if (result.value != 1 || result.has_error()) + return 0; + return tiny_buff; +} +template <> LIBC_INLINE bool FileReader<__llvm_libc::File>::has_error() { + return file->error_unlocked(); +} +template <> LIBC_INLINE bool FileReader<__llvm_libc::File>::unget_char(char c) { + int result = file->ungetc_unlocked(c); + return !(result == EOF || this->has_error()); +} + +// The interface for using the system's file implementation. +template <> LIBC_INLINE FileReader<::FILE>::FileReader(::FILE *init_file) { + file = init_file; + ::flockfile(file); +} +template <> LIBC_INLINE FileReader<::FILE>::~FileReader() { + ::funlockfile(file); +} + +template <> LIBC_INLINE char FileReader<::FILE>::get_char() { + int result = ::fgetc_unlocked(file); + if (result == EOF || ::ferror_unlocked(file)) + return 0; + return static_cast(result); +} +template <> LIBC_INLINE bool FileReader<::FILE>::has_error() { + return ::ferror(file) != 0; +} +template <> LIBC_INLINE bool FileReader<::FILE>::unget_char(char c) { + int result = ::ungetc(c, file); // There is no unlocked version of ungetc. + return !(result == EOF || this->has_error()); +} + } // namespace scanf_core } // namespace __llvm_libc diff --git a/libc/src/stdio/scanf_core/file_reader.cpp b/libc/src/stdio/scanf_core/file_reader.cpp deleted file mode 100644 --- a/libc/src/stdio/scanf_core/file_reader.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//===-- FILE Reader implementation 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/file_reader.h" -#include "src/__support/File/file.h" -#include - -namespace __llvm_libc { -namespace scanf_core { - -char FileReader::get_char() { - char tiny_buff = 0; - auto result = file->read_unlocked(&tiny_buff, 1); - if (result.value != 1 || result.has_error()) - return 0; - return tiny_buff; -} - -void FileReader::unget_char(char c) { file->ungetc_unlocked(c); } - -} // namespace scanf_core -} // namespace __llvm_libc diff --git a/libc/src/stdio/scanf_core/float_converter.cpp b/libc/src/stdio/scanf_core/float_converter.cpp --- a/libc/src/stdio/scanf_core/float_converter.cpp +++ b/libc/src/stdio/scanf_core/float_converter.cpp @@ -210,7 +210,9 @@ // We always read one more character than will be used, so we have to put the // last one back. - reader->ungetc(cur_char); + if (!reader->ungetc(cur_char)) { + return UNGET_ERROR; + } // If we haven't actually found any digits, this is a matching failure (this // catches cases like "+.") diff --git a/libc/src/stdio/scanf_core/int_converter.cpp b/libc/src/stdio/scanf_core/int_converter.cpp --- a/libc/src/stdio/scanf_core/int_converter.cpp +++ b/libc/src/stdio/scanf_core/int_converter.cpp @@ -144,7 +144,9 @@ } else { // If the first character isn't a valid digit, then there are no valid // digits at all. The number is 0. - reader->ungetc(cur_char); + if (!reader->ungetc(cur_char)) { + return UNGET_ERROR; + } write_int_with_length(0, to_conv); return MATCHING_FAILURE; } @@ -195,7 +197,9 @@ // We always read one more character than will be used, so we have to put the // last one back. - reader->ungetc(cur_char); + if (!reader->ungetc(cur_char)) { + return UNGET_ERROR; + } if (has_overflow) { write_int_with_length(MAX, to_conv); diff --git a/libc/src/stdio/scanf_core/ptr_converter.cpp b/libc/src/stdio/scanf_core/ptr_converter.cpp --- a/libc/src/stdio/scanf_core/ptr_converter.cpp +++ b/libc/src/stdio/scanf_core/ptr_converter.cpp @@ -34,7 +34,9 @@ return MATCHING_FAILURE; } - reader->ungetc(cur_char); + if (!reader->ungetc(cur_char)) { + return UNGET_ERROR; + } // Else treat it as a hex int return convert_int(reader, to_conv); diff --git a/libc/src/stdio/scanf_core/reader.h b/libc/src/stdio/scanf_core/reader.h --- a/libc/src/stdio/scanf_core/reader.h +++ b/libc/src/stdio/scanf_core/reader.h @@ -16,12 +16,13 @@ namespace __llvm_libc { namespace scanf_core { -enum class ReaderType { String, File }; +enum class ReaderType { String, SystemFile, InternalFile }; class Reader final { union { StringReader *string_reader; - FileReader *file_reader; + FileReader<::FILE> *system_file_reader; + FileReader<__llvm_libc::File> *internal_file_reader; }; const ReaderType reader_type; @@ -32,8 +33,13 @@ Reader(StringReader *init_string_reader) : string_reader(init_string_reader), reader_type(ReaderType::String) {} - Reader(FileReader *init_file_reader) - : file_reader(init_file_reader), reader_type(ReaderType::File) {} + Reader(FileReader<__llvm_libc::File> *init_file_reader) + : internal_file_reader(init_file_reader), + reader_type(ReaderType::InternalFile) {} + + Reader(FileReader<::FILE> *init_file_reader) + : system_file_reader(init_file_reader), + reader_type(ReaderType::SystemFile) {} // This returns the next character from the input and advances it by one // character. When it hits the end of the string or file it returns '\0' to @@ -41,8 +47,8 @@ char getc(); // This moves the input back by one character, placing c into the buffer if - // this is a file reader, else c is ignored. - void ungetc(char c); + // this is a file reader, else c is ignored. It returns true on success. + bool ungetc(char c); size_t chars_read() { return cur_chars_read; } diff --git a/libc/src/stdio/scanf_core/reader.cpp b/libc/src/stdio/scanf_core/reader.cpp --- a/libc/src/stdio/scanf_core/reader.cpp +++ b/libc/src/stdio/scanf_core/reader.cpp @@ -14,30 +14,41 @@ char Reader::getc() { ++cur_chars_read; - if (reader_type == ReaderType::String) { + switch (reader_type) { + case ReaderType::String: return string_reader->get_char(); - } else { - return file_reader->get_char(); + case ReaderType::InternalFile: + return internal_file_reader->get_char(); + case ReaderType::SystemFile: + return system_file_reader->get_char(); } } -void Reader::ungetc(char c) { +bool Reader::ungetc(char c) { --cur_chars_read; - if (reader_type == ReaderType::String) { + switch (reader_type) { + case ReaderType::String: // The string reader ignores the char c passed to unget since it doesn't // need to place anything back into a buffer, and modifying the source // string would be dangerous. return string_reader->unget_char(); - } else { - return file_reader->unget_char(c); + case ReaderType::InternalFile: + return internal_file_reader->unget_char(c); + case ReaderType::SystemFile: + return system_file_reader->unget_char(c); } } bool Reader::has_error() { - if (reader_type == ReaderType::File) { - return file_reader->has_error(); + switch (reader_type) { + case ReaderType::String: + // The string reader can't error since it's just reading from a char*. + return false; + case ReaderType::InternalFile: + return internal_file_reader->has_error(); + case ReaderType::SystemFile: + return system_file_reader->has_error(); } - return false; } } // namespace scanf_core diff --git a/libc/src/stdio/scanf_core/string_converter.cpp b/libc/src/stdio/scanf_core/string_converter.cpp --- a/libc/src/stdio/scanf_core/string_converter.cpp +++ b/libc/src/stdio/scanf_core/string_converter.cpp @@ -56,7 +56,9 @@ // We always read one more character than will be used, so we have to put the // last one back. - reader->ungetc(cur_char); + if (!reader->ungetc(cur_char)) { + return UNGET_ERROR; + } // If this is %s or %[] if (to_conv.conv_name != 'c' && (to_conv.flags & NO_WRITE) == 0) { diff --git a/libc/src/stdio/scanf_core/string_reader.h b/libc/src/stdio/scanf_core/string_reader.h --- a/libc/src/stdio/scanf_core/string_reader.h +++ b/libc/src/stdio/scanf_core/string_reader.h @@ -24,7 +24,7 @@ ~StringReader() {} char get_char(); - void unget_char(); + bool unget_char(); }; } // namespace scanf_core diff --git a/libc/src/stdio/scanf_core/string_reader.cpp b/libc/src/stdio/scanf_core/string_reader.cpp --- a/libc/src/stdio/scanf_core/string_reader.cpp +++ b/libc/src/stdio/scanf_core/string_reader.cpp @@ -18,7 +18,10 @@ return cur_char; } -void StringReader::unget_char() { --cur_index; } +bool StringReader::unget_char() { + --cur_index; + return true; +} } // namespace scanf_core } // namespace __llvm_libc diff --git a/libc/src/stdio/scanf_core/vfscanf_internal.h b/libc/src/stdio/scanf_core/vfscanf_internal.h --- a/libc/src/stdio/scanf_core/vfscanf_internal.h +++ b/libc/src/stdio/scanf_core/vfscanf_internal.h @@ -10,14 +10,25 @@ #define LLVM_LIBC_SRC_STDIO_SCANF_CORE_VFSCANF_INTERNAL_H #include "src/__support/arg_list.h" +#include "src/__support/macros/attributes.h" // For LIBC_INLINE +#include "src/stdio/scanf_core/file_reader.h" +#include "src/stdio/scanf_core/reader.h" +#include "src/stdio/scanf_core/scanf_main.h" #include namespace __llvm_libc { namespace scanf_core { -int vfscanf_internal(::FILE *__restrict stream, const char *__restrict format, - internal::ArgList &args); +template +LIBC_INLINE int vfscanf_internal(file_t *__restrict stream, + const char *__restrict format, + internal::ArgList &args) { + FileReader file_reader(stream); + scanf_core::Reader reader(&file_reader); + return scanf_core::scanf_main(&reader, format, args); +} + } // namespace scanf_core } // namespace __llvm_libc diff --git a/libc/src/stdio/scanf_core/vfscanf_internal.cpp b/libc/src/stdio/scanf_core/vfscanf_internal.cpp deleted file mode 100644 --- a/libc/src/stdio/scanf_core/vfscanf_internal.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//===-- Internal implementation of vfscanf ---------------------*- 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/vfscanf_internal.h" - -#include "src/__support/arg_list.h" -#include "src/stdio/scanf_core/file_reader.h" -#include "src/stdio/scanf_core/reader.h" -#include "src/stdio/scanf_core/scanf_main.h" - -#include - -namespace __llvm_libc { -namespace scanf_core { - -int vfscanf_internal(::FILE *__restrict stream, const char *__restrict format, - internal::ArgList &args) { - FileReader file_reader(stream); - scanf_core::Reader reader(&file_reader); - return scanf_core::scanf_main(&reader, format, args); -} - -} // namespace scanf_core -} // namespace __llvm_libc diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt --- a/libc/test/src/stdio/CMakeLists.txt +++ b/libc/test/src/stdio/CMakeLists.txt @@ -134,23 +134,22 @@ libc.src.stdio.snprintf ) -# In fullbuild mode, fprintf's tests use the internal FILE for other functions. +list(APPEND fprintf_test_deps + libc.src.stdio.fprintf +) if(LLVM_LIBC_FULL_BUILD) -add_libc_unittest( - fprintf_test - SUITE - libc_stdio_unittests - SRCS - fprintf_test.cpp - DEPENDS - libc.src.stdio.fprintf +# In fullbuild mode, fprintf's tests use the internal FILE for other functions. + list(APPEND fprintf_test_deps libc.src.stdio.fclose libc.src.stdio.ferror libc.src.stdio.fopen libc.src.stdio.fread -) + ) else() # Else in overlay mode they use the system's FILE. + set(fprintf_test_copts "-DLIBC_COPT_PRINTF_USE_SYSTEM_FILE") +endif() + add_libc_unittest( fprintf_test SUITE @@ -158,11 +157,10 @@ SRCS fprintf_test.cpp DEPENDS - libc.src.stdio.fprintf + ${fprintf_test_deps} COMPILE_OPTIONS - -DLIBC_COPT_PRINTF_USE_SYSTEM_FILE + ${fprintf_test_copts} ) -endif() add_libc_unittest( printf_test @@ -174,6 +172,23 @@ libc.src.stdio.printf ) +list(APPEND fscanf_test_deps + libc.src.stdio.fscanf + libc.src.__support.CPP.string_view +) +if(LLVM_LIBC_FULL_BUILD) +# In fullbuild mode, fscanf's tests use the internal FILE for other functions. + list(APPEND fscanf_test_deps + libc.src.stdio.fclose + libc.src.stdio.ferror + libc.src.stdio.fopen + libc.src.stdio.fwrite + ) +else() +# Else in overlay mode they use the system's FILE. + set(fscanf_test_copts "-DLIBC_COPT_SCANF_USE_SYSTEM_FILE") +endif() + add_libc_unittest( fscanf_test SUITE @@ -181,12 +196,9 @@ SRCS fscanf_test.cpp DEPENDS - libc.src.stdio.fscanf - libc.src.stdio.fclose - libc.src.stdio.ferror - libc.src.stdio.fopen - libc.src.stdio.fwrite - libc.src.__support.CPP.string_view + ${fscanf_test_deps} + COMPILE_OPTIONS + ${fscanf_test_copts} ) add_libc_unittest( diff --git a/libc/test/src/stdio/fscanf_test.cpp b/libc/test/src/stdio/fscanf_test.cpp --- a/libc/test/src/stdio/fscanf_test.cpp +++ b/libc/test/src/stdio/fscanf_test.cpp @@ -6,21 +6,41 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/CPP/string_view.h" +#ifndef LIBC_COPT_SCANF_USE_SYSTEM_FILE #include "src/stdio/fclose.h" #include "src/stdio/ferror.h" #include "src/stdio/fopen.h" #include "src/stdio/fwrite.h" +#endif // LIBC_COPT_SCANF_USE_SYSTEM_FILE #include "src/stdio/fscanf.h" +#include "src/__support/CPP/string_view.h" + #include "test/UnitTest/Test.h" #include +namespace scanf_test { +#ifndef LIBC_COPT_SCANF_USE_SYSTEM_FILE +using __llvm_libc::fclose; +using __llvm_libc::ferror; +using __llvm_libc::fopen; +using __llvm_libc::fwrite; +#else // defined(LIBC_COPT_SCANF_USE_SYSTEM_FILE) +using ::fclose; +using ::ferror; +using ::fopen; +using ::fwrite; +#endif // LIBC_COPT_SCANF_USE_SYSTEM_FILE +} // namespace scanf_test + TEST(LlvmLibcFScanfTest, WriteToFile) { - constexpr char FILENAME[] = "testdata/fscanf_output.test"; - ::FILE *file = __llvm_libc::fopen(FILENAME, "w"); + + const char *FILENAME = "fscanf_output.test"; + auto FILE_PATH = libc_make_test_file_path(FILENAME); + + ::FILE *file = scanf_test::fopen(FILE_PATH, "w"); ASSERT_FALSE(file == nullptr); int read; @@ -28,26 +48,26 @@ constexpr char simple[] = "A simple string with no conversions.\n"; ASSERT_EQ(sizeof(simple) - 1, - __llvm_libc::fwrite(simple, 1, sizeof(simple) - 1, file)); + scanf_test::fwrite(simple, 1, sizeof(simple) - 1, file)); constexpr char numbers[] = "1234567890\n"; ASSERT_EQ(sizeof(numbers) - 1, - __llvm_libc::fwrite(numbers, 1, sizeof(numbers) - 1, file)); + scanf_test::fwrite(numbers, 1, sizeof(numbers) - 1, file)); constexpr char numbers_and_more[] = "1234 and more\n"; ASSERT_EQ(sizeof(numbers_and_more) - 1, - __llvm_libc::fwrite(numbers_and_more, 1, - sizeof(numbers_and_more) - 1, file)); + scanf_test::fwrite(numbers_and_more, 1, + sizeof(numbers_and_more) - 1, file)); read = __llvm_libc::fscanf(file, "Reading from a write-only file should fail."); EXPECT_LT(read, 0); - ASSERT_EQ(0, __llvm_libc::fclose(file)); + ASSERT_EQ(0, scanf_test::fclose(file)); - file = __llvm_libc::fopen(FILENAME, "r"); + file = scanf_test::fopen(FILENAME, "r"); ASSERT_FALSE(file == nullptr); char data[50]; @@ -67,6 +87,6 @@ ASSERT_EQ(__llvm_libc::cpp::string_view(numbers_and_more), __llvm_libc::cpp::string_view(data, sizeof(numbers_and_more) - 1)); - ASSERT_EQ(__llvm_libc::ferror(file), 0); - ASSERT_EQ(__llvm_libc::fclose(file), 0); + ASSERT_EQ(scanf_test::ferror(file), 0); + ASSERT_EQ(scanf_test::fclose(file), 0); }