diff --git a/src/lib/seallib/assert.cpp b/src/lib/seallib/assert.cpp new file mode 100644 index 0000000..d49c5c5 --- /dev/null +++ b/src/lib/seallib/assert.cpp @@ -0,0 +1,59 @@ +#include "assert.h" + +#include +#include + +#ifdef _WIN32 + // from: WinUser.h + #ifndef MB_ICONHAND + #define MB_ICONHAND 0x00000010L + #define MB_ICONERROR MB_ICONHAND + + #define MB_SYSTEMMODAL 0x00001000L + + #define MB_OK 0x00000000L + #endif + +extern "C" +{ + __declspec(dllimport) void* __stdcall GetModuleHandleA(const char* lpModuleName); + __declspec(dllimport) void* __stdcall LoadLibraryA(const char* lpLibFileName); + __declspec(dllimport) int(__stdcall* __stdcall GetProcAddress(void* hModule, const char* lpProcName))(); +} +#endif + +#ifdef __linux + #include +#endif + +std::string safeShellEscape(const std::string& input) +{ + std::string escaped; + for (char c : input) + { + if (c == '"' || c == '\\' || c == '`' || c == '$') escaped += '\\'; + escaped += c; + } + return escaped; +} + +void seallib::displayError(const char* msg, const char* file, int line) +{ + std::string fullError = std::string(msg) + "\n\nFile: " + file + "\nLine: " + std::to_string(line); + std::cerr << "[FATAL ERROR] " << fullError << std::endl; + +#ifdef _WIN32 + typedef int(__stdcall * fnMessageBoxA)(void*, const char*, const char*, unsigned int); + if (void* hUser32 = GetModuleHandleA("user32.dll") ? GetModuleHandleA("user32.dll") : LoadLibraryA("user32.dll")) + { + auto msgBoxA = reinterpret_cast(GetProcAddress(hUser32, "MessageBoxA")); + if (msgBoxA) msgBoxA(nullptr, fullError.c_str(), "Fatal Error Occurred", MB_ICONERROR | MB_OK | MB_SYSTEMMODAL); + } +#elif __linux__ + std::string safeMsg = safeShellEscape(fullError); + if (std::system("which zenity > /dev/null 2>&1") == 0) + std::system(("zenity --error --text=\"" + safeMsg + "\" --title=\"Fatal Error\" 2>/dev/null").c_str()); + else if (std::system("which kdialog > /dev/null 2>&1") == 0) + std::system(("kdialog --error \"" + safeMsg + "\" 2>/dev/null").c_str()); +#endif +} diff --git a/src/lib/seallib/assert.h b/src/lib/seallib/assert.h new file mode 100644 index 0000000..73b2d1f --- /dev/null +++ b/src/lib/seallib/assert.h @@ -0,0 +1,51 @@ +#pragma once + +#if defined(_MSC_VER) + #define SEALLIB_DEBUGBREAK() __debugbreak() + #define SEALLIB_ASSUME(cond) __assume(cond) +#elif defined(__GNUC__) || defined(__clang__) + #define SEALLIB_DEBUGBREAK() __builtin_trap() + #define SEALLIB_ASSUME(cond) \ + do \ + { \ + if (!(cond)) __builtin_unreachable(); \ + } while (0) +#else + #define SEALLIB_DEBUGBREAK() \ + do \ + { \ + } while (0) + #define SEALLIB_ASSUME(cond) \ + do \ + { \ + } while (0) +#endif + +#ifdef _DEBUG + #define ASSERT(cond, msg) \ + do \ + { \ + if (!(cond)) \ + { \ + seallib::displayError(msg, __FILE__, __LINE__); \ + SEALLIB_DEBUGBREAK(); \ + std::exit(EXIT_FAILURE); \ + } \ + SEALLIB_ASSUME(cond); \ + } while (0) +#else + #define ASSERT(cond, msg) SEALLIB_ASSUME(cond) +#endif + +#define PANIC(msg) \ + do \ + { \ + seallib::displayError(msg, __FILE__, __LINE__); \ + SEALLIB_DEBUGBREAK(); \ + std::exit(EXIT_FAILURE); \ + } while (0) + +namespace seallib +{ + void displayError(const char* msg, const char* file, int line); +}