mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 18:01:15 +00:00
[gamecode] Add debug hooks to the VM engine
While there was a breakpoint hook, it was for only breakpoints and more was needed. Now there's a generic hook that is called for tracing, breakpoints, watch points, runtime errors and VM errors, with the "event" type passed as the first parameter and a data pointer in the second.
This commit is contained in:
parent
148a351e94
commit
713150b41a
3 changed files with 39 additions and 7 deletions
|
@ -1690,6 +1690,15 @@ typedef struct {
|
|||
strref_t *tstr; ///< Linked list of temporary strings.
|
||||
} prstack_t;
|
||||
|
||||
typedef enum {
|
||||
prd_none,
|
||||
prd_trace,
|
||||
prd_breakpoint,
|
||||
prd_watchpoint,
|
||||
prd_runerror,
|
||||
prd_error, // lower level error thann prd_runerror
|
||||
} prdebug_t;
|
||||
|
||||
struct progs_s {
|
||||
int (*parse_field) (progs_t *pr, const char *key, const char *value);
|
||||
|
||||
|
@ -1831,7 +1840,9 @@ struct progs_s {
|
|||
/// \name debugging
|
||||
///@{
|
||||
struct prdeb_resources_s *pr_debug_resources;
|
||||
void (*breakpoint_handler) (progs_t *pr);
|
||||
void (*debug_handler) (prdebug_t event, void *data);
|
||||
void *debug_data;
|
||||
const char *error_string;
|
||||
pr_type_t *watch;
|
||||
int wp_conditional;
|
||||
pr_type_t wp_val;
|
||||
|
|
|
@ -62,6 +62,12 @@ PR_RunError (progs_t * pr, const char *error, ...)
|
|||
dvsprintf (string, error, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (pr->debug_handler) {
|
||||
pr->error_string = string->str;
|
||||
pr->debug_handler (prd_runerror, pr->debug_data);
|
||||
// not expected to return, but if so, behave as if there was no handler
|
||||
}
|
||||
|
||||
Sys_Printf ("%s\n", string->str);
|
||||
|
||||
PR_DumpState (pr);
|
||||
|
@ -477,12 +483,17 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
op_b = pr->pr_globals + st->b;
|
||||
op_c = pr->pr_globals + st->c;
|
||||
|
||||
if (pr->pr_trace)
|
||||
PR_PrintStatement (pr, st, 1);
|
||||
if (pr->pr_trace) {
|
||||
if (pr->debug_handler) {
|
||||
pr->debug_handler (prd_trace, pr->debug_data);
|
||||
} else {
|
||||
PR_PrintStatement (pr, st, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (st->op & OP_BREAK) {
|
||||
if (pr->breakpoint_handler) {
|
||||
pr->breakpoint_handler (pr);
|
||||
if (pr->debug_handler) {
|
||||
pr->debug_handler (prd_breakpoint, pr->debug_data);
|
||||
} else {
|
||||
PR_RunError (pr, "breakpoint hit");
|
||||
}
|
||||
|
@ -1701,8 +1712,12 @@ op_call:
|
|||
if (watch && watch->integer_var != old_val.integer_var) {
|
||||
if (!pr->wp_conditional
|
||||
|| watch->integer_var == pr->wp_val.integer_var) {
|
||||
PR_RunError (pr, "watchpoint hit: %d -> %d",
|
||||
old_val.integer_var, watch->integer_var);
|
||||
if (pr->debug_handler) {
|
||||
pr->debug_handler (prd_watchpoint, pr->debug_data);
|
||||
} else {
|
||||
PR_RunError (pr, "watchpoint hit: %d -> %d",
|
||||
old_val.integer_var, watch->integer_var);
|
||||
}
|
||||
}
|
||||
old_val.integer_var = watch->integer_var;
|
||||
}
|
||||
|
|
|
@ -323,6 +323,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
|
|||
def->type_encoding = xdef->type;
|
||||
}
|
||||
}
|
||||
pr->error_string = 0;
|
||||
pr->pr_trace = 0;
|
||||
pr->pr_trace_depth = 0;
|
||||
pr->pr_xfunction = 0;
|
||||
|
@ -485,5 +486,10 @@ PR_Error (progs_t *pr, const char *error, ...)
|
|||
dvsprintf (string, error, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (pr->debug_handler) {
|
||||
pr->error_string = string->str;
|
||||
pr->debug_handler (prd_error, pr->debug_data);
|
||||
// not expected to return, but if so, behave as if there was no handler
|
||||
}
|
||||
Sys_Error ("%s: %s", pr->progs_name, string->str);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue