Logging nice fatal errors when dying, w/ a msgbox when not in a console.
This commit is contained in:
parent
4741e3581a
commit
7641a5bfed
|
@ -12,11 +12,11 @@
|
|||
#include <xenia/common.h>
|
||||
|
||||
|
||||
void xe_log_line(const char* file_path, const uint32_t line_number,
|
||||
const char* function_name, const char level_char,
|
||||
const char* fmt, ...) {
|
||||
const int kLogMax = 2048;
|
||||
|
||||
void xe_format_log_line(
|
||||
char* buffer, size_t buffer_count,
|
||||
const char* file_path, const uint32_t line_number,
|
||||
const char* function_name, const char level_char,
|
||||
const char* fmt, va_list args) {
|
||||
// Strip out just the filename from the path.
|
||||
const char* filename = xestrrchra(file_path, XE_PATH_SEPARATOR);
|
||||
if (filename) {
|
||||
|
@ -27,32 +27,68 @@ void xe_log_line(const char* file_path, const uint32_t line_number,
|
|||
filename = file_path;
|
||||
}
|
||||
|
||||
// Format string - add a trailing newline if required.
|
||||
const char* outfmt = "XE[%c] %s:%d: ";
|
||||
char* buffer_ptr = buffer + xesnprintfa(
|
||||
buffer, buffer_count - 1, outfmt, level_char, filename, line_number);
|
||||
|
||||
// Scribble args into the print buffer.
|
||||
buffer_ptr = buffer_ptr + xevsnprintfa(
|
||||
buffer_ptr, buffer_count - (buffer_ptr - buffer) - 1, fmt, args);
|
||||
|
||||
// Add a trailing newline.
|
||||
if (buffer_ptr[-1] != '\n') {
|
||||
buffer_ptr[0] = '\n';
|
||||
buffer_ptr[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void xe_log_line(const char* file_path, const uint32_t line_number,
|
||||
const char* function_name, const char level_char,
|
||||
const char* fmt, ...) {
|
||||
char buffer[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char buffer[kLogMax];
|
||||
int buffer_length = xevsnprintfa(buffer, XECOUNT(buffer), fmt, args);
|
||||
xe_format_log_line(buffer, XECOUNT(buffer),
|
||||
file_path, line_number, function_name, level_char,
|
||||
fmt, args);
|
||||
va_end(args);
|
||||
if (buffer_length < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Format string - add a trailing newline if required.
|
||||
const char* outfmt;
|
||||
if ((buffer_length >= 1) && buffer[buffer_length - 1] == '\n') {
|
||||
outfmt = "XE[%c] %s:%d: %s";
|
||||
} else {
|
||||
outfmt = "XE[%c] %s:%d: %s\n";
|
||||
}
|
||||
fprintf(stderr, buffer);
|
||||
fflush(stderr);
|
||||
|
||||
#if 0// defined(OutputDebugString)
|
||||
char full_output[kLogMax];
|
||||
if (xesnprintfa(full_output, XECOUNT(buffer), outfmt, level_char,
|
||||
filename, line_number, buffer) >= 0) {
|
||||
OutputDebugStringA(full_output);
|
||||
}
|
||||
OutputDebugStringA(buffer);
|
||||
#else
|
||||
XEIGNORE(fprintf(stdout, outfmt, level_char, filename, line_number, buffer));
|
||||
XEIGNORE(fprintf(stdout, buffer));
|
||||
fflush(stdout);
|
||||
#endif // OutputDebugString
|
||||
}
|
||||
|
||||
void xe_handle_fatal(
|
||||
const char* file_path, const uint32_t line_number,
|
||||
const char* function_name, const char* fmt, ...) {
|
||||
char buffer[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
xe_format_log_line(buffer, XECOUNT(buffer),
|
||||
file_path, line_number, function_name, 'X',
|
||||
fmt, args);
|
||||
va_end(args);
|
||||
|
||||
#if defined(OutputDebugString)
|
||||
OutputDebugStringA(buffer);
|
||||
#endif // OutputDebugString
|
||||
|
||||
fprintf(stderr, buffer);
|
||||
fflush(stderr);
|
||||
|
||||
#if XE_LIKE_WIN32
|
||||
if (!xe_has_console()) {
|
||||
MessageBoxA(NULL, buffer, "Xenia Error",
|
||||
MB_OK | MB_ICONERROR | MB_APPLMODAL | MB_SETFOREGROUND);
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ void xe_log_line(const char* file_path, const uint32_t line_number,
|
|||
const char* function_name, const char level_char,
|
||||
const char* fmt, ...) XE_LOG_LINE_ATTRIBUTE;
|
||||
#undef XE_LOG_LINE_ATTRIBUTE
|
||||
void xe_handle_fatal(
|
||||
const char* file_path, const uint32_t line_number,
|
||||
const char* function_name, const char* fmt, ...);
|
||||
|
||||
#if XE_OPTION_ENABLE_LOGGING
|
||||
#define XELOGCORE(level, fmt, ...) xe_log_line( \
|
||||
|
@ -34,6 +37,11 @@ void xe_log_line(const char* file_path, const uint32_t line_number,
|
|||
#define XELOGCORE(level, fmt, ...) XE_EMPTY_MACRO
|
||||
#endif // ENABLE_LOGGING
|
||||
|
||||
#define XEFATAL(fmt, ...) do { \
|
||||
xe_handle_fatal(XE_CURRENT_FILE, XE_CURRENT_LINE, XE_CURRENT_FUNCTION, \
|
||||
fmt, ##__VA_ARGS__); \
|
||||
} while (false);
|
||||
|
||||
#if XE_OPTION_LOG_ERROR
|
||||
#define XELOGE(fmt, ...) XELOGCORE('!', fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace {
|
|||
|
||||
typedef int (*user_main_t)(int argc, xechar_t** argv);
|
||||
|
||||
bool _has_console = true;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
@ -58,14 +60,20 @@ int xe_main_thunk(
|
|||
return result;
|
||||
}
|
||||
|
||||
bool xe_has_console() {
|
||||
return _has_console;
|
||||
}
|
||||
|
||||
void xe_attach_console() {
|
||||
bool has_console = AttachConsole(ATTACH_PARENT_PROCESS) == TRUE;
|
||||
if (!has_console) {
|
||||
// We weren't launched from a console, so just return.
|
||||
// We could alloc our own console, but meh:
|
||||
// has_console = AllocConsole() == TRUE;
|
||||
_has_console = false;
|
||||
return;
|
||||
}
|
||||
_has_console = true;
|
||||
|
||||
auto std_handle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
auto con_handle = _open_osfhandle(std_handle, _O_TEXT);
|
||||
|
@ -100,6 +108,10 @@ int xe_main_window_thunk(
|
|||
|
||||
#else
|
||||
|
||||
bool xe_has_console() {
|
||||
return _has_console;
|
||||
}
|
||||
|
||||
int xe_main_thunk(
|
||||
int argc, char** argv,
|
||||
void* user_main, const char* usage) {
|
||||
|
|
|
@ -134,6 +134,7 @@ XE_CPU: 32BIT | 64BIT | BIGENDIAN | LITTLEENDIAN
|
|||
#define XE_ALIGNMENT 16
|
||||
#endif // 32BIT
|
||||
|
||||
bool xe_has_console();
|
||||
#if XE_LIKE_WIN32 && defined(UNICODE) && UNICODE
|
||||
int xe_main_thunk(
|
||||
int argc, wchar_t* argv[],
|
||||
|
|
|
@ -27,6 +27,7 @@ int xenia_run(int argc, xechar_t** argv) {
|
|||
// Grab path from the flag or unnamed argument.
|
||||
if (!FLAGS_target.size() && argc < 2) {
|
||||
google::ShowUsageWithFlags("xenia-run");
|
||||
XEFATAL("Pass a file to launch.");
|
||||
return 1;
|
||||
}
|
||||
const xechar_t* path = NULL;
|
||||
|
@ -55,6 +56,7 @@ int xenia_run(int argc, xechar_t** argv) {
|
|||
const xechar_t* dot = xestrrchr(abs_path, '.');
|
||||
if (!dot) {
|
||||
XELOGE("Invalid input path; no extension found");
|
||||
XEFATAL("Pass a valid file path to launch.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -85,6 +87,9 @@ int xenia_run(int argc, xechar_t** argv) {
|
|||
result_code = 0;
|
||||
XECLEANUP:
|
||||
delete emulator;
|
||||
if (result_code) {
|
||||
XEFATAL("Failed to launch emulator: %d", result_code);
|
||||
}
|
||||
return result_code;
|
||||
}
|
||||
XE_MAIN_WINDOW_THUNK(xenia_run, XETEXT("xenia-run"), "xenia-run some.xex");
|
||||
|
|
Loading…
Reference in New Issue