Allow Sys_Error to be hooked.

This makes debugging builtins that wrap normal functions a little easier by
giving a progs dump when such an error occurs.
This commit is contained in:
Bill Currie 2016-01-03 23:04:00 +09:00
parent 735fcf68d5
commit 546e333a3c
3 changed files with 59 additions and 4 deletions

View file

@ -63,13 +63,18 @@ int Sys_isdir (const char *path);
int Sys_mkdir (const char *path);
typedef void (*sys_printf_t) (const char *fmt, va_list args);
typedef void (*sys_error_t) (void *data);
void Sys_SetStdPrintf (sys_printf_t func);
void Sys_SetErrPrintf (sys_printf_t func);
void Sys_PushErrorHandler (sys_error_t func, void *data);
void Sys_PopErrorHandler (void);
void Sys_Print (FILE *stream, const char *fmt, va_list args);
void Sys_Printf (const char *fmt, ...) __attribute__((format(printf,1,2)));
void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn));
void Sys_FatalError (const char *error, ...) __attribute__((format(printf,1,2), noreturn));
void Sys_Quit (void) __attribute__((noreturn));
void Sys_Shutdown (void);
void Sys_RegisterShutdown (void (*func) (void));

View file

@ -328,6 +328,14 @@ signal_hook (int sig, void *data)
return 0;
}
static void
error_handler (void *data)
{
progs_t *pr = (progs_t *) data;
PR_DumpState (pr);
fflush (stdout);
}
VISIBLE int
PR_CallFunction (progs_t *pr, func_t fnum)
{
@ -370,11 +378,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
startprofile = profile = 0;
Sys_PushSignalHook (signal_hook, pr);
Sys_PushErrorHandler (error_handler, pr);
if (!PR_CallFunction (pr, fnum)) {
// called a builtin instead of progs code
Sys_PopSignalHook ();
return;
goto exit_program;
}
st = pr->pr_statements + pr->pr_xstatement;
@ -964,8 +972,8 @@ op_call:
if (pr->pr_depth == exitdepth) {
if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth)
pr->pr_trace = false;
Sys_PopSignalHook ();
return; // all done
// all done
goto exit_program;
}
break;
case OP_STATE:
@ -1116,4 +1124,7 @@ op_call:
PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var,
watch->integer_var);
}
exit_program:
Sys_PopErrorHandler ();
Sys_PopSignalHook ();
}

View file

@ -79,6 +79,7 @@
#include "qfalloca.h"
#include "QF/alloc.h"
#include "QF/cmd.h"
#include "QF/cvar.h"
#include "QF/dstring.h"
@ -107,8 +108,17 @@ typedef struct shutdown_list_s {
void (*func)(void);
} shutdown_list_t;
typedef struct error_handler_s {
struct error_handler_s *next;
sys_error_t func;
void *data;
} error_handler_t;
static shutdown_list_t *shutdown_list;
static error_handler_t *error_handler_freelist;
static error_handler_t *error_handler;
#ifndef _WIN32
static int do_stdin = 1;
qboolean stdin_ready;
@ -493,6 +503,31 @@ Sys_Quit (void)
exit (0);
}
VISIBLE void
Sys_PushErrorHandler (sys_error_t func, void *data)
{
error_handler_t *eh;
ALLOC (16, error_handler_t, error_handler, eh);
eh->func = func;
eh->data = data;
eh->next = error_handler;
error_handler = eh;
}
VISIBLE void
Sys_PopErrorHandler (void)
{
error_handler_t *eh;
if (!error_handler) {
Sys_Error ("Sys_PopErrorHandler: no handler to pop");
}
eh = error_handler;
error_handler = eh->next;
FREE (error_handler, eh);
}
VISIBLE void
Sys_Error (const char *error, ...)
{
@ -515,6 +550,10 @@ Sys_Error (const char *error, ...)
sys_err_printf_function (error, args);
va_end (args);
if (error_handler) {
error_handler->func (error_handler->data);
}
Sys_Shutdown ();
if (sys_err_printf_function != Sys_ErrPrintf) {