#include #include #include #include #include #include #include "assert.h" #include "cstring.h" #include "errors/errors.h" #include "errors/exceptions.h" #include "errors/report.h" #include "object.h" boolean stacktrace = false; #ifdef BSDBACKTRACE #define backtrace_symbols(FRAMES, LENGTH) \ backtrace_symbols_fmt((FRAMES), (LENGTH), "%a <%n%D>") #else #define backtrace_symbols(FRAMES, LENGTH) \ backtrace_symbols((FRAMES), (assert((LENGTH) <= INT_MAX), (int)(LENGTH))) #endif void reportexception(const struct exception caught, cstring const from, const int line, cstring const file) { cstring systemerrormessage = errno ? strerror(errno): 0; cstring exceptionname = ( caught.thrown < 0 ? ( "invalid" ) : caught.thrown == 0 ? ( "abort" ) : caught.thrown >= allerrors ? ( "unknown" ) : ( errorstring((error)caught.thrown).string[errorstring((error)caught.thrown).length] == '\0' ? (cstring)errorstring((error)caught.thrown).string : "-string-" ) ); report( "Debug", "%s; Thrown from %s() near '%s +%d'", exceptionname, caught.function, caught.file, caught.line ); report( "Debug", "%s; Reported by %s() near '%s +%d'", exceptionname, from, file, line ); if (systemerrormessage) { report( "Debug", "%s; strerror(errno): %s", exceptionname, systemerrormessage ); } if (stacktrace) { cstring * const symbols = (cstring *)backtrace_symbols( caught.stacktrace.frames, caught.stacktrace.length ); if (symbols == NULL) { report( "Debug", "%s; backtrace_symbols() failed near '" __FILE__ " +%d': %s", exceptionname, __LINE__, strerror(errno) ); } else { const size_t frames = ( sizeof caught.stacktrace.frames / sizeof *caught.stacktrace.frames ); if (frames && caught.stacktrace.length >= frames - 1) { report( "Debug", "%s; Stacktrace (Warning: May have been truncated.)", exceptionname ); } for (size_t index = 0; index < caught.stacktrace.length; ++index) { report( "Debug", "%s; Stacktrace: %s", exceptionname, symbols[index] ); } free(symbols); } } errno = 0; }