forked from dnkl/foot
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
5.5 KiB
210 lines
5.5 KiB
#pragma once |
|
|
|
#define PASTE(a, b) a##b |
|
#define XPASTE(a, b) PASTE(a, b) |
|
#define DO_PRAGMA(x) _Pragma(#x) |
|
#define VERCMP(x, y, cx, cy) ((cx > x) || ((cx == x) && (cy >= y))) |
|
|
|
#if defined(__GNUC__) && defined(__GNUC_MINOR__) |
|
#define GNUC_AT_LEAST(x, y) VERCMP(x, y, __GNUC__, __GNUC_MINOR__) |
|
#else |
|
#define GNUC_AT_LEAST(x, y) 0 |
|
#endif |
|
|
|
#if defined(__clang_major__) && defined(__clang_minor__) |
|
#define CLANG_AT_LEAST(x, y) VERCMP(x, y, __clang_major__, __clang_minor__) |
|
#else |
|
#define CLANG_AT_LEAST(x, y) 0 |
|
#endif |
|
|
|
#ifdef __has_attribute |
|
#define HAS_ATTRIBUTE(x) __has_attribute(x) |
|
#else |
|
#define HAS_ATTRIBUTE(x) 0 |
|
#endif |
|
|
|
#ifdef __has_builtin |
|
#define HAS_BUILTIN(x) __has_builtin(x) |
|
#else |
|
#define HAS_BUILTIN(x) 0 |
|
#endif |
|
|
|
#ifdef __has_include |
|
#define HAS_INCLUDE(x) __has_include(x) |
|
#else |
|
#define HAS_INCLUDE(x) 0 |
|
#endif |
|
|
|
#ifdef __has_feature |
|
#define HAS_FEATURE(x) __has_feature(x) |
|
#else |
|
#define HAS_FEATURE(x) 0 |
|
#endif |
|
|
|
// __has_extension() is a Clang macro used to determine if a feature is |
|
// available even if not standardized in the current "-std" mode. |
|
#ifdef __has_extension |
|
#define HAS_EXTENSION(x) __has_extension(x) |
|
#else |
|
// Clang versions prior to 3.0 only supported __has_feature() |
|
#define HAS_EXTENSION(x) HAS_FEATURE(x) |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(unused) || defined(__TINYC__) |
|
#define UNUSED __attribute__((__unused__)) |
|
#else |
|
#define UNUSED |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(const) |
|
#define CONST __attribute__((__const__)) |
|
#else |
|
#define CONST |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(malloc) |
|
#define MALLOC __attribute__((__malloc__)) |
|
#else |
|
#define MALLOC |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(constructor) |
|
#define CONSTRUCTOR __attribute__((__constructor__)) |
|
#define HAVE_ATTR_CONSTRUCTOR 1 |
|
#else |
|
#define CONSTRUCTOR |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(destructor) |
|
#define DESTRUCTOR __attribute__((__destructor__)) |
|
#else |
|
#define DESTRUCTOR |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(format) |
|
#define PRINTF(x) __attribute__((__format__(__printf__, (x), (x + 1)))) |
|
#define VPRINTF(x) __attribute__((__format__(__printf__, (x), 0))) |
|
#else |
|
#define PRINTF(x) |
|
#define VPRINTF(x) |
|
#endif |
|
|
|
#if (GNUC_AT_LEAST(3, 0) || HAS_BUILTIN(__builtin_expect)) && defined(__OPTIMIZE__) |
|
#define likely(x) __builtin_expect(!!(x), 1) |
|
#define unlikely(x) __builtin_expect(!!(x), 0) |
|
#else |
|
#define likely(x) (x) |
|
#define unlikely(x) (x) |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 1) || HAS_ATTRIBUTE(noinline) |
|
#define NOINLINE __attribute__((__noinline__)) |
|
#else |
|
#define NOINLINE |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 1) || HAS_ATTRIBUTE(always_inline) |
|
#define ALWAYS_INLINE __attribute__((__always_inline__)) |
|
#else |
|
#define ALWAYS_INLINE |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 3) || HAS_ATTRIBUTE(nonnull) |
|
#define NONNULL_ARGS __attribute__((__nonnull__)) |
|
#define NONNULL_ARG(...) __attribute__((__nonnull__(__VA_ARGS__))) |
|
#else |
|
#define NONNULL_ARGS |
|
#define NONNULL_ARG(...) |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(3, 4) || HAS_ATTRIBUTE(warn_unused_result) |
|
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) |
|
#else |
|
#define WARN_UNUSED_RESULT |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(4, 1) || HAS_ATTRIBUTE(flatten) |
|
#define FLATTEN __attribute__((__flatten__)) |
|
#else |
|
#define FLATTEN |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(4, 3) || HAS_ATTRIBUTE(hot) |
|
#define HOT __attribute__((__hot__)) |
|
#else |
|
#define HOT |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(4, 3) || HAS_ATTRIBUTE(cold) |
|
#define COLD __attribute__((__cold__)) |
|
#else |
|
#define COLD |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(4, 5) || HAS_BUILTIN(__builtin_unreachable) |
|
#define UNREACHABLE() __builtin_unreachable() |
|
#else |
|
#define UNREACHABLE() |
|
#endif |
|
|
|
#if GNUC_AT_LEAST(5, 0) || HAS_ATTRIBUTE(returns_nonnull) |
|
#define RETURNS_NONNULL __attribute__((__returns_nonnull__)) |
|
#else |
|
#define RETURNS_NONNULL |
|
#endif |
|
|
|
#if HAS_ATTRIBUTE(diagnose_if) |
|
#define DIAGNOSE_IF(x) __attribute__((diagnose_if((x), (#x), "error"))) |
|
#else |
|
#define DIAGNOSE_IF(x) |
|
#endif |
|
|
|
#define XMALLOC MALLOC RETURNS_NONNULL WARN_UNUSED_RESULT |
|
#define XSTRDUP XMALLOC NONNULL_ARGS |
|
|
|
#if __STDC_VERSION__ >= 201112L |
|
#define noreturn _Noreturn |
|
#elif GNUC_AT_LEAST(3, 0) |
|
#define noreturn __attribute__((__noreturn__)) |
|
#else |
|
#define noreturn |
|
#endif |
|
|
|
#if CLANG_AT_LEAST(3, 6) |
|
#define UNROLL_LOOP(n) DO_PRAGMA(clang loop unroll_count(n)) |
|
#elif GNUC_AT_LEAST(8, 0) |
|
#define UNROLL_LOOP(n) DO_PRAGMA(GCC unroll (n)) |
|
#else |
|
#define UNROLL_LOOP(n) |
|
#endif |
|
|
|
#ifdef __COUNTER__ |
|
// Supported by GCC 4.3+ and Clang |
|
#define COUNTER_ __COUNTER__ |
|
#else |
|
#define COUNTER_ __LINE__ |
|
#endif |
|
|
|
#if defined(_DEBUG) && defined(HAVE_ATTR_CONSTRUCTOR) |
|
#define UNITTEST static void CONSTRUCTOR XPASTE(unittest_, COUNTER_)(void) |
|
#else |
|
#define UNITTEST static void UNUSED XPASTE(unittest_, COUNTER_)(void) |
|
#endif |
|
|
|
#ifdef __clang__ |
|
#define IGNORE_WARNING(wflag) \ |
|
DO_PRAGMA(clang diagnostic push) \ |
|
DO_PRAGMA(clang diagnostic ignored "-Wunknown-pragmas") \ |
|
DO_PRAGMA(clang diagnostic ignored "-Wunknown-warning-option") \ |
|
DO_PRAGMA(clang diagnostic ignored wflag) |
|
#define UNIGNORE_WARNINGS DO_PRAGMA(clang diagnostic pop) |
|
#elif GNUC_AT_LEAST(4, 6) |
|
#define IGNORE_WARNING(wflag) \ |
|
DO_PRAGMA(GCC diagnostic push) \ |
|
DO_PRAGMA(GCC diagnostic ignored "-Wpragmas") \ |
|
DO_PRAGMA(GCC diagnostic ignored wflag) |
|
#define UNIGNORE_WARNINGS DO_PRAGMA(GCC diagnostic pop) |
|
#else |
|
#define IGNORE_WARNING(wflag) |
|
#define UNIGNORE_WARNINGS |
|
#endif
|
|
|