summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/critter.cpp6
-rw-r--r--compat/assert.cpp80
-rw-r--r--compat/assert.hpp100
-rw-r--r--editor/inspect.cpp3
-rw-r--r--editor/save.cpp9
-rw-r--r--main/draw.cpp2
-rw-r--r--src/script.inl14
-rw-r--r--src/timer-ns.cpp1
-rw-r--r--test/critter.cpp5
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++)