mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
"hardware" (haha) watch points (one!) in progs. only catches changes done by progs, and the expression parser is as flaky as anything, but it's better than nothing :)
This commit is contained in:
parent
0e78c3f6da
commit
fe4a4a9e55
4 changed files with 82 additions and 1 deletions
|
@ -1283,6 +1283,7 @@ void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size);
|
|||
void PR_Debug_Init (void);
|
||||
void PR_Debug_Init_Cvars (void);
|
||||
int PR_LoadDebug (progs_t *pr);
|
||||
void PR_Debug_Watch (progs_t *pr, const char *expr);
|
||||
pr_auxfunction_t *PR_Get_Lineno_Func (progs_t *pr, pr_lineno_t *lineno);
|
||||
pr_uint_t PR_Get_Lineno_Addr (progs_t *pr, pr_lineno_t *lineno);
|
||||
pr_uint_t PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno);
|
||||
|
@ -1452,6 +1453,7 @@ struct progs_s {
|
|||
struct pr_auxfunction_s **auxfunction_map;
|
||||
struct pr_lineno_s *linenos;
|
||||
ddef_t *local_defs;
|
||||
pr_type_t *watch;
|
||||
//@}
|
||||
|
||||
/// required globals (for OP_STATE)
|
||||
|
|
|
@ -41,7 +41,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
# include <strings.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/cvar.h"
|
||||
|
@ -51,6 +51,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "QF/progs.h"
|
||||
#include "QF/qendian.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/script.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
#include "QF/zone.h"
|
||||
|
@ -119,6 +120,68 @@ source_path_f (cvar_t *var)
|
|||
source_paths[i] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_watch_error (script_t *script, const char *msg)
|
||||
{
|
||||
Sys_Printf ("%s\n", msg);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_Debug_Watch (progs_t *pr, const char *expr)
|
||||
{
|
||||
script_t *ws;
|
||||
char *e;
|
||||
|
||||
if (!expr) {
|
||||
Sys_Printf ("watch <watchpoint expr>\n");
|
||||
if (pr->watch) {
|
||||
Sys_Printf (" watching [%d]\n",
|
||||
(int) (intptr_t) (pr->watch - pr->pr_globals));
|
||||
} else {
|
||||
Sys_Printf (" none active\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
ws = Script_New ();
|
||||
ws->error = pr_debug_watch_error;
|
||||
Script_Start (ws, "<console>", expr);
|
||||
pr->watch = 0;
|
||||
if (Script_GetToken (ws, 1)) {
|
||||
if (strequal (ws->token->str, "[")) {
|
||||
edict_t *ent;
|
||||
ddef_t *field;
|
||||
|
||||
if (!Script_GetToken (ws, 1))
|
||||
goto error;
|
||||
ent = EDICT_NUM (pr, strtol (ws->token->str, &e, 0));
|
||||
if (e == ws->token->str)
|
||||
goto error;
|
||||
if (!Script_GetToken (ws, 1) && !strequal (ws->token->str, "]" ))
|
||||
goto error;
|
||||
if (!Script_GetToken (ws, 1) && !strequal (ws->token->str, "." ))
|
||||
goto error;
|
||||
if (!Script_GetToken (ws, 1))
|
||||
goto error;
|
||||
field = PR_FindField (pr, ws->token->str);
|
||||
if (!field)
|
||||
goto error;
|
||||
if (Script_TokenAvailable (ws, 1))
|
||||
Sys_Printf ("ignoring tail\n");
|
||||
pr->watch = &ent->v[field->ofs];
|
||||
} else {
|
||||
ddef_t *global = PR_FindGlobal (pr, ws->token->str);
|
||||
if (!global)
|
||||
goto error;
|
||||
pr->watch = PR_GetPointer (pr, global->ofs);
|
||||
}
|
||||
}
|
||||
error:
|
||||
if (pr->watch)
|
||||
Sys_Printf ("watchpoint set to [%d]\n", PR_SetPointer (pr, pr->watch));
|
||||
else
|
||||
Sys_Printf ("watchpoint cleared\n");
|
||||
}
|
||||
|
||||
void
|
||||
PR_Debug_Init (void)
|
||||
{
|
||||
|
|
|
@ -307,6 +307,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
dstatement_t *st;
|
||||
edict_t *ed;
|
||||
pr_type_t *ptr;
|
||||
pr_type_t old_val, *watch = 0;
|
||||
|
||||
// make a stack frame
|
||||
exitdepth = pr->pr_depth;
|
||||
|
@ -321,6 +322,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
}
|
||||
st = pr->pr_statements + pr->pr_xstatement;
|
||||
|
||||
if (pr->watch) {
|
||||
watch = pr->watch;
|
||||
old_val = *watch;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
pr_type_t *op_a, *op_b, *op_c;
|
||||
|
||||
|
@ -1014,5 +1020,8 @@ op_call:
|
|||
default:
|
||||
PR_RunError (pr, "Bad opcode %i", st->op);
|
||||
}
|
||||
if (watch && watch->integer_var != old_val.integer_var)
|
||||
PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var,
|
||||
watch->integer_var);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,6 +157,12 @@ PR_Profile_f (void)
|
|||
PR_Profile (&sv_pr_state);
|
||||
}
|
||||
|
||||
static void
|
||||
watch_f (void)
|
||||
{
|
||||
PR_Debug_Watch (&sv_pr_state, Cmd_Argc () < 2 ? 0 : Cmd_Args (1));
|
||||
}
|
||||
|
||||
static int
|
||||
parse_field (progs_t *pr, const char *key, const char *value)
|
||||
{
|
||||
|
@ -528,6 +534,7 @@ SV_Progs_Init (void)
|
|||
"Display summary information on the edicts in the game.");
|
||||
Cmd_AddCommand ("profile", PR_Profile_f, "FIXME: Report information about "
|
||||
"QuakeC Stuff (\?\?\?) No Description");
|
||||
Cmd_AddCommand ("watch", watch_f, "set watchpoint");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue