diff --git a/include/QF/progs.h b/include/QF/progs.h index 2448423da..1a6b28f7e 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -143,6 +143,7 @@ typedef void (*builtin_proc) (progs_t *pr); typedef struct { const char *name; builtin_proc proc; + int first_statement; } builtin_t; ddef_t *PR_FindGlobal (progs_t *pr, const char *name); @@ -277,7 +278,7 @@ struct progs_s { int (*prune_edict)(progs_t *pr, edict_t *ent); void (*free_edict)(progs_t *pr, edict_t *ent); - builtin_t *builtins; + builtin_t **builtins; int numbuiltins; // debug info diff --git a/libs/gamecode/engine/pr_edict.c b/libs/gamecode/engine/pr_edict.c index 7efb30495..525ea95b4 100644 --- a/libs/gamecode/engine/pr_edict.c +++ b/libs/gamecode/engine/pr_edict.c @@ -1287,35 +1287,39 @@ PR_AddBuiltin (progs_t *pr, const char *name, builtin_proc builtin, int num) { int i; + if (!pr->builtin_hash) + pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr); + if (pr->numbuiltins == 0) { - pr->builtins = calloc (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"); - 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++) + i < pr->numbuiltins && pr->builtins[i]; i++) ; if (i >= pr->numbuiltins) { pr->numbuiltins++; pr->builtins = realloc (pr->builtins, - pr->numbuiltins * sizeof (builtin_t)); + pr->numbuiltins * sizeof (builtin_t*)); if (!pr->builtins) PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n"); } } else { if (num >= PR_AUTOBUILTIN || num == 0) PR_Error (pr, "PR_AddBuiltin: invalid builtin number.\n"); - if (pr->builtins[num].proc) + if (pr->builtins[num]) PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n"); i = num; } - pr->builtins[i].proc = builtin; - pr->builtins[i].name = name; - Hash_Add (pr->builtin_hash, &pr->builtins[i]); + pr->builtins[i] = malloc (sizeof (builtin_t)); + pr->builtins[i]->proc = builtin; + pr->builtins[i]->name = name; + pr->builtins[i]->first_statement = i; + Hash_Add (pr->builtin_hash, pr->builtins[i]); } builtin_t * @@ -1405,7 +1409,7 @@ PR_RelocateBuiltins (progs_t *pr) pr->progs_name, bi_name); return 0; } - func->first_statement = -(bi - pr->builtins); + func->first_statement = -bi->first_statement; } return 1; } diff --git a/libs/gamecode/engine/pr_exec.c b/libs/gamecode/engine/pr_exec.c index 86367db56..e4fd97e66 100644 --- a/libs/gamecode/engine/pr_exec.c +++ b/libs/gamecode/engine/pr_exec.c @@ -710,21 +710,15 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) pr->pr_argc = st->op - OP_CALL0; if (!OPA.func_var) PR_RunError (pr, "NULL function"); - if (OPA.func_var < 0) { // dynamic builtin - int i = -OPA.func_var; - if (i >= pr->numbuiltins || !pr->builtins[i].proc) - PR_RunError (pr, "Bad builtin call number"); - pr->builtins[i].proc (pr); - break; - } newf = &pr->pr_functions[OPA.func_var]; if (newf->first_statement < 0) { // negative statements are built in functions int i = -newf->first_statement; - if (i >= pr->numbuiltins || !pr->builtins[i].proc) + if (i >= pr->numbuiltins || !pr->builtins[i] + || !pr->builtins[i]->proc) PR_RunError (pr, "Bad builtin call number"); - pr->builtins[i].proc (pr); + pr->builtins[i]->proc (pr); break; } diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 191e8c4b7..c75431473 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1599,7 +1599,7 @@ SV_PR_Cmds_Init () { PR_Cmds_Init (&sv_pr_state); - sv_pr_state.builtins[45].proc = 0; // (override standard builtin) + sv_pr_state.builtins[45] = 0; // (override standard builtin) PR_AddBuiltin (&sv_pr_state, "cvar", PF_sv_cvar, 45); // float (string s) cvar