mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
break out the non-edict code into sensible locations
This commit is contained in:
parent
418f922f0f
commit
21b6e68a8c
6 changed files with 586 additions and 421 deletions
|
@ -200,6 +200,7 @@ void PR_DumpState (progs_t *pr);
|
||||||
void PR_StackTrace (progs_t * pr);
|
void PR_StackTrace (progs_t * pr);
|
||||||
|
|
||||||
extern struct cvar_s *pr_debug;
|
extern struct cvar_s *pr_debug;
|
||||||
|
extern struct cvar_s *pr_deadbeef_ents;
|
||||||
extern struct cvar_s *pr_deadbeef_locals;
|
extern struct cvar_s *pr_deadbeef_locals;
|
||||||
extern struct cvar_s *pr_boundscheck;
|
extern struct cvar_s *pr_boundscheck;
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,5 @@ lib_LTLIBRARIES= libQFgamecode.la
|
||||||
|
|
||||||
libQFgamecode_la_LDFLAGS= -version-info 1:0:0
|
libQFgamecode_la_LDFLAGS= -version-info 1:0:0
|
||||||
libQFgamecode_la_SOURCES= \
|
libQFgamecode_la_SOURCES= \
|
||||||
pr_edict.c pr_debug.c pr_exec.c pr_opcode.c pr_strings.c pr_zone.c
|
pr_builtins.c pr_edict.c pr_debug.c pr_exec.c pr_load.c pr_opcode.c \
|
||||||
|
pr_resolve.c pr_strings.c pr_zone.c
|
||||||
|
|
132
libs/gamecode/engine/pr_builtins.c
Normal file
132
libs/gamecode/engine/pr_builtins.c
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
pr_edict.c
|
||||||
|
|
||||||
|
entity dictionary
|
||||||
|
|
||||||
|
Copyright (C) 1996-1997 Id Software, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
static const char rcsid[] =
|
||||||
|
"$Id$";
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "QF/cmd.h"
|
||||||
|
#include "QF/crc.h"
|
||||||
|
#include "QF/cvar.h"
|
||||||
|
#include "QF/hash.h"
|
||||||
|
#include "QF/progs.h"
|
||||||
|
#include "QF/qdefs.h"
|
||||||
|
#include "QF/qendian.h"
|
||||||
|
#include "QF/sys.h"
|
||||||
|
#include "QF/zone.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
#include "QF/vfs.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
builtin_get_key (void *_bi, void *unused)
|
||||||
|
{
|
||||||
|
builtin_t *bi = (builtin_t *)_bi;
|
||||||
|
return bi->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PR_AUTOBUILTIN 120
|
||||||
|
void
|
||||||
|
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->numbuiltins = PR_AUTOBUILTIN;
|
||||||
|
if (!pr->builtins)
|
||||||
|
PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num < 0) {
|
||||||
|
for (i = PR_AUTOBUILTIN;
|
||||||
|
i < pr->numbuiltins && pr->builtins[i]; i++)
|
||||||
|
;
|
||||||
|
if (i >= pr->numbuiltins) {
|
||||||
|
pr->numbuiltins++;
|
||||||
|
pr->builtins = realloc (pr->builtins,
|
||||||
|
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])
|
||||||
|
PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n");
|
||||||
|
i = num;
|
||||||
|
}
|
||||||
|
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 *
|
||||||
|
PR_FindBuiltin (progs_t *pr, const char *name)
|
||||||
|
{
|
||||||
|
return (builtin_t *) Hash_Find (pr->builtin_hash, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
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) {
|
||||||
|
Sys_Printf ("PR_RelocateBuiltins: %s: undefined builtin %s\n",
|
||||||
|
pr->progs_name, bi_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
func->first_statement = -bi->first_statement;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -206,110 +206,6 @@ ED_Free (progs_t * pr, edict_t *ed)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
/*
|
|
||||||
ED_GlobalAtOfs
|
|
||||||
*/
|
|
||||||
ddef_t *
|
|
||||||
ED_GlobalAtOfs (progs_t * pr, int ofs)
|
|
||||||
{
|
|
||||||
ddef_t *def;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < pr->progs->numglobaldefs; i++) {
|
|
||||||
def = &pr->pr_globaldefs[i];
|
|
||||||
if (def->ofs == ofs)
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
ED_FieldAtOfs
|
|
||||||
*/
|
|
||||||
ddef_t *
|
|
||||||
ED_FieldAtOfs (progs_t * pr, int ofs)
|
|
||||||
{
|
|
||||||
ddef_t *def;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < pr->progs->numfielddefs; i++) {
|
|
||||||
def = &pr->pr_fielddefs[i];
|
|
||||||
if (def->ofs == ofs)
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
ED_FindField
|
|
||||||
*/
|
|
||||||
ddef_t *
|
|
||||||
ED_FindField (progs_t * pr, const char *name)
|
|
||||||
{
|
|
||||||
return Hash_Find (pr->field_hash, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ED_GetFieldIndex (progs_t *pr, const char *name)
|
|
||||||
{
|
|
||||||
ddef_t *def;
|
|
||||||
|
|
||||||
def = ED_FindField (pr, name);
|
|
||||||
if (def)
|
|
||||||
return def->ofs;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
PR_FindGlobal
|
|
||||||
*/
|
|
||||||
ddef_t *
|
|
||||||
PR_FindGlobal (progs_t * pr, const char *name)
|
|
||||||
{
|
|
||||||
return Hash_Find (pr->global_hash, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_type_t *
|
|
||||||
PR_GetGlobalPointer (progs_t *pr, const char *name)
|
|
||||||
{
|
|
||||||
ddef_t *def;
|
|
||||||
|
|
||||||
def = PR_FindGlobal (pr, name);
|
|
||||||
if (def)
|
|
||||||
return &pr->pr_globals[def->ofs];
|
|
||||||
PR_Error (pr, "undefined global %s", name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
func_t
|
|
||||||
PR_GetFunctionIndex (progs_t *pr, const char *name)
|
|
||||||
{
|
|
||||||
dfunction_t *func = ED_FindFunction (pr, name);
|
|
||||||
if (func)
|
|
||||||
return func - pr->pr_functions;
|
|
||||||
PR_Error (pr, "undefined function %s", name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PR_GetFieldOffset (progs_t *pr, const char *name)
|
|
||||||
{
|
|
||||||
ddef_t *def = ED_FindField (pr, name);
|
|
||||||
if (def)
|
|
||||||
return def->ofs;
|
|
||||||
PR_Error (pr, "undefined field %s", name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
ED_FindFunction
|
|
||||||
*/
|
|
||||||
dfunction_t *
|
|
||||||
ED_FindFunction (progs_t * pr, const char *name)
|
|
||||||
{
|
|
||||||
return Hash_Find (pr->function_hash, 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)
|
||||||
{
|
{
|
||||||
|
@ -1044,202 +940,6 @@ 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 *
|
|
||||||
function_get_key (void *f, void *_pr)
|
|
||||||
{
|
|
||||||
progs_t *pr = (progs_t*)_pr;
|
|
||||||
dfunction_t *func = (dfunction_t*)f;
|
|
||||||
return PR_GetString (pr, func->s_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
var_get_key (void *d, void *_pr)
|
|
||||||
{
|
|
||||||
progs_t *pr = (progs_t*)_pr;
|
|
||||||
ddef_t *def = (ddef_t*)d;
|
|
||||||
return PR_GetString (pr, def->s_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PR_LoadProgsFile (progs_t * pr, const char *progsname)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (progsname)
|
|
||||||
pr->progs = (dprograms_t *) COM_LoadHunkFile (progsname);
|
|
||||||
else
|
|
||||||
progsname = pr->progs_name;
|
|
||||||
if (!pr->progs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pr->progs_size = com_filesize;
|
|
||||||
Sys_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024);
|
|
||||||
|
|
||||||
// store prog crc
|
|
||||||
pr->crc = CRC_Block ((byte *) pr->progs, com_filesize);
|
|
||||||
|
|
||||||
// byte swap the header
|
|
||||||
for (i = 0; i < sizeof (*pr->progs) / 4; i++)
|
|
||||||
((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]);
|
|
||||||
|
|
||||||
if (pr->progs->version != PROG_VERSION
|
|
||||||
&& pr->progs->version != PROG_ID_VERSION) {
|
|
||||||
if (pr->progs->version < 0x00fff000) {
|
|
||||||
PR_Error (pr, "%s has unrecognised version number (%d)",
|
|
||||||
progsname, pr->progs->version);
|
|
||||||
} else {
|
|
||||||
PR_Error (pr,
|
|
||||||
"%s has unrecognised version number (%02x.%03x.%03x)"
|
|
||||||
" [%02x.%03x.%03x expected]",
|
|
||||||
progsname,
|
|
||||||
pr->progs->version >> 24,
|
|
||||||
(pr->progs->version >> 12) & 0xfff,
|
|
||||||
pr->progs->version & 0xfff,
|
|
||||||
PROG_VERSION >> 24,
|
|
||||||
(PROG_VERSION >> 12) & 0xfff,
|
|
||||||
PROG_VERSION & 0xfff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pr->progs_name = progsname; //XXX is this safe?
|
|
||||||
|
|
||||||
pr->zone = 0; // caller sets up afterwards
|
|
||||||
|
|
||||||
pr->pr_functions =
|
|
||||||
(dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions);
|
|
||||||
pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings;
|
|
||||||
pr->pr_stringsize = pr->progs->numstrings;
|
|
||||||
pr->pr_globaldefs =
|
|
||||||
(ddef_t *) ((byte *) pr->progs + pr->progs->ofs_globaldefs);
|
|
||||||
pr->pr_fielddefs =
|
|
||||||
(ddef_t *) ((byte *) pr->progs + pr->progs->ofs_fielddefs);
|
|
||||||
pr->pr_statements =
|
|
||||||
(dstatement_t *) ((byte *) pr->progs + pr->progs->ofs_statements);
|
|
||||||
|
|
||||||
pr->pr_globals =
|
|
||||||
(pr_type_t *) ((byte *) pr->progs + pr->progs->ofs_globals);
|
|
||||||
|
|
||||||
// size of edict ascked for by progs
|
|
||||||
pr->pr_edict_size = pr->progs->entityfields * 4;
|
|
||||||
// size of engine data
|
|
||||||
pr->pr_edict_size += sizeof (edict_t) - sizeof (pr_type_t);
|
|
||||||
// round off to next highest whole word address (esp for Alpha)
|
|
||||||
// this ensures that pointers in the engine data area are always
|
|
||||||
// properly aligned
|
|
||||||
pr->pr_edict_size += sizeof (void*) - 1;
|
|
||||||
pr->pr_edict_size &= ~(sizeof (void*) - 1);
|
|
||||||
|
|
||||||
pr->pr_edictareasize = 0;
|
|
||||||
|
|
||||||
if (pr->function_hash) {
|
|
||||||
Hash_FlushTable (pr->function_hash);
|
|
||||||
} else {
|
|
||||||
pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr);
|
|
||||||
}
|
|
||||||
if (pr->global_hash) {
|
|
||||||
Hash_FlushTable (pr->global_hash);
|
|
||||||
} else {
|
|
||||||
pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr);
|
|
||||||
}
|
|
||||||
if (pr->field_hash) {
|
|
||||||
Hash_FlushTable (pr->field_hash);
|
|
||||||
} else {
|
|
||||||
pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// byte swap the lumps
|
|
||||||
for (i = 0; i < pr->progs->numstatements; i++) {
|
|
||||||
pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op);
|
|
||||||
pr->pr_statements[i].a = LittleShort (pr->pr_statements[i].a);
|
|
||||||
pr->pr_statements[i].b = LittleShort (pr->pr_statements[i].b);
|
|
||||||
pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pr->progs->numfunctions; i++) {
|
|
||||||
pr->pr_functions[i].first_statement =
|
|
||||||
LittleLong (pr->pr_functions[i].first_statement);
|
|
||||||
pr->pr_functions[i].parm_start =
|
|
||||||
LittleLong (pr->pr_functions[i].parm_start);
|
|
||||||
pr->pr_functions[i].s_name = LittleLong (pr->pr_functions[i].s_name);
|
|
||||||
pr->pr_functions[i].s_file = LittleLong (pr->pr_functions[i].s_file);
|
|
||||||
pr->pr_functions[i].numparms =
|
|
||||||
LittleLong (pr->pr_functions[i].numparms);
|
|
||||||
pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals);
|
|
||||||
Hash_Add (pr->function_hash, &pr->pr_functions[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pr->progs->numglobaldefs; i++) {
|
|
||||||
pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type);
|
|
||||||
pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs);
|
|
||||||
pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name);
|
|
||||||
Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pr->progs->numfielddefs; i++) {
|
|
||||||
pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type);
|
|
||||||
if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL)
|
|
||||||
PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
|
|
||||||
pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs);
|
|
||||||
pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name);
|
|
||||||
Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pr->progs->numglobals; i++)
|
|
||||||
((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PR_ResolveGlobals (progs_t *pr)
|
|
||||||
{
|
|
||||||
char *sym;
|
|
||||||
|
|
||||||
if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, sym = "time")))
|
|
||||||
goto error;
|
|
||||||
if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, sym = "self")))
|
|
||||||
goto error;
|
|
||||||
if ((pr->fields.nextthink = ED_GetFieldIndex (pr, sym = "nextthink")) == -1)
|
|
||||||
goto error;
|
|
||||||
if ((pr->fields.frame = ED_GetFieldIndex (pr, sym = "frame")) == -1)
|
|
||||||
goto error;
|
|
||||||
if ((pr->fields.think = ED_GetFieldIndex (pr, sym = "think")) == -1)
|
|
||||||
goto error;
|
|
||||||
return 1;
|
|
||||||
error:
|
|
||||||
Sys_Printf ("%s: undefined symbol: %s", pr->progs_name, sym);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
PR_LoadProgs
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
PR_LoadProgs (progs_t *pr, const char *progsname)
|
|
||||||
{
|
|
||||||
PR_LoadProgsFile (pr, progsname);
|
|
||||||
if (!pr->progs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!progsname)
|
|
||||||
progsname = "(preloaded)";
|
|
||||||
|
|
||||||
if (!PR_ResolveGlobals (pr))
|
|
||||||
PR_Error (pr, "unable to load %s", progsname);
|
|
||||||
|
|
||||||
// initialise the strings managment code
|
|
||||||
PR_LoadStrings (pr);
|
|
||||||
|
|
||||||
PR_LoadDebug (pr);
|
|
||||||
|
|
||||||
PR_Check_Opcodes (pr);
|
|
||||||
}
|
|
||||||
|
|
||||||
edict_t *
|
edict_t *
|
||||||
PR_InitEdicts (progs_t *pr, int num_edicts)
|
PR_InitEdicts (progs_t *pr, int num_edicts)
|
||||||
{
|
{
|
||||||
|
@ -1262,74 +962,6 @@ PR_InitEdicts (progs_t *pr, int num_edicts)
|
||||||
return edicts;
|
return edicts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PR_Init_Cvars (void)
|
|
||||||
{
|
|
||||||
pr_boundscheck =
|
|
||||||
Cvar_Get ("pr_boundscheck", "1", CVAR_NONE, NULL,
|
|
||||||
"Server progs bounds checking");
|
|
||||||
pr_deadbeef_ents = Cvar_Get ("pr_deadbeef_ents", "0", CVAR_NONE, NULL,
|
|
||||||
"set to clear unallocated memory to 0xdeadbeef");
|
|
||||||
pr_deadbeef_locals = Cvar_Get ("pr_deadbeef_locals", "0", CVAR_NONE, NULL,
|
|
||||||
"set to clear uninitialized local vars to "
|
|
||||||
"0xdeadbeef");
|
|
||||||
PR_Debug_Init_Cvars ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PR_Init (void)
|
|
||||||
{
|
|
||||||
PR_Opcode_Init ();
|
|
||||||
PR_Debug_Init ();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PR_AUTOBUILTIN 120
|
|
||||||
void
|
|
||||||
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->numbuiltins = PR_AUTOBUILTIN;
|
|
||||||
if (!pr->builtins)
|
|
||||||
PR_Error (pr, "PR_AddBuiltin: memory allocation error!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num < 0) {
|
|
||||||
for (i = PR_AUTOBUILTIN;
|
|
||||||
i < pr->numbuiltins && pr->builtins[i]; i++)
|
|
||||||
;
|
|
||||||
if (i >= pr->numbuiltins) {
|
|
||||||
pr->numbuiltins++;
|
|
||||||
pr->builtins = realloc (pr->builtins,
|
|
||||||
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])
|
|
||||||
PR_Error (pr, "PR_AddBuiltin: builtin number already exists.\n");
|
|
||||||
i = num;
|
|
||||||
}
|
|
||||||
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 *
|
|
||||||
PR_FindBuiltin (progs_t *pr, const char *name)
|
|
||||||
{
|
|
||||||
return (builtin_t *) Hash_Find (pr->builtin_hash, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
edict_t *
|
edict_t *
|
||||||
EDICT_NUM (progs_t * pr, int n)
|
EDICT_NUM (progs_t * pr, int n)
|
||||||
{
|
{
|
||||||
|
@ -1363,55 +995,3 @@ NUM_FOR_EDICT (progs_t *pr, edict_t *e)
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PR_Error (progs_t *pr, const char *error, ...)
|
|
||||||
{
|
|
||||||
va_list argptr;
|
|
||||||
char string[1024];
|
|
||||||
|
|
||||||
va_start (argptr, error);
|
|
||||||
vsnprintf (string, sizeof (string), error, argptr);
|
|
||||||
va_end (argptr);
|
|
||||||
|
|
||||||
Sys_Error ("%s: %s", pr->progs_name, string);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PR_AccessField (progs_t *pr, const char *name, etype_t type,
|
|
||||||
const char *file, int line)
|
|
||||||
{
|
|
||||||
ddef_t *def = ED_FindField (pr, name);
|
|
||||||
|
|
||||||
if (!def)
|
|
||||||
PR_Error (pr, "undefined field %s accessed at %s:%d", name, file, line);
|
|
||||||
if (def->type != type)
|
|
||||||
PR_Error (pr, "bad type access to %s as %s (should be %s) at %s:%d",
|
|
||||||
name, pr_type_name[type], pr_type_name[def->type],
|
|
||||||
file, line);
|
|
||||||
return def->ofs;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
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) {
|
|
||||||
Sys_Printf ("PR_RelocateBuiltins: %s: undefined builtin %s\n",
|
|
||||||
pr->progs_name, bi_name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
func->first_statement = -bi->first_statement;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
256
libs/gamecode/engine/pr_load.c
Normal file
256
libs/gamecode/engine/pr_load.c
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
/*
|
||||||
|
pr_edict.c
|
||||||
|
|
||||||
|
entity dictionary
|
||||||
|
|
||||||
|
Copyright (C) 1996-1997 Id Software, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
static const char rcsid[] =
|
||||||
|
"$Id$";
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "QF/cmd.h"
|
||||||
|
#include "QF/crc.h"
|
||||||
|
#include "QF/cvar.h"
|
||||||
|
#include "QF/hash.h"
|
||||||
|
#include "QF/progs.h"
|
||||||
|
#include "QF/qdefs.h"
|
||||||
|
#include "QF/qendian.h"
|
||||||
|
#include "QF/sys.h"
|
||||||
|
#include "QF/zone.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
#include "QF/vfs.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
function_get_key (void *f, void *_pr)
|
||||||
|
{
|
||||||
|
progs_t *pr = (progs_t*)_pr;
|
||||||
|
dfunction_t *func = (dfunction_t*)f;
|
||||||
|
return PR_GetString (pr, func->s_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
var_get_key (void *d, void *_pr)
|
||||||
|
{
|
||||||
|
progs_t *pr = (progs_t*)_pr;
|
||||||
|
ddef_t *def = (ddef_t*)d;
|
||||||
|
return PR_GetString (pr, def->s_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PR_LoadProgsFile (progs_t * pr, const char *progsname)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (progsname)
|
||||||
|
pr->progs = (dprograms_t *) COM_LoadHunkFile (progsname);
|
||||||
|
else
|
||||||
|
progsname = pr->progs_name;
|
||||||
|
if (!pr->progs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pr->progs_size = com_filesize;
|
||||||
|
Sys_DPrintf ("Programs occupy %iK.\n", com_filesize / 1024);
|
||||||
|
|
||||||
|
// store prog crc
|
||||||
|
pr->crc = CRC_Block ((byte *) pr->progs, com_filesize);
|
||||||
|
|
||||||
|
// byte swap the header
|
||||||
|
for (i = 0; i < sizeof (*pr->progs) / 4; i++)
|
||||||
|
((int *) pr->progs)[i] = LittleLong (((int *) pr->progs)[i]);
|
||||||
|
|
||||||
|
if (pr->progs->version != PROG_VERSION
|
||||||
|
&& pr->progs->version != PROG_ID_VERSION) {
|
||||||
|
if (pr->progs->version < 0x00fff000) {
|
||||||
|
PR_Error (pr, "%s has unrecognised version number (%d)",
|
||||||
|
progsname, pr->progs->version);
|
||||||
|
} else {
|
||||||
|
PR_Error (pr,
|
||||||
|
"%s has unrecognised version number (%02x.%03x.%03x)"
|
||||||
|
" [%02x.%03x.%03x expected]",
|
||||||
|
progsname,
|
||||||
|
pr->progs->version >> 24,
|
||||||
|
(pr->progs->version >> 12) & 0xfff,
|
||||||
|
pr->progs->version & 0xfff,
|
||||||
|
PROG_VERSION >> 24,
|
||||||
|
(PROG_VERSION >> 12) & 0xfff,
|
||||||
|
PROG_VERSION & 0xfff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr->progs_name = progsname; //XXX is this safe?
|
||||||
|
|
||||||
|
pr->zone = 0; // caller sets up afterwards
|
||||||
|
|
||||||
|
pr->pr_functions =
|
||||||
|
(dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions);
|
||||||
|
pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings;
|
||||||
|
pr->pr_stringsize = pr->progs->numstrings;
|
||||||
|
pr->pr_globaldefs =
|
||||||
|
(ddef_t *) ((byte *) pr->progs + pr->progs->ofs_globaldefs);
|
||||||
|
pr->pr_fielddefs =
|
||||||
|
(ddef_t *) ((byte *) pr->progs + pr->progs->ofs_fielddefs);
|
||||||
|
pr->pr_statements =
|
||||||
|
(dstatement_t *) ((byte *) pr->progs + pr->progs->ofs_statements);
|
||||||
|
|
||||||
|
pr->pr_globals =
|
||||||
|
(pr_type_t *) ((byte *) pr->progs + pr->progs->ofs_globals);
|
||||||
|
|
||||||
|
// size of edict ascked for by progs
|
||||||
|
pr->pr_edict_size = pr->progs->entityfields * 4;
|
||||||
|
// size of engine data
|
||||||
|
pr->pr_edict_size += sizeof (edict_t) - sizeof (pr_type_t);
|
||||||
|
// round off to next highest whole word address (esp for Alpha)
|
||||||
|
// this ensures that pointers in the engine data area are always
|
||||||
|
// properly aligned
|
||||||
|
pr->pr_edict_size += sizeof (void*) - 1;
|
||||||
|
pr->pr_edict_size &= ~(sizeof (void*) - 1);
|
||||||
|
|
||||||
|
pr->pr_edictareasize = 0;
|
||||||
|
|
||||||
|
if (pr->function_hash) {
|
||||||
|
Hash_FlushTable (pr->function_hash);
|
||||||
|
} else {
|
||||||
|
pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr);
|
||||||
|
}
|
||||||
|
if (pr->global_hash) {
|
||||||
|
Hash_FlushTable (pr->global_hash);
|
||||||
|
} else {
|
||||||
|
pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr);
|
||||||
|
}
|
||||||
|
if (pr->field_hash) {
|
||||||
|
Hash_FlushTable (pr->field_hash);
|
||||||
|
} else {
|
||||||
|
pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// byte swap the lumps
|
||||||
|
for (i = 0; i < pr->progs->numstatements; i++) {
|
||||||
|
pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op);
|
||||||
|
pr->pr_statements[i].a = LittleShort (pr->pr_statements[i].a);
|
||||||
|
pr->pr_statements[i].b = LittleShort (pr->pr_statements[i].b);
|
||||||
|
pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pr->progs->numfunctions; i++) {
|
||||||
|
pr->pr_functions[i].first_statement =
|
||||||
|
LittleLong (pr->pr_functions[i].first_statement);
|
||||||
|
pr->pr_functions[i].parm_start =
|
||||||
|
LittleLong (pr->pr_functions[i].parm_start);
|
||||||
|
pr->pr_functions[i].s_name = LittleLong (pr->pr_functions[i].s_name);
|
||||||
|
pr->pr_functions[i].s_file = LittleLong (pr->pr_functions[i].s_file);
|
||||||
|
pr->pr_functions[i].numparms =
|
||||||
|
LittleLong (pr->pr_functions[i].numparms);
|
||||||
|
pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals);
|
||||||
|
Hash_Add (pr->function_hash, &pr->pr_functions[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pr->progs->numglobaldefs; i++) {
|
||||||
|
pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type);
|
||||||
|
pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs);
|
||||||
|
pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name);
|
||||||
|
Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pr->progs->numfielddefs; i++) {
|
||||||
|
pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type);
|
||||||
|
if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL)
|
||||||
|
PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
|
||||||
|
pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs);
|
||||||
|
pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name);
|
||||||
|
Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pr->progs->numglobals; i++)
|
||||||
|
((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
PR_LoadProgs
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PR_LoadProgs (progs_t *pr, const char *progsname)
|
||||||
|
{
|
||||||
|
PR_LoadProgsFile (pr, progsname);
|
||||||
|
if (!pr->progs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!progsname)
|
||||||
|
progsname = "(preloaded)";
|
||||||
|
|
||||||
|
if (!PR_ResolveGlobals (pr))
|
||||||
|
PR_Error (pr, "unable to load %s", progsname);
|
||||||
|
|
||||||
|
// initialise the strings managment code
|
||||||
|
PR_LoadStrings (pr);
|
||||||
|
|
||||||
|
PR_LoadDebug (pr);
|
||||||
|
|
||||||
|
PR_Check_Opcodes (pr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PR_Init_Cvars (void)
|
||||||
|
{
|
||||||
|
pr_boundscheck =
|
||||||
|
Cvar_Get ("pr_boundscheck", "1", CVAR_NONE, NULL,
|
||||||
|
"Server progs bounds checking");
|
||||||
|
pr_deadbeef_ents = Cvar_Get ("pr_deadbeef_ents", "0", CVAR_NONE, NULL,
|
||||||
|
"set to clear unallocated memory to 0xdeadbeef");
|
||||||
|
pr_deadbeef_locals = Cvar_Get ("pr_deadbeef_locals", "0", CVAR_NONE, NULL,
|
||||||
|
"set to clear uninitialized local vars to "
|
||||||
|
"0xdeadbeef");
|
||||||
|
PR_Debug_Init_Cvars ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PR_Init (void)
|
||||||
|
{
|
||||||
|
PR_Opcode_Init ();
|
||||||
|
PR_Debug_Init ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PR_Error (progs_t *pr, const char *error, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char string[1024];
|
||||||
|
|
||||||
|
va_start (argptr, error);
|
||||||
|
vsnprintf (string, sizeof (string), error, argptr);
|
||||||
|
va_end (argptr);
|
||||||
|
|
||||||
|
Sys_Error ("%s: %s", pr->progs_name, string);
|
||||||
|
}
|
195
libs/gamecode/engine/pr_resolve.c
Normal file
195
libs/gamecode/engine/pr_resolve.c
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
pr_edict.c
|
||||||
|
|
||||||
|
entity dictionary
|
||||||
|
|
||||||
|
Copyright (C) 1996-1997 Id Software, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
static const char rcsid[] =
|
||||||
|
"$Id$";
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "QF/cmd.h"
|
||||||
|
#include "QF/crc.h"
|
||||||
|
#include "QF/cvar.h"
|
||||||
|
#include "QF/hash.h"
|
||||||
|
#include "QF/progs.h"
|
||||||
|
#include "QF/qdefs.h"
|
||||||
|
#include "QF/qendian.h"
|
||||||
|
#include "QF/sys.h"
|
||||||
|
#include "QF/zone.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
#include "QF/vfs.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
ED_GlobalAtOfs
|
||||||
|
*/
|
||||||
|
ddef_t *
|
||||||
|
ED_GlobalAtOfs (progs_t * pr, int ofs)
|
||||||
|
{
|
||||||
|
ddef_t *def;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < pr->progs->numglobaldefs; i++) {
|
||||||
|
def = &pr->pr_globaldefs[i];
|
||||||
|
if (def->ofs == ofs)
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ED_FieldAtOfs
|
||||||
|
*/
|
||||||
|
ddef_t *
|
||||||
|
ED_FieldAtOfs (progs_t * pr, int ofs)
|
||||||
|
{
|
||||||
|
ddef_t *def;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < pr->progs->numfielddefs; i++) {
|
||||||
|
def = &pr->pr_fielddefs[i];
|
||||||
|
if (def->ofs == ofs)
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ED_FindField
|
||||||
|
*/
|
||||||
|
ddef_t *
|
||||||
|
ED_FindField (progs_t * pr, const char *name)
|
||||||
|
{
|
||||||
|
return Hash_Find (pr->field_hash, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ED_GetFieldIndex (progs_t *pr, const char *name)
|
||||||
|
{
|
||||||
|
ddef_t *def;
|
||||||
|
|
||||||
|
def = ED_FindField (pr, name);
|
||||||
|
if (def)
|
||||||
|
return def->ofs;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
PR_FindGlobal
|
||||||
|
*/
|
||||||
|
ddef_t *
|
||||||
|
PR_FindGlobal (progs_t * pr, const char *name)
|
||||||
|
{
|
||||||
|
return Hash_Find (pr->global_hash, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_type_t *
|
||||||
|
PR_GetGlobalPointer (progs_t *pr, const char *name)
|
||||||
|
{
|
||||||
|
ddef_t *def;
|
||||||
|
|
||||||
|
def = PR_FindGlobal (pr, name);
|
||||||
|
if (def)
|
||||||
|
return &pr->pr_globals[def->ofs];
|
||||||
|
PR_Error (pr, "undefined global %s", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
func_t
|
||||||
|
PR_GetFunctionIndex (progs_t *pr, const char *name)
|
||||||
|
{
|
||||||
|
dfunction_t *func = ED_FindFunction (pr, name);
|
||||||
|
if (func)
|
||||||
|
return func - pr->pr_functions;
|
||||||
|
PR_Error (pr, "undefined function %s", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PR_GetFieldOffset (progs_t *pr, const char *name)
|
||||||
|
{
|
||||||
|
ddef_t *def = ED_FindField (pr, name);
|
||||||
|
if (def)
|
||||||
|
return def->ofs;
|
||||||
|
PR_Error (pr, "undefined field %s", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ED_FindFunction
|
||||||
|
*/
|
||||||
|
dfunction_t *
|
||||||
|
ED_FindFunction (progs_t * pr, const char *name)
|
||||||
|
{
|
||||||
|
return Hash_Find (pr->function_hash, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PR_ResolveGlobals (progs_t *pr)
|
||||||
|
{
|
||||||
|
char *sym;
|
||||||
|
|
||||||
|
if (!(pr->globals.time = (float*)PR_GetGlobalPointer (pr, sym = "time")))
|
||||||
|
goto error;
|
||||||
|
if (!(pr->globals.self = (int*)PR_GetGlobalPointer (pr, sym = "self")))
|
||||||
|
goto error;
|
||||||
|
if ((pr->fields.nextthink = ED_GetFieldIndex (pr, sym = "nextthink")) == -1)
|
||||||
|
goto error;
|
||||||
|
if ((pr->fields.frame = ED_GetFieldIndex (pr, sym = "frame")) == -1)
|
||||||
|
goto error;
|
||||||
|
if ((pr->fields.think = ED_GetFieldIndex (pr, sym = "think")) == -1)
|
||||||
|
goto error;
|
||||||
|
return 1;
|
||||||
|
error:
|
||||||
|
Sys_Printf ("%s: undefined symbol: %s", pr->progs_name, sym);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PR_AccessField (progs_t *pr, const char *name, etype_t type,
|
||||||
|
const char *file, int line)
|
||||||
|
{
|
||||||
|
ddef_t *def = ED_FindField (pr, name);
|
||||||
|
|
||||||
|
if (!def)
|
||||||
|
PR_Error (pr, "undefined field %s accessed at %s:%d", name, file, line);
|
||||||
|
if (def->type != type)
|
||||||
|
PR_Error (pr, "bad type access to %s as %s (should be %s) at %s:%d",
|
||||||
|
name, pr_type_name[type], pr_type_name[def->type],
|
||||||
|
file, line);
|
||||||
|
return def->ofs;
|
||||||
|
}
|
Loading…
Reference in a new issue