mirror of
https://github.com/gbdev/rgbds.git
synced 2026-09-22 13:47:05 +00:00
Interestingly, Clang's `-Wformat-overflow` seems to only warn about buffers so small they will *always* underflow, whereas GCC tries to infer whether they can overflow *at all*. (I'm guessing they lean towards false-negatives and false-positives resp.) Anyway, calling `sprintf` here remains safe, since GCC (notably, via CI) checks our work, and it simplifies the code ever so slightly while also providing an (admittedly negligible) performance improvement. Note that there may be more locations where we could use `sprintf`, but a cursory glance at our other uses of `snprintf` didn't seem fruitful. (One way to test is to set the target buffer size to 1, and see if a warning pops up for such a trivially-wrong size. If not, you can be certain the compiler won't be able to help you with a more realistic size.)
92 lines
2.8 KiB
C++
92 lines
2.8 KiB
C++
// SPDX-License-Identifier: MIT
|
|
|
|
#ifndef RGBDS_PLATFORM_HPP
|
|
#define RGBDS_PLATFORM_HPP
|
|
|
|
// MSVC doesn't have str(n)casecmp, use a suitable replacement
|
|
#ifdef _MSC_VER
|
|
#include <string.h> // IWYU pragma: export
|
|
#define strcasecmp _stricmp
|
|
#define strncasecmp _strnicmp
|
|
#else
|
|
#include <strings.h> // IWYU pragma: export
|
|
#endif
|
|
|
|
// MSVC prefixes the names of S_* macros with underscores,
|
|
// and doesn't define any S_IS* macros; define them ourselves
|
|
#ifdef _MSC_VER
|
|
#define S_IFMT _S_IFMT
|
|
#define S_IFDIR _S_IFDIR
|
|
#define S_ISDIR(mode) (((mode) & (S_IFMT)) == S_IFDIR)
|
|
#endif
|
|
|
|
// MSVC doesn't use POSIX types or defines for `read`
|
|
#ifdef _MSC_VER
|
|
#include <io.h> // IWYU pragma: export
|
|
#define STDIN_FILENO 0
|
|
#define STDOUT_FILENO 1
|
|
#define STDERR_FILENO 2
|
|
#define ssize_t int
|
|
#define SSIZE_MAX INT_MAX
|
|
#define isatty _isatty
|
|
#else
|
|
#include <fcntl.h> // IWYU pragma: export
|
|
#include <limits.h> // IWYU pragma: export
|
|
#include <unistd.h> // IWYU pragma: export
|
|
#endif
|
|
|
|
// MSVC uses a different name for O_RDWR, and needs an additional _O_BINARY flag
|
|
#ifdef _MSC_VER
|
|
#include <fcntl.h> // IWYU pragma: export
|
|
#define O_RDWR _O_RDWR
|
|
#define S_ISREG(field) ((field) & (_S_IFREG))
|
|
#define O_BINARY _O_BINARY
|
|
#define O_TEXT _O_TEXT
|
|
#elif !defined(O_BINARY) // Cross-compilers define O_BINARY
|
|
#define O_BINARY 0 // POSIX says we shouldn't care!
|
|
#define O_TEXT 0 // Assume that it's not defined either
|
|
#endif // _MSC_VER
|
|
|
|
// Windows has stdin and stdout open as text by default, which we may not want
|
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
#include <io.h> // IWYU pragma: export
|
|
#define setmode(fd, mode) _setmode(fd, mode)
|
|
#else
|
|
#define setmode(fd, mode) (0)
|
|
#endif
|
|
|
|
// Windows has 32-bit `long`, which limits `fseek` and `ftell` to 2 GiB
|
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
#define fseek _fseeki64
|
|
#define ftell _ftelli64
|
|
#endif
|
|
|
|
// MingGW and Cygwin may need POSIX functions which are not standard C explicitly enabled
|
|
#if (defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(_POSIX_C_SOURCE)
|
|
#define _POSIX_C_SOURCE 200809L
|
|
#endif
|
|
|
|
// Apple has deprecated `sprintf` since Xcode 14 (for macOS 13), but we use it solely in
|
|
// contexts where both the size of the buffer *and* max size of the printed string are
|
|
// known statically, which GCC thus checks for.
|
|
#ifdef __APPLE__
|
|
#define sprintf_to_array(array, ...) \
|
|
do { \
|
|
static_assert( \
|
|
std::is_array_v<decltype(array)>, "Only use this macro to print to an array!" \
|
|
); \
|
|
snprintf(array, sizeof(array), __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
#else
|
|
#define sprintf_to_array(array, ...) \
|
|
do { \
|
|
static_assert( \
|
|
std::is_array_v<decltype(array)>, "Only use this macro to print to an array!" \
|
|
); \
|
|
sprintf(array, __VA_ARGS__); \
|
|
} while (0)
|
|
#endif
|
|
|
|
#endif // RGBDS_PLATFORM_HPP
|