diff options
-rw-r--r-- | bench/critter.cpp | 6 | ||||
-rw-r--r-- | compat/assert.cpp | 80 | ||||
-rw-r--r-- | compat/assert.hpp | 100 | ||||
-rw-r--r-- | editor/inspect.cpp | 3 | ||||
-rw-r--r-- | editor/save.cpp | 9 | ||||
-rw-r--r-- | main/draw.cpp | 2 | ||||
-rw-r--r-- | src/script.inl | 14 | ||||
-rw-r--r-- | src/timer-ns.cpp | 1 | ||||
-rw-r--r-- | test/critter.cpp | 5 |
9 files changed, 126 insertions, 94 deletions
diff --git a/bench/critter.cpp b/bench/critter.cpp index 3f8505c1..dc60a71a 100644 --- a/bench/critter.cpp +++ b/bench/critter.cpp @@ -138,11 +138,7 @@ bool run(world& w, const function_view<Ns() const>& make_dt, if (b) [[likely]] return false; else - { - fm_assert(false); - fm_EMIT_DEBUG("", "assertion failed: false in %s:%d", file, line); - fm_EMIT_ABORT(); - } + fm_emit_assert_fail("false", file, line); }; for (i = 0; true; i++) diff --git a/compat/assert.cpp b/compat/assert.cpp new file mode 100644 index 00000000..279a08c0 --- /dev/null +++ b/compat/assert.cpp @@ -0,0 +1,80 @@ +#include "assert.hpp" +#include <cstdlib> +#include <cstdio> +#include <cstdarg> + +#ifdef __GNUG__ +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + +namespace floormat { + +namespace { + +template<bool DoPrefix, bool DoSourceLocation> +CORRADE_NEVER_INLINE +void fm_emit_debug_(const char* prefix, const char* file, int line, const char* fmt, va_list arg_ptr) +{ + std::fflush(stdout); + std::fflush(stderr); + if constexpr(DoPrefix) + std::fputs(prefix, stderr); + std::vfprintf(stderr, fmt, arg_ptr); + if constexpr(DoSourceLocation) + std::fprintf(stderr, " in %s:%d", file, line); + std::fputc('\n', stderr); + std::fflush(stderr); +} + +} // namespace + +void fm_emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<true, false>(prefix, nullptr, 0, fmt, arg_ptr); + va_end(arg_ptr); +} + +void fm_emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<false, false>(nullptr, nullptr, 0, fmt, arg_ptr); + va_end(arg_ptr); +} + +void CORRADE_NEVER_INLINE fm_emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<true, true>(prefix, file, line, fmt, arg_ptr); + va_end(arg_ptr); +} + +void fm_emit_assert_fail(const char* expr, const char* file, int line) +{ + std::fflush(stdout); + std::fflush(stderr); + std::fprintf(stderr, "assertion failed: %s in %s:%d", expr, file, line); + std::fflush(stderr); + std::abort(); +} + +void fm_emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<true, true>("fatal: ", file, line, fmt, arg_ptr); + va_end(arg_ptr); + std::abort(); +} + +void fm_emit_abort() +{ + std::fflush(stdout); + std::fflush(stderr); + std::abort(); +} + +} // namespace floormat diff --git a/compat/assert.hpp b/compat/assert.hpp index 363d418b..b048f547 100644 --- a/compat/assert.hpp +++ b/compat/assert.hpp @@ -1,78 +1,43 @@ #pragma once -#include "defs.hpp" -#include <cstdlib> // todo speed up loading by moving printing into a .cpp file -#include <cstdio> // idem. - -namespace floormat::assert_detail { +//#include "defs.hpp" +#if defined __GNUG__ || defined __CLION_IDE__ +#define fm_FORMAT_ARG(n) __attribute__((format (gnu_printf, (n), (n+1)))) +#define fm_FORMAT_ARG_MSVC +#elif defined _MSC_VER +#include <sal.h> +#define fm_FORMAT_ARG(n) +#define fm_FORMAT_ARG_MSVC _Printf_format_string_ +#else +#define fm_FORMAT_ARG(n) +#define fm_FORMAT_ARG_MSVC +#endif +namespace floormat { -#define fm_EMIT_ABORT() do { std::fflush(stdout); std::fflush(stderr); ::std::abort(); } while (false) +void fm_emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(2); +void fm_emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(1); +void fm_emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(4); +void fm_emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3); -} // namespace floormat::assert_detail +[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_assert_fail(const char* expr, const char* file, int line); +[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3); +[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_abort(); +} // namespace floormat #ifdef __GNUG__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-macros" -#ifdef __clang__ -# define FM_KILL_PRINTF_WARN_1_2() \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wformat-nonliteral\"") -# define FM_KILL_PRINTF_WARN_2_2() _Pragma("clang diagnostic pop") -#else -#define FM_KILL_PRINTF_WARN_1_2() -#define FM_KILL_PRINTF_WARN_2_2() -#endif - -#define FM_KILL_PRINTF_WARN_1() \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wdouble-promotion\"") \ - FM_KILL_PRINTF_WARN_1_2() - -#define FM_KILL_PRINTF_WARN_2() _Pragma("GCC diagnostic pop") FM_KILL_PRINTF_WARN_2_2() -#else -#define FM_KILL_PRINTF_WARN_1() -#define FM_KILL_PRINTF_WARN_2() #endif -#define fm_EMIT_DEBUG2(pfx, ...) \ - do { \ - if (!std::is_constant_evaluated()) \ - { \ - if constexpr (sizeof(pfx) > 1) \ - std::fputs((pfx), stderr); \ - std::fflush(stderr); \ - FM_KILL_PRINTF_WARN_1() \ - std::fprintf(stderr, __VA_ARGS__); \ - FM_KILL_PRINTF_WARN_2() \ - } \ - } while (false) - -#define fm_EMIT_DEBUG(pfx, ...) \ - do { \ - if (!std::is_constant_evaluated()) \ - { \ - fm_EMIT_DEBUG2(pfx, __VA_ARGS__); \ - std::fputc('\n', stderr); \ - std::fflush(stderr); \ - } \ - } while (false) - -#define fm_abort(...) \ - do { \ - fm_EMIT_DEBUG2("fatal: ", __VA_ARGS__); \ - fm_EMIT_DEBUG("", " in %s:%d", __FILE__, __LINE__); \ - fm_EMIT_ABORT(); \ - } while (false) - -#define fm_assert(...) \ - do { \ - if (!(__VA_ARGS__)) /*NOLINT(*-simplify-boolean-expr)*/ [[unlikely]] { \ - fm_EMIT_DEBUG("", "assertion failed: %s in %s:%d", \ - #__VA_ARGS__, __FILE__, __LINE__); \ - fm_EMIT_ABORT(); \ - } \ - } while(false) +#define fm_assert(...) ((__VA_ARGS__) ? void() : ::floormat::fm_emit_assert_fail(#__VA_ARGS__, __FILE__, __LINE__)) +#define fm_abort(...) (::floormat::fm_emit_abort(__FILE__, __LINE__, __VA_ARGS__)) +#define fm_warn(...) (::floormat::fm_emit_debug("warning: ", __VA_ARGS__)) +#define fm_error(...) (::floormat::fm_emit_debug("error: ", __VA_ARGS__)) +#define fm_log(...) (::floormat::fm_emit_debug0(__VA_ARGS__)) +#define fm_debug(...) (::floormat::fm_emit_debug0(__VA_ARGS__)) +#define fm_debug_loc(pfx, ...) (::floormat::fm_emit_debug_loc(pfx, __FILE__, __LINE__,__VA_ARGS__)) +#define fm_debug_loc0(...) (::floormat::fm_emit_debug_loc0(__FILE__, __LINE__,__VA_ARGS__)) #ifndef FM_NO_DEBUG #define fm_debug_assert(...) fm_assert(__VA_ARGS__) @@ -80,11 +45,6 @@ namespace floormat::assert_detail { #define fm_debug_assert(...) void() #endif -#define fm_warn(...) fm_EMIT_DEBUG("warning: ", __VA_ARGS__) -#define fm_error(...) fm_EMIT_DEBUG("error: ", __VA_ARGS__) -#define fm_log(...) fm_EMIT_DEBUG("", __VA_ARGS__) -#define fm_debug(...) fm_EMIT_DEBUG("", __VA_ARGS__) - #define fm_warn_once(...) do { \ static bool _fm_once_flag = false; \ if (!_fm_once_flag) [[unlikely]] { \ @@ -106,7 +66,7 @@ namespace floormat::assert_detail { ERR_nospace << #__VA_ARGS__; \ ERR_nospace << " expected: " << a; \ ERR_nospace << " actual: " << b; \ - fm_EMIT_ABORT(); \ + fm_emit_abort(); \ } \ })(__VA_ARGS__) diff --git a/editor/inspect.cpp b/editor/inspect.cpp index 470c5bd2..e7d8878a 100644 --- a/editor/inspect.cpp +++ b/editor/inspect.cpp @@ -3,6 +3,8 @@ #include "compat/defs.hpp" #include "entity/accessor.hpp" #include "imgui-raii.hpp" +#include <cstdio> +#include <utility> #include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/String.h> #include <Magnum/Math/Functions.h> @@ -10,7 +12,6 @@ #include <Magnum/Math/Vector3.h> #include <Magnum/Math/Vector4.h> #include <Magnum/Math/Color.h> -#include <utility> namespace floormat::entities { diff --git a/editor/save.cpp b/editor/save.cpp index ef14c11c..2c073e01 100644 --- a/editor/save.cpp +++ b/editor/save.cpp @@ -2,6 +2,7 @@ #include "floormat/main.hpp" #include "src/world.hpp" #include "loader/loader.hpp" +#include <cstdio> #include <Corrade/Containers/String.h> #include <Corrade/Utility/Path.h> @@ -36,10 +37,10 @@ void app::do_quicksave() world.collect(true); if (Path::exists(tmp)) Path::remove(tmp); - fputs("quicksave... ", stderr); fflush(stderr); + std::fputs("quicksave... ", stderr); std::fflush(stderr); world.serialize(tmp); Path::move(tmp, file); - fputs("done\n", stderr); fflush(stderr); + std::fputs("done\n", stderr); std::fflush(stderr); } void app::do_quickload() @@ -52,9 +53,9 @@ void app::do_quickload() fm_warn("no quicksave"); return; } - fputs("quickload... ", stderr); fflush(stderr); + std::fputs("quickload... ", stderr); std::fflush(stderr); reset_world(world::deserialize(file, loader_policy::warn)); - fputs("done\n", stderr); fflush(stderr); + std::fputs("done\n", stderr); std::fflush(stderr); } void app::do_new_file() diff --git a/main/draw.cpp b/main/draw.cpp index e5fb9e69..802a4e9d 100644 --- a/main/draw.cpp +++ b/main/draw.cpp @@ -36,7 +36,7 @@ void main_impl::do_update(const Ns& dtʹ) value = secs; #endif if (secs > 35e-3f /* && !dt_expected.do_sleep */) [[likely]] - fm_debug("%zu frame took %.2f milliseconds", bad_frame_counter++, (double)(secs*1e3)); + fm_debug("%zu frame took %.2f milliseconds", bad_frame_counter++, (double)secs*1e3); } else swapBuffers(); diff --git a/src/script.inl b/src/script.inl index e5057039..a6c93588 100644 --- a/src/script.inl +++ b/src/script.inl @@ -63,15 +63,11 @@ Script<S, Obj>::Script(): ptr{nullptr}, _state{script_lifecycle::no_init} template <typename S, typename Obj> void Script<S, Obj>::_assert_state(script_lifecycle s, const char* file, int line) { - if (_state != s) - { - fm_EMIT_DEBUG2("fatal: ", - "invalid state transition from '%s' to '%s'", - base_script::state_name(_state).data(), - base_script::state_name(s).data()); - fm_EMIT_DEBUG("", " in %s:%d", file, line); - fm_EMIT_ABORT(); - } + if (_state != s) [[unlikely]] + fm_emit_abort(file, line, + "invalid state transition from '%s' to '%s'", + base_script::state_name(_state).data(), + base_script::state_name(s).data()); } template <typename S, typename Obj> script_lifecycle Script<S, Obj>::state() const { return _state; } diff --git a/src/timer-ns.cpp b/src/timer-ns.cpp index e781e66c..196888d0 100644 --- a/src/timer-ns.cpp +++ b/src/timer-ns.cpp @@ -2,6 +2,7 @@ #include "compat/assert.hpp" #include "compat/debug.hpp" #include <cinttypes> +#include <cstdio> #include <cr/Debug.h> #include <mg/Functions.h> diff --git a/test/critter.cpp b/test/critter.cpp index d9f50205..950e2d01 100644 --- a/test/critter.cpp +++ b/test/critter.cpp @@ -147,10 +147,7 @@ bool run(world& w, const function_view<Ns() const>& make_dt, if (b) [[likely]] return false; else - { - fm_EMIT_DEBUG("", "assertion failed: false in %s:%d", file, line); - fm_EMIT_ABORT(); - } + fm_emit_assert_fail("false", file, line); }; for (i = 0; true; i++) |