diff --git a/include/QF/progs.h b/include/QF/progs.h index a351dc9b7..6eee485de 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -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); 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 @@ -223,6 +224,7 @@ struct progs_s { dprograms_t *progs; int progs_size; + struct hashtab_s *builtin_hash; struct hashtab_s *function_hash; struct hashtab_s *global_hash; struct hashtab_s *field_hash; diff --git a/libs/gamecode/builtins/pr_cmds.c b/libs/gamecode/builtins/pr_cmds.c index 49996f56a..b44247de8 100644 --- a/libs/gamecode/builtins/pr_cmds.c +++ b/libs/gamecode/builtins/pr_cmds.c @@ -593,25 +593,6 @@ PF_charcount (progs_t *pr) 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) # define INT_WIDTH 11 #else /* I hope... */ diff --git a/libs/gamecode/engine/pr_edict.c b/libs/gamecode/engine/pr_edict.c index 3fc67acba..60129b693 100644 --- a/libs/gamecode/engine/pr_edict.c +++ b/libs/gamecode/engine/pr_edict.c @@ -92,16 +92,6 @@ const char *pr_type_name[ev_type_count] = { 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); -#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 @@ -323,26 +313,10 @@ ED_FindFunction (progs_t * pr, const char *name) pr_type_t * GetEdictFieldValue (progs_t * pr, edict_t *ed, const char *field) { - ddef_t *def = NULL; - 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; - } - } + ddef_t *def; 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) return NULL; @@ -1070,6 +1044,13 @@ ED_LoadFromFile (progs_t * pr, const char *data) 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 * function_get_key (void *f, void *_pr) { @@ -1218,8 +1199,6 @@ PR_LoadProgsFile (progs_t * pr, const char *progsname) void PR_LoadProgs (progs_t * pr, const char *progsname) { - int i; - PR_LoadProgsFile (pr, progsname); if (!pr->progs) return; @@ -1227,10 +1206,6 @@ PR_LoadProgs (progs_t * pr, const char *progsname) if (!progsname) 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"))) PR_Error (pr, "%s: undefined symbol: time", progsname); if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, "self"))) @@ -1297,48 +1272,43 @@ PR_Init (void) void PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num) { - int i, j; + int i; if (pr->numbuiltins == 0) { - pr->builtins = malloc (PR_AUTOBUILTIN * sizeof (builtin_t)); + pr->builtins = calloc (PR_AUTOBUILTIN, sizeof (builtin_t)); pr->numbuiltins = PR_AUTOBUILTIN; if (!pr->builtins) PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n"); - for (i = 0; i < pr->numbuiltins; i++) { - pr->builtins[i].proc = 0; - pr->builtins[i].name = 0; - } + pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr); } 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) { 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) PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n"); } - j = i; } else { if (num >= PR_AUTOBUILTIN || num == 0) PR_Error (pr, "PR_AddBuiltin: invalid builtin number.\n"); if (pr->builtins[num].proc) PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n"); - j = num; + i = num; } - pr->builtins[j].proc = builtin; - pr->builtins[j].name = name; + pr->builtins[i].proc = builtin; + pr->builtins[i].name = name; + Hash_Add (pr->builtin_hash, &pr->builtins[i]); } -int +builtin_t * PR_FindBuiltin (progs_t *pr, const char *name) { - int i; - for (i = 0; i < pr->numbuiltins; i++) - if (pr->builtins[i].name && strequal (pr->builtins[i].name, name)) - return i; - return 0; + return (builtin_t *) Hash_Find (pr->builtin_hash, name); } edict_t * @@ -1385,7 +1355,7 @@ PR_Error (progs_t *pr, const char *error, ...) vsnprintf (string, sizeof (string), error, argptr); va_end (argptr); - Sys_Error ("%s", string); + Sys_Error ("%s: %s", pr->progs_name, string); } int @@ -1402,3 +1372,23 @@ PR_AccessField (progs_t *pr, const char *name, etype_t type, file, line); 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); + } +} diff --git a/libs/gamecode/engine/pr_exec.c b/libs/gamecode/engine/pr_exec.c index ed1661fee..86367db56 100644 --- a/libs/gamecode/engine/pr_exec.c +++ b/libs/gamecode/engine/pr_exec.c @@ -291,8 +291,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) while (1) { st++; - if (!pr->no_exec_limit - && ++profile > 1000000) { + if (++profile > 1000000 && !pr->no_exec_limit) { pr->pr_xstatement = st - pr->pr_statements; PR_RunError (pr, "runaway loop error"); } @@ -379,7 +378,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) case OP_AND: // OPA and OPB have to be float for -0.0 OPC.integer_var = FNZ (OPA) && FNZ (OPB); break; - case OP_OR: // OPA and OPB have to be float for -0.0 + case OP_OR: // OPA and OPB have to be float for -0.0 OPC.integer_var = FNZ (OPA) || FNZ (OPB); break; case OP_NOT_F: diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index d8c997e5a..16f8c649a 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -88,8 +88,9 @@ main () progs.num_edicts = &num_edicts; progs.reserved_edicts = &reserved_edicts; progs.no_exec_limit = 1; + progs.progs_name = "qwaq.dat"; - f = fopen ("qwaq.dat", "rb"); + f = fopen (progs.progs_name, "rb"); if (f) { fseek (f, 0, SEEK_END); len = ftell (f); @@ -99,10 +100,11 @@ main () fclose (f); com_filesize = len; if (progs.progs) - PR_LoadProgs (&progs, 0); + PR_LoadProgs (&progs, progs.progs_name); } if (!progs.progs) Sys_Error ("couldn't load %s\n", "qwaq.dat"); + PR_RelocateBuiltins (&progs); *progs.edicts = PR_InitEdicts (&progs, MAX_EDICTS); for (i = 0; i < progs.progs->numstatements; i++) {