mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-21 11:11:37 +00:00
correctly save and restore the parameters when calling +initialize. fixes the segfault in the qwaq test.
This commit is contained in:
parent
4973a38cce
commit
ca0bbd909c
6 changed files with 59 additions and 6 deletions
|
@ -87,6 +87,16 @@ void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(pri
|
||||||
(pr)->pr_params[1] = (pr)->pr_real_params[1]; \
|
(pr)->pr_params[1] = (pr)->pr_real_params[1]; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/** Save the current parameters.
|
||||||
|
\param pr pointer to ::progs_t VM struct
|
||||||
|
*/
|
||||||
|
void PR_SaveParams (progs_t *pr);
|
||||||
|
|
||||||
|
/** Restore the parameters saved by PR_SaveParams().
|
||||||
|
\param pr pointer to ::progs_t VM struct
|
||||||
|
*/
|
||||||
|
void PR_RestoreParams (progs_t *pr);
|
||||||
|
|
||||||
/** Push an execution frame onto the VM stack. Saves current execution state.
|
/** Push an execution frame onto the VM stack. Saves current execution state.
|
||||||
\param pr pointer to ::progs_t VM struct
|
\param pr pointer to ::progs_t VM struct
|
||||||
*/
|
*/
|
||||||
|
@ -1407,6 +1417,9 @@ struct progs_s {
|
||||||
pr_type_t *pr_return;
|
pr_type_t *pr_return;
|
||||||
pr_type_t *pr_params[MAX_PARMS];
|
pr_type_t *pr_params[MAX_PARMS];
|
||||||
pr_type_t *pr_real_params[MAX_PARMS];
|
pr_type_t *pr_real_params[MAX_PARMS];
|
||||||
|
pr_type_t *pr_param_ptrs[2];
|
||||||
|
pr_type_t *pr_saved_params;
|
||||||
|
int pr_saved_argc;
|
||||||
int pr_param_size; ///< covers both params and return
|
int pr_param_size; ///< covers both params and return
|
||||||
|
|
||||||
int pr_edict_size; ///< in bytes
|
int pr_edict_size; ///< in bytes
|
||||||
|
|
|
@ -75,6 +75,39 @@ PR_RunError (progs_t * pr, const char *error, ...)
|
||||||
PR_Error (pr, "Program error: %s", string->str);
|
PR_Error (pr, "Program error: %s", string->str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VISIBLE void
|
||||||
|
PR_SaveParams (progs_t *pr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int size = pr->pr_param_size * sizeof (pr_type_t);
|
||||||
|
|
||||||
|
pr->pr_param_ptrs[0] = pr->pr_params[0];
|
||||||
|
pr->pr_param_ptrs[1] = pr->pr_params[1];
|
||||||
|
pr->pr_params[0] = pr->pr_real_params[0];
|
||||||
|
pr->pr_params[1] = pr->pr_real_params[1];
|
||||||
|
for (i = 0; i < pr->pr_argc; i++) {
|
||||||
|
memcpy (pr->pr_saved_params + i * pr->pr_param_size,
|
||||||
|
pr->pr_real_params[i], size);
|
||||||
|
if (i < 2)
|
||||||
|
memcpy (pr->pr_real_params[i], pr->pr_param_ptrs[0], size);
|
||||||
|
}
|
||||||
|
pr->pr_saved_argc = pr->pr_argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
VISIBLE void
|
||||||
|
PR_RestoreParams (progs_t *pr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int size = pr->pr_param_size * sizeof (pr_type_t);
|
||||||
|
|
||||||
|
pr->pr_params[0] = pr->pr_param_ptrs[0];
|
||||||
|
pr->pr_params[1] = pr->pr_param_ptrs[1];
|
||||||
|
pr->pr_argc = pr->pr_saved_argc;
|
||||||
|
for (i = 0; i < pr->pr_argc; i++)
|
||||||
|
memcpy (pr->pr_real_params[i],
|
||||||
|
pr->pr_saved_params + i * pr->pr_param_size, size);
|
||||||
|
}
|
||||||
|
|
||||||
VISIBLE inline void
|
VISIBLE inline void
|
||||||
PR_PushFrame (progs_t *pr)
|
PR_PushFrame (progs_t *pr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -138,6 +138,10 @@ PR_ResolveGlobals (progs_t *pr)
|
||||||
goto error;
|
goto error;
|
||||||
pr->pr_param_size = G_INT (pr, def->ofs);
|
pr->pr_param_size = G_INT (pr, def->ofs);
|
||||||
}
|
}
|
||||||
|
if (pr->pr_saved_params)
|
||||||
|
free (pr->pr_saved_params);
|
||||||
|
pr->pr_saved_params = calloc (pr->pr_param_size * MAX_PARMS,
|
||||||
|
sizeof (pr_type_t));
|
||||||
memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params));
|
memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params));
|
||||||
if (!pr->globals.time) {
|
if (!pr->globals.time) {
|
||||||
if ((def = PR_FindGlobal (pr, "time")))
|
if ((def = PR_FindGlobal (pr, "time")))
|
||||||
|
|
|
@ -696,11 +696,14 @@ obj_send_initialize (progs_t *pr, pr_class_t *class)
|
||||||
i < method_list->method_count; i++, method++) {
|
i < method_list->method_count; i++, method++) {
|
||||||
sel = &G_STRUCT (pr, pr_sel_t, method->method_name);
|
sel = &G_STRUCT (pr, pr_sel_t, method->method_name);
|
||||||
if (sel->sel_id == selector->sel_id) {
|
if (sel->sel_id == selector->sel_id) {
|
||||||
int size = pr->pr_param_size * MAX_PARMS;
|
PR_PushFrame (pr);
|
||||||
pr_type_t *params = alloca (size * sizeof (pr_type_t));
|
PR_SaveParams (pr);
|
||||||
memcpy (params, *pr->pr_params, size * sizeof (pr_type_t));
|
// param 0 is known to be the class pointer
|
||||||
|
P_POINTER (pr, 1) = method->method_name;
|
||||||
|
// pr->pr_argc is known to be 2
|
||||||
PR_ExecuteProgram (pr, method->method_imp);
|
PR_ExecuteProgram (pr, method->method_imp);
|
||||||
memcpy (*pr->pr_params, params, size * sizeof (pr_type_t));
|
PR_RestoreParams (pr);
|
||||||
|
PR_PopFrame (pr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ init_qf (void)
|
||||||
|
|
||||||
Memory_Init (malloc (1024 * 1024), 1024 * 1024);
|
Memory_Init (malloc (1024 * 1024), 1024 * 1024);
|
||||||
|
|
||||||
Cvar_Get ("pr_debug", "1", 0, 0, 0);
|
Cvar_Get ("pr_debug", "2", 0, 0, 0);
|
||||||
Cvar_Get ("pr_boundscheck", "0", 0, 0, 0);
|
Cvar_Get ("pr_boundscheck", "0", 0, 0, 0);
|
||||||
|
|
||||||
pr.edicts = &edicts;
|
pr.edicts = &edicts;
|
||||||
|
|
|
@ -5,7 +5,7 @@ string read_file (string filename)
|
||||||
file = Qopen (filename, "rtz");
|
file = Qopen (filename, "rtz");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
printf ("Can't open %s for reading."
|
printf ("Can't open %s for reading."
|
||||||
" Probably a bad hardcoded filename:)\n");
|
" Probably a bad hardcoded filename:)\n", filename);
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
while ((d = Qgetline (file)))
|
while ((d = Qgetline (file)))
|
||||||
|
|
Loading…
Reference in a new issue