mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
"print" command for dumping values in the progs and add return type info to the debugging information
This commit is contained in:
parent
01b71c40d2
commit
3e50aae01f
9 changed files with 115 additions and 55 deletions
|
@ -40,6 +40,8 @@ typedef struct pr_auxfunction_s {
|
|||
pr_uint_t line_info; // index to first lineno entry
|
||||
pr_uint_t local_defs; // index to the first local def
|
||||
pr_uint_t num_locals; // number of local defs
|
||||
pr_short_t return_type; // return type of this function
|
||||
pr_short_t reserved;
|
||||
} pr_auxfunction_t;
|
||||
|
||||
typedef struct pr_lineno_s {
|
||||
|
@ -50,7 +52,7 @@ typedef struct pr_lineno_s {
|
|||
pr_uint_t line;
|
||||
} pr_lineno_t;
|
||||
|
||||
#define PROG_DEBUG_VERSION 0x00001001 // MMmmmRRR 0.001.001 (hex)
|
||||
#define PROG_DEBUG_VERSION 0x00001002 // MMmmmRRR 0.001.002 (hex)
|
||||
|
||||
typedef struct pr_debug_header_s {
|
||||
pr_int_t version;
|
||||
|
|
|
@ -1294,6 +1294,7 @@ 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);
|
||||
void PR_Debug_Print (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);
|
||||
|
|
|
@ -121,84 +121,68 @@ source_path_f (cvar_t *var)
|
|||
}
|
||||
|
||||
static void
|
||||
pr_debug_watch_error (script_t *script, const char *msg)
|
||||
pr_debug_expression_error (script_t *script, const char *msg)
|
||||
{
|
||||
Sys_Printf ("%s\n", msg);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_Debug_Watch (progs_t *pr, const char *expr)
|
||||
static pr_type_t *
|
||||
parse_expression (progs_t *pr, const char *expr)
|
||||
{
|
||||
script_t *ws;
|
||||
script_t *es;
|
||||
char *e;
|
||||
pr_type_t *expr_ptr;
|
||||
|
||||
if (!expr) {
|
||||
Sys_Printf ("watch <watchpoint expr>\n");
|
||||
if (pr->watch) {
|
||||
Sys_Printf (" watching [%d]\n",
|
||||
(int) (intptr_t) (pr->watch - pr->pr_globals));
|
||||
if (pr->wp_conditional)
|
||||
Sys_Printf (" if new val == %d\n",
|
||||
pr->wp_val.integer_var);
|
||||
} 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, "[")) {
|
||||
es = Script_New ();
|
||||
es->error = pr_debug_expression_error;
|
||||
Script_Start (es, "<console>", expr);
|
||||
expr_ptr = 0;
|
||||
if (Script_GetToken (es, 1)) {
|
||||
if (strequal (es->token->str, "[")) {
|
||||
edict_t *ent;
|
||||
ddef_t *field;
|
||||
|
||||
if (!Script_GetToken (ws, 1))
|
||||
if (!Script_GetToken (es, 1))
|
||||
goto error;
|
||||
ent = EDICT_NUM (pr, strtol (ws->token->str, &e, 0));
|
||||
if (e == ws->token->str)
|
||||
ent = EDICT_NUM (pr, strtol (es->token->str, &e, 0));
|
||||
if (e == es->token->str)
|
||||
goto error;
|
||||
if (!Script_GetToken (ws, 1) && !strequal (ws->token->str, "]" ))
|
||||
if (!Script_GetToken (es, 1) && !strequal (es->token->str, "]" ))
|
||||
goto error;
|
||||
if (!Script_GetToken (ws, 1) && !strequal (ws->token->str, "." ))
|
||||
if (!Script_GetToken (es, 1) && !strequal (es->token->str, "." ))
|
||||
goto error;
|
||||
if (!Script_GetToken (ws, 1))
|
||||
if (!Script_GetToken (es, 1))
|
||||
goto error;
|
||||
field = PR_FindField (pr, ws->token->str);
|
||||
field = PR_FindField (pr, es->token->str);
|
||||
if (!field)
|
||||
goto error;
|
||||
pr->watch = &ent->v[field->ofs];
|
||||
expr_ptr = &ent->v[field->ofs];
|
||||
} else if (isdigit (es->token->str[0])) {
|
||||
expr_ptr = PR_GetPointer (pr, strtol (es->token->str, 0, 0));
|
||||
} else {
|
||||
ddef_t *global = PR_FindGlobal (pr, ws->token->str);
|
||||
ddef_t *global = PR_FindGlobal (pr, es->token->str);
|
||||
if (!global)
|
||||
goto error;
|
||||
pr->watch = PR_GetPointer (pr, global->ofs);
|
||||
expr_ptr = PR_GetPointer (pr, global->ofs);
|
||||
}
|
||||
pr->wp_conditional = 0;
|
||||
if (Script_TokenAvailable (ws, 1)) {
|
||||
if (!Script_GetToken (ws, 1) && !strequal (ws->token->str, "==" ))
|
||||
if (Script_TokenAvailable (es, 1)) {
|
||||
if (!Script_GetToken (es, 1) && !strequal (es->token->str, "==" ))
|
||||
goto error;
|
||||
if (!Script_GetToken (ws, 1))
|
||||
if (!Script_GetToken (es, 1))
|
||||
goto error;
|
||||
pr->wp_val.integer_var = strtol (ws->token->str, &e, 0);
|
||||
if (e == ws->token->str)
|
||||
pr->wp_val.integer_var = strtol (es->token->str, &e, 0);
|
||||
if (e == es->token->str)
|
||||
goto error;
|
||||
if (*e == '.' || *e == 'e' || *e == 'E')
|
||||
pr->wp_val.float_var = strtod (ws->token->str, &e);
|
||||
pr->wp_val.float_var = strtod (es->token->str, &e);
|
||||
pr->wp_conditional = 1;
|
||||
}
|
||||
if (Script_TokenAvailable (ws, 1))
|
||||
if (Script_TokenAvailable (es, 1))
|
||||
Sys_Printf ("ignoring tail\n");
|
||||
}
|
||||
error:
|
||||
if (pr->watch) {
|
||||
Sys_Printf ("watchpoint set to [%d]\n", PR_SetPointer (pr, pr->watch));
|
||||
if (pr->wp_conditional)
|
||||
Sys_Printf (" if new val == %d\n", pr->wp_val.integer_var);
|
||||
} else {
|
||||
Sys_Printf ("watchpoint cleared\n");
|
||||
}
|
||||
return expr_ptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -493,6 +477,16 @@ PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm)
|
|||
return ddef;
|
||||
}
|
||||
|
||||
static pr_auxfunction_t *
|
||||
get_aux_function (progs_t *pr)
|
||||
{
|
||||
dfunction_t *func;
|
||||
if (!pr->pr_xfunction)
|
||||
return 0;
|
||||
func = pr->pr_xfunction->descriptor;
|
||||
return pr->auxfunction_map[func - pr->pr_functions];
|
||||
}
|
||||
|
||||
ddef_t *
|
||||
PR_Get_Local_Def (progs_t *pr, pr_int_t offs)
|
||||
{
|
||||
|
@ -712,6 +706,51 @@ global_string (progs_t *pr, pr_int_t ofs, etype_t type, int contents)
|
|||
return line->str;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_Debug_Watch (progs_t *pr, const char *expr)
|
||||
{
|
||||
if (!expr) {
|
||||
Sys_Printf ("watch <watchpoint expr>\n");
|
||||
if (pr->watch) {
|
||||
Sys_Printf (" watching [%d]\n",
|
||||
(int) (intptr_t) (pr->watch - pr->pr_globals));
|
||||
if (pr->wp_conditional)
|
||||
Sys_Printf (" if new val == %d\n",
|
||||
pr->wp_val.integer_var);
|
||||
} else {
|
||||
Sys_Printf (" none active\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pr->watch = parse_expression (pr, expr);
|
||||
if (pr->watch) {
|
||||
Sys_Printf ("watchpoint set to [%d]\n", PR_SetPointer (pr, pr->watch));
|
||||
if (pr->wp_conditional)
|
||||
Sys_Printf (" if new val == %d\n", pr->wp_val.integer_var);
|
||||
} else {
|
||||
Sys_Printf ("watchpoint cleared\n");
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_Debug_Print (progs_t *pr, const char *expr)
|
||||
{
|
||||
pr_type_t *print;
|
||||
|
||||
if (!expr) {
|
||||
Sys_Printf ("print <print expr>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
print = parse_expression (pr, expr);
|
||||
if (print) {
|
||||
pr_int_t ofs = PR_SetPointer (pr, print);
|
||||
const char *s = global_string (pr, ofs, ev_void, 1);
|
||||
Sys_Printf ("[%d] = %s\n", ofs, s);
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
||||
{
|
||||
|
@ -722,6 +761,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
|||
static dstring_t *line;
|
||||
dfunction_t *call_func = 0;
|
||||
ddef_t *parm_def = 0;
|
||||
pr_auxfunction_t *aux_func = 0;
|
||||
|
||||
if (!line)
|
||||
line = dstring_new ();
|
||||
|
@ -805,6 +845,13 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
|||
goto err;
|
||||
}
|
||||
switch (mode) {
|
||||
case 'R':
|
||||
optype = ev_void;
|
||||
aux_func = get_aux_function (pr);
|
||||
if (aux_func)
|
||||
optype = aux_func->return_type;
|
||||
str = global_string (pr, opval, optype, contents & 1);
|
||||
break;
|
||||
case 'F':
|
||||
str = global_string (pr, opval, optype, contents & 1);
|
||||
call_func = pr->pr_functions + G_FUNCTION (pr, opval);
|
||||
|
|
|
@ -96,6 +96,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = {
|
|||
// O address + short
|
||||
// P function parameter
|
||||
// F function (must come before any P)
|
||||
// R return value
|
||||
//
|
||||
// a operand a
|
||||
// b operand b
|
||||
|
@ -710,7 +711,7 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
{"<RETURN>", "return", OP_RETURN, false,
|
||||
ev_void, ev_void, ev_void,
|
||||
PROG_ID_VERSION,
|
||||
"%Va",
|
||||
"%Ra",
|
||||
},
|
||||
|
||||
{"!", "not.f", OP_NOT_F, false,
|
||||
|
|
|
@ -107,7 +107,7 @@ PF_objerror (progs_t *pr)
|
|||
ED_Print (pr, ed);
|
||||
ED_Free (pr, ed);
|
||||
|
||||
Sys_Error ("Program error");
|
||||
PR_RunError (pr, "object error");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -163,6 +163,12 @@ watch_f (void)
|
|||
PR_Debug_Watch (&sv_pr_state, Cmd_Argc () < 2 ? 0 : Cmd_Args (1));
|
||||
}
|
||||
|
||||
static void
|
||||
print_f (void)
|
||||
{
|
||||
PR_Debug_Print (&sv_pr_state, Cmd_Argc () < 2 ? 0 : Cmd_Args (1));
|
||||
}
|
||||
|
||||
static int
|
||||
parse_field (progs_t *pr, const char *key, const char *value)
|
||||
{
|
||||
|
@ -535,6 +541,7 @@ SV_Progs_Init (void)
|
|||
Cmd_AddCommand ("profile", PR_Profile_f, "FIXME: Report information about "
|
||||
"QuakeC Stuff (\?\?\?) No Description");
|
||||
Cmd_AddCommand ("watch", watch_f, "set watchpoint");
|
||||
Cmd_AddCommand ("print", print_f, "print value at location");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -79,13 +79,13 @@ dump_lines (progs_t *pr)
|
|||
addr = lineno->line ? lineno->fa.addr
|
||||
: (unsigned int) func->first_statement;
|
||||
if (aux_func && func)
|
||||
printf (" %05x %s:%u %s+%u", addr, pr->pr_strings + func->s_file,
|
||||
printf (" %05x %s:%u %s+%u %d", addr, pr->pr_strings + func->s_file,
|
||||
line, pr->pr_strings + func->s_name,
|
||||
addr - func->first_statement);
|
||||
addr - func->first_statement, aux_func->return_type);
|
||||
else if (aux_func)
|
||||
printf ("%u %u %u %u %u", aux_func->function, line,
|
||||
printf ("%u %u %u %u %u %d", aux_func->function, line,
|
||||
aux_func->line_info, aux_func->local_defs,
|
||||
aux_func->num_locals);
|
||||
aux_func->num_locals, aux_func->return_type);
|
||||
else if (lineno->line)
|
||||
printf ("%5x", lineno->fa.addr);
|
||||
printf ("\n");
|
||||
|
|
|
@ -566,18 +566,19 @@ qfo_to_progs (qfo_t *qfo, pr_info_t *pr)
|
|||
i < qfo->num_funcs; i++, pf++, qf++) {
|
||||
*pr->func_tail = pf;
|
||||
pr->func_tail = &pf->next;
|
||||
pf->def = pr->scope->head + qf->def;
|
||||
pf->aux = new_auxfunction ();
|
||||
pf->aux->function = i + 1;
|
||||
pf->aux->source_line = qf->line;
|
||||
pf->aux->line_info = qf->line_info;
|
||||
pf->aux->local_defs = 0;
|
||||
pf->aux->num_locals = 0;
|
||||
pf->aux->return_type = pf->def->type->aux_type->type;
|
||||
pf->builtin = qf->builtin;
|
||||
pf->code = qf->code;
|
||||
pf->function_num = i + 1;
|
||||
pf->s_file = qf->file;
|
||||
pf->s_name = qf->name;
|
||||
pf->def = pr->scope->head + qf->def;
|
||||
pf->scope = new_scope (sc_params, init_space (qf->locals_size, 0),
|
||||
pr->scope);
|
||||
if (qf->num_local_defs) {
|
||||
|
|
|
@ -724,6 +724,7 @@ begin_function
|
|||
$$->aux->source_line = $$->def->line;
|
||||
$$->aux->line_info = lineno - pr.linenos;
|
||||
$$->aux->local_defs = pr.num_locals;
|
||||
$$->aux->return_type = $$->def->type->aux_type->type;
|
||||
|
||||
lineno->fa.func = $$->aux - pr.auxfunctions;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue