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:
Bill Currie 2001-12-14 08:15:04 +00:00
parent 2185e0a92e
commit 3dafbebf10
5 changed files with 51 additions and 77 deletions

View file

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

View file

@ -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... */

View file

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

View file

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

View file

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