#ifndef GU_ASSERT_H_ #define GU_ASSERT_H_ #include typedef enum { GU_ASSERT_PRECOND, GU_ASSERT_ASSERTION, GU_ASSERT_POSTCOND, GU_ASSERT_NEVER } GuAssertMode; void gu_abort_v_(GuAssertMode mode, const char* file, const char* func, int line, const char* msg_fmt, va_list args); void gu_abort_(GuAssertMode mode, const char* file, const char* func, int line, const char* msg_fmt, ...); #ifndef NDEBUG #define gu_assertion_(mode_, expr_, ...) \ GU_BEGIN \ if (!(expr_)) { \ gu_abort_(mode_, __FILE__, __func__, __LINE__, __VA_ARGS__); \ } \ GU_END #else // this should prevent unused variable warnings when a variable is only used // in an assertion #define gu_assertion_(mode_, expr_, ...) \ GU_BEGIN \ (void) (sizeof (expr_)); \ GU_END #endif #define gu_require(expr) \ gu_assertion_(GU_ASSERT_PRECOND, expr, "%s", #expr) #define gu_assert_msg(expr, ...) \ gu_assertion_(GU_ASSERT_ASSERTION, expr, __VA_ARGS__) #define gu_assert(expr) \ gu_assert_msg(expr, "%s", #expr) #define gu_ensure(expr) \ gu_assertion_(GU_ASSERT_POSTCOND, expr, "%s", #expr) #define gu_impossible_msg(...) \ gu_assertion_(GU_ASSERT_ASSERTION, false, __VA_ARGS__) #define gu_impossible() \ gu_impossible_msg(NULL) void gu_fatal(const char* fmt, ...); #endif /* GU_ASSERT_H_ */