From fba8bc3975704f4622e35d7846170bc6dfa511ae Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sat, 2 Jul 2022 11:30:43 +0100 Subject: [PATCH] Optional Win9x support Adds optional support for Windows 9x/ME and the original Xbox (nxdk). Most of libfmt is available except functions that depend on `fileno`, such as file descriptor duplication. For now, support must be enabled explicitly by defining `FMT_WIN9X`. --- CMakeLists.txt | 5 +++++ include/fmt/chrono.h | 8 ++++---- include/fmt/core.h | 8 ++++++++ include/fmt/format-inl.h | 8 ++++---- include/fmt/os.h | 6 +++++- src/os.cc | 6 +++++- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b096e4e2..ecf529df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,6 +268,11 @@ target_include_directories(fmt-header-only ${FMT_SYSTEM_HEADERS_ATTRIBUTE} INTER $ $) +if (FMT_WIN98X) + target_compile_definitions(fmt PUBLIC FMT_WIN98X=1) + target_compile_definitions(fmt-header-only INTERFACE FMT_WIN98X=1) +endif() + # Install targets. if (FMT_INSTALL) include(CMakePackageConfigHelpers) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 11565d63..ca198379 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -46,8 +46,8 @@ FMT_BEGIN_NAMESPACE # if FMT_HAS_INCLUDE("winapifamily.h") # include # endif -# if defined(_WIN32) && (!defined(WINAPI_FAMILY) || \ - (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) +# if defined(_WIN32) && !FMT_WIN9X && \ + (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) # define FMT_USE_TZSET 1 # else # define FMT_USE_TZSET 0 @@ -488,7 +488,7 @@ inline std::tm localtime(std::time_t time) { bool fallback(int res) { return res == 0; } -#if !FMT_MSC_VERSION +#if !FMT_MSC_VERSION || FMT_WIN9X bool fallback(detail::null<>) { using namespace fmt::detail; std::tm* tm = std::localtime(&time_); @@ -537,7 +537,7 @@ inline std::tm gmtime(std::time_t time) { bool fallback(int res) { return res == 0; } -#if !FMT_MSC_VERSION +#if !FMT_MSC_VERSION || FMT_WIN9X bool fallback(detail::null<>) { std::tm* tm = std::gmtime(&time_); if (tm) tm_ = *tm; diff --git a/include/fmt/core.h b/include/fmt/core.h index 27143856..90c55c42 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -257,6 +257,14 @@ # define FMT_UNICODE !FMT_MSC_VERSION #endif +#ifndef FMT_WIN9X +# if defined(NXDK) +# define FMT_WIN9X 1 +# else +# define FMT_WIN9X 0 +# endif +#endif + #ifndef FMT_CONSTEVAL # if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \ (!defined(__apple_build_version__) || \ diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index ba1ab462..32fa426b 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -22,7 +22,7 @@ # include #endif -#ifdef _WIN32 +#if defined(_WIN32) && !FMT_WIN9X # include // _isatty #endif @@ -1453,7 +1453,7 @@ FMT_FUNC std::string vformat(string_view fmt, format_args args) { } namespace detail { -#ifdef _WIN32 +#if defined(_WIN32) && !FMT_WIN9X using dword = conditional_t; extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // void*, const void*, dword, dword*, void*); @@ -1478,7 +1478,7 @@ FMT_FUNC bool write_console(std::FILE* f, string_view text) { #endif FMT_FUNC void print(std::FILE* f, string_view text) { -#ifdef _WIN32 +#if defined(_WIN32) && !FMT_WIN9X if (write_console(f, text)) return; #endif detail::fwrite_fully(text.data(), 1, text.size(), f); @@ -1491,7 +1491,7 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { detail::print(f, {buffer.data(), buffer.size()}); } -#ifdef _WIN32 +#if defined(_WIN32) && !FMT_WIN9X // Print assuming legacy (non-Unicode) encoding. FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str, format_args args) { diff --git a/include/fmt/os.h b/include/fmt/os.h index e39f38cd..29413a5b 100644 --- a/include/fmt/os.h +++ b/include/fmt/os.h @@ -49,7 +49,7 @@ # define FMT_POSIX_CALL(call) FMT_SYSTEM(call) #else # define FMT_SYSTEM(call) ::call -# ifdef _WIN32 +# if defined(_WIN32) && !FMT_WIN9X // Fix warnings about deprecated symbols. # define FMT_POSIX_CALL(call) ::_##call # else @@ -242,7 +242,9 @@ class buffered_file { // Returns the pointer to a FILE object representing this file. FILE* get() const noexcept { return file_; } +#if !FMT_WIN9X FMT_API int descriptor() const; +#endif void vprint(string_view format_str, format_args args) { fmt::vprint(file_, format_str, args); @@ -318,6 +320,7 @@ class FMT_API file { // Attempts to write count bytes from the specified buffer to the file. size_t write(const void* buffer, size_t count); +#if !FMT_WIN9X // Duplicates a file descriptor with the dup function and returns // the duplicate as a file object. static file dup(int fd); @@ -333,6 +336,7 @@ class FMT_API file { // Creates a pipe setting up read_end and write_end file objects for reading // and writing respectively. static void pipe(file& read_end, file& write_end); +#endif // Creates a buffered_file object associated with this file and detaches // this file object from the file. diff --git a/src/os.cc b/src/os.cc index 521b84de..fd27d622 100644 --- a/src/os.cc +++ b/src/os.cc @@ -71,7 +71,7 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; } FMT_BEGIN_NAMESPACE -#ifdef _WIN32 +#if defined(_WIN32) && !FMT_WIN9X detail::utf16_to_utf8::utf16_to_utf8(basic_string_view s) { if (int error_code = convert(s)) { FMT_THROW(windows_error(error_code, @@ -205,6 +205,7 @@ void buffered_file::close() { FMT_THROW(system_error(errno, FMT_STRING("cannot close file"))); } +#if !FMT_WIN9X int buffered_file::descriptor() const { #ifdef fileno // fileno is a macro on OpenBSD so we cannot use FMT_POSIX_CALL. int fd = fileno(file_); @@ -215,6 +216,7 @@ int buffered_file::descriptor() const { FMT_THROW(system_error(errno, FMT_STRING("cannot get file descriptor"))); return fd; } +#endif // !FMT_WIN9X #if FMT_USE_FCNTL # ifdef _WIN32 @@ -295,6 +297,7 @@ std::size_t file::write(const void* buffer, std::size_t count) { return detail::to_unsigned(result); } +#if !FMT_WIN9X file file::dup(int fd) { // Don't retry as dup doesn't return EINTR. // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html @@ -343,6 +346,7 @@ void file::pipe(file& read_end, file& write_end) { read_end = file(fds[0]); write_end = file(fds[1]); } +#endif buffered_file file::fdopen(const char* mode) { // Don't retry as fdopen doesn't return EINTR.