From 3e50aae01f1146070ea4107b47064dbd736f0297 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Sep 2007 07:47:31 +0000 Subject: [PATCH] "print" command for dumping values in the progs and add return type info to the debugging information --- include/QF/pr_debug.h | 4 +- include/QF/progs.h | 1 + libs/gamecode/engine/pr_debug.c | 141 ++++++++++++++++++++----------- libs/gamecode/engine/pr_opcode.c | 3 +- qw/source/sv_pr_cmds.c | 2 +- qw/source/sv_progs.c | 7 ++ tools/qfcc/source/lines.c | 8 +- tools/qfcc/source/obj_file.c | 3 +- tools/qfcc/source/qc-parse.y | 1 + 9 files changed, 115 insertions(+), 55 deletions(-) diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index 908bca5bb..3d3063c7e 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -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; diff --git a/include/QF/progs.h b/include/QF/progs.h index 2dfb671c2..fb75d4def 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -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); diff --git a/libs/gamecode/engine/pr_debug.c b/libs/gamecode/engine/pr_debug.c index a6407f2d8..6acf5f56f 100644 --- a/libs/gamecode/engine/pr_debug.c +++ b/libs/gamecode/engine/pr_debug.c @@ -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 \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, "", 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, "", 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 \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 \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); diff --git a/libs/gamecode/engine/pr_opcode.c b/libs/gamecode/engine/pr_opcode.c index 549c3194e..3bedefd4b 100644 --- a/libs/gamecode/engine/pr_opcode.c +++ b/libs/gamecode/engine/pr_opcode.c @@ -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", OP_RETURN, false, ev_void, ev_void, ev_void, PROG_ID_VERSION, - "%Va", + "%Ra", }, {"!", "not.f", OP_NOT_F, false, diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index df6acf4c4..b3cd330db 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -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"); } /* diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 336f9511d..6a45db86c 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -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 diff --git a/tools/qfcc/source/lines.c b/tools/qfcc/source/lines.c index 64be5e99b..2474cab56 100644 --- a/tools/qfcc/source/lines.c +++ b/tools/qfcc/source/lines.c @@ -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"); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 26df1e9a7..cd8c154c3 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -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) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index c4dfa00ac..707e96c16 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -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; }