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`.
This commit is contained in:
Gleb Mazovetskiy 2022-07-02 11:30:43 +01:00
parent f6276a2c2b
commit fba8bc3975
6 changed files with 31 additions and 10 deletions

View File

@ -268,6 +268,11 @@ target_include_directories(fmt-header-only ${FMT_SYSTEM_HEADERS_ATTRIBUTE} INTER
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${FMT_INC_DIR}>)
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)

View File

@ -46,8 +46,8 @@ FMT_BEGIN_NAMESPACE
# if FMT_HAS_INCLUDE("winapifamily.h")
# include <winapifamily.h>
# 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;

View File

@ -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__) || \

View File

@ -22,7 +22,7 @@
# include <locale>
#endif
#ifdef _WIN32
#if defined(_WIN32) && !FMT_WIN9X
# include <io.h> // _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<sizeof(long) == 4, unsigned long, unsigned>;
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) {

View File

@ -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.

View File

@ -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<wchar_t> 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.