#pragma once #define PASTE(a, b) a##b #define XPASTE(a, b) PASTE(a, b) #define STRLEN(str) (sizeof("" str "") - 1) #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