"print" command for dumping values in the progs and add return type info to the debugging information

This commit is contained in:
Bill Currie 2007-09-15 07:47:31 +00:00 committed by Jeff Teunissen
parent 01b71c40d2
commit 3e50aae01f
9 changed files with 115 additions and 55 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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");
}
/*

View file

@ -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

View file

@ -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");

View file

@ -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) {

View file

@ -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;
}