mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 06:51:47 +00:00
fix up #0 builtin functions at runtime. not done automaticly (need to call
PR_RelocateBuiltins) and fix a bug with profiling and unlimited execution counts
This commit is contained in:
parent
2185e0a92e
commit
3dafbebf10
5 changed files with 51 additions and 77 deletions
|
@ -166,7 +166,8 @@ char *PR_GlobalStringNoContents (progs_t *pr, int ofs, etype_t type);
|
||||||
pr_type_t *GetEdictFieldValue(progs_t *pr, edict_t *ed, const char *field);
|
pr_type_t *GetEdictFieldValue(progs_t *pr, edict_t *ed, const char *field);
|
||||||
|
|
||||||
void PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num);
|
void PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num);
|
||||||
int PR_FindBuiltin (progs_t *pr, const char *name);
|
builtin_t *PR_FindBuiltin (progs_t *pr, const char *name);
|
||||||
|
void PR_RelocateBuiltins (progs_t *pr);
|
||||||
|
|
||||||
//
|
//
|
||||||
// PR Strings stuff
|
// PR Strings stuff
|
||||||
|
@ -223,6 +224,7 @@ struct progs_s {
|
||||||
dprograms_t *progs;
|
dprograms_t *progs;
|
||||||
int progs_size;
|
int progs_size;
|
||||||
|
|
||||||
|
struct hashtab_s *builtin_hash;
|
||||||
struct hashtab_s *function_hash;
|
struct hashtab_s *function_hash;
|
||||||
struct hashtab_s *global_hash;
|
struct hashtab_s *global_hash;
|
||||||
struct hashtab_s *field_hash;
|
struct hashtab_s *field_hash;
|
||||||
|
|
|
@ -593,25 +593,6 @@ PF_charcount (progs_t *pr)
|
||||||
G_FLOAT (pr, OFS_RETURN) = count;
|
G_FLOAT (pr, OFS_RETURN) = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PF_checkbuiltin (progs_t *pr)
|
|
||||||
{
|
|
||||||
G_FUNCTION (pr, OFS_RETURN) = -PR_FindBuiltin (pr, G_STRING (pr, OFS_PARM0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PF_getbuiltin (progs_t *pr)
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
name = G_STRING (pr, OFS_PARM0);
|
|
||||||
i = PR_FindBuiltin (pr, name);
|
|
||||||
if (!i)
|
|
||||||
PR_RunError (pr, "PF_getfunction: function '%s' not found!\n", name);
|
|
||||||
G_FUNCTION (pr, OFS_RETURN) = -i;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (INT_MAX == 2147483647) && (INT_MIN == -2147483648)
|
#if (INT_MAX == 2147483647) && (INT_MIN == -2147483648)
|
||||||
# define INT_WIDTH 11
|
# define INT_WIDTH 11
|
||||||
#else /* I hope... */
|
#else /* I hope... */
|
||||||
|
|
|
@ -92,16 +92,6 @@ const char *pr_type_name[ev_type_count] = {
|
||||||
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
|
ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs);
|
||||||
qboolean ED_ParseEpair (progs_t * pr, pr_type_t *base, ddef_t *key, const char *s);
|
qboolean ED_ParseEpair (progs_t * pr, pr_type_t *base, ddef_t *key, const char *s);
|
||||||
|
|
||||||
#define MAX_FIELD_LEN 64
|
|
||||||
#define GEFV_CACHESIZE 2
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ddef_t *pcache;
|
|
||||||
char field[MAX_FIELD_LEN];
|
|
||||||
} gefv_cache;
|
|
||||||
|
|
||||||
static gefv_cache gefvCache[GEFV_CACHESIZE] = { {NULL, ""}, {NULL, ""} };
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ED_ClearEdict
|
ED_ClearEdict
|
||||||
|
|
||||||
|
@ -323,26 +313,10 @@ ED_FindFunction (progs_t * pr, const char *name)
|
||||||
pr_type_t *
|
pr_type_t *
|
||||||
GetEdictFieldValue (progs_t * pr, edict_t *ed, const char *field)
|
GetEdictFieldValue (progs_t * pr, edict_t *ed, const char *field)
|
||||||
{
|
{
|
||||||
ddef_t *def = NULL;
|
ddef_t *def;
|
||||||
int i;
|
|
||||||
static int rep = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < GEFV_CACHESIZE; i++) {
|
|
||||||
if (!strcmp (field, gefvCache[i].field)) {
|
|
||||||
def = gefvCache[i].pcache;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def = ED_FindField (pr, field);
|
def = ED_FindField (pr, field);
|
||||||
|
|
||||||
if (strlen (field) < MAX_FIELD_LEN) {
|
|
||||||
gefvCache[rep].pcache = def;
|
|
||||||
strcpy (gefvCache[rep].field, field);
|
|
||||||
rep ^= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Done:
|
|
||||||
if (!def)
|
if (!def)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -1070,6 +1044,13 @@ ED_LoadFromFile (progs_t * pr, const char *data)
|
||||||
Sys_DPrintf ("%i entities inhibited\n", inhibit);
|
Sys_DPrintf ("%i entities inhibited\n", inhibit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
builtin_get_key (void *_bi, void *unused)
|
||||||
|
{
|
||||||
|
builtin_t *bi = (builtin_t *)_bi;
|
||||||
|
return bi->name;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
function_get_key (void *f, void *_pr)
|
function_get_key (void *f, void *_pr)
|
||||||
{
|
{
|
||||||
|
@ -1218,8 +1199,6 @@ PR_LoadProgsFile (progs_t * pr, const char *progsname)
|
||||||
void
|
void
|
||||||
PR_LoadProgs (progs_t * pr, const char *progsname)
|
PR_LoadProgs (progs_t * pr, const char *progsname)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
PR_LoadProgsFile (pr, progsname);
|
PR_LoadProgsFile (pr, progsname);
|
||||||
if (!pr->progs)
|
if (!pr->progs)
|
||||||
return;
|
return;
|
||||||
|
@ -1227,10 +1206,6 @@ PR_LoadProgs (progs_t * pr, const char *progsname)
|
||||||
if (!progsname)
|
if (!progsname)
|
||||||
progsname = "(preloaded)";
|
progsname = "(preloaded)";
|
||||||
|
|
||||||
// flush the non-C variable lookup cache
|
|
||||||
for (i = 0; i < GEFV_CACHESIZE; i++)
|
|
||||||
gefvCache[i].field[0] = 0;
|
|
||||||
|
|
||||||
if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, "time")))
|
if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, "time")))
|
||||||
PR_Error (pr, "%s: undefined symbol: time", progsname);
|
PR_Error (pr, "%s: undefined symbol: time", progsname);
|
||||||
if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, "self")))
|
if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, "self")))
|
||||||
|
@ -1297,48 +1272,43 @@ PR_Init (void)
|
||||||
void
|
void
|
||||||
PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num)
|
PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i;
|
||||||
|
|
||||||
if (pr->numbuiltins == 0) {
|
if (pr->numbuiltins == 0) {
|
||||||
pr->builtins = malloc (PR_AUTOBUILTIN * sizeof (builtin_t));
|
pr->builtins = calloc (PR_AUTOBUILTIN, sizeof (builtin_t));
|
||||||
pr->numbuiltins = PR_AUTOBUILTIN;
|
pr->numbuiltins = PR_AUTOBUILTIN;
|
||||||
if (!pr->builtins)
|
if (!pr->builtins)
|
||||||
PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n");
|
PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n");
|
||||||
for (i = 0; i < pr->numbuiltins; i++) {
|
pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr);
|
||||||
pr->builtins[i].proc = 0;
|
|
||||||
pr->builtins[i].name = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
for (i = PR_AUTOBUILTIN; i < pr->numbuiltins && pr->builtins[i].proc; i++)
|
for (i = PR_AUTOBUILTIN;
|
||||||
|
i < pr->numbuiltins && pr->builtins[i].proc; i++)
|
||||||
;
|
;
|
||||||
if (i >= pr->numbuiltins) {
|
if (i >= pr->numbuiltins) {
|
||||||
pr->numbuiltins++;
|
pr->numbuiltins++;
|
||||||
pr->builtins = realloc (pr->builtins, pr->numbuiltins * sizeof (builtin_t));
|
pr->builtins = realloc (pr->builtins,
|
||||||
|
pr->numbuiltins * sizeof (builtin_t));
|
||||||
if (!pr->builtins)
|
if (!pr->builtins)
|
||||||
PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n");
|
PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n");
|
||||||
}
|
}
|
||||||
j = i;
|
|
||||||
} else {
|
} else {
|
||||||
if (num >= PR_AUTOBUILTIN || num == 0)
|
if (num >= PR_AUTOBUILTIN || num == 0)
|
||||||
PR_Error (pr, "PR_AddBuiltin: invalid builtin number.\n");
|
PR_Error (pr, "PR_AddBuiltin: invalid builtin number.\n");
|
||||||
if (pr->builtins[num].proc)
|
if (pr->builtins[num].proc)
|
||||||
PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n");
|
PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n");
|
||||||
j = num;
|
i = num;
|
||||||
}
|
}
|
||||||
pr->builtins[j].proc = builtin;
|
pr->builtins[i].proc = builtin;
|
||||||
pr->builtins[j].name = name;
|
pr->builtins[i].name = name;
|
||||||
|
Hash_Add (pr->builtin_hash, &pr->builtins[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
builtin_t *
|
||||||
PR_FindBuiltin (progs_t *pr, const char *name)
|
PR_FindBuiltin (progs_t *pr, const char *name)
|
||||||
{
|
{
|
||||||
int i;
|
return (builtin_t *) Hash_Find (pr->builtin_hash, name);
|
||||||
for (i = 0; i < pr->numbuiltins; i++)
|
|
||||||
if (pr->builtins[i].name && strequal (pr->builtins[i].name, name))
|
|
||||||
return i;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
edict_t *
|
edict_t *
|
||||||
|
@ -1385,7 +1355,7 @@ PR_Error (progs_t *pr, const char *error, ...)
|
||||||
vsnprintf (string, sizeof (string), error, argptr);
|
vsnprintf (string, sizeof (string), error, argptr);
|
||||||
va_end (argptr);
|
va_end (argptr);
|
||||||
|
|
||||||
Sys_Error ("%s", string);
|
Sys_Error ("%s: %s", pr->progs_name, string);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1402,3 +1372,23 @@ PR_AccessField (progs_t *pr, const char *name, etype_t type,
|
||||||
file, line);
|
file, line);
|
||||||
return def->ofs;
|
return def->ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PR_RelocateBuiltins (progs_t *pr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
dfunction_t *func;
|
||||||
|
builtin_t *bi;
|
||||||
|
const char *bi_name;
|
||||||
|
|
||||||
|
for (i = 1; i < pr->progs->numfunctions; i++) {
|
||||||
|
func = pr->pr_functions + i;
|
||||||
|
if (func->first_statement)
|
||||||
|
continue;
|
||||||
|
bi_name = PR_GetString (pr, func->s_name);
|
||||||
|
bi = PR_FindBuiltin (pr, bi_name);
|
||||||
|
if (!bi)
|
||||||
|
PR_Error (pr, "undefined builtin %s", bi_name);
|
||||||
|
func->first_statement = -(bi - pr->builtins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -291,8 +291,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
st++;
|
st++;
|
||||||
if (!pr->no_exec_limit
|
if (++profile > 1000000 && !pr->no_exec_limit) {
|
||||||
&& ++profile > 1000000) {
|
|
||||||
pr->pr_xstatement = st - pr->pr_statements;
|
pr->pr_xstatement = st - pr->pr_statements;
|
||||||
PR_RunError (pr, "runaway loop error");
|
PR_RunError (pr, "runaway loop error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,9 @@ main ()
|
||||||
progs.num_edicts = &num_edicts;
|
progs.num_edicts = &num_edicts;
|
||||||
progs.reserved_edicts = &reserved_edicts;
|
progs.reserved_edicts = &reserved_edicts;
|
||||||
progs.no_exec_limit = 1;
|
progs.no_exec_limit = 1;
|
||||||
|
progs.progs_name = "qwaq.dat";
|
||||||
|
|
||||||
f = fopen ("qwaq.dat", "rb");
|
f = fopen (progs.progs_name, "rb");
|
||||||
if (f) {
|
if (f) {
|
||||||
fseek (f, 0, SEEK_END);
|
fseek (f, 0, SEEK_END);
|
||||||
len = ftell (f);
|
len = ftell (f);
|
||||||
|
@ -99,10 +100,11 @@ main ()
|
||||||
fclose (f);
|
fclose (f);
|
||||||
com_filesize = len;
|
com_filesize = len;
|
||||||
if (progs.progs)
|
if (progs.progs)
|
||||||
PR_LoadProgs (&progs, 0);
|
PR_LoadProgs (&progs, progs.progs_name);
|
||||||
}
|
}
|
||||||
if (!progs.progs)
|
if (!progs.progs)
|
||||||
Sys_Error ("couldn't load %s\n", "qwaq.dat");
|
Sys_Error ("couldn't load %s\n", "qwaq.dat");
|
||||||
|
PR_RelocateBuiltins (&progs);
|
||||||
|
|
||||||
*progs.edicts = PR_InitEdicts (&progs, MAX_EDICTS);
|
*progs.edicts = PR_InitEdicts (&progs, MAX_EDICTS);
|
||||||
for (i = 0; i < progs.progs->numstatements; i++) {
|
for (i = 0; i < progs.progs->numstatements; i++) {
|
||||||
|
|
Loading…
Reference in a new issue