mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
Rework progs debug to use the type encodings
It's only a start: the output is, if anything, slightly worse than before, but it does have the basics going.
This commit is contained in:
parent
4b7ecdf74a
commit
b173c35eb4
2 changed files with 519 additions and 188 deletions
|
@ -1492,6 +1492,49 @@ void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size);
|
|||
/// \addtogroup debug
|
||||
///@{
|
||||
|
||||
struct qfot_type_s;
|
||||
|
||||
/** Callback for viewing progs data
|
||||
|
||||
\param type C pointer to the type definition by which to view the
|
||||
data.
|
||||
\param value C pointer to the data to be viewed.
|
||||
\param data User data.
|
||||
*/
|
||||
typedef void (*type_view_func) (struct qfot_type_s *type, pr_type_t *value,
|
||||
void *data);
|
||||
|
||||
/** Set of callbacks for viewing progs data
|
||||
|
||||
Each possible type has its own callback. Basic types (those for which the
|
||||
VM has specific instructions) all have separate callbacks, one for each
|
||||
type, but the callbacks for compound types are expected to some
|
||||
interpretation on their own, such as displaying a simple identifier or
|
||||
the entire contents of the data.
|
||||
*/
|
||||
typedef struct type_view_s {
|
||||
type_view_func void_view;
|
||||
type_view_func string_view;
|
||||
type_view_func float_view;
|
||||
type_view_func vector_view;
|
||||
type_view_func entity_view;
|
||||
type_view_func field_view;
|
||||
type_view_func func_view;
|
||||
type_view_func pointer_view;
|
||||
type_view_func quat_view;
|
||||
type_view_func integer_view;
|
||||
type_view_func uinteger_view;
|
||||
type_view_func short_view;
|
||||
type_view_func double_view;
|
||||
|
||||
type_view_func struct_view;
|
||||
type_view_func union_view;
|
||||
type_view_func enum_view;
|
||||
type_view_func array_view;
|
||||
type_view_func class_view;
|
||||
type_view_func alias_view;
|
||||
} type_view_t;
|
||||
|
||||
void PR_Debug_Init (progs_t *pr);
|
||||
void PR_Debug_Init_Cvars (void);
|
||||
int PR_LoadDebug (progs_t *pr);
|
||||
|
|
|
@ -71,12 +71,81 @@ typedef struct {
|
|||
progs_t *pr;
|
||||
} file_t;
|
||||
|
||||
typedef struct {
|
||||
dstring_t *string;
|
||||
} pr_debug_resources_t;
|
||||
|
||||
typedef struct {
|
||||
progs_t *pr;
|
||||
dstring_t *dstr;
|
||||
} pr_debug_data_t;
|
||||
|
||||
cvar_t *pr_debug;
|
||||
cvar_t *pr_source_path;
|
||||
static hashtab_t *file_hash;
|
||||
static char *source_path_string;
|
||||
static char **source_paths;
|
||||
|
||||
static void pr_debug_void_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_string_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_float_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_vector_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_entity_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_field_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_func_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_quat_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_integer_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_short_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_double_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_struct_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_union_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_enum_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_array_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_class_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
static void pr_debug_alias_view (qfot_type_t *type, pr_type_t *value,
|
||||
void *_data);
|
||||
|
||||
static type_view_t raw_type_view = {
|
||||
pr_debug_void_view,
|
||||
pr_debug_string_view,
|
||||
pr_debug_float_view,
|
||||
pr_debug_vector_view,
|
||||
pr_debug_entity_view,
|
||||
pr_debug_field_view,
|
||||
pr_debug_func_view,
|
||||
pr_debug_pointer_view,
|
||||
pr_debug_quat_view,
|
||||
pr_debug_integer_view,
|
||||
pr_debug_uinteger_view,
|
||||
pr_debug_short_view,
|
||||
pr_debug_double_view,
|
||||
pr_debug_struct_view,
|
||||
pr_debug_union_view,
|
||||
pr_debug_enum_view,
|
||||
pr_debug_array_view,
|
||||
pr_debug_class_view,
|
||||
pr_debug_alias_view,
|
||||
};
|
||||
|
||||
static const char *
|
||||
file_get_key (const void *_f, void *unused)
|
||||
|
@ -199,10 +268,28 @@ error:
|
|||
return d;
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_clear (progs_t *pr, void *data)
|
||||
{
|
||||
__auto_type res = (pr_debug_resources_t *) data;
|
||||
|
||||
if (res->string) {
|
||||
dstring_clearstr (res->string);
|
||||
} else {
|
||||
res->string = dstring_newstr ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PR_Debug_Init (progs_t *pr)
|
||||
{
|
||||
file_hash = Hash_NewTable (1024, file_get_key, file_free, 0);
|
||||
pr_debug_resources_t *res = calloc (1, sizeof (*res));
|
||||
res->string = 0;
|
||||
|
||||
PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear);
|
||||
if (!file_hash) {
|
||||
file_hash = Hash_NewTable (1024, file_get_key, file_free, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -591,181 +678,386 @@ PR_DumpState (progs_t *pr)
|
|||
#define ISDENORM(x) ((x) && !((x) & 0x7f800000))
|
||||
|
||||
static const char *
|
||||
value_string (progs_t *pr, etype_t type, pr_type_t *val)
|
||||
value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value)
|
||||
{
|
||||
static dstring_t *line;
|
||||
pr_def_t *def;
|
||||
pr_int_t ofs;
|
||||
edict_t *edict;
|
||||
dfunction_t *f;
|
||||
const char *str;
|
||||
|
||||
if (!line)
|
||||
line = dstring_new ();
|
||||
|
||||
type &= ~DEF_SAVEGLOBAL;
|
||||
|
||||
switch (type) {
|
||||
case ev_string:
|
||||
if (!PR_StringValid (pr, val->string_var))
|
||||
return "*** invalid ***";
|
||||
str = PR_GetString (pr, val->string_var);
|
||||
dstring_copystr (line, "\"");
|
||||
while (*str) {
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s && !strchr ("\"\n\t", *s); s++)
|
||||
;
|
||||
if (s != str)
|
||||
dstring_appendsubstr (line, str, s - str);
|
||||
if (*s) {
|
||||
switch (*s) {
|
||||
case '\"':
|
||||
dstring_appendstr (line, "\\\"");
|
||||
break;
|
||||
case '\n':
|
||||
dstring_appendstr (line, "\\n");
|
||||
break;
|
||||
case '\t':
|
||||
dstring_appendstr (line, "\\t");
|
||||
break;
|
||||
default:
|
||||
dasprintf (line, "\\x%02x", *s & 0xff);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
str = s;
|
||||
}
|
||||
dstring_appendstr (line, "\"");
|
||||
break;
|
||||
case ev_entity:
|
||||
edict = PROG_TO_EDICT (pr, val->entity_var);
|
||||
dsprintf (line, "entity %d", NUM_FOR_BAD_EDICT (pr, edict));
|
||||
break;
|
||||
case ev_func:
|
||||
if (val->func_var < 0 || val->func_var >= pr->progs->numfunctions)
|
||||
dsprintf (line, "INVALID:%d", val->func_var);
|
||||
else if (!val->func_var)
|
||||
return "NULL";
|
||||
else {
|
||||
f = pr->pr_functions + val->func_var;
|
||||
dsprintf (line, "%s()", PR_GetString (pr, f->s_name));
|
||||
switch (type->meta) {
|
||||
case ty_basic:
|
||||
switch (type->t.type) {
|
||||
case ev_void:
|
||||
raw_type_view.void_view (type, value, data);
|
||||
break;
|
||||
case ev_string:
|
||||
raw_type_view.string_view (type, value, data);
|
||||
break;
|
||||
case ev_float:
|
||||
raw_type_view.float_view (type, value, data);
|
||||
break;
|
||||
case ev_vector:
|
||||
raw_type_view.vector_view (type, value, data);
|
||||
break;
|
||||
case ev_entity:
|
||||
raw_type_view.entity_view (type, value, data);
|
||||
break;
|
||||
case ev_field:
|
||||
raw_type_view.field_view (type, value, data);
|
||||
break;
|
||||
case ev_func:
|
||||
raw_type_view.func_view (type, value, data);
|
||||
break;
|
||||
case ev_pointer:
|
||||
raw_type_view.pointer_view (type, value, data);
|
||||
break;
|
||||
case ev_quat:
|
||||
raw_type_view.quat_view (type, value, data);
|
||||
break;
|
||||
case ev_integer:
|
||||
raw_type_view.integer_view (type, value, data);
|
||||
break;
|
||||
case ev_uinteger:
|
||||
raw_type_view.uinteger_view (type, value, data);
|
||||
break;
|
||||
case ev_short:
|
||||
raw_type_view.short_view (type, value, data);
|
||||
break;
|
||||
case ev_double:
|
||||
raw_type_view.double_view (type, value, data);
|
||||
break;
|
||||
case ev_invalid:
|
||||
case ev_type_count:
|
||||
dstring_appendstr (data->dstr, "<?""?>");
|
||||
}
|
||||
break;
|
||||
case ev_field:
|
||||
def = PR_FieldAtOfs (pr, val->integer_var);
|
||||
if (def)
|
||||
dsprintf (line, ".%s", PR_GetString (pr, def->name));
|
||||
else
|
||||
dsprintf (line, ".<$%04x>", val->integer_var);
|
||||
case ty_struct:
|
||||
raw_type_view.struct_view (type, value, data);
|
||||
break;
|
||||
case ev_void:
|
||||
return "void";
|
||||
case ev_float:
|
||||
if (ISDENORM (val->integer_var) && val->uinteger_var != 0x80000000)
|
||||
dsprintf (line, "<%08x>", val->integer_var);
|
||||
else
|
||||
dsprintf (line, "%g", val->float_var);
|
||||
case ty_union:
|
||||
raw_type_view.union_view (type, value, data);
|
||||
break;
|
||||
case ev_vector:
|
||||
dsprintf (line, "'%g %g %g'",
|
||||
val->vector_var[0], val->vector_var[1],
|
||||
val->vector_var[2]);
|
||||
case ty_enum:
|
||||
raw_type_view.enum_view (type, value, data);
|
||||
break;
|
||||
case ev_pointer:
|
||||
def = 0;
|
||||
ofs = val->integer_var;
|
||||
if (pr_debug->int_val && pr->debug)
|
||||
def = PR_Get_Local_Def (pr, ofs);
|
||||
if (!def)
|
||||
def = PR_GlobalAtOfs (pr, ofs);
|
||||
if (def && def->name)
|
||||
dsprintf (line, "&%s", PR_GetString (pr, def->name));
|
||||
else
|
||||
dsprintf (line, "[$%x]", ofs);
|
||||
case ty_array:
|
||||
raw_type_view.array_view (type, value, data);
|
||||
break;
|
||||
case ev_quat:
|
||||
dsprintf (line, "'%g %g %g %g'",
|
||||
val->vector_var[0], val->vector_var[1],
|
||||
val->vector_var[2], val->vector_var[3]);
|
||||
case ty_class:
|
||||
raw_type_view.class_view (type, value, data);
|
||||
break;
|
||||
case ev_integer:
|
||||
dsprintf (line, "%d", val->integer_var);
|
||||
break;
|
||||
case ev_uinteger:
|
||||
dsprintf (line, "$%08x", val->uinteger_var);
|
||||
break;
|
||||
case ev_double:
|
||||
dsprintf (line, "%g", *(double *)val);
|
||||
break;
|
||||
case ev_short:
|
||||
case ev_invalid:
|
||||
case ev_type_count:
|
||||
//dsprintf (line, "bad type %i", type);
|
||||
dsprintf (line, "<%x %x %x %x>",
|
||||
val[0].integer_var, val[1].integer_var,
|
||||
val[2].integer_var, val[3].integer_var);
|
||||
case ty_alias:
|
||||
raw_type_view.alias_view (type, value, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return line->str;
|
||||
return data->dstr->str;
|
||||
}
|
||||
|
||||
static pr_def_t *
|
||||
def_string (progs_t *pr, pr_int_t ofs, dstring_t *dstr)
|
||||
pr_debug_find_def (progs_t *pr, pr_int_t ofs)
|
||||
{
|
||||
pr_def_t *def = 0;
|
||||
const char *name;
|
||||
|
||||
if (pr_debug->int_val && pr->debug)
|
||||
def = PR_Get_Local_Def (pr, ofs);
|
||||
if (!def)
|
||||
def = PR_GlobalAtOfs (pr, ofs);
|
||||
if (!def || !*(name = PR_GetString (pr, def->name)))
|
||||
dsprintf (dstr, "[$%x]", ofs);
|
||||
else
|
||||
dsprintf (dstr, "%s", name);
|
||||
return def;
|
||||
}
|
||||
|
||||
static const char *
|
||||
global_string (progs_t *pr, pointer_t ofs, etype_t type, int contents)
|
||||
global_string (pr_debug_data_t *data, pointer_t ofs, etype_t etype,
|
||||
int contents)
|
||||
{
|
||||
static dstring_t *line = NULL;
|
||||
progs_t *pr = data->pr;
|
||||
dstring_t *dstr = data->dstr;
|
||||
pr_def_t *def = NULL;
|
||||
const char *s;
|
||||
qfot_type_t dummy_type = { };
|
||||
qfot_type_t *type;
|
||||
const char *name = 0;
|
||||
|
||||
if (!line)
|
||||
line = dstring_newstr();
|
||||
dstring_clearstr (dstr);
|
||||
|
||||
if (type == ev_short) {
|
||||
dsprintf (line, "%04x", (short) ofs);
|
||||
return line->str;
|
||||
if (etype == ev_short) {
|
||||
dsprintf (dstr, "%04x", (short) ofs);
|
||||
return dstr->str;
|
||||
}
|
||||
|
||||
def = def_string (pr, ofs, line);
|
||||
if (ofs > pr->globals_size) {
|
||||
dsprintf (dstr, "%08x out of bounds", ofs);
|
||||
return dstr->str;
|
||||
}
|
||||
|
||||
if (contents && (def || type != ev_void)) {
|
||||
const char *oi = "";
|
||||
if (def) {
|
||||
if (type == ev_void)
|
||||
type = def->type;
|
||||
if (type != (etype_t) (def->type & ~DEF_SAVEGLOBAL))
|
||||
oi = "?";
|
||||
}
|
||||
|
||||
if (ofs > pr->globals_size)
|
||||
s = "Out of bounds";
|
||||
else
|
||||
s = value_string (pr, type, &pr->pr_globals[ofs]);
|
||||
|
||||
if (strequal(line->str, "IMMEDIATE") || strequal(line->str, ".imm")) {
|
||||
dsprintf (line, "%s", s);
|
||||
def = pr_debug_find_def (pr, ofs);
|
||||
if (!def || !PR_StringValid (pr, def->name)
|
||||
|| !*(name = PR_GetString (pr, def->name))) {
|
||||
dsprintf (dstr, "[$%x]", ofs);
|
||||
}
|
||||
if (name) {
|
||||
if (strequal (name, "IMMEDIATE") || strequal (name, ".imm")) {
|
||||
contents = 1;
|
||||
} else {
|
||||
dasprintf (line, "%s(%s)", oi, s);
|
||||
dsprintf (dstr, "%s", name);
|
||||
}
|
||||
}
|
||||
return line->str;
|
||||
if (contents) {
|
||||
if (name) {
|
||||
dstring_appendstr (dstr, "(");
|
||||
}
|
||||
if (def) {
|
||||
if (!def->type_encoding) {
|
||||
dummy_type.t.type = def->type;
|
||||
type = &dummy_type;
|
||||
} else {
|
||||
type = &G_STRUCT (pr, qfot_type_t, def->type_encoding);
|
||||
}
|
||||
} else {
|
||||
dummy_type.t.type = etype;
|
||||
type = &dummy_type;
|
||||
}
|
||||
value_string (data, type, pr->pr_globals + ofs);
|
||||
if (name) {
|
||||
dstring_appendstr (dstr, ")");
|
||||
}
|
||||
}
|
||||
return dstr->str;
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_void_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dasprintf (data->dstr, "<void>");
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_string_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
string_t string = value->string_var;
|
||||
if (PR_StringValid (data->pr, string)) {
|
||||
const char *str = PR_GetString (data->pr, string);
|
||||
|
||||
dstring_appendstr (dstr, "\"");
|
||||
while (*str) {
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s && !strchr ("\"\n\t", *s); s++) {
|
||||
}
|
||||
if (s != str) {
|
||||
dstring_appendsubstr (dstr, str, s - str);
|
||||
}
|
||||
if (*s) {
|
||||
switch (*s) {
|
||||
case '\"':
|
||||
dstring_appendstr (dstr, "\\\"");
|
||||
break;
|
||||
case '\n':
|
||||
dstring_appendstr (dstr, "\\n");
|
||||
break;
|
||||
case '\t':
|
||||
dstring_appendstr (dstr, "\\t");
|
||||
break;
|
||||
default:
|
||||
dasprintf (dstr, "\\x%02x", *s & 0xff);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
str = s;
|
||||
}
|
||||
dstring_appendstr (dstr, "\"");
|
||||
} else {
|
||||
dstring_appendstr (dstr, "*** invalid string offset ***");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
if (data->pr->progs->version == PROG_ID_VERSION
|
||||
&& ISDENORM (value->integer_var)
|
||||
&& value->uinteger_var != 0x80000000) {
|
||||
dasprintf (dstr, "<%08x>", value->integer_var);
|
||||
} else {
|
||||
dasprintf (dstr, "%g", value->float_var);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dasprintf (dstr, "'%g %g %g'",
|
||||
value->vector_var[0], value->vector_var[1],
|
||||
value->vector_var[2]);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
progs_t *pr = data->pr;
|
||||
dstring_t *dstr = data->dstr;
|
||||
edict_t *edict = PROG_TO_EDICT (pr, value->entity_var);
|
||||
|
||||
dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict));
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_field_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
progs_t *pr = data->pr;
|
||||
dstring_t *dstr = data->dstr;
|
||||
pr_def_t *def = PR_FieldAtOfs (pr, value->integer_var);
|
||||
|
||||
if (def) {
|
||||
dasprintf (dstr, ".%s", PR_GetString (pr, def->name));
|
||||
} else {
|
||||
dasprintf (dstr, ".<$%04x>", value->integer_var);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
progs_t *pr = data->pr;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
if (value->func_var < 0 || value->func_var >= pr->progs->numfunctions) {
|
||||
dasprintf (dstr, "INVALID:%d", value->func_var);
|
||||
} else if (!value->func_var) {
|
||||
dstring_appendstr (dstr, "NULL");
|
||||
} else {
|
||||
dfunction_t *f = pr->pr_functions + value->func_var;
|
||||
dasprintf (dstr, "%s()", PR_GetString (pr, f->s_name));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
progs_t *pr = data->pr;
|
||||
dstring_t *dstr = data->dstr;
|
||||
pointer_t ofs = value->integer_var;
|
||||
pr_def_t *def;
|
||||
|
||||
if (pr_debug->int_val && pr->debug) {
|
||||
def = PR_Get_Local_Def (pr, ofs);
|
||||
}
|
||||
if (!def) {
|
||||
def = PR_GlobalAtOfs (pr, ofs);
|
||||
}
|
||||
if (def && def->name) {
|
||||
dasprintf (dstr, "&%s", PR_GetString (pr, def->name));
|
||||
} else {
|
||||
dasprintf (dstr, "[$%x]", ofs);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dasprintf (dstr, "'%g %g %g %g'",
|
||||
value->vector_var[0], value->vector_var[1],
|
||||
value->vector_var[2], value->vector_var[3]);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_integer_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dasprintf (dstr, "%d", value->integer_var);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dasprintf (dstr, "$%08x", value->uinteger_var);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dasprintf (dstr, "%d", (short)value->integer_var);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dasprintf (dstr, "%g", *(double *)value);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dstring_appendstr (dstr, "<struct>");
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_union_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dstring_appendstr (dstr, "<union>");
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_enum_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dstring_appendstr (dstr, "<enum>");
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_array_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dstring_appendstr (dstr, "<array>");
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_class_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dstring_appendstr (dstr, "<class>");
|
||||
}
|
||||
|
||||
static void
|
||||
pr_debug_alias_view (qfot_type_t *type, pr_type_t *value, void *_data)
|
||||
{
|
||||
__auto_type data = (pr_debug_data_t *) _data;
|
||||
dstring_t *dstr = data->dstr;
|
||||
|
||||
dstring_appendstr (dstr, "<alias>");
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
|
@ -780,8 +1072,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr)
|
|||
if (pr->wp_conditional)
|
||||
Sys_Printf (" if new val == %d\n",
|
||||
pr->wp_val.integer_var);
|
||||
} else {
|
||||
Sys_Printf (" none active\n");
|
||||
} else { Sys_Printf (" none active\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -803,6 +1094,8 @@ VISIBLE void
|
|||
PR_Debug_Print (progs_t *pr, const char *expr)
|
||||
{
|
||||
pr_def_t print;
|
||||
dstring_t *dstr = dstring_newstr();
|
||||
pr_debug_data_t data = {pr, dstr};
|
||||
|
||||
if (!expr) {
|
||||
Sys_Printf ("print <print expr>\n");
|
||||
|
@ -811,9 +1104,10 @@ PR_Debug_Print (progs_t *pr, const char *expr)
|
|||
|
||||
print = parse_expression (pr, expr, 0);
|
||||
if (print.type != ev_invalid) {
|
||||
const char *s = global_string (pr, print.ofs, print.type, 1);
|
||||
const char *s = global_string (&data, print.ofs, print.type, 1);
|
||||
Sys_Printf ("[%d] = %s\n", print.ofs, s);
|
||||
}
|
||||
dstring_delete (dstr);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
|
@ -824,15 +1118,21 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
|||
const char *fmt;
|
||||
opcode_t *op;
|
||||
static dstring_t *line;
|
||||
static dstring_t *dstr;
|
||||
dfunction_t *call_func = 0;
|
||||
pr_def_t *parm_def = 0;
|
||||
pr_auxfunction_t *aux_func = 0;
|
||||
pr_debug_data_t data;
|
||||
|
||||
if (!line)
|
||||
if (!line) {
|
||||
line = dstring_new ();
|
||||
|
||||
dstr = dstring_new ();
|
||||
}
|
||||
dstring_clearstr (line);
|
||||
|
||||
data.pr = pr;
|
||||
data.dstr = dstr;
|
||||
|
||||
if (pr_debug->int_val > 1)
|
||||
dump_code = 1;
|
||||
|
||||
|
@ -915,10 +1215,12 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
|||
aux_func = get_aux_function (pr);
|
||||
if (aux_func)
|
||||
optype = get_etype (pr, aux_func->return_type);
|
||||
str = global_string (pr, opval, optype, contents & 1);
|
||||
str = global_string (&data, opval, optype,
|
||||
contents & 1);
|
||||
break;
|
||||
case 'F':
|
||||
str = global_string (pr, opval, optype, contents & 1);
|
||||
str = global_string (&data, opval, optype,
|
||||
contents & 1);
|
||||
if (G_FUNCTION (pr, opval) >= 0
|
||||
&& G_FUNCTION (pr, opval)
|
||||
< pr->progs->numfunctions)
|
||||
|
@ -929,16 +1231,19 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
|||
optype = ev_void;
|
||||
if (parm_def)
|
||||
optype = parm_def->type;
|
||||
str = global_string (pr, opval, optype, contents & 1);
|
||||
str = global_string (&data, opval, optype,
|
||||
contents & 1);
|
||||
break;
|
||||
case 'V':
|
||||
str = global_string (pr, opval, ev_void, contents & 1);
|
||||
str = global_string (&data, opval, ev_void,
|
||||
contents & 1);
|
||||
break;
|
||||
case 'G':
|
||||
str = global_string (pr, opval, optype, contents & 1);
|
||||
str = global_string (&data, opval, optype,
|
||||
contents & 1);
|
||||
break;
|
||||
case 'g':
|
||||
str = global_string (pr, opval, optype, 0);
|
||||
str = global_string (&data, opval, optype, 0);
|
||||
break;
|
||||
case 's':
|
||||
str = va ("%d", (short) opval);
|
||||
|
@ -961,7 +1266,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents)
|
|||
str = "bad entity.field";
|
||||
break;
|
||||
}
|
||||
str = global_string (pr, opval, optype,
|
||||
str = global_string (&data, opval, optype,
|
||||
contents & 1);
|
||||
str = va ("$%x $%x %s", s->a, s->b, str);
|
||||
}
|
||||
|
@ -1072,11 +1377,15 @@ PR_Profile (progs_t * pr)
|
|||
VISIBLE void
|
||||
ED_Print (progs_t *pr, edict_t *ed)
|
||||
{
|
||||
int type, l;
|
||||
int l;
|
||||
pr_uint_t i;
|
||||
const char *name;
|
||||
pr_def_t *d;
|
||||
pr_type_t *v;
|
||||
qfot_type_t dummy_type = { };
|
||||
qfot_type_t *type;
|
||||
dstring_t *dstr = dstring_newstr();
|
||||
pr_debug_data_t data = {pr, dstr};
|
||||
|
||||
if (ed->free) {
|
||||
Sys_Printf ("FREE\n");
|
||||
|
@ -1088,6 +1397,12 @@ ED_Print (progs_t *pr, edict_t *ed)
|
|||
d = &pr->pr_fielddefs[i];
|
||||
if (!d->name) // null field def (probably 1st)
|
||||
continue;
|
||||
if (!d->type_encoding) {
|
||||
dummy_type.t.type = d->type;
|
||||
type = &dummy_type;
|
||||
} else {
|
||||
type = &G_STRUCT (pr, qfot_type_t, d->type_encoding);
|
||||
}
|
||||
name = PR_GetString (pr, d->name);
|
||||
if (name[strlen (name) - 2] == '_'
|
||||
&& strchr ("xyz", name[strlen (name) -1]))
|
||||
|
@ -1095,41 +1410,14 @@ ED_Print (progs_t *pr, edict_t *ed)
|
|||
|
||||
v = ed->v + d->ofs;
|
||||
|
||||
// if the value is still all 0, skip the field
|
||||
type = d->type & ~DEF_SAVEGLOBAL;
|
||||
|
||||
switch (type) {
|
||||
case ev_entity:
|
||||
case ev_integer:
|
||||
case ev_uinteger:
|
||||
case ev_pointer:
|
||||
case ev_func:
|
||||
case ev_field:
|
||||
if (!v->integer_var)
|
||||
continue;
|
||||
break;
|
||||
case ev_string:
|
||||
if (PR_StringValid (pr, v->string_var))
|
||||
if (!PR_GetString (pr, v->string_var)[0])
|
||||
continue;
|
||||
break;
|
||||
case ev_float:
|
||||
if (!v->float_var)
|
||||
continue;
|
||||
break;
|
||||
case ev_vector:
|
||||
if (!v[0].float_var && !v[1].float_var && !v[2].float_var)
|
||||
continue;
|
||||
break;
|
||||
case ev_void:
|
||||
break;
|
||||
default:
|
||||
PR_Error (pr, "ED_Print: Unhandled type %d", type);
|
||||
}
|
||||
|
||||
l = 15 - strlen (name);
|
||||
if (l < 1)
|
||||
l = 1;
|
||||
Sys_Printf ("%s%*s%s\n", name, l, "", value_string (pr, d->type, v));
|
||||
|
||||
dstring_clearstr (dstr);
|
||||
value_string (&data, type, v);
|
||||
Sys_Printf ("%s%*s%s\n", name, l, "", dstr->str);
|
||||
}
|
||||
|
||||
dstring_delete (dstr);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue