DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
prvm_edict.c File Reference
#include "quakedef.h"
#include "progsvm.h"
#include "csprogs.h"
#include "prvm_cmds.h"
#include "prvm_offsets.h"
Include dependency graph for prvm_edict.c:

Go to the source code of this file.

Data Structures

struct  debug_data_t
struct  po_string_t
struct  po_t

Macros

#define PO_HASHSIZE   16384
#define PRVM_DECLARE_clientfieldedict(x)
#define PRVM_DECLARE_clientfieldfloat(x)
#define PRVM_DECLARE_clientfieldfunction(x)
#define PRVM_DECLARE_clientfieldstring(x)
#define PRVM_DECLARE_clientfieldvector(x)
#define PRVM_DECLARE_clientfunction(x)
#define PRVM_DECLARE_clientglobaledict(x)
#define PRVM_DECLARE_clientglobalfloat(x)
#define PRVM_DECLARE_clientglobalfunction(x)
#define PRVM_DECLARE_clientglobalstring(x)
#define PRVM_DECLARE_clientglobalvector(x)
#define PRVM_DECLARE_field(x)
#define PRVM_DECLARE_function(x)
#define PRVM_DECLARE_global(x)
#define PRVM_DECLARE_menufieldedict(x)
#define PRVM_DECLARE_menufieldfloat(x)
#define PRVM_DECLARE_menufieldfunction(x)
#define PRVM_DECLARE_menufieldstring(x)
#define PRVM_DECLARE_menufieldvector(x)
#define PRVM_DECLARE_menufunction(x)
#define PRVM_DECLARE_menuglobaledict(x)
#define PRVM_DECLARE_menuglobalfloat(x)
#define PRVM_DECLARE_menuglobalfunction(x)
#define PRVM_DECLARE_menuglobalstring(x)
#define PRVM_DECLARE_menuglobalvector(x)
#define PRVM_DECLARE_serverfieldedict(x)
#define PRVM_DECLARE_serverfieldfloat(x)
#define PRVM_DECLARE_serverfieldfunction(x)
#define PRVM_DECLARE_serverfieldstring(x)
#define PRVM_DECLARE_serverfieldvector(x)
#define PRVM_DECLARE_serverfunction(x)
#define PRVM_DECLARE_serverglobaledict(x)
#define PRVM_DECLARE_serverglobalfloat(x)
#define PRVM_DECLARE_serverglobalfunction(x)
#define PRVM_DECLARE_serverglobalstring(x)
#define PRVM_DECLARE_serverglobalvector(x)
#define PRVM_KNOWNSTRINGBASE   0x40000000
#define remapfield(index)
#define remapglobal(index)

Functions

const char * PRVM_AllocationOrigin (prvm_prog_t *prog)
int PRVM_AllocString (prvm_prog_t *prog, size_t bufferlength, char **pointer)
void PRVM_Breakpoint (prvm_prog_t *prog, int stack_index, const char *text)
static void PRVM_Breakpoint_f (cmd_state_t *cmd)
const char * PRVM_ChangeEngineString (prvm_prog_t *prog, int i, const char *s)
prvm_edict_tPRVM_ED_Alloc (prvm_prog_t *prog)
void PRVM_ED_CallPostspawnFunction (prvm_prog_t *prog, prvm_edict_t *ent)
void PRVM_ED_CallPrespawnFunction (prvm_prog_t *prog, prvm_edict_t *ent)
qbool PRVM_ED_CallSpawnFunction (prvm_prog_t *prog, prvm_edict_t *ent, const char *data, const char *start)
qbool PRVM_ED_CanAlloc (prvm_prog_t *prog, prvm_edict_t *e)
void PRVM_ED_ClearEdict (prvm_prog_t *prog, prvm_edict_t *e)
static void PRVM_ED_Count_f (cmd_state_t *cmd)
static void PRVM_ED_EdictGet_f (cmd_state_t *cmd)
static void PRVM_ED_EdictSet_f (cmd_state_t *cmd)
mdef_tPRVM_ED_FieldAtOfs (prvm_prog_t *prog, unsigned int ofs)
mdef_tPRVM_ED_FindField (prvm_prog_t *prog, const char *name)
int PRVM_ED_FindFieldOffset (prvm_prog_t *prog, const char *field)
mfunction_tPRVM_ED_FindFunction (prvm_prog_t *prog, const char *name)
func_t PRVM_ED_FindFunctionOffset (prvm_prog_t *prog, const char *function)
mdef_tPRVM_ED_FindGlobal (prvm_prog_t *prog, const char *name)
prvm_eval_tPRVM_ED_FindGlobalEval (prvm_prog_t *prog, const char *name)
int PRVM_ED_FindGlobalOffset (prvm_prog_t *prog, const char *global)
void PRVM_ED_Free (prvm_prog_t *prog, prvm_edict_t *ed)
static mdef_tPRVM_ED_GlobalAtOfs (prvm_prog_t *prog, unsigned int ofs)
static void PRVM_ED_GlobalGet_f (cmd_state_t *cmd)
void PRVM_ED_LoadFromFile (prvm_prog_t *prog, const char *data)
const char * PRVM_ED_ParseEdict (prvm_prog_t *prog, const char *data, prvm_edict_t *ent, qbool saveload)
qbool PRVM_ED_ParseEpair (prvm_prog_t *prog, prvm_edict_t *ent, mdef_t *key, const char *s, qbool parsebackslash)
void PRVM_ED_ParseGlobals (prvm_prog_t *prog, const char *data)
void PRVM_ED_Print (prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname)
static void PRVM_ED_PrintEdict_f (cmd_state_t *cmd)
void PRVM_ED_PrintEdicts_f (cmd_state_t *cmd)
void PRVM_ED_PrintNum (prvm_prog_t *prog, int ent, const char *wildcard_fieldname)
void PRVM_ED_Write (prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed)
void PRVM_ED_WriteGlobals (prvm_prog_t *prog, qfile_t *f)
unsigned int PRVM_EDICT_NUM_ERROR (prvm_prog_t *prog, unsigned int n, const char *filename, int fileline)
static void PRVM_EdictWatchpoint_f (cmd_state_t *cmd)
static void PRVM_Fields_f (cmd_state_t *cmd)
static void PRVM_FindOffsets (prvm_prog_t *prog)
void PRVM_FreeString (prvm_prog_t *prog, int num)
prvm_prog_tPRVM_FriendlyProgFromString (const char *str)
 for console commands (prints error if name unknown and returns NULL, prints error if prog not loaded and returns NULL)
static void PRVM_GameCommand (cmd_state_t *cmd, const char *whichprogs, const char *whichcmd)
static void PRVM_GameCommand_Client_f (cmd_state_t *cmd)
static void PRVM_GameCommand_Menu_f (cmd_state_t *cmd)
static void PRVM_GameCommand_Server_f (cmd_state_t *cmd)
void PRVM_GarbageCollection (prvm_prog_t *prog)
const char * PRVM_GetString (prvm_prog_t *prog, int num)
static void PRVM_Global_f (cmd_state_t *cmd)
static void PRVM_Globals_f (cmd_state_t *cmd)
static void PRVM_GlobalSet_f (cmd_state_t *cmd)
char * PRVM_GlobalString (prvm_prog_t *prog, int ofs, char *line, size_t linelength)
char * PRVM_GlobalStringNoContents (prvm_prog_t *prog, int ofs, char *line, size_t linelength)
static void PRVM_GlobalWatchpoint_f (cmd_state_t *cmd)
void PRVM_Init (void)
static qbool PRVM_IsEdictReferenced (prvm_prog_t *prog, prvm_edict_t *edict, int mark)
static qbool PRVM_IsEdictRelevant (prvm_prog_t *prog, prvm_edict_t *edict)
static qbool PRVM_IsStringReferenced (prvm_prog_t *prog, string_t string)
void PRVM_LeakTest (prvm_prog_t *prog)
static void PRVM_LoadLNO (prvm_prog_t *prog, const char *progname)
static void PRVM_MarkReferencedEdicts (prvm_prog_t *prog)
static void PRVM_MEM_Alloc (prvm_prog_t *prog)
void PRVM_MEM_IncreaseEdicts (prvm_prog_t *prog)
static void PRVM_NewKnownString (prvm_prog_t *prog, int i, int flags, const char *s)
static void PRVM_PO_Destroy (po_t *po)
static po_tPRVM_PO_Load (const char *filename, const char *filename2, mempool_t *pool)
static const char * PRVM_PO_Lookup (po_t *po, const char *str)
static void PRVM_PO_ParseString (char *out, const char *in, size_t outsize)
static void PRVM_PO_UnparseString (char *out, const char *in, size_t outsize)
void PRVM_Prog_Init (prvm_prog_t *prog, cmd_state_t *cmd)
void PRVM_Prog_Load (prvm_prog_t *prog, const char *filename, unsigned char *data, fs_offset_t size, void CheckRequiredFuncs(prvm_prog_t *prog, const char *filename), int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global)
void PRVM_Prog_Reset (prvm_prog_t *prog)
prvm_prog_tPRVM_ProgFromString (const char *str)
int PRVM_SetEngineString (prvm_prog_t *prog, const char *s)
int PRVM_SetTempString (prvm_prog_t *prog, const char *s, size_t slen)
 Takes an strlen (not a buffer size).
char * PRVM_UglyValueString (prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
static void PRVM_UpdateBreakpoints (prvm_prog_t *prog)
static char * PRVM_ValueString (prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
void PRVM_Watchpoint (prvm_prog_t *prog, int stack_index, const char *text, etype_t type, prvm_eval_t *o, prvm_eval_t *n)

Variables

static debug_data_t debug_data [PRVM_PROG_MAX]
cvar_t prvm_backtraceforwarnings = {CF_CLIENT | CF_SERVER, "prvm_backtraceforwarnings", "0", "print a backtrace for warnings too"}
prvm_eval_t prvm_badvalue
cvar_t prvm_breakpointdump = {CF_CLIENT | CF_SERVER, "prvm_breakpointdump", "0", "write a savegame on breakpoint to breakpoint-server.dmp"}
cvar_t prvm_coverage = {CF_CLIENT | CF_SERVER, "prvm_coverage", "0", "report and count coverage events (1: per-function, 2: coverage() builtin, 4: per-statement)"}
cvar_t prvm_errordump = {CF_CLIENT | CF_SERVER, "prvm_errordump", "0", "write a savegame on crash to crash-server.dmp"}
cvar_t prvm_gameplayfix_div0is0 = {CF_SERVER, "prvm_gameplayfix_div0is0", "0", "When set to 1, floating point division by 0 will return zero instead of returning the IEEE standardized result (likely nan or inf). Other ways of getting non-finite values are not affected, and the warning will still print."}
cvar_t prvm_garbagecollection_enable = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_enable", "1", "automatically scan for and free resources that are not referenced by the code being executed in the VM"}
cvar_t prvm_garbagecollection_notify = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_notify", "0", "print out a notification for each resource freed by garbage collection (set developer >= 1 to see these)"}
cvar_t prvm_garbagecollection_scan_limit = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_scan_limit", "50000", "scan this many fields or resources per second to free up unreferenced resources"}
 At 50k in Xonotic with 8 bots scans take about: 24s server, 25s menu, 9s client.
cvar_t prvm_garbagecollection_strings = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_strings", "1", "automatically call strunzone() on strings that are not referenced"}
cvar_t prvm_language = {CF_CLIENT | CF_SERVER | CF_ARCHIVE, "prvm_language", "", "when set, loads PROGSFILE.LANGUAGENAME.po and common.LANGUAGENAME.po for string translations; when set to dump, PROGSFILE.pot is written from the strings in the progs"}
cvar_t prvm_leaktest = {CF_CLIENT | CF_SERVER, "prvm_leaktest", "0", "try to detect memory leaks in strings or entities"}
cvar_t prvm_leaktest_follow_targetname = {CF_CLIENT | CF_SERVER, "prvm_leaktest_follow_targetname", "0", "if set, target/targetname links are considered when leak testing; this should normally not be required, as entities created during startup - e.g. info_notnull - are never considered leaky"}
cvar_t prvm_leaktest_ignore_classnames = {CF_CLIENT | CF_SERVER, "prvm_leaktest_ignore_classnames", "", "classnames of entities to NOT leak check because they are found by find(world, classname, ...) but are actually spawned by QC code (NOT map entities)"}
prvm_prog_t prvm_prog_list [PRVM_PROG_MAX]
static double prvm_reuseedicts_always_allow = 0
cvar_t prvm_reuseedicts_neverinsameframe = {CF_CLIENT | CF_SERVER, "prvm_reuseedicts_neverinsameframe", "1", "never allows re-use of freed entity slots during same frame"}
cvar_t prvm_reuseedicts_startuptime = {CF_CLIENT | CF_SERVER, "prvm_reuseedicts_startuptime", "2", "allows immediate re-use of freed entity slots during start of new level (value in seconds)"}
qbool prvm_runawaycheck = true
cvar_t prvm_statementprofiling = {CF_CLIENT | CF_SERVER, "prvm_statementprofiling", "0", "counts how many times each QuakeC statement has been executed, these counts are displayed in prvm_printfunction output (if enabled)"}
cvar_t prvm_stringdebug = {CF_CLIENT | CF_SERVER, "prvm_stringdebug", "0", "Print debug and warning messages related to strings"}
cvar_t prvm_timeprofiling = {CF_CLIENT | CF_SERVER, "prvm_timeprofiling", "0", "counts how long each function has been executed, these counts are displayed in prvm_profile output (if enabled)"}
cvar_t prvm_traceqc = {CF_CLIENT | CF_SERVER, "prvm_traceqc", "0", "prints every QuakeC statement as it is executed (only for really thorough debugging!)"}
int prvm_type_size [8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4}
 for consistency : I think a goal of this sub-project is to make the new vm mostly independent from the old one, thus if it's necessary, I copy everything
cvar_t sv_entfields_noescapes = {CF_SERVER, "sv_entfields_noescapes", "wad", "Space-separated list of fields in which backslashes won't be parsed as escapes when loading entities from .bsp or .ent files. This is a workaround for buggy maps with unescaped backslashes used as path separators (only forward slashes are allowed in Quake VFS paths)."}

Macro Definition Documentation

◆ PO_HASHSIZE

#define PO_HASHSIZE   16384

Definition at line 1694 of file prvm_edict.c.

Referenced by PRVM_PO_Destroy(), PRVM_PO_Load(), and PRVM_PO_Lookup().

◆ PRVM_DECLARE_clientfieldedict

#define PRVM_DECLARE_clientfieldedict ( x)

◆ PRVM_DECLARE_clientfieldfloat

#define PRVM_DECLARE_clientfieldfloat ( x)

◆ PRVM_DECLARE_clientfieldfunction

#define PRVM_DECLARE_clientfieldfunction ( x)

◆ PRVM_DECLARE_clientfieldstring

#define PRVM_DECLARE_clientfieldstring ( x)

◆ PRVM_DECLARE_clientfieldvector

#define PRVM_DECLARE_clientfieldvector ( x)

◆ PRVM_DECLARE_clientfunction

#define PRVM_DECLARE_clientfunction ( x)

◆ PRVM_DECLARE_clientglobaledict

#define PRVM_DECLARE_clientglobaledict ( x)

◆ PRVM_DECLARE_clientglobalfloat

#define PRVM_DECLARE_clientglobalfloat ( x)

◆ PRVM_DECLARE_clientglobalfunction

#define PRVM_DECLARE_clientglobalfunction ( x)

◆ PRVM_DECLARE_clientglobalstring

#define PRVM_DECLARE_clientglobalstring ( x)

◆ PRVM_DECLARE_clientglobalvector

#define PRVM_DECLARE_clientglobalvector ( x)

◆ PRVM_DECLARE_field

#define PRVM_DECLARE_field ( x)
Value:
prog->fieldoffsets.x = PRVM_ED_FindFieldOffset(prog, #x);
GLint GLenum GLint x
Definition glquake.h:651
int PRVM_ED_FindFieldOffset(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:134

◆ PRVM_DECLARE_function

#define PRVM_DECLARE_function ( x)
Value:
prog->funcoffsets.x = PRVM_ED_FindFunctionOffset(prog, #x);
func_t PRVM_ED_FindFunctionOffset(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:152

◆ PRVM_DECLARE_global

#define PRVM_DECLARE_global ( x)
Value:
prog->globaloffsets.x = PRVM_ED_FindGlobalOffset(prog, #x);
int PRVM_ED_FindGlobalOffset(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:143

◆ PRVM_DECLARE_menufieldedict

#define PRVM_DECLARE_menufieldedict ( x)

◆ PRVM_DECLARE_menufieldfloat

#define PRVM_DECLARE_menufieldfloat ( x)

◆ PRVM_DECLARE_menufieldfunction

#define PRVM_DECLARE_menufieldfunction ( x)

◆ PRVM_DECLARE_menufieldstring

#define PRVM_DECLARE_menufieldstring ( x)

◆ PRVM_DECLARE_menufieldvector

#define PRVM_DECLARE_menufieldvector ( x)

◆ PRVM_DECLARE_menufunction

#define PRVM_DECLARE_menufunction ( x)

◆ PRVM_DECLARE_menuglobaledict

#define PRVM_DECLARE_menuglobaledict ( x)

◆ PRVM_DECLARE_menuglobalfloat

#define PRVM_DECLARE_menuglobalfloat ( x)

◆ PRVM_DECLARE_menuglobalfunction

#define PRVM_DECLARE_menuglobalfunction ( x)

◆ PRVM_DECLARE_menuglobalstring

#define PRVM_DECLARE_menuglobalstring ( x)

◆ PRVM_DECLARE_menuglobalvector

#define PRVM_DECLARE_menuglobalvector ( x)

◆ PRVM_DECLARE_serverfieldedict

#define PRVM_DECLARE_serverfieldedict ( x)

◆ PRVM_DECLARE_serverfieldfloat

#define PRVM_DECLARE_serverfieldfloat ( x)

◆ PRVM_DECLARE_serverfieldfunction

#define PRVM_DECLARE_serverfieldfunction ( x)

◆ PRVM_DECLARE_serverfieldstring

#define PRVM_DECLARE_serverfieldstring ( x)

◆ PRVM_DECLARE_serverfieldvector

#define PRVM_DECLARE_serverfieldvector ( x)

◆ PRVM_DECLARE_serverfunction

#define PRVM_DECLARE_serverfunction ( x)

◆ PRVM_DECLARE_serverglobaledict

#define PRVM_DECLARE_serverglobaledict ( x)

◆ PRVM_DECLARE_serverglobalfloat

#define PRVM_DECLARE_serverglobalfloat ( x)

◆ PRVM_DECLARE_serverglobalfunction

#define PRVM_DECLARE_serverglobalfunction ( x)

◆ PRVM_DECLARE_serverglobalstring

#define PRVM_DECLARE_serverglobalstring ( x)

◆ PRVM_DECLARE_serverglobalvector

#define PRVM_DECLARE_serverglobalvector ( x)

◆ PRVM_KNOWNSTRINGBASE

#define PRVM_KNOWNSTRINGBASE   0x40000000

◆ remapfield

#define remapfield ( index)
Value:
GLuint index
Definition glquake.h:629

◆ remapglobal

#define remapglobal ( index)
Value:

Referenced by PRVM_Prog_Load().

Function Documentation

◆ PRVM_AllocationOrigin()

const char * PRVM_AllocationOrigin ( prvm_prog_t * prog)

Definition at line 223 of file prvm_edict.c.

224{
225 char *buf = NULL;
226 if(prog->leaktest_active)
227 if(prog->depth > 0) // actually in QC code and not just parsing the entities block of a map/savegame
228 {
229 // bones_was_here: this is the smallest 64 multiple that avoids truncation in Xonotic (was 256)
230 buf = (char *)PRVM_Alloc(448);
231 PRVM_ShortStackTrace(prog, buf, 448);
232 }
233 return buf;
234}
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
#define PRVM_Alloc(buffersize)
Definition progsvm.h:818
void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize)
Definition prvm_exec.c:464
#define NULL
Definition qtypes.h:12
qbool leaktest_active
Definition progsvm.h:711

References buf, prvm_prog_t::depth, prvm_prog_t::leaktest_active, NULL, PRVM_Alloc, and PRVM_ShortStackTrace().

Referenced by PRVM_AllocString(), PRVM_ED_ClearEdict(), VM_buf_create(), VM_fopen(), and VM_search_begin().

◆ PRVM_AllocString()

int PRVM_AllocString ( prvm_prog_t * prog,
size_t bufferlength,
char ** pointer )

Definition at line 3494 of file prvm_edict.c.

3495{
3496 int i;
3497 char *s;
3498 if (!bufferlength)
3499 {
3500 if (pointer)
3501 *pointer = NULL;
3502 return 0;
3503 }
3504 for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
3505 if (!prog->knownstrings[i])
3506 break;
3507 s = (char *)PRVM_Alloc(bufferlength);
3509 if(prog->leaktest_active)
3511 if (pointer)
3512 *pointer = (char *)(prog->knownstrings[i]);
3513 return PRVM_KNOWNSTRINGBASE + i;
3514}
GLenum GLvoid ** pointer
Definition glquake.h:714
#define KNOWNSTRINGFLAG_GCMARK
Definition progsvm.h:511
static void PRVM_NewKnownString(prvm_prog_t *prog, int i, int flags, const char *s)
#define PRVM_KNOWNSTRINGBASE
const char * PRVM_AllocationOrigin(prvm_prog_t *prog)
Definition prvm_edict.c:223
const char ** knownstrings
Definition progsvm.h:591
const char ** knownstrings_origin
Definition progsvm.h:593
int firstfreeknownstring
this is updated whenever a string is removed or added (simple optimization of the free string search)
Definition progsvm.h:590

References prvm_prog_t::firstfreeknownstring, KNOWNSTRINGFLAG_GCMARK, prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_origin, prvm_prog_t::leaktest_active, NULL, pointer, PRVM_Alloc, PRVM_AllocationOrigin(), PRVM_KNOWNSTRINGBASE, and PRVM_NewKnownString().

Referenced by PRVM_ED_CallSpawnFunction(), PRVM_ED_ParseEpair(), and VM_strzone().

◆ PRVM_Breakpoint()

void PRVM_Breakpoint ( prvm_prog_t * prog,
int stack_index,
const char * text )

Definition at line 3035 of file prvm_edict.c.

3036{
3037 char vabuf[1024];
3038 Con_Printf("PRVM_Breakpoint: %s\n", text);
3039 PRVM_PrintState(prog, stack_index);
3040 if (prvm_breakpointdump.integer)
3041 SV_Savegame_to(prog, va(vabuf, sizeof(vabuf), "breakpoint-%s.dmp", prog->name));
3042}
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
void PRVM_PrintState(prvm_prog_t *prog, int stack_index)
Definition prvm_exec.c:726
cvar_t prvm_breakpointdump
Definition prvm_edict.c:45
void SV_Savegame_to(prvm_prog_t *prog, const char *name)
Definition sv_save.c:35
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
Definition progsvm.h:700

References Con_Printf(), prvm_prog_t::name, prvm_breakpointdump, PRVM_PrintState(), SV_Savegame_to(), and va().

Referenced by PRVM_Watchpoint(), and while().

◆ PRVM_Breakpoint_f()

void PRVM_Breakpoint_f ( cmd_state_t * cmd)
static

Definition at line 3140 of file prvm_edict.c.

3141{
3142 prvm_prog_t *prog;
3143
3144 if( Cmd_Argc(cmd) == 2 ) {
3145 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
3146 return;
3147 {
3148 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3149 debug->break_statement[0] = 0;
3150 }
3152 return;
3153 }
3154 if( Cmd_Argc(cmd) != 3 ) {
3155 Con_Printf( "prvm_breakpoint <program name> <function name | statement>\n" );
3156 return;
3157 }
3158
3159 if (!(prog = PRVM_ProgFromString(Cmd_Argv(cmd, 1))))
3160 return;
3161
3162 {
3163 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3164 dp_strlcpy(debug->break_statement, Cmd_Argv(cmd, 2), sizeof(debug->break_statement));
3165 }
3167}
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void cmd(string command,...)
prvm_prog_t prvm_prog_list[PRVM_PROG_MAX]
Definition prvm_edict.c:27
static debug_data_t debug_data[PRVM_PROG_MAX]
prvm_prog_t * PRVM_ProgFromString(const char *str)
Definition prvm_edict.c:166
prvm_prog_t * PRVM_FriendlyProgFromString(const char *str)
for console commands (prints error if name unknown and returns NULL, prints error if prog not loaded ...
Definition prvm_edict.c:184
static void PRVM_UpdateBreakpoints(prvm_prog_t *prog)
char break_statement[256]

References debug_data_t::break_statement, cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), debug_data, dp_strlcpy, PRVM_FriendlyProgFromString(), prvm_prog_list, PRVM_ProgFromString(), and PRVM_UpdateBreakpoints().

Referenced by PRVM_Init().

◆ PRVM_ChangeEngineString()

const char * PRVM_ChangeEngineString ( prvm_prog_t * prog,
int i,
const char * s )

Definition at line 3380 of file prvm_edict.c.

3381{
3382 const char *old;
3383 i = i - PRVM_KNOWNSTRINGBASE;
3384 if (i < 0 || i >= prog->numknownstrings)
3385 prog->error_cmd("PRVM_ChangeEngineString: string index %i is out of bounds", i);
3386 else if ((prog->knownstrings_flags[i] & KNOWNSTRINGFLAG_ENGINE) == 0)
3387 prog->error_cmd("PRVM_ChangeEngineString: string index %i is not an engine string", i);
3388 old = prog->knownstrings[i];
3389 prog->knownstrings[i] = s;
3390 return old;
3391}
#define KNOWNSTRINGFLAG_ENGINE
Definition progsvm.h:510
unsigned char * knownstrings_flags
Definition progsvm.h:592
void(* error_cmd)(const char *format,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
[INIT]
Definition progsvm.h:747
int numknownstrings
Definition progsvm.h:587

References prvm_prog_t::error_cmd, KNOWNSTRINGFLAG_ENGINE, prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_flags, prvm_prog_t::numknownstrings, and PRVM_KNOWNSTRINGBASE.

Referenced by Cvar_UpdateAutoCvar().

◆ PRVM_ED_Alloc()

prvm_edict_t * PRVM_ED_Alloc ( prvm_prog_t * prog)

Definition at line 269 of file prvm_edict.c.

270{
271 int i;
272 prvm_edict_t *e;
273
274 // the client qc dont need maxclients
275 // thus it doesnt need to use svs.maxclients
276 // AK: changed i=svs.maxclients+1
277 // AK: changed so the edict 0 wont spawn -> used as reserved/world entity
278 // although the menu/client has no world
279 for (i = prog->reserved_edicts + 1;i < prog->num_edicts;i++)
280 {
281 e = PRVM_EDICT_NUM(i);
282 if(PRVM_ED_CanAlloc(prog, e))
283 {
284 PRVM_ED_ClearEdict (prog, e);
285 return e;
286 }
287 }
288
289 if (i == prog->limit_edicts)
290 prog->error_cmd("%s: PRVM_ED_Alloc: no free edicts", prog->name);
291
292 prog->num_edicts++;
293 if (prog->num_edicts >= prog->max_edicts)
295
296 e = PRVM_EDICT_NUM(i);
297
298 PRVM_ED_ClearEdict(prog, e);
299 return e;
300}
#define PRVM_EDICT_NUM(n)
Definition progsvm.h:867
void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e)
Definition prvm_edict.c:210
void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog)
Definition prvm_edict.c:105
qbool PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e)
Definition prvm_edict.c:243
int num_edicts
copies of some vars that were former read from sv
Definition progsvm.h:671
int limit_edicts
used instead of the constant MAX_EDICTS
Definition progsvm.h:675
int max_edicts
number of edicts for which space has been (should be) allocated
Definition progsvm.h:673
int reserved_edicts
number of reserved edicts (allocated from 1)
Definition progsvm.h:678

References prvm_prog_t::error_cmd, prvm_prog_t::limit_edicts, prvm_prog_t::max_edicts, prvm_prog_t::name, prvm_prog_t::num_edicts, PRVM_ED_CanAlloc(), PRVM_ED_ClearEdict(), PRVM_EDICT_NUM, PRVM_MEM_IncreaseEdicts(), and prvm_prog_t::reserved_edicts.

Referenced by CSQC_ReadEntities(), PRVM_ED_LoadFromFile(), SV_Ent_Create_f(), VM_CL_spawn(), and VM_spawn().

◆ PRVM_ED_CallPostspawnFunction()

void PRVM_ED_CallPostspawnFunction ( prvm_prog_t * prog,
prvm_edict_t * ent )

Definition at line 1490 of file prvm_edict.c.

1491{
1492 if(!ent->free)
1493 if (PRVM_serverfunction(SV_OnEntityPostSpawnFunction))
1494 {
1495 // self = ent
1498 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPostSpawnFunction), "QC function SV_OnEntityPostSpawnFunction is missing");
1499 }
1500}
entity self
float time
#define PRVM_serverglobaledict(fieldname)
Definition progsvm.h:180
#define PRVM_EDICT_TO_PROG(e)
Definition progsvm.h:875
#define PRVM_serverglobalfloat(fieldname)
Definition progsvm.h:177
#define PRVM_serverfunction(funcname)
Definition progsvm.h:182
server_t sv
local server
Definition sv_main.c:223
qbool free
true if this edict is unused
Definition progsvm.h:93
void(* ExecuteProgram)(struct prvm_prog_s *prog, func_t fnum, const char *errormessage)
pointer to one of the *VM_ExecuteProgram functions
Definition progsvm.h:749

References prvm_prog_t::ExecuteProgram, prvm_edict_t::free, PRVM_EDICT_TO_PROG, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, and time.

Referenced by PRVM_ED_LoadFromFile(), and SV_Ent_Create_f().

◆ PRVM_ED_CallPrespawnFunction()

void PRVM_ED_CallPrespawnFunction ( prvm_prog_t * prog,
prvm_edict_t * ent )

Definition at line 1395 of file prvm_edict.c.

1396{
1397 if (PRVM_serverfunction(SV_OnEntityPreSpawnFunction))
1398 {
1399 // self = ent
1402 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPreSpawnFunction), "QC function SV_OnEntityPreSpawnFunction is missing");
1403 }
1404}

References prvm_prog_t::ExecuteProgram, PRVM_EDICT_TO_PROG, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, and time.

Referenced by PRVM_ED_LoadFromFile(), and SV_Ent_Create_f().

◆ PRVM_ED_CallSpawnFunction()

qbool PRVM_ED_CallSpawnFunction ( prvm_prog_t * prog,
prvm_edict_t * ent,
const char * data,
const char * start )

Definition at line 1406 of file prvm_edict.c.

1407{
1408 const char *funcname;
1409 mfunction_t *func;
1410 prvm_eval_t *fulldata = NULL;
1411 char vabuf[1024];
1412
1413//
1414// immediately call spawn function, but only if there is a self global and a classname
1415//
1416 if (!ent->free)
1417 {
1418 if (!PRVM_alledictstring(ent, classname))
1419 {
1420 Con_Print("No classname for:\n");
1421 PRVM_ED_Print(prog, ent, NULL);
1422 PRVM_ED_Free (prog, ent);
1423 return false;
1424 }
1425 /*
1426 * This is required for FTE compatibility (FreeCS).
1427 * It copies the key/value pairs themselves into a
1428 * global for QC to parse on its own.
1429 */
1430 else if (data && start)
1431 {
1432 if((fulldata = PRVM_ED_FindGlobalEval(prog, "__fullspawndata")))
1433 {
1434 const char *in;
1435 char *spawndata;
1436 fulldata->string = PRVM_AllocString(prog, data - start + 1, &spawndata);
1437 for(in = start; in < data; )
1438 {
1439 char c = *in++;
1440 if(c == '\n')
1441 *spawndata++ = '\t';
1442 else
1443 *spawndata++ = c;
1444 }
1445 *spawndata = 0;
1446 }
1447 }
1448
1449 // look for the spawn function
1450 funcname = PRVM_GetString(prog, PRVM_alledictstring(ent, classname));
1451 func = PRVM_ED_FindFunction (prog, va(vabuf, sizeof(vabuf), "spawnfunc_%s", funcname));
1452 if(!func)
1453 if(!PRVM_allglobalfloat(require_spawnfunc_prefix))
1454 func = PRVM_ED_FindFunction (prog, funcname);
1455
1456 if (!func)
1457 {
1458 // check for OnEntityNoSpawnFunction
1459 if (PRVM_serverfunction(SV_OnEntityNoSpawnFunction))
1460 {
1461 // self = ent
1464 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityNoSpawnFunction), "QC function SV_OnEntityNoSpawnFunction is missing");
1465 }
1466 else
1467 {
1468
1469 Con_DPrint("No spawn function for:\n");
1470 if (developer.integer > 0) // don't confuse non-developers with errors
1471 PRVM_ED_Print(prog, ent, NULL);
1472
1473 PRVM_ED_Free (prog, ent);
1474 return false; // not included in "inhibited" count
1475 }
1476 }
1477 else
1478 {
1479 // self = ent
1482 prog->ExecuteProgram(prog, func - prog->functions, "");
1483 }
1484 return true;
1485 }
1486 PRVM_ED_Free(prog, ent);
1487 return false;
1488}
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_DPrint(const char *msg)
A Con_Print that only shows up if the "developer" cvar is set.
Definition console.c:1531
string classname
GLsizeiptr const GLvoid * data
Definition glquake.h:639
cvar_t developer
Definition host.c:48
#define PRVM_alledictstring(ed, fieldname)
Definition progsvm.h:138
#define PRVM_allglobaledict(fieldname)
Definition progsvm.h:144
#define PRVM_allglobalfloat(fieldname)
Definition progsvm.h:141
mfunction_t * PRVM_ED_FindFunction(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:425
int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer)
const char * PRVM_GetString(prvm_prog_t *prog, int num)
prvm_eval_t * PRVM_ED_FindGlobalEval(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:414
void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed)
Definition prvm_edict.c:314
void PRVM_ED_Print(prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname)
Definition prvm_edict.c:657
mfunction_t * functions
Definition progsvm.h:541
prvm_int_t string
Definition progsvm.h:62

References classname, Con_DPrint(), Con_Print(), data, developer, prvm_prog_t::ExecuteProgram, prvm_edict_t::free, prvm_prog_t::functions, NULL, PRVM_alledictstring, PRVM_allglobaledict, PRVM_allglobalfloat, PRVM_AllocString(), PRVM_ED_FindFunction(), PRVM_ED_FindGlobalEval(), PRVM_ED_Free(), PRVM_ED_Print(), PRVM_EDICT_TO_PROG, PRVM_GetString(), PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, prvm_eval_t::string, sv, time, and va().

Referenced by PRVM_ED_LoadFromFile(), and SV_Ent_Create_f().

◆ PRVM_ED_CanAlloc()

qbool PRVM_ED_CanAlloc ( prvm_prog_t * prog,
prvm_edict_t * e )

Definition at line 243 of file prvm_edict.c.

244{
245 if(!e->free)
246 return false;
247 if(prvm_reuseedicts_always_allow == host.realtime)
248 return true;
249 if(host.realtime <= e->freetime + 0.1 && prvm_reuseedicts_neverinsameframe.integer)
250 return false; // never allow reuse in same frame (causes networking trouble)
251 if(e->freetime < prog->starttime + prvm_reuseedicts_startuptime.value)
252 return true;
253 if(host.realtime > e->freetime + 1)
254 return true;
255 return false; // entity slot still blocked because the entity was freed less than one second ago
256}
host_static_t host
Definition host.c:41
cvar_t prvm_reuseedicts_neverinsameframe
Definition prvm_edict.c:47
static double prvm_reuseedicts_always_allow
Definition prvm_edict.c:59
cvar_t prvm_reuseedicts_startuptime
Definition prvm_edict.c:46
double freetime
sv.time when the object was freed (to prevent early reuse which could mess up client interpolation or...
Definition progsvm.h:96
double starttime
system time when PRVM_Prog_Load was called
Definition progsvm.h:538

References prvm_edict_t::free, prvm_edict_t::freetime, host, prvm_reuseedicts_always_allow, prvm_reuseedicts_neverinsameframe, prvm_reuseedicts_startuptime, and prvm_prog_t::starttime.

Referenced by PRVM_ED_Alloc(), and SV_Physics().

◆ PRVM_ED_ClearEdict()

void PRVM_ED_ClearEdict ( prvm_prog_t * prog,
prvm_edict_t * e )

Definition at line 210 of file prvm_edict.c.

211{
212 memset(e->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
213 e->free = false;
214 e->freetime = host.realtime;
218
219 // AK: Let the init_edict function determine if something needs to be initialized
220 prog->init_edict(prog, e);
221}
float prvm_vec_t
Definition qtypes.h:55
const char * allocation_origin
place in the code where it was allocated (for the leak detector)
Definition progsvm.h:87
prvm_vec_t * fp
Definition progsvm.h:102
union prvm_edict_t::@123106147040330276163271355201011305114267000315 priv
union prvm_edict_t::@130370055076073023136252053272156300303324036224 fields
prvm_edict_private_t * required
Definition progsvm.h:101
int entityfields
number of vec_t fields in progs (some variables are 3)
Definition progsvm.h:548
void(* init_edict)(struct prvm_prog_s *prog, prvm_edict_t *edict)
[INIT] used by PRVM_ED_ClearEdict
Definition progsvm.h:737
#define Mem_Free(mem)
Definition zone.h:96

References prvm_edict_private_t::allocation_origin, prvm_prog_t::entityfields, prvm_edict_t::fields, prvm_edict_t::fp, prvm_edict_t::free, prvm_edict_t::freetime, host, prvm_prog_t::init_edict, Mem_Free, prvm_edict_t::priv, PRVM_AllocationOrigin(), and prvm_edict_t::required.

Referenced by PRVM_ED_Alloc(), SV_ConnectClient(), SV_DropClient(), SV_Ent_Remove_All_f(), SV_Ent_Remove_f(), and SV_SpawnServer().

◆ PRVM_ED_Count_f()

void PRVM_ED_Count_f ( cmd_state_t * cmd)
static

Definition at line 871 of file prvm_edict.c.

872{
873 prvm_prog_t *prog;
874
875 if(Cmd_Argc(cmd) != 2)
876 {
877 Con_Print("prvm_count <program name>\n");
878 return;
879 }
880
881 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
882 return;
883
884 prog->count_edicts(prog);
885}
void(* count_edicts)(struct prvm_prog_s *prog)
[INIT] used by PRVM_ED_Count_f
Definition progsvm.h:740

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), prvm_prog_t::count_edicts, and PRVM_FriendlyProgFromString().

Referenced by PRVM_Init().

◆ PRVM_ED_EdictGet_f()

void PRVM_ED_EdictGet_f ( cmd_state_t * cmd)
static

Definition at line 1157 of file prvm_edict.c.

1158{
1159 prvm_prog_t *prog;
1160 prvm_edict_t *ed;
1161 mdef_t *key;
1162 const char *s;
1163 prvm_eval_t *v;
1164 char valuebuf[MAX_INPUTLINE];
1165
1166 if(Cmd_Argc(cmd) != 4 && Cmd_Argc(cmd) != 5)
1167 {
1168 Con_Print("prvm_edictget <program name> <edict number> <field> [<cvar>]\n");
1169 return;
1170 }
1171
1172 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
1173 return;
1174
1175 ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(cmd, 2)));
1176
1177 if((key = PRVM_ED_FindField(prog, Cmd_Argv(cmd, 3))) == 0)
1178 {
1179 Con_Printf("Key %s not found !\n", Cmd_Argv(cmd, 3));
1180 goto fail;
1181 }
1182
1183 v = (prvm_eval_t *)(ed->fields.fp + key->ofs);
1184 s = PRVM_UglyValueString(prog, (etype_t)key->type, v, valuebuf, sizeof(valuebuf));
1185 if(Cmd_Argc(cmd) == 5)
1186 {
1187 cvar_t *cvar = Cvar_FindVar(cmd->cvars, Cmd_Argv(cmd, 4), cmd->cvars_flagsmask);
1188 if (cvar)
1189 if(Cvar_Readonly(cvar, "prvm_edictget"))
1190 goto fail;
1191
1192 Cvar_Get(cmd->cvars, Cmd_Argv(cmd, 4), s, cmd->cvars_flagsmask, NULL);
1193 }
1194 else
1195 Con_Printf("%s\n", s);
1196
1197fail:
1198 ;
1199}
cvar_t * Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, unsigned flags, const char *newdescription)
allocates a cvar by name and returns its address, or merely sets its value if it already exists.
Definition cvar.c:695
cvar_t * Cvar_FindVar(cvar_state_t *cvars, const char *var_name, unsigned neededflags)
Definition cvar.c:36
qbool Cvar_Readonly(cvar_t *var, const char *cmd_name)
Definition cvar.c:813
const GLdouble * v
Definition glquake.h:762
float cvar(string name)
etype_t
Definition pr_comp.h:29
char * PRVM_UglyValueString(prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
Definition prvm_edict.c:513
mdef_t * PRVM_ED_FindField(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:376
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
Definition cvar.h:66
uint32_t ofs
Definition pr_comp.h:365
uint32_t type
Definition pr_comp.h:363

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), cvar(), Cvar_FindVar(), Cvar_Get(), Cvar_Readonly(), prvm_edict_t::fields, prvm_edict_t::fp, MAX_INPUTLINE, NULL, mdef_t::ofs, PRVM_ED_FindField(), PRVM_EDICT_NUM, PRVM_FriendlyProgFromString(), PRVM_UglyValueString(), mdef_t::type, and v.

Referenced by PRVM_ED_EdictSet_f(), and PRVM_Init().

◆ PRVM_ED_EdictSet_f()

void PRVM_ED_EdictSet_f ( cmd_state_t * cmd)
static

Definition at line 1249 of file prvm_edict.c.

1250{
1251 prvm_prog_t *prog;
1252 prvm_edict_t *ed;
1253 mdef_t *key;
1254
1255 if (Cmd_Argc(cmd) == 4) {
1256 // Baker: Turn into prvm_edictget when no value(s) provided
1258 return;
1259 }
1260
1261 if (Cmd_Argc(cmd) != 5)
1262 {
1263 Con_Print("prvm_edictset <program name> <edict number> <field> <value>\n");
1264 return;
1265 }
1266
1267 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
1268 return;
1269
1270 ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(cmd, 2)));
1271
1272 if((key = PRVM_ED_FindField(prog, Cmd_Argv(cmd, 3))) == 0)
1273 Con_Printf("Key %s not found!\n", Cmd_Argv(cmd, 3));
1274 else
1275 PRVM_ED_ParseEpair(prog, ed, key, Cmd_Argv(cmd, 4), true);
1276}
qbool PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, mdef_t *key, const char *s, qbool parsebackslash)
Definition prvm_edict.c:991
static void PRVM_ED_EdictGet_f(cmd_state_t *cmd)

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), PRVM_ED_EdictGet_f(), PRVM_ED_FindField(), PRVM_ED_ParseEpair(), PRVM_EDICT_NUM, and PRVM_FriendlyProgFromString().

Referenced by PRVM_Init().

◆ PRVM_ED_FieldAtOfs()

mdef_t * PRVM_ED_FieldAtOfs ( prvm_prog_t * prog,
unsigned int ofs )

Definition at line 357 of file prvm_edict.c.

358{
359 mdef_t *def;
360 int i;
361
362 for (i = 0;i < prog->numfielddefs;i++)
363 {
364 def = &prog->fielddefs[i];
365 if (def->ofs == ofs)
366 return def;
367 }
368 return NULL;
369}
prvm_uint_t ofs
int numfielddefs
Definition progsvm.h:565
mdef_t * fielddefs
Definition progsvm.h:545

References prvm_prog_t::fielddefs, NULL, prvm_prog_t::numfielddefs, mdef_t::ofs, and ofs.

Referenced by PRVM_UglyValueString(), PRVM_ValueString(), and while().

◆ PRVM_ED_FindField()

mdef_t * PRVM_ED_FindField ( prvm_prog_t * prog,
const char * name )

Definition at line 376 of file prvm_edict.c.

377{
378 mdef_t *def;
379 int i;
380
381 for (i = 0;i < prog->numfielddefs;i++)
382 {
383 def = &prog->fielddefs[i];
384 if (!strcmp(PRVM_GetString(prog, def->s_name), name))
385 return def;
386 }
387 return NULL;
388}
const GLchar * name
Definition glquake.h:601
int32_t s_name
Definition pr_comp.h:366

References prvm_prog_t::fielddefs, name, NULL, prvm_prog_t::numfielddefs, PRVM_GetString(), and mdef_t::s_name.

Referenced by PRVM_ED_EdictGet_f(), PRVM_ED_EdictSet_f(), PRVM_ED_FindFieldOffset(), PRVM_ED_ParseEdict(), PRVM_ED_ParseEpair(), PRVM_UpdateBreakpoints(), and SV_Ent_Create_f().

◆ PRVM_ED_FindFieldOffset()

int PRVM_ED_FindFieldOffset ( prvm_prog_t * prog,
const char * field )

Definition at line 134 of file prvm_edict.c.

135{
136 mdef_t *d;
137 d = PRVM_ED_FindField(prog, field);
138 if (!d)
139 return -1;
140 return d->ofs;
141}

References mdef_t::ofs, and PRVM_ED_FindField().

◆ PRVM_ED_FindFunction()

mfunction_t * PRVM_ED_FindFunction ( prvm_prog_t * prog,
const char * name )

Definition at line 425 of file prvm_edict.c.

426{
427 mfunction_t *func;
428 int i;
429
430 for (i = 0;i < prog->numfunctions;i++)
431 {
432 func = &prog->functions[i];
433 if (!strcmp(PRVM_GetString(prog, func->s_name), name))
434 return func;
435 }
436 return NULL;
437}
int32_t s_name
Definition pr_comp.h:409
int numfunctions
Definition progsvm.h:566

References prvm_prog_t::functions, name, NULL, prvm_prog_t::numfunctions, PRVM_GetString(), and mfunction_t::s_name.

Referenced by CL_CheckRequiredFuncs(), MP_CheckRequiredFuncs(), PRVM_ED_CallSpawnFunction(), PRVM_ED_FindFunctionOffset(), PRVM_ED_ParseEpair(), PRVM_PrintFunctionStatements(), PRVM_UpdateBreakpoints(), VM_callfunction(), and VM_isfunction().

◆ PRVM_ED_FindFunctionOffset()

func_t PRVM_ED_FindFunctionOffset ( prvm_prog_t * prog,
const char * function )

Definition at line 152 of file prvm_edict.c.

153{
154 mfunction_t *f;
155 f = PRVM_ED_FindFunction(prog, function);
156 if (!f)
157 return 0;
158 return (func_t)(f - prog->functions);
159}
unsigned int func_t
Definition pr_comp.h:26
float f

References f, prvm_prog_t::functions, and PRVM_ED_FindFunction().

◆ PRVM_ED_FindGlobal()

mdef_t * PRVM_ED_FindGlobal ( prvm_prog_t * prog,
const char * name )

Definition at line 395 of file prvm_edict.c.

396{
397 mdef_t *def;
398 int i;
399
400 for (i = 0;i < prog->numglobaldefs;i++)
401 {
402 def = &prog->globaldefs[i];
403 if (!strcmp(PRVM_GetString(prog, def->s_name), name))
404 return def;
405 }
406 return NULL;
407}
mdef_t * globaldefs
Definition progsvm.h:546
int numglobaldefs
Definition progsvm.h:564

References prvm_prog_t::globaldefs, name, NULL, prvm_prog_t::numglobaldefs, PRVM_GetString(), and mdef_t::s_name.

Referenced by PRVM_ED_FindGlobalEval(), PRVM_ED_FindGlobalOffset(), PRVM_ED_GlobalGet_f(), PRVM_ED_ParseGlobals(), PRVM_Global_f(), PRVM_GlobalSet_f(), and PRVM_UpdateBreakpoints().

◆ PRVM_ED_FindGlobalEval()

prvm_eval_t * PRVM_ED_FindGlobalEval ( prvm_prog_t * prog,
const char * name )

Definition at line 414 of file prvm_edict.c.

415{
416 mdef_t *def = PRVM_ED_FindGlobal(prog, name);
417 return def ? (prvm_eval_t *) &prog->globals.fp[def->ofs] : NULL;
418}
mdef_t * PRVM_ED_FindGlobal(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:395
prvm_vec_t * fp
Definition progsvm.h:580
union prvm_prog_t::@154363101014374065374200170016167302241050246021 globals

References prvm_prog_t::fp, prvm_prog_t::globals, name, NULL, mdef_t::ofs, and PRVM_ED_FindGlobal().

Referenced by PRVM_ED_CallSpawnFunction().

◆ PRVM_ED_FindGlobalOffset()

int PRVM_ED_FindGlobalOffset ( prvm_prog_t * prog,
const char * global )

Definition at line 143 of file prvm_edict.c.

144{
145 mdef_t *d;
146 d = PRVM_ED_FindGlobal(prog, global);
147 if (!d)
148 return -1;
149 return d->ofs;
150}

References mdef_t::ofs, and PRVM_ED_FindGlobal().

◆ PRVM_ED_Free()

void PRVM_ED_Free ( prvm_prog_t * prog,
prvm_edict_t * ed )

Definition at line 314 of file prvm_edict.c.

315{
316 // dont delete the null entity (world) or reserved edicts
317 if (ed - prog->edicts <= prog->reserved_edicts)
318 return;
319
320 prog->free_edict(prog, ed);
321
322 ed->free = true;
323 ed->freetime = host.realtime;
325 {
328 }
329}
void(* free_edict)(struct prvm_prog_s *prog, prvm_edict_t *ed)
[INIT] used by PRVM_ED_Free
Definition progsvm.h:738
prvm_edict_t * edicts
Definition progsvm.h:680

References prvm_edict_private_t::allocation_origin, prvm_prog_t::edicts, prvm_edict_t::free, prvm_prog_t::free_edict, prvm_edict_t::freetime, host, Mem_Free, NULL, prvm_edict_t::priv, prvm_edict_t::required, and prvm_prog_t::reserved_edicts.

Referenced by PRVM_ED_CallSpawnFunction(), PRVM_ED_LoadFromFile(), SV_Ent_Create_f(), SV_Ent_Remove_All_f(), SV_Ent_Remove_f(), VM_CL_makestatic(), VM_objerror(), VM_remove(), and VM_SV_makestatic().

◆ PRVM_ED_GlobalAtOfs()

mdef_t * PRVM_ED_GlobalAtOfs ( prvm_prog_t * prog,
unsigned int ofs )
static

Definition at line 338 of file prvm_edict.c.

339{
340 mdef_t *def;
341 int i;
342
343 for (i = 0;i < prog->numglobaldefs;i++)
344 {
345 def = &prog->globaldefs[i];
346 if (def->ofs == ofs)
347 return def;
348 }
349 return NULL;
350}

References prvm_prog_t::globaldefs, NULL, prvm_prog_t::numglobaldefs, mdef_t::ofs, and ofs.

Referenced by PRVM_GlobalString(), and PRVM_GlobalStringNoContents().

◆ PRVM_ED_GlobalGet_f()

void PRVM_ED_GlobalGet_f ( cmd_state_t * cmd)
static

Definition at line 1201 of file prvm_edict.c.

1202{
1203 prvm_prog_t *prog;
1204 mdef_t *key;
1205 const char *s;
1206 prvm_eval_t *v;
1207 char valuebuf[MAX_INPUTLINE];
1208
1209 if(Cmd_Argc(cmd) != 3 && Cmd_Argc(cmd) != 4)
1210 {
1211 Con_Print("prvm_globalget <program name> <global> [<cvar>]\n");
1212 return;
1213 }
1214
1215 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
1216 return;
1217
1218 key = PRVM_ED_FindGlobal(prog, Cmd_Argv(cmd, 2));
1219 if(!key)
1220 {
1221 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(cmd, 2), Cmd_Argv(cmd, 1) );
1222 goto fail;
1223 }
1224
1225 v = (prvm_eval_t *) &prog->globals.fp[key->ofs];
1226 s = PRVM_UglyValueString(prog, (etype_t)key->type, v, valuebuf, sizeof(valuebuf));
1227 if(Cmd_Argc(cmd) == 4)
1228 {
1229 cvar_t *cvar = Cvar_FindVar(cmd->cvars, Cmd_Argv(cmd, 3), cmd->cvars_flagsmask);
1230 if (cvar)
1231 if(Cvar_Readonly(cvar, "prvm_globalget"))
1232 goto fail;
1233 Cvar_Get(cmd->cvars, Cmd_Argv(cmd, 3), s, cmd->cvars_flagsmask, NULL);
1234 }
1235 else
1236 Con_Printf("%s\n", s);
1237
1238fail:
1239 ;
1240}

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), cvar(), Cvar_FindVar(), Cvar_Get(), Cvar_Readonly(), prvm_prog_t::fp, prvm_prog_t::globals, MAX_INPUTLINE, NULL, mdef_t::ofs, PRVM_ED_FindGlobal(), PRVM_FriendlyProgFromString(), PRVM_UglyValueString(), mdef_t::type, and v.

Referenced by PRVM_Init().

◆ PRVM_ED_LoadFromFile()

void PRVM_ED_LoadFromFile ( prvm_prog_t * prog,
const char * data )

Definition at line 1517 of file prvm_edict.c.

1518{
1519 prvm_edict_t *ent;
1520 const char *start;
1521 int parsed, inhibited, spawned, died;
1522
1523 parsed = 0;
1524 inhibited = 0;
1525 spawned = 0;
1526 died = 0;
1527
1529
1530 // parse ents
1531 while (1)
1532 {
1533 start = data;
1534
1535 // parse the opening brace
1536 if (!COM_ParseToken_Simple(&data, false, false, true))
1537 break;
1538 if (com_token[0] != '{')
1539 prog->error_cmd("PRVM_ED_LoadFromFile: %s: found %s when expecting {", prog->name, com_token);
1540
1541 // CHANGED: this is not conform to PR_LoadFromFile
1542 if(prog->loadintoworld)
1543 {
1544 prog->loadintoworld = false;
1545 ent = PRVM_EDICT_NUM(0);
1546 }
1547 else
1548 ent = PRVM_ED_Alloc(prog);
1549
1550 // clear it
1551 if (ent != prog->edicts) // hack
1552 memset (ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
1553
1554 data = PRVM_ED_ParseEdict (prog, data, ent, false);
1555 parsed++;
1556
1557 // remove the entity ?
1558 if(!prog->load_edict(prog, ent))
1559 {
1560 PRVM_ED_Free(prog, ent);
1561 inhibited++;
1562 continue;
1563 }
1564
1566
1567 if(ent->free)
1568 {
1569 inhibited++;
1570 continue;
1571 }
1572
1573 SV_LinkEdict(ent);
1574
1575 if(!PRVM_ED_CallSpawnFunction(prog, ent, data, start))
1576 continue;
1577
1579
1580 spawned++;
1581 if (ent->free)
1582 died++;
1583 }
1584
1585 Con_DPrintf("%s: %i new entities parsed, %i new inhibited, %i (%i new) spawned (whereas %i removed self, %i stayed)\n", prog->name, parsed, inhibited, prog->num_edicts, spawned, died, spawned - died);
1586
1588}
char com_token[MAX_INPUTLINE]
Definition common.c:39
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
Definition common.c:463
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void PRVM_ED_CallPostspawnFunction(prvm_prog_t *prog, prvm_edict_t *ent)
const char * PRVM_ED_ParseEdict(prvm_prog_t *prog, const char *data, prvm_edict_t *ent, qbool saveload)
qbool PRVM_ED_CallSpawnFunction(prvm_prog_t *prog, prvm_edict_t *ent, const char *data, const char *start)
void PRVM_ED_CallPrespawnFunction(prvm_prog_t *prog, prvm_edict_t *ent)
prvm_edict_t * PRVM_ED_Alloc(prvm_prog_t *prog)
Definition prvm_edict.c:269
void SV_LinkEdict(prvm_edict_t *ent)
Definition sv_phys.c:804
qbool loadintoworld
Definition progsvm.h:707
qbool(* load_edict)(struct prvm_prog_s *prog, prvm_edict_t *ent)
[INIT] used by PRVM_ED_LoadFromFile
Definition progsvm.h:742

References COM_ParseToken_Simple(), com_token, Con_DPrintf(), data, prvm_prog_t::edicts, prvm_prog_t::entityfields, prvm_prog_t::error_cmd, prvm_edict_t::fields, prvm_edict_t::fp, prvm_edict_t::free, host, prvm_prog_t::load_edict, prvm_prog_t::loadintoworld, prvm_prog_t::name, prvm_prog_t::num_edicts, PRVM_ED_Alloc(), PRVM_ED_CallPostspawnFunction(), PRVM_ED_CallPrespawnFunction(), PRVM_ED_CallSpawnFunction(), PRVM_ED_Free(), PRVM_ED_ParseEdict(), PRVM_EDICT_NUM, prvm_reuseedicts_always_allow, and SV_LinkEdict().

Referenced by SV_SpawnServer(), VM_loadfromdata(), and VM_loadfromfile().

◆ PRVM_ED_ParseEdict()

const char * PRVM_ED_ParseEdict ( prvm_prog_t * prog,
const char * data,
prvm_edict_t * ent,
qbool saveload )

Definition at line 1287 of file prvm_edict.c.

1288{
1289 mdef_t *key;
1290 qbool anglehack;
1291 qbool init = false;
1292 qbool parsebackslash = true;
1293 char keyname[256];
1294 size_t n;
1295
1296// go through all the dictionary pairs
1297 while (1)
1298 {
1299 // parse key
1300 if (!COM_ParseToken_Simple(&data, false, false, true))
1301 prog->error_cmd("PRVM_ED_ParseEdict: EOF without closing brace");
1302 if (developer_entityparsing.integer)
1303 Con_Printf("Key: \"%s\"", com_token);
1304 if (com_token[0] == '}')
1305 break;
1306
1307 // anglehack is to allow QuakeEd to write single scalar angles
1308 // and allow them to be turned into vectors. (FIXME...)
1309 if (!strcmp(com_token, "angle"))
1310 {
1311 dp_strlcpy (com_token, "angles", sizeof(com_token));
1312 anglehack = true;
1313 }
1314 else
1315 anglehack = false;
1316
1317 // FIXME: change light to _light to get rid of this hack
1318 if (!strcmp(com_token, "light"))
1319 dp_strlcpy (com_token, "light_lev", sizeof(com_token)); // hack for single light def
1320
1321 n = dp_strlcpy (keyname, com_token, sizeof(keyname));
1322
1323 // another hack to fix keynames with trailing spaces
1324 while (n && keyname[n-1] == ' ')
1325 {
1326 keyname[n-1] = 0;
1327 n--;
1328 }
1329
1330 // Check if escape parsing is disabled for this key (see cvar description).
1331 // Escapes are always used in savegames and DP_QC_ENTITYSTRING for compatibility.
1332 if (!saveload)
1333 {
1334 const char *cvarpos = sv_entfields_noescapes.string;
1335
1336 while (COM_ParseToken_Console(&cvarpos))
1337 {
1338 if (strcmp(com_token, keyname) == 0)
1339 {
1340 parsebackslash = false;
1341 break;
1342 }
1343 }
1344 }
1345
1346 // parse value
1347 // If loading a save, unescape characters (they're escaped when saving).
1348 // Otherwise, load them as they are (BSP compilers don't support escaping).
1349 if (!COM_ParseToken_Simple(&data, false, parsebackslash, true))
1350 prog->error_cmd("PRVM_ED_ParseEdict: EOF without closing brace");
1351 if (developer_entityparsing.integer)
1352 Con_Printf(" \"%s\"\n", com_token);
1353
1354 if (com_token[0] == '}')
1355 prog->error_cmd("PRVM_ED_ParseEdict: closing brace without data");
1356
1357 init = true;
1358
1359 // ignore attempts to set key "" (this problem occurs in nehahra neh1m8.bsp)
1360 if (!keyname[0])
1361 continue;
1362
1363// keynames with a leading underscore are used for utility comments,
1364// and are immediately discarded by quake
1365 if (keyname[0] == '_')
1366 continue;
1367
1368 key = PRVM_ED_FindField (prog, keyname);
1369 if (!key)
1370 {
1371 Con_DPrintf("%s: '%s' is not a field\n", prog->name, keyname);
1372 continue;
1373 }
1374
1375 if (anglehack)
1376 {
1377 char temp[32];
1378 dp_strlcpy (temp, com_token, sizeof(temp));
1379 dpsnprintf (com_token, sizeof(com_token), "0 %s 0", temp);
1380 }
1381
1382 if (!PRVM_ED_ParseEpair(prog, ent, key, com_token, false))
1383 prog->error_cmd("PRVM_ED_ParseEdict: parse error");
1384 }
1385
1386 if (!init)
1387 {
1388 ent->free = true;
1389 ent->freetime = host.realtime;
1390 }
1391
1392 return data;
1393}
qbool COM_ParseToken_Console(const char **datapointer)
Definition common.c:819
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
#define n(x, y)
cvar_t developer_entityparsing
Definition host.c:53
cvar_t sv_entfields_noescapes
Definition prvm_edict.c:56
bool qbool
Definition qtypes.h:9

References COM_ParseToken_Console(), COM_ParseToken_Simple(), com_token, Con_DPrintf(), Con_Printf(), data, developer_entityparsing, dp_strlcpy, dpsnprintf(), prvm_prog_t::error_cmd, prvm_edict_t::free, prvm_edict_t::freetime, host, n, prvm_prog_t::name, PRVM_ED_FindField(), PRVM_ED_ParseEpair(), and sv_entfields_noescapes.

Referenced by PRVM_ED_LoadFromFile(), SV_Loadgame_f(), and VM_parseentitydata().

◆ PRVM_ED_ParseEpair()

qbool PRVM_ED_ParseEpair ( prvm_prog_t * prog,
prvm_edict_t * ent,
mdef_t * key,
const char * s,
qbool parsebackslash )

Definition at line 991 of file prvm_edict.c.

992{
993 int i, l;
994 char *new_p;
995 mdef_t *def;
996 prvm_eval_t *val;
997 mfunction_t *func;
998
999 if (ent)
1000 val = (prvm_eval_t *)(ent->fields.fp + key->ofs);
1001 else
1002 val = (prvm_eval_t *)(prog->globals.fp + key->ofs);
1003 switch (key->type & ~DEF_SAVEGLOBAL)
1004 {
1005 case ev_string:
1006 l = (int)strlen(s) + 1;
1007 val->string = PRVM_AllocString(prog, l, &new_p);
1008 for (i = 0;i < l;i++)
1009 {
1010 if (s[i] == '\\' && s[i+1] && parsebackslash)
1011 {
1012 i++;
1013 if (s[i] == 'n')
1014 *new_p++ = '\n';
1015 else if (s[i] == 'r')
1016 *new_p++ = '\r';
1017 else
1018 *new_p++ = s[i];
1019 }
1020 else
1021 *new_p++ = s[i];
1022 }
1023 break;
1024
1025 case ev_float:
1026 while (*s && ISWHITESPACE(*s))
1027 s++;
1028 val->_float = atof(s);
1029 break;
1030
1031 case ev_vector:
1032 for (i = 0;i < 3;i++)
1033 {
1034 while (*s && ISWHITESPACE(*s))
1035 s++;
1036 if (!*s)
1037 break;
1038 val->vector[i] = atof(s);
1039 while (!ISWHITESPACE(*s))
1040 s++;
1041 if (!*s)
1042 break;
1043 }
1044 break;
1045
1046 case ev_entity:
1047 while (*s && ISWHITESPACE(*s))
1048 s++;
1049 i = atoi(s);
1050 if (i >= prog->limit_edicts)
1051 Con_Printf("PRVM_ED_ParseEpair: ev_entity reference too large (edict %u >= MAX_EDICTS %u) on %s\n", (unsigned int)i, prog->limit_edicts, prog->name);
1052 while (i >= prog->max_edicts)
1054 // if IncreaseEdicts was called the base pointer needs to be updated
1055 if (ent)
1056 val = (prvm_eval_t *)(ent->fields.fp + key->ofs);
1057 val->edict = PRVM_EDICT_TO_PROG(PRVM_EDICT_NUM((int)i));
1058 break;
1059
1060 case ev_field:
1061 if (*s != '.')
1062 {
1063 Con_DPrintf("PRVM_ED_ParseEpair: Bogus field name %s in %s\n", s, prog->name);
1064 return false;
1065 }
1066 def = PRVM_ED_FindField(prog, s + 1);
1067 if (!def)
1068 {
1069 Con_DPrintf("PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, prog->name);
1070 return false;
1071 }
1072 val->_int = def->ofs;
1073 break;
1074
1075 case ev_function:
1076 func = PRVM_ED_FindFunction(prog, s);
1077 if (!func)
1078 {
1079 Con_Printf("PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, prog->name);
1080 return false;
1081 }
1082 val->function = func - prog->functions;
1083 break;
1084
1085 default:
1086 Con_Printf("PRVM_ED_ParseEpair: Unknown key->type %i for key \"%s\" on %s\n", key->type, PRVM_GetString(prog, key->s_name), prog->name);
1087 return false;
1088 }
1089 return true;
1090}
static int(ZEXPORT *qz_inflate)(z_stream *strm
float strlen(string s)
#define DEF_SAVEGLOBAL
Definition pr_comp.h:370
@ ev_function
Definition pr_comp.h:29
@ ev_vector
Definition pr_comp.h:29
@ ev_entity
Definition pr_comp.h:29
@ ev_field
Definition pr_comp.h:29
@ ev_string
Definition pr_comp.h:29
@ ev_float
Definition pr_comp.h:29
const char * PRVM_GetString(prvm_prog_t *prog, int num)
#define ISWHITESPACE(ch)
Definition qdefs.h:184
prvm_vec_t _float
Definition progsvm.h:63
prvm_vec_t vector[3]
Definition progsvm.h:64
prvm_int_t _int
Definition progsvm.h:67
prvm_int_t function
Definition progsvm.h:65
prvm_int_t edict
Definition progsvm.h:69

References prvm_eval_t::_float, prvm_eval_t::_int, Con_DPrintf(), Con_Printf(), DEF_SAVEGLOBAL, prvm_eval_t::edict, ev_entity, ev_field, ev_float, ev_function, ev_string, ev_vector, prvm_edict_t::fields, prvm_edict_t::fp, prvm_prog_t::fp, prvm_eval_t::function, prvm_prog_t::functions, prvm_prog_t::globals, int(), ISWHITESPACE, prvm_prog_t::limit_edicts, prvm_prog_t::max_edicts, prvm_prog_t::name, mdef_t::ofs, PRVM_AllocString(), PRVM_ED_FindField(), PRVM_ED_FindFunction(), PRVM_EDICT_NUM, PRVM_EDICT_TO_PROG, PRVM_GetString(), PRVM_MEM_IncreaseEdicts(), mdef_t::s_name, prvm_eval_t::string, strlen(), mdef_t::type, and prvm_eval_t::vector.

Referenced by PRVM_ED_EdictSet_f(), PRVM_ED_ParseEdict(), PRVM_ED_ParseGlobals(), PRVM_GlobalSet_f(), SV_Ent_Create_f(), and VM_putentityfieldstring().

◆ PRVM_ED_ParseGlobals()

void PRVM_ED_ParseGlobals ( prvm_prog_t * prog,
const char * data )

Definition at line 940 of file prvm_edict.c.

941{
942 char keyname[MAX_INPUTLINE];
943 mdef_t *key;
944
945 while (1)
946 {
947 // parse key
948 if (!COM_ParseToken_Simple(&data, false, false, true))
949 prog->error_cmd("PRVM_ED_ParseGlobals: EOF without closing brace");
950 if (com_token[0] == '}')
951 break;
952
953 if (developer_entityparsing.integer)
954 Con_Printf("Key: \"%s\"", com_token);
955
956 dp_strlcpy (keyname, com_token, sizeof(keyname));
957
958 // parse value
959 if (!COM_ParseToken_Simple(&data, false, true, true))
960 prog->error_cmd("PRVM_ED_ParseGlobals: EOF without closing brace");
961
962 if (developer_entityparsing.integer)
963 Con_Printf(" \"%s\"\n", com_token);
964
965 if (com_token[0] == '}')
966 prog->error_cmd("PRVM_ED_ParseGlobals: closing brace without data");
967
968 key = PRVM_ED_FindGlobal (prog, keyname);
969 if (!key)
970 {
971 Con_DPrintf("'%s' is not a global on %s\n", keyname, prog->name);
972 continue;
973 }
974
975 if (!PRVM_ED_ParseEpair(prog, NULL, key, com_token, true))
976 prog->error_cmd("PRVM_ED_ParseGlobals: parse error");
977 }
978}

References COM_ParseToken_Simple(), com_token, Con_DPrintf(), Con_Printf(), data, developer_entityparsing, dp_strlcpy, prvm_prog_t::error_cmd, MAX_INPUTLINE, prvm_prog_t::name, NULL, PRVM_ED_FindGlobal(), and PRVM_ED_ParseEpair().

Referenced by SV_Loadgame_f().

◆ PRVM_ED_Print()

void PRVM_ED_Print ( prvm_prog_t * prog,
prvm_edict_t * ed,
const char * wildcard_fieldname )

Definition at line 657 of file prvm_edict.c.

658{
659 size_t l;
660 mdef_t *d;
661 prvm_eval_t *val;
662 int i, j;
663 const char *name;
664 int type;
665 char tempstring[MAX_INPUTLINE], tempstring2[260]; // temporary string buffers
666 char valuebuf[MAX_INPUTLINE];
667
668 if (ed->free)
669 {
670 Con_Printf("%s: FREE\n",prog->name);
671 return;
672 }
673
674 tempstring[0] = 0;
675 dpsnprintf(tempstring, sizeof(tempstring), "\n%s EDICT %i:\n", prog->name, PRVM_NUM_FOR_EDICT(ed));
676 for (i = 1;i < prog->numfielddefs;i++)
677 {
678 d = &prog->fielddefs[i];
679 name = PRVM_GetString(prog, d->s_name);
680 if(strlen(name) > 1 && name[strlen(name)-2] == '_' && (name[strlen(name)-1] == 'x' || name[strlen(name)-1] == 'y' || name[strlen(name)-1] == 'z'))
681 continue; // skip _x, _y, _z vars
682
683 // Check Field Name Wildcard
684 if(wildcard_fieldname)
685 if( !matchpattern(name, wildcard_fieldname, 1) )
686 // Didn't match; skip
687 continue;
688
689 val = (prvm_eval_t *)(ed->fields.fp + d->ofs);
690
691 // if the value is still all 0, skip the field
693
694 for (j=0 ; j<prvm_type_size[type] ; j++)
695 if (val->ivector[j])
696 break;
697 if (j == prvm_type_size[type])
698 continue;
699
700 if (strlen(name) > sizeof(tempstring2)-4)
701 {
702 memcpy (tempstring2, name, sizeof(tempstring2)-4);
703 tempstring2[sizeof(tempstring2)-4] = tempstring2[sizeof(tempstring2)-3] = tempstring2[sizeof(tempstring2)-2] = '.';
704 tempstring2[sizeof(tempstring2)-1] = 0;
705 name = tempstring2;
706 }
707 dp_strlcat(tempstring, name, sizeof(tempstring));
708 for (l = strlen(name);l < 14;l++)
709 dp_strlcat(tempstring, " ", sizeof(tempstring));
710 dp_strlcat(tempstring, " ", sizeof(tempstring));
711
712 name = PRVM_ValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf));
713 if (strlen(name) > sizeof(tempstring2)-4)
714 {
715 memcpy (tempstring2, name, sizeof(tempstring2)-4);
716 tempstring2[sizeof(tempstring2)-4] = tempstring2[sizeof(tempstring2)-3] = tempstring2[sizeof(tempstring2)-2] = '.';
717 tempstring2[sizeof(tempstring2)-1] = 0;
718 name = tempstring2;
719 }
720 dp_strlcat(tempstring, name, sizeof(tempstring));
721 dp_strlcat(tempstring, "\n", sizeof(tempstring));
722 if (strlen(tempstring) >= sizeof(tempstring)/2)
723 {
724 Con_Print(tempstring);
725 tempstring[0] = 0;
726 }
727 }
728 if (tempstring[0])
729 Con_Print(tempstring);
730}
#define dp_strlcat(dst, src, dsize)
Definition common.h:304
int matchpattern(const char *in, const char *pattern, int caseinsensitive)
Definition filematch.c:16
GLenum type
Definition glquake.h:656
int prvm_type_size[8]
for consistency : I think a goal of this sub-project is to make the new vm mostly independent from th...
Definition prvm_edict.c:29
#define PRVM_NUM_FOR_EDICT(e)
Definition progsvm.h:870
static char * PRVM_ValueString(prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
Definition prvm_edict.c:447
prvm_int_t ivector[3]
Definition progsvm.h:66

References Con_Print(), Con_Printf(), DEF_SAVEGLOBAL, dp_strlcat, dpsnprintf(), prvm_prog_t::fielddefs, prvm_edict_t::fields, prvm_edict_t::fp, prvm_edict_t::free, prvm_eval_t::ivector, matchpattern(), MAX_INPUTLINE, name, prvm_prog_t::name, prvm_prog_t::numfielddefs, mdef_t::ofs, PRVM_GetString(), PRVM_NUM_FOR_EDICT, prvm_type_size, PRVM_ValueString(), mdef_t::s_name, strlen(), mdef_t::type, and type.

Referenced by CLVM_ExecuteProgram(), PRVM_ED_CallSpawnFunction(), PRVM_ED_PrintNum(), PRVM_LeakTest(), SVVM_ExecuteProgram(), VM_error(), and VM_objerror().

◆ PRVM_ED_PrintEdict_f()

void PRVM_ED_PrintEdict_f ( cmd_state_t * cmd)
static

Definition at line 832 of file prvm_edict.c.

833{
834 prvm_prog_t *prog;
835 int i;
836 const char *wildcard_fieldname;
837
838 if(Cmd_Argc(cmd) < 3 || Cmd_Argc(cmd) > 4)
839 {
840 Con_Print("prvm_edict <program name> <edict number> <optional field name wildcard>\n");
841 return;
842 }
843
844 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
845 return;
846
847 i = atoi (Cmd_Argv(cmd, 2));
848 if (i >= prog->num_edicts)
849 {
850 Con_Print("Bad edict number\n");
851 return;
852 }
853 if( Cmd_Argc(cmd) == 4)
854 // Optional Wildcard Provided
855 wildcard_fieldname = Cmd_Argv(cmd, 3);
856 else
857 // Use All
858 wildcard_fieldname = NULL;
859 PRVM_ED_PrintNum (prog, i, wildcard_fieldname);
860}
void PRVM_ED_PrintNum(prvm_prog_t *prog, int ent, const char *wildcard_fieldname)
Definition prvm_edict.c:788

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), NULL, prvm_prog_t::num_edicts, PRVM_ED_PrintNum(), and PRVM_FriendlyProgFromString().

Referenced by PRVM_Init().

◆ PRVM_ED_PrintEdicts_f()

void PRVM_ED_PrintEdicts_f ( cmd_state_t * cmd)

Definition at line 800 of file prvm_edict.c.

801{
802 prvm_prog_t *prog;
803 int i;
804 const char *wildcard_fieldname;
805
806 if(Cmd_Argc(cmd) < 2 || Cmd_Argc(cmd) > 3)
807 {
808 Con_Print("prvm_edicts <program name> <optional field name wildcard>\n");
809 return;
810 }
811
812 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
813 return;
814
815 if( Cmd_Argc(cmd) == 3)
816 wildcard_fieldname = Cmd_Argv(cmd, 2);
817 else
818 wildcard_fieldname = NULL;
819
820 Con_Printf("%s: %i entities\n", prog->name, prog->num_edicts);
821 for (i=0 ; i<prog->num_edicts ; i++)
822 PRVM_ED_PrintNum (prog, i, wildcard_fieldname);
823}
void PRVM_ED_PrintNum(prvm_prog_t *prog, int ent, const char *wildcard_fieldname)
Definition prvm_edict.c:788

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), prvm_prog_t::name, NULL, prvm_prog_t::num_edicts, PRVM_ED_PrintNum(), and PRVM_FriendlyProgFromString().

◆ PRVM_ED_PrintNum()

void PRVM_ED_PrintNum ( prvm_prog_t * prog,
int ent,
const char * wildcard_fieldname )

Definition at line 788 of file prvm_edict.c.

789{
790 PRVM_ED_Print(prog, PRVM_EDICT_NUM(ent), wildcard_fieldname);
791}

References PRVM_ED_Print(), and PRVM_EDICT_NUM.

Referenced by PRVM_ED_PrintEdict_f(), PRVM_ED_PrintEdicts_f(), and VM_eprint().

◆ PRVM_ED_Write()

void PRVM_ED_Write ( prvm_prog_t * prog,
qfile_t * f,
prvm_edict_t * ed )

Definition at line 739 of file prvm_edict.c.

740{
741 mdef_t *d;
742 prvm_eval_t *val;
743 int i, j;
744 const char *name;
745 int type;
746 char vabuf[1024];
747 char valuebuf[MAX_INPUTLINE];
748
749 FS_Print(f, "{\n");
750
751 if (ed->free)
752 {
753 FS_Print(f, "}\n");
754 return;
755 }
756
757 for (i = 1;i < prog->numfielddefs;i++)
758 {
759 d = &prog->fielddefs[i];
760 name = PRVM_GetString(prog, d->s_name);
761
762 if(developer_entityparsing.integer)
763 Con_Printf("PRVM_ED_Write: at entity %d field %s\n", PRVM_NUM_FOR_EDICT(ed), name);
764
765 //if(strlen(name) > 1 && name[strlen(name)-2] == '_' && (name[strlen(name)-1] == 'x' || name[strlen(name)-1] == 'y' || name[strlen(name)-1] == 'z'))
766 if(strlen(name) > 1 && name[strlen(name)-2] == '_')
767 continue; // skip _x, _y, _z vars, and ALSO other _? vars as some mods expect them to be never saved (TODO: a gameplayfix for using the "more precise" condition above?)
768
769 val = (prvm_eval_t *)(ed->fields.fp + d->ofs);
770
771 // if the value is still all 0, skip the field
773 for (j=0 ; j<prvm_type_size[type] ; j++)
774 if (val->ivector[j])
775 break;
776 if (j == prvm_type_size[type])
777 continue;
778
779 FS_Printf(f,"\"%s\" ",name);
780 prog->statestring = va(vabuf, sizeof(vabuf), "PRVM_ED_Write, ent=%d, name=%s", i, name);
781 FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)d->type, val, valuebuf, sizeof(valuebuf)));
782 prog->statestring = NULL;
783 }
784
785 FS_Print(f, "}\n");
786}
int FS_Printf(qfile_t *file, const char *format,...)
Definition fs.c:3274
int FS_Print(qfile_t *file, const char *msg)
Definition fs.c:3262
const char * statestring
printed together with backtraces
Definition progsvm.h:717

References Con_Printf(), DEF_SAVEGLOBAL, developer_entityparsing, f, prvm_prog_t::fielddefs, prvm_edict_t::fields, prvm_edict_t::fp, prvm_edict_t::free, FS_Print(), FS_Printf(), prvm_eval_t::ivector, MAX_INPUTLINE, name, NULL, prvm_prog_t::numfielddefs, mdef_t::ofs, PRVM_GetString(), PRVM_NUM_FOR_EDICT, prvm_type_size, PRVM_UglyValueString(), mdef_t::s_name, prvm_prog_t::statestring, strlen(), mdef_t::type, type, and va().

◆ PRVM_ED_WriteGlobals()

void PRVM_ED_WriteGlobals ( prvm_prog_t * prog,
qfile_t * f )

Definition at line 901 of file prvm_edict.c.

902{
903 mdef_t *def;
904 int i;
905 const char *name;
906 int type;
907 char vabuf[1024];
908 char valuebuf[MAX_INPUTLINE];
909
910 FS_Print(f,"{\n");
911 for (i = 0;i < prog->numglobaldefs;i++)
912 {
913 def = &prog->globaldefs[i];
914 type = def->type;
915 if ( !(def->type & DEF_SAVEGLOBAL) )
916 continue;
918
919 if (type != ev_string && type != ev_float && type != ev_entity)
920 continue;
921
922 name = PRVM_GetString(prog, def->s_name);
923
924 if(developer_entityparsing.integer)
925 Con_Printf("PRVM_ED_WriteGlobals: at global %s\n", name);
926
927 prog->statestring = va(vabuf, sizeof(vabuf), "PRVM_ED_WriteGlobals, name=%s", name);
928 FS_Printf(f,"\"%s\" ", name);
929 FS_Printf(f,"\"%s\"\n", PRVM_UglyValueString(prog, (etype_t)type, (prvm_eval_t *)&prog->globals.fp[def->ofs], valuebuf, sizeof(valuebuf)));
930 prog->statestring = NULL;
931 }
932 FS_Print(f,"}\n");
933}

References Con_Printf(), DEF_SAVEGLOBAL, developer_entityparsing, ev_entity, ev_float, ev_string, f, prvm_prog_t::fp, FS_Print(), FS_Printf(), prvm_prog_t::globaldefs, prvm_prog_t::globals, MAX_INPUTLINE, name, NULL, prvm_prog_t::numglobaldefs, mdef_t::ofs, PRVM_GetString(), PRVM_UglyValueString(), mdef_t::s_name, prvm_prog_t::statestring, mdef_t::type, type, and va().

◆ PRVM_EDICT_NUM_ERROR()

unsigned int PRVM_EDICT_NUM_ERROR ( prvm_prog_t * prog,
unsigned int n,
const char * filename,
int fileline )

Definition at line 3310 of file prvm_edict.c.

3311{
3312 prog->error_cmd("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", prog->name, n, filename, fileline);
3313 return 0;
3314}

References prvm_prog_t::error_cmd, n, and prvm_prog_t::name.

◆ PRVM_EdictWatchpoint_f()

void PRVM_EdictWatchpoint_f ( cmd_state_t * cmd)
static

Definition at line 3198 of file prvm_edict.c.

3199{
3200 prvm_prog_t *prog;
3201
3202 if( Cmd_Argc(cmd) == 2 ) {
3203 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
3204 return;
3205 {
3206 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3207 debug->watch_field[0] = 0;
3208 }
3210 return;
3211 }
3212 if( Cmd_Argc(cmd) != 4 ) {
3213 Con_Printf( "prvm_edictwatchpoint <program name> <edict number> <field name>\n" );
3214 return;
3215 }
3216
3217 if (!(prog = PRVM_ProgFromString(Cmd_Argv(cmd, 1))))
3218 return;
3219
3220 {
3221 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3222 debug->watch_edict = atoi(Cmd_Argv(cmd, 2));
3223 dp_strlcpy(debug->watch_field, Cmd_Argv(cmd, 3), sizeof(debug->watch_field));
3224 }
3226}
char watch_field[256]

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), debug_data, dp_strlcpy, PRVM_FriendlyProgFromString(), prvm_prog_list, PRVM_ProgFromString(), PRVM_UpdateBreakpoints(), debug_data_t::watch_edict, and debug_data_t::watch_field.

Referenced by PRVM_Init().

◆ PRVM_Fields_f()

void PRVM_Fields_f ( cmd_state_t * cmd)
static

Definition at line 2808 of file prvm_edict.c.

2809{
2810 prvm_prog_t *prog;
2811 int i, j, ednum, used, usedamount;
2812 int *counts;
2813 char tempstring[MAX_INPUTLINE], tempstring2[260];
2814 const char *name;
2815 prvm_edict_t *ed;
2816 mdef_t *d;
2817 prvm_eval_t *val;
2818
2819 // TODO
2820 /*
2821 if (!sv.active)
2822 {
2823 Con_Print("no progs loaded\n");
2824 return;
2825 }
2826 */
2827
2828 if(Cmd_Argc(cmd) != 2)
2829 {
2830 Con_Print("prvm_fields <program name>\n");
2831 return;
2832 }
2833
2834 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
2835 return;
2836
2837 counts = (int *)Mem_Alloc(tempmempool, prog->numfielddefs * sizeof(int));
2838 for (ednum = 0;ednum < prog->max_edicts;ednum++)
2839 {
2840 ed = PRVM_EDICT_NUM(ednum);
2841 if (ed->free)
2842 continue;
2843 for (i = 1;i < prog->numfielddefs;i++)
2844 {
2845 d = &prog->fielddefs[i];
2846 name = PRVM_GetString(prog, d->s_name);
2847 if (name[strlen(name)-2] == '_')
2848 continue; // skip _x, _y, _z vars
2849 val = (prvm_eval_t *)(ed->fields.fp + d->ofs);
2850 // if the value is still all 0, skip the field
2851 for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
2852 {
2853 if (val->ivector[j])
2854 {
2855 counts[i]++;
2856 break;
2857 }
2858 }
2859 }
2860 }
2861 used = 0;
2862 usedamount = 0;
2863 tempstring[0] = 0;
2864 for (i = 0;i < prog->numfielddefs;i++)
2865 {
2866 d = &prog->fielddefs[i];
2867 name = PRVM_GetString(prog, d->s_name);
2868 if (name[strlen(name)-2] == '_')
2869 continue; // skip _x, _y, _z vars
2870 switch(d->type & ~DEF_SAVEGLOBAL)
2871 {
2872 case ev_string:
2873 dp_strlcat(tempstring, "string ", sizeof(tempstring));
2874 break;
2875 case ev_entity:
2876 dp_strlcat(tempstring, "entity ", sizeof(tempstring));
2877 break;
2878 case ev_function:
2879 dp_strlcat(tempstring, "function ", sizeof(tempstring));
2880 break;
2881 case ev_field:
2882 dp_strlcat(tempstring, "field ", sizeof(tempstring));
2883 break;
2884 case ev_void:
2885 dp_strlcat(tempstring, "void ", sizeof(tempstring));
2886 break;
2887 case ev_float:
2888 dp_strlcat(tempstring, "float ", sizeof(tempstring));
2889 break;
2890 case ev_vector:
2891 dp_strlcat(tempstring, "vector ", sizeof(tempstring));
2892 break;
2893 case ev_pointer:
2894 dp_strlcat(tempstring, "pointer ", sizeof(tempstring));
2895 break;
2896 default:
2897 dpsnprintf (tempstring2, sizeof(tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
2898 dp_strlcat(tempstring, tempstring2, sizeof(tempstring));
2899 break;
2900 }
2901 if (strlen(name) > sizeof(tempstring2)-4)
2902 {
2903 memcpy (tempstring2, name, sizeof(tempstring2)-4);
2904 tempstring2[sizeof(tempstring2)-4] = tempstring2[sizeof(tempstring2)-3] = tempstring2[sizeof(tempstring2)-2] = '.';
2905 tempstring2[sizeof(tempstring2)-1] = 0;
2906 name = tempstring2;
2907 }
2908 dp_strlcat(tempstring, name, sizeof(tempstring));
2909 for (j = (int)strlen(name);j < 25;j++)
2910 dp_strlcat(tempstring, " ", sizeof(tempstring));
2911 dpsnprintf(tempstring2, sizeof(tempstring2), "%5d", counts[i]);
2912 dp_strlcat(tempstring, tempstring2, sizeof(tempstring));
2913 dp_strlcat(tempstring, "\n", sizeof(tempstring));
2914 if (strlen(tempstring) >= sizeof(tempstring)/2)
2915 {
2916 Con_Print(tempstring);
2917 tempstring[0] = 0;
2918 }
2919 if (counts[i])
2920 {
2921 used++;
2922 usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
2923 }
2924 }
2925 Mem_Free(counts);
2926 Con_Printf("%s: %i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", prog->name, prog->entityfields, used, prog->entityfields * 4, usedamount * 4, prog->max_edicts, prog->entityfields * 4 * prog->max_edicts, usedamount * 4 * prog->max_edicts);
2927}
@ ev_void
Definition pr_comp.h:29
@ ev_pointer
Definition pr_comp.h:29
mempool_t * tempmempool
Definition zone.c:794
#define Mem_Alloc(pool, size)
Definition zone.h:92

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), DEF_SAVEGLOBAL, dp_strlcat, dpsnprintf(), prvm_prog_t::entityfields, ev_entity, ev_field, ev_float, ev_function, ev_pointer, ev_string, ev_vector, ev_void, prvm_prog_t::fielddefs, prvm_edict_t::fields, prvm_edict_t::fp, prvm_edict_t::free, prvm_eval_t::ivector, prvm_prog_t::max_edicts, MAX_INPUTLINE, Mem_Alloc, Mem_Free, name, prvm_prog_t::name, prvm_prog_t::numfielddefs, mdef_t::ofs, PRVM_EDICT_NUM, PRVM_FriendlyProgFromString(), PRVM_GetString(), prvm_type_size, mdef_t::s_name, strlen(), tempmempool, and mdef_t::type.

Referenced by PRVM_Init().

◆ PRVM_FindOffsets()

void PRVM_FindOffsets ( prvm_prog_t * prog)
static

Definition at line 1590 of file prvm_edict.c.

1591{
1592 // field and global searches use -1 for NULL
1593 memset(&prog->fieldoffsets, -1, sizeof(prog->fieldoffsets));
1594 memset(&prog->globaloffsets, -1, sizeof(prog->globaloffsets));
1595 // function searches use 0 for NULL
1596 memset(&prog->funcoffsets, 0, sizeof(prog->funcoffsets));
1597#define PRVM_DECLARE_serverglobalfloat(x)
1598#define PRVM_DECLARE_serverglobalvector(x)
1599#define PRVM_DECLARE_serverglobalstring(x)
1600#define PRVM_DECLARE_serverglobaledict(x)
1601#define PRVM_DECLARE_serverglobalfunction(x)
1602#define PRVM_DECLARE_clientglobalfloat(x)
1603#define PRVM_DECLARE_clientglobalvector(x)
1604#define PRVM_DECLARE_clientglobalstring(x)
1605#define PRVM_DECLARE_clientglobaledict(x)
1606#define PRVM_DECLARE_clientglobalfunction(x)
1607#define PRVM_DECLARE_menuglobalfloat(x)
1608#define PRVM_DECLARE_menuglobalvector(x)
1609#define PRVM_DECLARE_menuglobalstring(x)
1610#define PRVM_DECLARE_menuglobaledict(x)
1611#define PRVM_DECLARE_menuglobalfunction(x)
1612#define PRVM_DECLARE_serverfieldfloat(x)
1613#define PRVM_DECLARE_serverfieldvector(x)
1614#define PRVM_DECLARE_serverfieldstring(x)
1615#define PRVM_DECLARE_serverfieldedict(x)
1616#define PRVM_DECLARE_serverfieldfunction(x)
1617#define PRVM_DECLARE_clientfieldfloat(x)
1618#define PRVM_DECLARE_clientfieldvector(x)
1619#define PRVM_DECLARE_clientfieldstring(x)
1620#define PRVM_DECLARE_clientfieldedict(x)
1621#define PRVM_DECLARE_clientfieldfunction(x)
1622#define PRVM_DECLARE_menufieldfloat(x)
1623#define PRVM_DECLARE_menufieldvector(x)
1624#define PRVM_DECLARE_menufieldstring(x)
1625#define PRVM_DECLARE_menufieldedict(x)
1626#define PRVM_DECLARE_menufieldfunction(x)
1627#define PRVM_DECLARE_serverfunction(x)
1628#define PRVM_DECLARE_clientfunction(x)
1629#define PRVM_DECLARE_menufunction(x)
1630#define PRVM_DECLARE_field(x) prog->fieldoffsets.x = PRVM_ED_FindFieldOffset(prog, #x);
1631#define PRVM_DECLARE_global(x) prog->globaloffsets.x = PRVM_ED_FindGlobalOffset(prog, #x);
1632#define PRVM_DECLARE_function(x) prog->funcoffsets.x = PRVM_ED_FindFunctionOffset(prog, #x);
1633#include "prvm_offsets.h"
1634#undef PRVM_DECLARE_serverglobalfloat
1635#undef PRVM_DECLARE_serverglobalvector
1636#undef PRVM_DECLARE_serverglobalstring
1637#undef PRVM_DECLARE_serverglobaledict
1638#undef PRVM_DECLARE_serverglobalfunction
1639#undef PRVM_DECLARE_clientglobalfloat
1640#undef PRVM_DECLARE_clientglobalvector
1641#undef PRVM_DECLARE_clientglobalstring
1642#undef PRVM_DECLARE_clientglobaledict
1643#undef PRVM_DECLARE_clientglobalfunction
1644#undef PRVM_DECLARE_menuglobalfloat
1645#undef PRVM_DECLARE_menuglobalvector
1646#undef PRVM_DECLARE_menuglobalstring
1647#undef PRVM_DECLARE_menuglobaledict
1648#undef PRVM_DECLARE_menuglobalfunction
1649#undef PRVM_DECLARE_serverfieldfloat
1650#undef PRVM_DECLARE_serverfieldvector
1651#undef PRVM_DECLARE_serverfieldstring
1652#undef PRVM_DECLARE_serverfieldedict
1653#undef PRVM_DECLARE_serverfieldfunction
1654#undef PRVM_DECLARE_clientfieldfloat
1655#undef PRVM_DECLARE_clientfieldvector
1656#undef PRVM_DECLARE_clientfieldstring
1657#undef PRVM_DECLARE_clientfieldedict
1658#undef PRVM_DECLARE_clientfieldfunction
1659#undef PRVM_DECLARE_menufieldfloat
1660#undef PRVM_DECLARE_menufieldvector
1661#undef PRVM_DECLARE_menufieldstring
1662#undef PRVM_DECLARE_menufieldedict
1663#undef PRVM_DECLARE_menufieldfunction
1664#undef PRVM_DECLARE_serverfunction
1665#undef PRVM_DECLARE_clientfunction
1666#undef PRVM_DECLARE_menufunction
1667#undef PRVM_DECLARE_field
1668#undef PRVM_DECLARE_global
1669#undef PRVM_DECLARE_function
1670}
prvm_prog_funcoffsets_t funcoffsets
Definition progsvm.h:693
prvm_prog_fieldoffsets_t fieldoffsets
Definition progsvm.h:691
prvm_prog_globaloffsets_t globaloffsets
Definition progsvm.h:692

References prvm_prog_t::fieldoffsets, prvm_prog_t::funcoffsets, and prvm_prog_t::globaloffsets.

Referenced by PRVM_Prog_Load().

◆ PRVM_FreeString()

void PRVM_FreeString ( prvm_prog_t * prog,
int num )

Definition at line 3516 of file prvm_edict.c.

3517{
3518 if (num == 0)
3519 prog->error_cmd("PRVM_FreeString %s: attempt to free a NULL string", prog->name);
3520 else if (num >= 0 && num < prog->stringssize)
3521 prog->error_cmd("PRVM_FreeString %s: attempt to free a constant string", prog->name);
3522 else if (num >= PRVM_KNOWNSTRINGBASE && num < PRVM_KNOWNSTRINGBASE + prog->numknownstrings)
3523 {
3524 num = num - PRVM_KNOWNSTRINGBASE;
3525 if (!prog->knownstrings[num])
3526 prog->error_cmd("PRVM_FreeString %s: attempt to free a non-existent or already freed string", prog->name);
3527 if (!prog->knownstrings_flags[num])
3528 prog->error_cmd("PRVM_FreeString %s: attempt to free a string owned by the engine", prog->name);
3529 PRVM_Free((char *)prog->knownstrings[num]);
3530 if(prog->leaktest_active)
3531 if(prog->knownstrings_origin[num])
3532 PRVM_Free((char *)prog->knownstrings_origin[num]);
3533 prog->knownstrings[num] = NULL;
3534 prog->knownstrings_flags[num] = 0;
3535 prog->firstfreeknownstring = min(prog->firstfreeknownstring, num);
3536 }
3537 else
3538 prog->error_cmd("PRVM_FreeString %s: invalid string offset %i", prog->name, num);
3539}
#define min(A, B)
Definition mathlib.h:37
#define PRVM_Free(buffer)
Definition progsvm.h:819

References prvm_prog_t::error_cmd, prvm_prog_t::firstfreeknownstring, prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_flags, prvm_prog_t::knownstrings_origin, prvm_prog_t::leaktest_active, min, prvm_prog_t::name, NULL, PRVM_Free, and PRVM_KNOWNSTRINGBASE.

Referenced by VM_strunzone().

◆ PRVM_FriendlyProgFromString()

prvm_prog_t * PRVM_FriendlyProgFromString ( const char * str)

for console commands (prints error if name unknown and returns NULL, prints error if prog not loaded and returns NULL)

Definition at line 184 of file prvm_edict.c.

185{
186 prvm_prog_t *prog = PRVM_ProgFromString(str);
187 if (!prog)
188 {
189 Con_Printf("%s: unknown program name\n", str);
190 return NULL;
191 }
192 if (!prog->loaded)
193 {
194 Con_Printf("%s: program is not loaded\n", str);
195 return NULL;
196 }
197 return prog;
198}
qbool loaded
used to indicate whether a prog is loaded
Definition progsvm.h:710

References Con_Printf(), prvm_prog_t::loaded, NULL, and PRVM_ProgFromString().

Referenced by PRVM_Breakpoint_f(), PRVM_CallProfile_f(), PRVM_ChildProfile_f(), PRVM_ED_Count_f(), PRVM_ED_EdictGet_f(), PRVM_ED_EdictSet_f(), PRVM_ED_GlobalGet_f(), PRVM_ED_PrintEdict_f(), PRVM_ED_PrintEdicts_f(), PRVM_EdictWatchpoint_f(), PRVM_Fields_f(), PRVM_GameCommand(), PRVM_Global_f(), PRVM_Globals_f(), PRVM_GlobalSet_f(), PRVM_GlobalWatchpoint_f(), PRVM_PrintFunction_f(), and PRVM_Profile_f().

◆ PRVM_GameCommand()

void PRVM_GameCommand ( cmd_state_t * cmd,
const char * whichprogs,
const char * whichcmd )
static

Definition at line 1108 of file prvm_edict.c.

1109{
1110 prvm_prog_t *prog;
1111 if(Cmd_Argc(cmd) < 1)
1112 {
1113 Con_Printf("%s text...\n", whichcmd);
1114 return;
1115 }
1116
1117 if (!(prog = PRVM_FriendlyProgFromString(whichprogs)))
1118 return;
1119
1120 if(!PRVM_allfunction(GameCommand))
1121 {
1122 Con_Printf("%s program do not support GameCommand!\n", whichprogs);
1123 }
1124 else
1125 {
1126 int restorevm_tempstringsbuf_cursize;
1127 const char *s;
1128
1129 s = Cmd_Args(cmd);
1130
1131 restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
1132 PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s ? s : "", s ? strlen(s) : 0);
1133 prog->ExecuteProgram(prog, PRVM_allfunction(GameCommand), "QC function GameCommand is missing");
1134 prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
1135 }
1136}
static const char * Cmd_Args(cmd_state_t *cmd)
Definition cmd.h:260
#define OFS_PARM0
Definition pr_comp.h:34
#define PRVM_allfunction(funcname)
Definition progsvm.h:146
#define PRVM_G_INT(o)
Definition progsvm.h:883
int PRVM_SetTempString(prvm_prog_t *prog, const char *s, size_t slen)
Takes an strlen (not a buffer size).
sizebuf_t tempstringsbuf
buffer for storing all tempstrings created during one invocation of ExecuteProgram
Definition progsvm.h:644
int cursize
Definition common.h:54

References cmd(), Cmd_Argc(), Cmd_Args(), Con_Printf(), sizebuf_t::cursize, prvm_prog_t::ExecuteProgram, OFS_PARM0, PRVM_allfunction, PRVM_FriendlyProgFromString(), PRVM_G_INT, PRVM_SetTempString(), strlen(), and prvm_prog_t::tempstringsbuf.

Referenced by PRVM_GameCommand_Client_f(), PRVM_GameCommand_Menu_f(), and PRVM_GameCommand_Server_f().

◆ PRVM_GameCommand_Client_f()

void PRVM_GameCommand_Client_f ( cmd_state_t * cmd)
static

Definition at line 1141 of file prvm_edict.c.

1142{
1143 PRVM_GameCommand(cmd, "client", "cl_cmd");
1144}
static void PRVM_GameCommand(cmd_state_t *cmd, const char *whichprogs, const char *whichcmd)

References cmd(), and PRVM_GameCommand().

Referenced by PRVM_Init().

◆ PRVM_GameCommand_Menu_f()

void PRVM_GameCommand_Menu_f ( cmd_state_t * cmd)
static

Definition at line 1145 of file prvm_edict.c.

1146{
1147 PRVM_GameCommand(cmd, "menu", "menu_cmd");
1148}

References cmd(), and PRVM_GameCommand().

Referenced by PRVM_Init().

◆ PRVM_GameCommand_Server_f()

void PRVM_GameCommand_Server_f ( cmd_state_t * cmd)
static

Definition at line 1137 of file prvm_edict.c.

1138{
1139 PRVM_GameCommand(cmd, "server", "sv_cmd");
1140}

References cmd(), and PRVM_GameCommand().

Referenced by PRVM_Init().

◆ PRVM_GarbageCollection()

void PRVM_GarbageCollection ( prvm_prog_t * prog)

Definition at line 3792 of file prvm_edict.c.

3793{
3794 int limit = prvm_garbagecollection_scan_limit.integer * (prog == SVVM_prog ? sv.frametime : cl.realframetime);
3796 if (!prvm_garbagecollection_enable.integer)
3797 return;
3798 // philosophy:
3799 // we like to limit how much scanning we do so it doesn't put a significant
3800 // burden on the cpu, so each of these are not complete scans, we also like
3801 // to have consistent cpu usage so we do a bit of work on each category of
3802 // leaked object every frame
3803 switch (gc->stage)
3804 {
3805 case PRVM_GC_START:
3806 gc->stage++;
3807 break;
3809 for (; gc->globals_mark_progress < prog->numglobaldefs && (limit--) > 0; gc->globals_mark_progress++)
3810 {
3811 mdef_t *d = &prog->globaldefs[gc->globals_mark_progress];
3812 switch (d->type)
3813 {
3814 case ev_string:
3815 {
3816 prvm_int_t s = prog->globals.ip[d->ofs];
3817 if (s & PRVM_KNOWNSTRINGBASE)
3818 {
3820 if (!prog->knownstrings[num])
3821 {
3822 // invalid
3823 Con_DPrintf("PRVM_GarbageCollection: Found bogus strzone reference in global %i (global name: \"%s\"), erasing reference", d->ofs, PRVM_GetString(prog, d->s_name));
3824 prog->globals.ip[d->ofs] = 0;
3825 continue;
3826 }
3828 }
3829 }
3830 break;
3831 default:
3832 break;
3833 }
3834 }
3835 if (gc->globals_mark_progress >= prog->numglobaldefs)
3836 gc->stage++;
3837 break;
3839 for (; gc->fields_mark_progress < prog->numfielddefs && limit > 0;)
3840 {
3841 mdef_t *d = &prog->fielddefs[gc->fields_mark_progress];
3842 switch (d->type)
3843 {
3844 case ev_string:
3845 //for (gc-> entityindex = 0; entityindex < prog->num_edicts; entityindex++)
3846 for (;gc->fields_mark_progress_entity < prog->num_edicts && (limit--) > 0;gc->fields_mark_progress_entity++)
3847 {
3848 int entityindex = gc->fields_mark_progress_entity;
3849 prvm_int_t s = prog->edictsfields.ip[entityindex * prog->entityfields + d->ofs];
3850 if (s & PRVM_KNOWNSTRINGBASE)
3851 {
3853 if (!prog->knownstrings[num])
3854 {
3855 // invalid
3856 Con_DPrintf("PRVM_GarbageCollection: Found bogus strzone reference in edict %i field %i (field name: \"%s\"), erasing reference", entityindex, d->ofs, PRVM_GetString(prog, d->s_name));
3857 prog->edictsfields.ip[entityindex * prog->entityfields + d->ofs] = 0;
3858 continue;
3859 }
3861 }
3862 }
3863 if (gc->fields_mark_progress_entity >= prog->num_edicts)
3864 {
3867 }
3868 break;
3869 default:
3872 break;
3873 }
3874 }
3875 if (gc->fields_mark_progress >= prog->numfielddefs)
3876 gc->stage++;
3877 break;
3879 // free any strzone'd strings that are not marked
3880 if (!prvm_garbagecollection_strings.integer)
3881 {
3882 gc->stage++;
3883 break;
3884 }
3885 for (;gc->knownstrings_sweep_progress < prog->numknownstrings && (limit--) > 0;gc->knownstrings_sweep_progress++)
3886 {
3887 int num = gc->knownstrings_sweep_progress;
3888 if (prog->knownstrings[num] && (prog->knownstrings_flags[num] & (KNOWNSTRINGFLAG_GCMARK | KNOWNSTRINGFLAG_ENGINE)) == 0)
3889 {
3891 {
3892 // string has been marked for pruning two passes in a row
3894 Con_DPrintf("prvm_garbagecollection_notify: %s: freeing unreferenced string %i: \"%s\"\n", prog->name, num, prog->knownstrings[num]);
3895 Mem_Free((char *)prog->knownstrings[num]);
3896 prog->knownstrings[num] = NULL;
3897 prog->knownstrings_flags[num] = 0;
3898 prog->firstfreeknownstring = min(prog->firstfreeknownstring, num);
3899 }
3900 else
3901 {
3902 // mark it for pruning next pass
3904 }
3905 }
3906 }
3908 gc->stage++;
3909 break;
3910 case PRVM_GC_RESET:
3911 default:
3912 memset(gc, 0, sizeof(*gc));
3913// Con_Printf("%s%s GC: reset @ %f frametime %f scan_limit per frame %i\n", prog == SVVM_prog ? "^6" : "^5", prog->name, host.realtime, prog == SVVM_prog ? sv.frametime : cl.realframetime, limit);
3914 }
3915}
client_state_t cl
Definition cl_main.c:117
@ PRVM_GC_START
Definition progsvm.h:516
@ PRVM_GC_RESET
Definition progsvm.h:520
@ PRVM_GC_KNOWNSTRINGS_SWEEP
Definition progsvm.h:519
@ PRVM_GC_GLOBALS_MARK
Definition progsvm.h:517
@ PRVM_GC_FIELDS_MARK
Definition progsvm.h:518
#define KNOWNSTRINGFLAG_GCPRUNE
Definition progsvm.h:512
#define SVVM_prog
Definition progsvm.h:766
cvar_t prvm_garbagecollection_notify
Definition prvm_edict.c:49
cvar_t prvm_garbagecollection_enable
Definition prvm_edict.c:48
cvar_t prvm_garbagecollection_scan_limit
At 50k in Xonotic with 8 bots scans take about: 24s server, 25s menu, 9s client.
Definition prvm_edict.c:53
cvar_t prvm_garbagecollection_strings
Definition prvm_edict.c:54
int32_t prvm_int_t
Definition qtypes.h:56
prvm_int_t * ip
Definition progsvm.h:581
union prvm_prog_t::@327125214102202150166162221173336172250075227076 edictsfields
prvm_prog_garbagecollection_state_t gc
garbage collection status
Definition progsvm.h:599

References cl, Con_DPrintf(), prvm_prog_t::edictsfields, prvm_prog_t::entityfields, ev_string, prvm_prog_t::fielddefs, prvm_prog_garbagecollection_state_t::fields_mark_progress, prvm_prog_garbagecollection_state_t::fields_mark_progress_entity, prvm_prog_t::firstfreeknownstring, prvm_prog_t::gc, prvm_prog_t::globaldefs, prvm_prog_t::globals, prvm_prog_garbagecollection_state_t::globals_mark_progress, prvm_prog_t::ip, KNOWNSTRINGFLAG_ENGINE, KNOWNSTRINGFLAG_GCMARK, KNOWNSTRINGFLAG_GCPRUNE, prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_flags, prvm_prog_garbagecollection_state_t::knownstrings_sweep_progress, Mem_Free, min, prvm_prog_t::name, NULL, prvm_prog_t::num_edicts, prvm_prog_t::numfielddefs, prvm_prog_t::numglobaldefs, prvm_prog_t::numknownstrings, mdef_t::ofs, prvm_garbagecollection_enable, prvm_garbagecollection_notify, prvm_garbagecollection_scan_limit, prvm_garbagecollection_strings, PRVM_GC_FIELDS_MARK, PRVM_GC_GLOBALS_MARK, PRVM_GC_KNOWNSTRINGS_SWEEP, PRVM_GC_RESET, PRVM_GC_START, PRVM_GetString(), PRVM_KNOWNSTRINGBASE, mdef_t::s_name, prvm_prog_garbagecollection_state_t::stage, sv, SVVM_prog, and mdef_t::type.

Referenced by CL_VM_DrawHud(), CL_VM_UpdateView(), MP_Draw(), and SV_Physics().

◆ PRVM_GetString()

const char * PRVM_GetString ( prvm_prog_t * prog,
int num )

Definition at line 3318 of file prvm_edict.c.

3319{
3320 if (num < 0)
3321 {
3322 // invalid
3323 if (prvm_stringdebug.integer)
3324 VM_Warning(prog, "PRVM_GetString: Invalid string offset (%i < 0)\n", num);
3325 return "";
3326 }
3327 else if (num < prog->stringssize)
3328 {
3329 // constant string from progs.dat
3330 return prog->strings + num;
3331 }
3332 else if (num <= prog->stringssize + prog->tempstringsbuf.maxsize)
3333 {
3334 // tempstring returned by engine to QC (becomes invalid after returning to engine)
3335 num -= prog->stringssize;
3336 if (num < prog->tempstringsbuf.cursize)
3337 return (char *)prog->tempstringsbuf.data + num;
3338 else
3339 {
3340 if (prvm_stringdebug.integer)
3341 VM_Warning(prog, "PRVM_GetString: Invalid temp-string offset (%i >= %i prog->tempstringsbuf.cursize)\n", num, prog->tempstringsbuf.cursize);
3342 return "";
3343 }
3344 }
3345 else if (num & PRVM_KNOWNSTRINGBASE)
3346 {
3347 // allocated string
3348 num = num - PRVM_KNOWNSTRINGBASE;
3349 if (num >= 0 && num < prog->numknownstrings)
3350 {
3351 if (!prog->knownstrings[num])
3352 {
3353 if (prvm_stringdebug.integer)
3354 VM_Warning(prog, "PRVM_GetString: Invalid zone-string offset (%i has been freed)\n", num);
3355 return "";
3356 }
3357 // refresh the garbage collection on the string - this guards
3358 // against a certain sort of repeated migration to earlier
3359 // points in the scan that could otherwise result in the string
3360 // being freed for being unused
3362 return prog->knownstrings[num];
3363 }
3364 else
3365 {
3366 if (prvm_stringdebug.integer)
3367 VM_Warning(prog, "PRVM_GetString: Invalid zone-string offset (%i >= %i)\n", num, prog->numknownstrings);
3368 return "";
3369 }
3370 }
3371 else
3372 {
3373 // invalid string offset
3374 if (prvm_stringdebug.integer)
3375 VM_Warning(prog, "PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)\n", num, prog->stringssize);
3376 return "";
3377 }
3378}
void VM_Warning(prvm_prog_t *prog, const char *fmt,...) DP_FUNC_PRINTF(2)
Definition prvm_cmds.c:25
cvar_t prvm_stringdebug
Definition prvm_edict.c:55
int stringssize
Definition progsvm.h:544
char * strings
Definition progsvm.h:543
unsigned char * data
Definition common.h:52
int maxsize
Definition common.h:53

References sizebuf_t::cursize, sizebuf_t::data, KNOWNSTRINGFLAG_GCMARK, KNOWNSTRINGFLAG_GCPRUNE, prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_flags, sizebuf_t::maxsize, prvm_prog_t::numknownstrings, PRVM_KNOWNSTRINGBASE, prvm_stringdebug, prvm_prog_t::strings, prvm_prog_t::stringssize, prvm_prog_t::tempstringsbuf, and VM_Warning().

Referenced by CLVM_ExecuteProgram(), FindViewthing(), NetConn_BuildStatusResponse(), PRVM_CallProfile(), PRVM_ED_CallSpawnFunction(), PRVM_ED_FindField(), PRVM_ED_FindFunction(), PRVM_ED_FindGlobal(), PRVM_ED_ParseEpair(), PRVM_ED_Print(), PRVM_ED_Write(), PRVM_ED_WriteGlobals(), PRVM_Fields_f(), PRVM_FunctionCoverageEvent(), PRVM_GarbageCollection(), PRVM_Globals_f(), PRVM_GlobalString(), PRVM_GlobalStringNoContents(), PRVM_IsEdictReferenced(), PRVM_IsEdictRelevant(), PRVM_MarkReferencedEdicts(), PRVM_PrintStatement(), PRVM_Profile(), PRVM_Prog_Load(), PRVM_ShortStackTrace(), PRVM_StackTrace(), PRVM_UglyValueString(), PRVM_ValueString(), PRVM_WhereAmI(), SV_CheckVelocity(), SV_Ent_Remove_All_f(), SV_Ent_Remove_f(), SV_PrepareEntityForSending(), SV_Savegame_to(), SV_SendServerinfo(), SV_SpawnServer(), SV_Status_f(), SV_UnstickEntity(), SV_UpdateToReliableMessages(), SV_WriteClientdataToMessage(), SVVM_ExecuteProgram(), VM_error(), VM_objerror(), VM_SV_droptofloor(), and while().

◆ PRVM_Global_f()

void PRVM_Global_f ( cmd_state_t * cmd)
static

Definition at line 2976 of file prvm_edict.c.

2977{
2978 prvm_prog_t *prog;
2979 mdef_t *global;
2980 char valuebuf[MAX_INPUTLINE];
2981 if( Cmd_Argc(cmd) != 3 ) {
2982 Con_Printf( "prvm_global <program name> <global name>\n" );
2983 return;
2984 }
2985
2986 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
2987 return;
2988
2989 global = PRVM_ED_FindGlobal( prog, Cmd_Argv(cmd, 2) );
2990 if( !global )
2991 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(cmd, 2), Cmd_Argv(cmd, 1) );
2992 else
2993 Con_Printf( "%s: %s\n", Cmd_Argv(cmd, 2), PRVM_ValueString( prog, (etype_t)global->type, PRVM_GLOBALFIELDVALUE(global->ofs), valuebuf, sizeof(valuebuf) ) );
2994}
#define PRVM_GLOBALFIELDVALUE(fieldoffset)
Definition progsvm.h:215

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), MAX_INPUTLINE, mdef_t::ofs, PRVM_ED_FindGlobal(), PRVM_FriendlyProgFromString(), PRVM_GLOBALFIELDVALUE, PRVM_ValueString(), and mdef_t::type.

Referenced by PRVM_Init().

◆ PRVM_Globals_f()

void PRVM_Globals_f ( cmd_state_t * cmd)
static

Definition at line 2929 of file prvm_edict.c.

2930{
2931 prvm_prog_t *prog;
2932 int i;
2933 const char *wildcard;
2934 int numculled;
2935 numculled = 0;
2936 // TODO
2937 /*if (!sv.active)
2938 {
2939 Con_Print("no progs loaded\n");
2940 return;
2941 }*/
2942 if(Cmd_Argc (cmd) < 2 || Cmd_Argc(cmd) > 3)
2943 {
2944 Con_Print("prvm_globals <program name> <optional name wildcard>\n");
2945 return;
2946 }
2947
2948 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
2949 return;
2950
2951 if( Cmd_Argc(cmd) == 3)
2952 wildcard = Cmd_Argv(cmd, 2);
2953 else
2954 wildcard = NULL;
2955
2956 Con_Printf("%s :", prog->name);
2957
2958 for (i = 0;i < prog->numglobaldefs;i++)
2959 {
2960 if(wildcard)
2961 if( !matchpattern( PRVM_GetString(prog, prog->globaldefs[i].s_name), wildcard, 1) )
2962 {
2963 numculled++;
2964 continue;
2965 }
2966 Con_Printf("%s\n", PRVM_GetString(prog, prog->globaldefs[i].s_name));
2967 }
2968 Con_Printf("%i global variables, %i culled, totalling %i bytes\n", prog->numglobals, numculled, prog->numglobals * 4);
2969}
int numglobals
Definition progsvm.h:568

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), prvm_prog_t::globaldefs, matchpattern(), prvm_prog_t::name, NULL, prvm_prog_t::numglobaldefs, prvm_prog_t::numglobals, PRVM_FriendlyProgFromString(), PRVM_GetString(), and mdef_t::s_name.

Referenced by PRVM_Init().

◆ PRVM_GlobalSet_f()

void PRVM_GlobalSet_f ( cmd_state_t * cmd)
static

Definition at line 3001 of file prvm_edict.c.

3002{
3003 prvm_prog_t *prog;
3004 mdef_t *global;
3005 if( Cmd_Argc(cmd) != 4 ) {
3006 Con_Printf( "prvm_globalset <program name> <global name> <value>\n" );
3007 return;
3008 }
3009
3010 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
3011 return;
3012
3013 global = PRVM_ED_FindGlobal( prog, Cmd_Argv(cmd, 2) );
3014 if( !global )
3015 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(cmd, 2), Cmd_Argv(cmd, 1) );
3016 else
3017 PRVM_ED_ParseEpair( prog, NULL, global, Cmd_Argv(cmd, 3), true );
3018}

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), NULL, PRVM_ED_FindGlobal(), PRVM_ED_ParseEpair(), and PRVM_FriendlyProgFromString().

Referenced by PRVM_Init().

◆ PRVM_GlobalString()

char * PRVM_GlobalString ( prvm_prog_t * prog,
int ofs,
char * line,
size_t linelength )

Definition at line 602 of file prvm_edict.c.

603{
604 char *s;
605 //size_t i;
606 mdef_t *def;
607 prvm_eval_t *val;
608 char valuebuf[MAX_INPUTLINE];
609
610 val = (prvm_eval_t *)&prog->globals.fp[ofs];
611 def = PRVM_ED_GlobalAtOfs(prog, ofs);
612 if (!def)
613 dpsnprintf (line, linelength, "GLOBAL%i", ofs);
614 else
615 {
616 s = PRVM_ValueString (prog, (etype_t)def->type, val, valuebuf, sizeof(valuebuf));
617 dpsnprintf (line, linelength, "%s (=%s)", PRVM_GetString(prog, def->s_name), s);
618 }
619
620 //i = strlen(line);
621 //for ( ; i<20 ; i++)
622 // strcat (line," ");
623 //strcat (line," ");
624
625 return line;
626}
static mdef_t * PRVM_ED_GlobalAtOfs(prvm_prog_t *prog, unsigned int ofs)
Definition prvm_edict.c:338

References dpsnprintf(), prvm_prog_t::fp, prvm_prog_t::globals, MAX_INPUTLINE, ofs, PRVM_ED_GlobalAtOfs(), PRVM_GetString(), PRVM_ValueString(), mdef_t::s_name, and mdef_t::type.

Referenced by PRVM_PrintStatement().

◆ PRVM_GlobalStringNoContents()

char * PRVM_GlobalStringNoContents ( prvm_prog_t * prog,
int ofs,
char * line,
size_t linelength )

Definition at line 628 of file prvm_edict.c.

629{
630 //size_t i;
631 mdef_t *def;
632
633 def = PRVM_ED_GlobalAtOfs(prog, ofs);
634 if (!def)
635 dpsnprintf (line, linelength, "GLOBAL%i", ofs);
636 else
637 dpsnprintf (line, linelength, "%s", PRVM_GetString(prog, def->s_name));
638
639 //i = strlen(line);
640 //for ( ; i<20 ; i++)
641 // strcat (line," ");
642 //strcat (line," ");
643
644 return line;
645}

References dpsnprintf(), ofs, PRVM_ED_GlobalAtOfs(), PRVM_GetString(), and mdef_t::s_name.

◆ PRVM_GlobalWatchpoint_f()

void PRVM_GlobalWatchpoint_f ( cmd_state_t * cmd)
static

Definition at line 3169 of file prvm_edict.c.

3170{
3171 prvm_prog_t *prog;
3172
3173 if( Cmd_Argc(cmd) == 2 ) {
3174 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
3175 return;
3176 {
3177 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3178 debug->watch_global[0] = 0;
3179 }
3181 return;
3182 }
3183 if( Cmd_Argc(cmd) != 3 ) {
3184 Con_Printf( "prvm_globalwatchpoint <program name> <global name>\n" );
3185 return;
3186 }
3187
3188 if (!(prog = PRVM_ProgFromString(Cmd_Argv(cmd, 1))))
3189 return;
3190
3191 {
3192 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3193 dp_strlcpy(debug->watch_global, Cmd_Argv(cmd, 2), sizeof(debug->watch_global));
3194 }
3196}
char watch_global[256]

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), debug_data, dp_strlcpy, PRVM_FriendlyProgFromString(), prvm_prog_list, PRVM_ProgFromString(), PRVM_UpdateBreakpoints(), and debug_data_t::watch_global.

Referenced by PRVM_Init().

◆ PRVM_Init()

void PRVM_Init ( void )

Definition at line 3233 of file prvm_edict.c.

3234{
3235 unsigned int i;
3236
3237 Cmd_AddCommand(CF_SHARED, "prvm_edict", PRVM_ED_PrintEdict_f, "print all data about an entity number in the selected VM (server, client, menu)");
3238 Cmd_AddCommand(CF_SHARED, "prvm_edicts", PRVM_ED_PrintEdicts_f, "prints all data about all entities in the selected VM (server, client, menu)");
3239 Cmd_AddCommand(CF_SHARED, "prvm_edictcount", PRVM_ED_Count_f, "prints number of active entities in the selected VM (server, client, menu)");
3240 Cmd_AddCommand(CF_SHARED, "prvm_profile", PRVM_Profile_f, "prints execution statistics about the most used QuakeC functions in the selected VM (server, client, menu)");
3241 Cmd_AddCommand(CF_SHARED, "prvm_childprofile", PRVM_ChildProfile_f, "prints execution statistics about the most used QuakeC functions in the selected VM (server, client, menu), sorted by time taken in function with child calls");
3242 Cmd_AddCommand(CF_SHARED, "prvm_callprofile", PRVM_CallProfile_f, "prints execution statistics about the most time consuming QuakeC calls from the engine in the selected VM (server, client, menu)");
3243 Cmd_AddCommand(CF_SHARED, "prvm_fields", PRVM_Fields_f, "prints usage statistics on properties (how many entities have non-zero values) in the selected VM (server, client, menu)");
3244 Cmd_AddCommand(CF_SHARED, "prvm_globals", PRVM_Globals_f, "prints all global variables in the selected VM (server, client, menu)");
3245 Cmd_AddCommand(CF_SHARED, "prvm_global", PRVM_Global_f, "prints value of a specified global variable in the selected VM (server, client, menu)");
3246 Cmd_AddCommand(CF_SHARED, "prvm_globalset", PRVM_GlobalSet_f, "sets value of a specified global variable in the selected VM (server, client, menu)");
3247 Cmd_AddCommand(CF_SHARED, "prvm_edictset", PRVM_ED_EdictSet_f, "changes value of a specified property of a specified entity in the selected VM (server, client, menu)");
3248 Cmd_AddCommand(CF_SHARED, "prvm_edictget", PRVM_ED_EdictGet_f, "retrieves the value of a specified property of a specified entity in the selected VM (server, client menu) into a cvar or to the console");
3249 Cmd_AddCommand(CF_SHARED, "prvm_globalget", PRVM_ED_GlobalGet_f, "retrieves the value of a specified global variable in the selected VM (server, client menu) into a cvar or to the console");
3250 Cmd_AddCommand(CF_SHARED, "prvm_printfunction", PRVM_PrintFunction_f, "prints a disassembly (QuakeC instructions) of the specified function in the selected VM (server, client, menu)");
3251 Cmd_AddCommand(CF_SHARED, "cl_cmd", PRVM_GameCommand_Client_f, "calls the client QC function GameCommand with the supplied string as argument");
3252 Cmd_AddCommand(CF_SHARED, "menu_cmd", PRVM_GameCommand_Menu_f, "calls the menu QC function GameCommand with the supplied string as argument");
3253 Cmd_AddCommand(CF_SHARED, "sv_cmd", PRVM_GameCommand_Server_f, "calls the server QC function GameCommand with the supplied string as argument");
3254 Cmd_AddCommand(CF_SHARED, "prvm_breakpoint", PRVM_Breakpoint_f, "marks a statement or function as breakpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear breakpoint");
3255 Cmd_AddCommand(CF_SHARED, "prvm_globalwatchpoint", PRVM_GlobalWatchpoint_f, "marks a global as watchpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear watchpoint");
3256 Cmd_AddCommand(CF_SHARED, "prvm_edictwatchpoint", PRVM_EdictWatchpoint_f, "marks an entity field as watchpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear watchpoint");
3257
3278
3279 // COMMANDLINEOPTION: PRVM: -norunaway disables the runaway loop check (it might be impossible to exit DarkPlaces if used!)
3280 prvm_runawaycheck = !Sys_CheckParm("-norunaway");
3281
3282 //VM_Cmd_Init();
3283
3284 // LadyHavoc: report supported extensions
3285 Con_DPrintf("\nQuakeC extensions for server and client:");
3286 for (i = 0; vm_sv_extensions[i]; i++)
3287 Con_DPrintf(" %s", vm_sv_extensions[i]);
3288 Con_DPrintf("\n");
3289#ifdef CONFIG_MENU
3290 Con_DPrintf("\nQuakeC extensions for menu:");
3291 for (i = 0; vm_m_extensions[i]; i++)
3292 Con_DPrintf(" %s", vm_m_extensions[i]);
3293 Con_DPrintf("\n");
3294#endif
3295}
qbool prvm_runawaycheck
Definition prvm_edict.c:60
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
Definition cmd.c:1661
#define CF_SHARED
Definition cmd.h:67
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
const char * vm_m_extensions[]
Definition mvm_cmds.c:13
void PRVM_Profile_f(struct cmd_state_s *cmd)
void PRVM_ChildProfile_f(struct cmd_state_s *cmd)
const char * vm_sv_extensions[]
client also uses this
Definition svvm_cmds.c:11
void PRVM_CallProfile_f(struct cmd_state_s *cmd)
void PRVM_PrintFunction_f(struct cmd_state_s *cmd)
void PRVM_ED_PrintEdicts_f(struct cmd_state_s *cmd)
cvar_t prvm_coverage
Definition prvm_edict.c:39
cvar_t prvm_backtraceforwarnings
Definition prvm_edict.c:40
static void PRVM_GameCommand_Client_f(cmd_state_t *cmd)
static void PRVM_EdictWatchpoint_f(cmd_state_t *cmd)
static void PRVM_Global_f(cmd_state_t *cmd)
static void PRVM_ED_EdictSet_f(cmd_state_t *cmd)
cvar_t prvm_gameplayfix_div0is0
Definition prvm_edict.c:57
static void PRVM_GlobalSet_f(cmd_state_t *cmd)
static void PRVM_GlobalWatchpoint_f(cmd_state_t *cmd)
cvar_t prvm_timeprofiling
Definition prvm_edict.c:38
cvar_t prvm_language
Definition prvm_edict.c:33
static void PRVM_GameCommand_Menu_f(cmd_state_t *cmd)
static void PRVM_ED_PrintEdict_f(cmd_state_t *cmd)
Definition prvm_edict.c:832
static void PRVM_ED_GlobalGet_f(cmd_state_t *cmd)
cvar_t prvm_leaktest
Definition prvm_edict.c:41
static void PRVM_Fields_f(cmd_state_t *cmd)
cvar_t prvm_statementprofiling
Definition prvm_edict.c:37
static void PRVM_Globals_f(cmd_state_t *cmd)
static void PRVM_ED_Count_f(cmd_state_t *cmd)
Definition prvm_edict.c:871
cvar_t prvm_leaktest_follow_targetname
Definition prvm_edict.c:42
cvar_t prvm_traceqc
Definition prvm_edict.c:35
cvar_t prvm_leaktest_ignore_classnames
Definition prvm_edict.c:43
static void PRVM_Breakpoint_f(cmd_state_t *cmd)
static void PRVM_GameCommand_Server_f(cmd_state_t *cmd)
cvar_t prvm_errordump
Definition prvm_edict.c:44
int Sys_CheckParm(const char *parm)
Definition sys_shared.c:327

References CF_SHARED, Cmd_AddCommand(), Con_DPrintf(), Cvar_RegisterVariable(), prvm_backtraceforwarnings, PRVM_Breakpoint_f(), prvm_breakpointdump, PRVM_CallProfile_f(), PRVM_ChildProfile_f(), prvm_coverage, PRVM_ED_Count_f(), PRVM_ED_EdictGet_f(), PRVM_ED_EdictSet_f(), PRVM_ED_GlobalGet_f(), PRVM_ED_PrintEdict_f(), PRVM_ED_PrintEdicts_f(), PRVM_EdictWatchpoint_f(), prvm_errordump, PRVM_Fields_f(), PRVM_GameCommand_Client_f(), PRVM_GameCommand_Menu_f(), PRVM_GameCommand_Server_f(), prvm_gameplayfix_div0is0, prvm_garbagecollection_enable, prvm_garbagecollection_notify, prvm_garbagecollection_scan_limit, prvm_garbagecollection_strings, PRVM_Global_f(), PRVM_Globals_f(), PRVM_GlobalSet_f(), PRVM_GlobalWatchpoint_f(), prvm_language, prvm_leaktest, prvm_leaktest_follow_targetname, prvm_leaktest_ignore_classnames, PRVM_PrintFunction_f(), PRVM_Profile_f(), prvm_reuseedicts_neverinsameframe, prvm_reuseedicts_startuptime, prvm_runawaycheck, prvm_statementprofiling, prvm_stringdebug, prvm_timeprofiling, prvm_traceqc, sv_entfields_noescapes, Sys_CheckParm(), vm_m_extensions, and vm_sv_extensions.

Referenced by Host_Init().

◆ PRVM_IsEdictReferenced()

qbool PRVM_IsEdictReferenced ( prvm_prog_t * prog,
prvm_edict_t * edict,
int mark )
static

Definition at line 3624 of file prvm_edict.c.

3625{
3626 int i, j;
3627 int edictnum = PRVM_NUM_FOR_EDICT(edict);
3628 const char *targetname = NULL;
3629
3630 if (prog == SVVM_prog && prvm_leaktest_follow_targetname.integer)
3632
3633 if(targetname)
3634 if(!*targetname) // ""
3635 targetname = NULL;
3636
3637 for(j = 0; j < prog->num_edicts; ++j)
3638 {
3640 if (ed->priv.required->mark < mark)
3641 continue;
3642 if(ed == edict)
3643 continue;
3644 if(targetname)
3645 {
3646 const char *target = PRVM_GetString(prog, PRVM_serveredictstring(ed, target));
3647 if(target)
3648 if(!strcmp(target, targetname))
3649 return true;
3650 }
3651 for (i=0; i<prog->numfielddefs; ++i)
3652 {
3653 mdef_t *d = &prog->fielddefs[i];
3654 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
3655 continue;
3656 if(edictnum == PRVM_EDICTFIELDEDICT(ed, d->ofs))
3657 return true;
3658 }
3659 }
3660
3661 return false;
3662}
string targetname
Definition progsdefs.qc:194
string target
Definition progsdefs.qc:193
#define PRVM_EDICTFIELDEDICT(ed, fieldoffset)
Definition progsvm.h:213
#define PRVM_serveredictstring(ed, fieldname)
Definition progsvm.h:174
int mark
mark for the leak detector
Definition progsvm.h:85

References DEF_SAVEGLOBAL, ev_entity, prvm_prog_t::fielddefs, prvm_edict_private_t::mark, NULL, prvm_prog_t::num_edicts, prvm_prog_t::numfielddefs, mdef_t::ofs, prvm_edict_t::priv, PRVM_EDICT_NUM, PRVM_EDICTFIELDEDICT, PRVM_GetString(), prvm_leaktest_follow_targetname, PRVM_NUM_FOR_EDICT, PRVM_serveredictstring, prvm_edict_t::required, SVVM_prog, target, targetname, and mdef_t::type.

Referenced by PRVM_MarkReferencedEdicts().

◆ PRVM_IsEdictRelevant()

qbool PRVM_IsEdictRelevant ( prvm_prog_t * prog,
prvm_edict_t * edict )
static

Definition at line 3572 of file prvm_edict.c.

3573{
3574 char vabuf[1024];
3575 char vabuf2[1024];
3576 if(PRVM_NUM_FOR_EDICT(edict) <= prog->reserved_edicts)
3577 return true; // world or clients
3578 if (edict->freetime <= prog->inittime)
3579 return true; // created during startup
3580 if (prog == SVVM_prog)
3581 {
3582 if(PRVM_serveredictfloat(edict, solid)) // can block other stuff, or is a trigger?
3583 return true;
3584 if(PRVM_serveredictfloat(edict, modelindex)) // visible ent?
3585 return true;
3586 if(PRVM_serveredictfloat(edict, effects)) // particle effect?
3587 return true;
3588 if(PRVM_serveredictfunction(edict, think)) // has a think function?
3589 if(PRVM_serveredictfloat(edict, nextthink) > 0) // that actually will eventually run?
3590 return true;
3592 return true;
3594 {
3595 if(strstr(va(vabuf, sizeof(vabuf), " %s ", prvm_leaktest_ignore_classnames.string), va(vabuf2, sizeof(vabuf2), " %s ", PRVM_GetString(prog, PRVM_serveredictstring(edict, classname)))))
3596 return true;
3597 }
3598 }
3599 else if (prog == CLVM_prog)
3600 {
3601 // TODO someone add more stuff here
3602 if(PRVM_clientedictfloat(edict, entnum)) // csqc networked
3603 return true;
3604 if(PRVM_clientedictfloat(edict, modelindex)) // visible ent?
3605 return true;
3606 if(PRVM_clientedictfloat(edict, effects)) // particle effect?
3607 return true;
3608 if(PRVM_clientedictfunction(edict, think)) // has a think function?
3609 if(PRVM_clientedictfloat(edict, nextthink) > 0) // that actually will eventually run?
3610 return true;
3612 {
3613 if(strstr(va(vabuf, sizeof(vabuf), " %s ", prvm_leaktest_ignore_classnames.string), va(vabuf2, sizeof(vabuf2), " %s ", PRVM_GetString(prog, PRVM_clientedictstring(edict, classname)))))
3614 return true;
3615 }
3616 }
3617 else
3618 {
3619 // menu prog does not have classnames
3620 }
3621 return false;
3622}
float modelindex
float effects
float nextthink
float entnum
float solid
float takedamage
Definition progsdefs.qc:147
#define CLVM_prog
Definition progsvm.h:767
#define PRVM_clientedictstring(ed, fieldname)
Definition progsvm.h:186
#define PRVM_clientedictfunction(ed, fieldname)
Definition progsvm.h:188
#define PRVM_serveredictfloat(ed, fieldname)
Definition progsvm.h:172
#define PRVM_clientedictfloat(ed, fieldname)
Definition progsvm.h:184
#define PRVM_serveredictfunction(ed, fieldname)
Definition progsvm.h:176
double inittime
system time when QC initialization code finished (any entity created before is not a leak)
Definition progsvm.h:539

References classname, CLVM_prog, effects, entnum, prvm_edict_t::freetime, prvm_prog_t::inittime, modelindex, nextthink, PRVM_clientedictfloat, PRVM_clientedictfunction, PRVM_clientedictstring, PRVM_GetString(), prvm_leaktest_ignore_classnames, PRVM_NUM_FOR_EDICT, PRVM_serveredictfloat, PRVM_serveredictfunction, PRVM_serveredictstring, prvm_prog_t::reserved_edicts, solid, SVVM_prog, takedamage, and va().

Referenced by PRVM_MarkReferencedEdicts().

◆ PRVM_IsStringReferenced()

qbool PRVM_IsStringReferenced ( prvm_prog_t * prog,
string_t string )
static

Definition at line 3541 of file prvm_edict.c.

3542{
3543 int i, j;
3544
3545 for (i = 0;i < prog->numglobaldefs;i++)
3546 {
3547 mdef_t *d = &prog->globaldefs[i];
3548 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_string)
3549 continue;
3550 if(string == PRVM_GLOBALFIELDSTRING(d->ofs))
3551 return true;
3552 }
3553
3554 for(j = 0; j < prog->num_edicts; ++j)
3555 {
3557 if (ed->free)
3558 continue;
3559 for (i=0; i<prog->numfielddefs; ++i)
3560 {
3561 mdef_t *d = &prog->fielddefs[i];
3562 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_string)
3563 continue;
3564 if(string == PRVM_EDICTFIELDSTRING(ed, d->ofs))
3565 return true;
3566 }
3567 }
3568
3569 return false;
3570}
#define PRVM_EDICTFIELDSTRING(ed, fieldoffset)
Definition progsvm.h:212
#define PRVM_GLOBALFIELDSTRING(fieldoffset)
Definition progsvm.h:218

References DEF_SAVEGLOBAL, ev_string, prvm_prog_t::fielddefs, prvm_edict_t::free, prvm_prog_t::globaldefs, prvm_prog_t::num_edicts, prvm_prog_t::numfielddefs, prvm_prog_t::numglobaldefs, mdef_t::ofs, PRVM_EDICT_NUM, PRVM_EDICTFIELDSTRING, PRVM_GLOBALFIELDSTRING, and mdef_t::type.

Referenced by PRVM_LeakTest().

◆ PRVM_LeakTest()

void PRVM_LeakTest ( prvm_prog_t * prog)

Definition at line 3717 of file prvm_edict.c.

3718{
3719 int i, j;
3720 qbool leaked = false;
3721
3722 if(!prog->leaktest_active)
3723 return;
3724
3725 // 1. Strings
3726 for (i = 0; i < prog->numknownstrings; ++i)
3727 {
3728 if(prog->knownstrings[i])
3729 if(prog->knownstrings_flags[i])
3730 if(prog->knownstrings_origin[i])
3732 {
3733 Con_Printf("Unreferenced string found!\n Value: %s\n Origin: %s\n", prog->knownstrings[i], prog->knownstrings_origin[i]);
3734 leaked = true;
3735 }
3736 }
3737
3738 // 2. Edicts
3740 for(j = 0; j < prog->num_edicts; ++j)
3741 {
3743 if(ed->free)
3744 continue;
3745 if(!ed->priv.required->mark)
3747 {
3748 Con_Printf("Unreferenced edict found!\n Allocated at: %s\n", ed->priv.required->allocation_origin);
3749 PRVM_ED_Print(prog, ed, NULL);
3750 Con_Print("\n");
3751 leaked = true;
3752 }
3753
3754 ed->priv.required->mark = 0; // clear marks again when done
3755 }
3756
3757 for (i = 0; i < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); ++i)
3758 {
3760 if(stringbuffer)
3761 if(stringbuffer->origin)
3762 {
3763 Con_Printf("Open string buffer handle found!\n Allocated at: %s\n", stringbuffer->origin);
3764 leaked = true;
3765 }
3766 }
3767
3768 for(i = 0; i < PRVM_MAX_OPENFILES; ++i)
3769 {
3770 if(prog->openfiles[i])
3771 if(prog->openfiles_origin[i])
3772 {
3773 Con_Printf("Open file handle found!\n Allocated at: %s\n", prog->openfiles_origin[i]);
3774 leaked = true;
3775 }
3776 }
3777
3778 for(i = 0; i < PRVM_MAX_OPENSEARCHES; ++i)
3779 {
3780 if(prog->opensearches[i])
3781 if(prog->opensearches_origin[i])
3782 {
3783 Con_Printf("Open search handle found!\n Allocated at: %s\n", prog->opensearches_origin[i]);
3784 leaked = true;
3785 }
3786 }
3787
3788 if(!leaked)
3789 Con_Printf("Congratulations. No leaks found.\n");
3790}
#define PRVM_MAX_OPENFILES
Definition progsvm.h:251
#define PRVM_MAX_OPENSEARCHES
Definition progsvm.h:252
static void PRVM_MarkReferencedEdicts(prvm_prog_t *prog)
static qbool PRVM_IsStringReferenced(prvm_prog_t *prog, string_t string)
struct qfile_s * openfiles[PRVM_MAX_OPENFILES]
Definition progsvm.h:636
const char * opensearches_origin[PRVM_MAX_OPENSEARCHES]
Definition progsvm.h:639
struct fssearch_s * opensearches[PRVM_MAX_OPENSEARCHES]
Definition progsvm.h:638
memexpandablearray_t stringbuffersarray
Definition progsvm.h:596
const char * openfiles_origin[PRVM_MAX_OPENFILES]
Definition progsvm.h:637
const char * origin
Definition progsvm.h:504
size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l)
Definition zone.c:763
void * Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index)
Definition zone.c:780

References prvm_edict_private_t::allocation_origin, Con_Print(), Con_Printf(), prvm_edict_t::free, int(), prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_flags, prvm_prog_t::knownstrings_origin, prvm_prog_t::leaktest_active, prvm_edict_private_t::mark, Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), NULL, prvm_prog_t::num_edicts, prvm_prog_t::numknownstrings, prvm_prog_t::openfiles, prvm_prog_t::openfiles_origin, prvm_prog_t::opensearches, prvm_prog_t::opensearches_origin, prvm_stringbuffer_t::origin, prvm_edict_t::priv, PRVM_ED_Print(), PRVM_EDICT_NUM, PRVM_IsStringReferenced(), PRVM_KNOWNSTRINGBASE, PRVM_MarkReferencedEdicts(), PRVM_MAX_OPENFILES, PRVM_MAX_OPENSEARCHES, prvm_edict_t::required, and prvm_prog_t::stringbuffersarray.

Referenced by PRVM_Prog_Reset().

◆ PRVM_LoadLNO()

void PRVM_LoadLNO ( prvm_prog_t * prog,
const char * progname )
static

Definition at line 1974 of file prvm_edict.c.

1974 {
1975 fs_offset_t filesize;
1976 unsigned char *lno;
1977 unsigned int *header;
1978 char filename[512];
1979
1980 FS_StripExtension( progname, filename, sizeof( filename ) );
1981 dp_strlcat( filename, ".lno", sizeof( filename ) );
1982
1983 lno = FS_LoadFile( filename, tempmempool, false, &filesize );
1984 if( !lno ) {
1985 return;
1986 }
1987
1988/*
1989<Spike> SafeWrite (h, &lnotype, sizeof(int));
1990<Spike> SafeWrite (h, &version, sizeof(int));
1991<Spike> SafeWrite (h, &numglobaldefs, sizeof(int));
1992<Spike> SafeWrite (h, &numpr_globals, sizeof(int));
1993<Spike> SafeWrite (h, &numfielddefs, sizeof(int));
1994<Spike> SafeWrite (h, &numstatements, sizeof(int));
1995<Spike> SafeWrite (h, statement_linenums, numstatements*sizeof(int));
1996*/
1997 if ((unsigned int)filesize < (6 + prog->progs_numstatements) * sizeof(int))
1998 {
1999 Mem_Free(lno);
2000 return;
2001 }
2002
2003 header = (unsigned int *) lno;
2004 if (memcmp(lno, "LNOF", 4) == 0
2005 && LittleLong( header[ 1 ] ) == 1
2006 && (unsigned int)LittleLong( header[ 2 ] ) == (unsigned int)prog->progs_numglobaldefs
2007 && (unsigned int)LittleLong( header[ 3 ] ) == (unsigned int)prog->progs_numglobals
2008 && (unsigned int)LittleLong( header[ 4 ] ) == (unsigned int)prog->progs_numfielddefs
2009 && (unsigned int)LittleLong( header[ 5 ] ) == (unsigned int)prog->progs_numstatements)
2010 {
2011 prog->statement_linenums = (int *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof( int ) );
2012 memcpy( prog->statement_linenums, header + 6, prog->progs_numstatements * sizeof( int ) );
2013
2014 /* gmqcc suports columnums */
2015 if ((unsigned int)filesize > ((6 + 2 * prog->progs_numstatements) * sizeof( int )))
2016 {
2017 prog->statement_columnnums = (int *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof( int ) );
2018 memcpy( prog->statement_columnnums, header + 6 + prog->progs_numstatements, prog->progs_numstatements * sizeof( int ) );
2019 }
2020 }
2021 Mem_Free( lno );
2022}
#define LittleLong(l)
Definition common.h:92
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3541
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3612
int64_t fs_offset_t
Definition fs.h:37
int progs_numglobals
Definition progsvm.h:559
int * statement_linenums
NULL if not available.
Definition progsvm.h:570
int progs_numglobaldefs
Definition progsvm.h:555
int progs_numstatements
Definition progsvm.h:554
mempool_t * progs_mempool
all memory allocations related to this vm_prog (code, edicts, strings)
Definition progsvm.h:602
int progs_numfielddefs
Definition progsvm.h:556
int * statement_columnnums
NULL if not available.
Definition progsvm.h:571

References dp_strlcat, FS_LoadFile(), FS_StripExtension(), LittleLong, Mem_Alloc, Mem_Free, prvm_prog_t::progs_mempool, prvm_prog_t::progs_numfielddefs, prvm_prog_t::progs_numglobaldefs, prvm_prog_t::progs_numglobals, prvm_prog_t::progs_numstatements, prvm_prog_t::statement_columnnums, prvm_prog_t::statement_linenums, and tempmempool.

Referenced by PRVM_Prog_Load().

◆ PRVM_MarkReferencedEdicts()

void PRVM_MarkReferencedEdicts ( prvm_prog_t * prog)
static

Definition at line 3664 of file prvm_edict.c.

3665{
3666 int i, j;
3667 qbool found_new;
3668 int stage;
3669
3670 // Stage 1: world, all entities that are relevant, and all entities that are referenced by globals.
3671 stage = 1;
3672 for(j = 0; j < prog->num_edicts; ++j)
3673 {
3675 if(ed->free)
3676 continue;
3677 ed->priv.required->mark = PRVM_IsEdictRelevant(prog, ed) ? stage : 0;
3678 }
3679 for (i = 0;i < prog->numglobaldefs;i++)
3680 {
3681 mdef_t *d = &prog->globaldefs[i];
3682 prvm_edict_t *ed;
3683 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
3684 continue;
3685 j = PRVM_GLOBALFIELDEDICT(d->ofs);
3686 if (i < 0 || j >= prog->max_edicts) {
3687 Con_Printf("Invalid entity reference from global %s.\n", PRVM_GetString(prog, d->s_name));
3688 continue;
3689 }
3690 ed = PRVM_EDICT_NUM(j);;
3691 ed->priv.required->mark = stage;
3692 }
3693
3694 // Future stages: all entities that are referenced by an entity of the previous stage.
3695 do
3696 {
3697 found_new = false;
3698 for(j = 0; j < prog->num_edicts; ++j)
3699 {
3701 if(ed->free)
3702 continue;
3703 if(ed->priv.required->mark)
3704 continue;
3705 if(PRVM_IsEdictReferenced(prog, ed, stage))
3706 {
3707 ed->priv.required->mark = stage + 1;
3708 found_new = true;
3709 }
3710 }
3711 ++stage;
3712 }
3713 while(found_new);
3714 Con_DPrintf("leak check used %d stages to find all references\n", stage);
3715}
#define PRVM_GLOBALFIELDEDICT(fieldoffset)
Definition progsvm.h:219
static qbool PRVM_IsEdictRelevant(prvm_prog_t *prog, prvm_edict_t *edict)
static qbool PRVM_IsEdictReferenced(prvm_prog_t *prog, prvm_edict_t *edict, int mark)

References Con_DPrintf(), Con_Printf(), DEF_SAVEGLOBAL, ev_entity, prvm_edict_t::free, prvm_prog_t::globaldefs, prvm_edict_private_t::mark, prvm_prog_t::max_edicts, prvm_prog_t::num_edicts, prvm_prog_t::numglobaldefs, mdef_t::ofs, prvm_edict_t::priv, PRVM_EDICT_NUM, PRVM_GetString(), PRVM_GLOBALFIELDEDICT, PRVM_IsEdictReferenced(), PRVM_IsEdictRelevant(), prvm_edict_t::required, mdef_t::s_name, and mdef_t::type.

Referenced by PRVM_LeakTest().

◆ PRVM_MEM_Alloc()

void PRVM_MEM_Alloc ( prvm_prog_t * prog)
static

Definition at line 70 of file prvm_edict.c.

71{
72 int i;
73
74 // reserve space for the null entity aka world
75 // check bound of max_edicts
76 prog->max_edicts = bound(1 + prog->reserved_edicts, prog->max_edicts, prog->limit_edicts);
77 prog->num_edicts = bound(1 + prog->reserved_edicts, prog->num_edicts, prog->max_edicts);
78
79 // edictprivate_size has to be min as big prvm_edict_private_t
81
82 // alloc edicts
83 prog->edicts = (prvm_edict_t *)Mem_Alloc(prog->progs_mempool,prog->limit_edicts * sizeof(prvm_edict_t));
84
85 // alloc edict private space
87
88 // alloc edict fields
89 prog->entityfieldsarea = prog->entityfields * prog->max_edicts;
91
92 // set edict pointers
93 for(i = 0; i < prog->max_edicts; i++)
94 {
95 prog->edicts[i].priv.required = (prvm_edict_private_t *)((unsigned char *)prog->edictprivate + i * prog->edictprivate_size);
96 prog->edicts[i].fields.fp = prog->edictsfields.fp + i * prog->entityfields;
97 }
98}
#define max(A, B)
Definition mathlib.h:38
#define bound(min, num, max)
Definition mathlib.h:34
int entityfieldsarea
LadyHavoc: equal to max_edicts * entityfields (for bounds checking)
Definition progsvm.h:549
void * edictprivate
Definition progsvm.h:686
int edictprivate_size
size of the engine private struct
Definition progsvm.h:689

References bound, prvm_prog_t::edictprivate, prvm_prog_t::edictprivate_size, prvm_prog_t::edicts, prvm_prog_t::edictsfields, prvm_prog_t::entityfields, prvm_prog_t::entityfieldsarea, prvm_edict_t::fields, prvm_edict_t::fp, prvm_prog_t::fp, prvm_prog_t::limit_edicts, max, prvm_prog_t::max_edicts, Mem_Alloc, prvm_prog_t::num_edicts, prvm_edict_t::priv, prvm_prog_t::progs_mempool, prvm_edict_t::required, and prvm_prog_t::reserved_edicts.

Referenced by PRVM_Prog_Load().

◆ PRVM_MEM_IncreaseEdicts()

void PRVM_MEM_IncreaseEdicts ( prvm_prog_t * prog)

Definition at line 105 of file prvm_edict.c.

106{
107 int i;
108
109 if(prog->max_edicts >= prog->limit_edicts)
110 return;
111
112 prog->begin_increase_edicts(prog);
113
114 // increase edicts
115 prog->max_edicts = min(prog->max_edicts + 256, prog->limit_edicts);
116
117 prog->entityfieldsarea = prog->entityfields * prog->max_edicts;
118 prog->edictsfields.fp = (prvm_vec_t*)Mem_Realloc(prog->progs_mempool, (void *)prog->edictsfields.fp, prog->entityfieldsarea * sizeof(prvm_vec_t));
119 prog->edictprivate = (void *)Mem_Realloc(prog->progs_mempool, (void *)prog->edictprivate, prog->max_edicts * prog->edictprivate_size);
120
121 //set e and v pointers
122 for(i = 0; i < prog->max_edicts; i++)
123 {
124 prog->edicts[i].priv.required = (prvm_edict_private_t *)((unsigned char *)prog->edictprivate + i * prog->edictprivate_size);
125 prog->edicts[i].fields.fp = prog->edictsfields.fp + i * prog->entityfields;
126 }
127
128 prog->end_increase_edicts(prog);
129}
void(* begin_increase_edicts)(struct prvm_prog_s *prog)
[INIT] used by PRVM_MEM_Increase_Edicts
Definition progsvm.h:734
void(* end_increase_edicts)(struct prvm_prog_s *prog)
[INIT]
Definition progsvm.h:735
#define Mem_Realloc(pool, data, size)
Definition zone.h:94

References prvm_prog_t::begin_increase_edicts, prvm_prog_t::edictprivate, prvm_prog_t::edictprivate_size, prvm_prog_t::edicts, prvm_prog_t::edictsfields, prvm_prog_t::end_increase_edicts, prvm_prog_t::entityfields, prvm_prog_t::entityfieldsarea, prvm_edict_t::fields, prvm_edict_t::fp, prvm_prog_t::fp, prvm_prog_t::limit_edicts, prvm_prog_t::max_edicts, Mem_Realloc, min, prvm_edict_t::priv, prvm_prog_t::progs_mempool, and prvm_edict_t::required.

Referenced by PRVM_ED_Alloc(), PRVM_ED_ParseEpair(), and SV_Loadgame_f().

◆ PRVM_NewKnownString()

void PRVM_NewKnownString ( prvm_prog_t * prog,
int i,
int flags,
const char * s )
static

Definition at line 3393 of file prvm_edict.c.

3394{
3395 if (i >= prog->numknownstrings)
3396 {
3397 if (i >= prog->maxknownstrings)
3398 {
3399 const char **oldstrings = prog->knownstrings;
3400 const unsigned char *oldstrings_flags = prog->knownstrings_flags;
3401 const char **oldstrings_origin = prog->knownstrings_origin;
3402 prog->maxknownstrings += 128;
3403 prog->knownstrings = (const char **)PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
3404 prog->knownstrings_flags = (unsigned char *)PRVM_Alloc(prog->maxknownstrings * sizeof(unsigned char));
3405 if (prog->leaktest_active)
3406 prog->knownstrings_origin = (const char **)PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
3407 if (prog->numknownstrings)
3408 {
3409 memcpy((char **)prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
3410 memcpy((char **)prog->knownstrings_flags, oldstrings_flags, prog->numknownstrings * sizeof(unsigned char));
3411 if (prog->leaktest_active)
3412 memcpy((char **)prog->knownstrings_origin, oldstrings_origin, prog->numknownstrings * sizeof(char *));
3413 }
3414 }
3415 prog->numknownstrings++;
3416 }
3417 prog->firstfreeknownstring = i + 1;
3418 prog->knownstrings[i] = s;
3419 // it's in use right now, spare it until the next gc pass - that said, it is not freeable so this is probably moot
3420 prog->knownstrings_flags[i] = flags;
3421 if (prog->leaktest_active)
3422 prog->knownstrings_origin[i] = NULL;
3423}
float flags
int maxknownstrings
Definition progsvm.h:586

References prvm_prog_t::firstfreeknownstring, flags, prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_flags, prvm_prog_t::knownstrings_origin, prvm_prog_t::leaktest_active, prvm_prog_t::maxknownstrings, NULL, prvm_prog_t::numknownstrings, and PRVM_Alloc.

Referenced by PRVM_AllocString(), and PRVM_SetEngineString().

◆ PRVM_PO_Destroy()

void PRVM_PO_Destroy ( po_t * po)
static

Definition at line 1931 of file prvm_edict.c.

1932{
1933 int i;
1934 for(i = 0; i < PO_HASHSIZE; ++i)
1935 {
1936 po_string_t *p = po->hashtable[i];
1937 while(p)
1938 {
1939 po_string_t *q = p;
1940 p = p->nextonhashchain;
1941 Mem_Free(q->key);
1942 Mem_Free(q->value);
1943 Mem_Free(q);
1944 }
1945 }
1946 Mem_Free(po);
1947}
#define PO_HASHSIZE
struct po_string_s * nextonhashchain
po_string_t * hashtable[PO_HASHSIZE]

References po_t::hashtable, po_string_t::key, Mem_Free, po_string_t::nextonhashchain, PO_HASHSIZE, and po_string_t::value.

Referenced by PRVM_Prog_Reset().

◆ PRVM_PO_Load()

po_t * PRVM_PO_Load ( const char * filename,
const char * filename2,
mempool_t * pool )
static

Definition at line 1806 of file prvm_edict.c.

1807{
1808 po_t *po = NULL;
1809 const char *p, *q;
1810 int mode;
1811 char inbuf[MAX_INPUTLINE];
1812 char decodedbuf[MAX_INPUTLINE];
1813 size_t decodedpos;
1814 int hashindex;
1815 po_string_t thisstr;
1816 int i;
1817
1818 for (i = 0; i < 2; ++i)
1819 {
1820 const char *buf = (const char *)
1821 FS_LoadFile((i > 0 ? filename : filename2), pool, true, NULL);
1822 // first read filename2, then read filename
1823 // so that progs.dat.de.po wins over common.de.po
1824 // and within file, last item wins
1825
1826 if(!buf)
1827 continue;
1828
1829 if (!po)
1830 {
1831 po = (po_t *)Mem_Alloc(pool, sizeof(*po));
1832 memset(po, 0, sizeof(*po));
1833 }
1834
1835 memset(&thisstr, 0, sizeof(thisstr)); // hush compiler warning
1836
1837 p = buf;
1838 while(*p)
1839 {
1840 if(*p == '#')
1841 {
1842 // skip to newline
1843 p = strchr(p, '\n');
1844 if(!p)
1845 break;
1846 ++p;
1847 continue;
1848 }
1849 if(*p == '\r' || *p == '\n')
1850 {
1851 ++p;
1852 continue;
1853 }
1854 if(!strncmp(p, "msgid \"", 7))
1855 {
1856 mode = 0;
1857 p += 6;
1858 }
1859 else if(!strncmp(p, "msgstr \"", 8))
1860 {
1861 mode = 1;
1862 p += 7;
1863 }
1864 else
1865 {
1866 p = strchr(p, '\n');
1867 if(!p)
1868 break;
1869 ++p;
1870 continue;
1871 }
1872 decodedpos = 0;
1873 while(*p == '"')
1874 {
1875 ++p;
1876 q = strchr(p, '\n');
1877 if(!q)
1878 break;
1879 if(*(q-1) == '\r')
1880 --q;
1881 if(*(q-1) != '"')
1882 break;
1883 if((size_t)(q - p) >= (size_t) sizeof(inbuf))
1884 break;
1885 memcpy(inbuf, p, q - p - 1);
1886 inbuf[q - p - 1] = '\0';
1887 PRVM_PO_ParseString(decodedbuf + decodedpos, inbuf, sizeof(decodedbuf) - decodedpos);
1888 decodedpos += strlen(decodedbuf + decodedpos);
1889 if(*q == '\r')
1890 ++q;
1891 if(*q == '\n')
1892 ++q;
1893 p = q;
1894 }
1895 if(mode == 0)
1896 {
1897 if(thisstr.key)
1898 Mem_Free(thisstr.key);
1899 thisstr.key = (char *)Mem_Alloc(pool, decodedpos + 1);
1900 memcpy(thisstr.key, decodedbuf, decodedpos + 1);
1901 }
1902 else if(decodedpos > 0 && thisstr.key) // skip empty translation results
1903 {
1904 thisstr.value = (char *)Mem_Alloc(pool, decodedpos + 1);
1905 memcpy(thisstr.value, decodedbuf, decodedpos + 1);
1906 hashindex = CRC_Block((const unsigned char *) thisstr.key, strlen(thisstr.key)) % PO_HASHSIZE;
1907 thisstr.nextonhashchain = po->hashtable[hashindex];
1908 po->hashtable[hashindex] = (po_string_t *)Mem_Alloc(pool, sizeof(thisstr));
1909 memcpy(po->hashtable[hashindex], &thisstr, sizeof(thisstr));
1910 memset(&thisstr, 0, sizeof(thisstr));
1911 }
1912 }
1913
1914 Mem_Free((char *) buf);
1915 }
1916
1917 return po;
1918}
unsigned short CRC_Block(const unsigned char *data, size_t size)
Definition com_crc16.c:75
GLenum mode
Definition glquake.h:718
static void PRVM_PO_ParseString(char *out, const char *in, size_t outsize)

References buf, CRC_Block(), FS_LoadFile(), po_t::hashtable, po_string_t::key, MAX_INPUTLINE, Mem_Alloc, Mem_Free, mode, po_string_t::nextonhashchain, NULL, PO_HASHSIZE, PRVM_PO_ParseString(), strlen(), and po_string_t::value.

Referenced by PRVM_Prog_Load().

◆ PRVM_PO_Lookup()

const char * PRVM_PO_Lookup ( po_t * po,
const char * str )
static

Definition at line 1919 of file prvm_edict.c.

1920{
1921 int hashindex = CRC_Block((const unsigned char *) str, strlen(str)) % PO_HASHSIZE;
1922 po_string_t *p = po->hashtable[hashindex];
1923 while(p)
1924 {
1925 if(!strcmp(str, p->key))
1926 return p->value;
1927 p = p->nextonhashchain;
1928 }
1929 return NULL;
1930}

References CRC_Block(), po_t::hashtable, po_string_t::key, po_string_t::nextonhashchain, NULL, PO_HASHSIZE, strlen(), and po_string_t::value.

Referenced by PRVM_Prog_Load().

◆ PRVM_PO_ParseString()

void PRVM_PO_ParseString ( char * out,
const char * in,
size_t outsize )
static

Definition at line 1747 of file prvm_edict.c.

1748{
1749 for(;;)
1750 {
1751 switch(*in)
1752 {
1753 case 0:
1754 *out++ = 0;
1755 return;
1756 case '\\':
1757 ++in;
1758 switch(*in)
1759 {
1760 case 'a': if(outsize > 0) { *out++ = '\a'; --outsize; } break;
1761 case 'b': if(outsize > 0) { *out++ = '\b'; --outsize; } break;
1762 case 't': if(outsize > 0) { *out++ = '\t'; --outsize; } break;
1763 case 'r': if(outsize > 0) { *out++ = '\r'; --outsize; } break;
1764 case 'n': if(outsize > 0) { *out++ = '\n'; --outsize; } break;
1765 case '\\': if(outsize > 0) { *out++ = '\\'; --outsize; } break;
1766 case '"': if(outsize > 0) { *out++ = '"'; --outsize; } break;
1767 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
1768 if(outsize > 0)
1769 *out = *in - '0';
1770 ++in;
1771 if(*in >= '0' && *in <= '7')
1772 {
1773 if(outsize > 0)
1774 *out = (*out << 3) | (*in - '0');
1775 ++in;
1776 }
1777 if(*in >= '0' && *in <= '7')
1778 {
1779 if(outsize > 0)
1780 *out = (*out << 3) | (*in - '0');
1781 ++in;
1782 }
1783 --in;
1784 if(outsize > 0)
1785 {
1786 ++out;
1787 --outsize;
1788 }
1789 break;
1790 default:
1791 if(outsize > 0) { *out++ = *in; --outsize; }
1792 break;
1793 }
1794 break;
1795 default:
1796 if(outsize > 0)
1797 {
1798 *out++ = *in;
1799 --outsize;
1800 }
1801 break;
1802 }
1803 ++in;
1804 }
1805}

Referenced by PRVM_PO_Load().

◆ PRVM_PO_UnparseString()

void PRVM_PO_UnparseString ( char * out,
const char * in,
size_t outsize )
static

Definition at line 1706 of file prvm_edict.c.

1707{
1708 for(;;)
1709 {
1710 switch(*in)
1711 {
1712 case 0:
1713 *out++ = 0;
1714 return;
1715 case '\a': if(outsize >= 2) { *out++ = '\\'; *out++ = 'a'; outsize -= 2; } break;
1716 case '\b': if(outsize >= 2) { *out++ = '\\'; *out++ = 'b'; outsize -= 2; } break;
1717 case '\t': if(outsize >= 2) { *out++ = '\\'; *out++ = 't'; outsize -= 2; } break;
1718 case '\r': if(outsize >= 2) { *out++ = '\\'; *out++ = 'r'; outsize -= 2; } break;
1719 case '\n': if(outsize >= 2) { *out++ = '\\'; *out++ = 'n'; outsize -= 2; } break;
1720 case '\\': if(outsize >= 2) { *out++ = '\\'; *out++ = '\\'; outsize -= 2; } break;
1721 case '"': if(outsize >= 2) { *out++ = '\\'; *out++ = '"'; outsize -= 2; } break;
1722 default:
1723 if(*in >= 0 && *in <= 0x1F)
1724 {
1725 if(outsize >= 4)
1726 {
1727 *out++ = '\\';
1728 *out++ = '0' + ((*in & 0700) >> 6);
1729 *out++ = '0' + ((*in & 0070) >> 3);
1730 *out++ = '0' + (*in & 0007) ;
1731 outsize -= 4;
1732 }
1733 }
1734 else
1735 {
1736 if(outsize >= 1)
1737 {
1738 *out++ = *in;
1739 outsize -= 1;
1740 }
1741 }
1742 break;
1743 }
1744 ++in;
1745 }
1746}

Referenced by PRVM_Prog_Load().

◆ PRVM_Prog_Init()

void PRVM_Prog_Init ( prvm_prog_t * prog,
cmd_state_t * cmd )

Definition at line 3302 of file prvm_edict.c.

3303{
3304 PRVM_Prog_Reset(prog);
3305 prog->leaktest_active = prvm_leaktest.integer != 0;
3306 prog->console_cmd = cmd;
3307}
void PRVM_Prog_Reset(prvm_prog_t *prog)
struct cmd_state_s * console_cmd
points to the relevant console command interpreter for this vm (cmd_local or &cmd_server),...
Definition progsvm.h:641

References cmd(), prvm_prog_t::console_cmd, prvm_prog_t::leaktest_active, prvm_leaktest, and PRVM_Prog_Reset().

◆ PRVM_Prog_Load()

void PRVM_Prog_Load ( prvm_prog_t * prog,
const char * filename,
unsigned char * data,
fs_offset_t size,
void CheckRequiredFuncsprvm_prog_t *prog, const char *filename,
int numrequiredfields,
prvm_required_field_t * required_field,
int numrequiredglobals,
prvm_required_field_t * required_global )

Definition at line 2030 of file prvm_edict.c.

2031{
2032 int i;
2033 dprograms_t *dprograms;
2034
2035 dstatement16_t *instatements16;
2036 dstatement32_t *instatements32;
2037 ddef16_t *infielddefs16;
2038 ddef32_t *infielddefs32;
2039 ddef16_t *inglobaldefs16;
2040 ddef32_t *inglobaldefs32;
2041
2042 int *inglobals;
2043 dfunction_t *infunctions;
2044 char *instrings;
2045 fs_offset_t filesize;
2046 int requiredglobalspace;
2047 opcode_t op;
2048 int a;
2049 int b;
2050 int c;
2051 union
2052 {
2053 unsigned int i;
2054 float f;
2055 }
2056 u;
2057 unsigned int d;
2058 char vabuf[1024];
2059 char vabuf2[1024];
2060 cvar_t *cvar;
2061 int structtype = 0;
2062 int max_safe_edicts;
2063 bool gaddress_warned = false;
2064
2065 if (prog->loaded)
2066 prog->error_cmd("%s: there is already a %s program loaded!", __func__, prog->name);
2067
2068 Host_LockSession(); // all progs can use the session cvar
2069 Crypto_LoadKeys(); // all progs might use the keys at init time
2070
2071 if (data)
2072 {
2073 dprograms = (dprograms_t *) data;
2074 filesize = size;
2075 }
2076 else
2077 dprograms = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false, &filesize);
2078 if (dprograms == NULL || filesize < (fs_offset_t)sizeof(dprograms_t))
2079 prog->error_cmd("%s: couldn't load \"%s\" for %s", __func__, filename, prog->name);
2080 // TODO bounds check header fields (e.g. numstatements), they must never go behind end of file
2081
2082 prog->profiletime = Sys_DirtyTime();
2083 prog->starttime = host.realtime;
2084
2085 requiredglobalspace = 0;
2086 for (i = 0;i < numrequiredglobals;i++)
2087 requiredglobalspace += required_global[i].type == ev_vector ? 3 : 1;
2088
2089 prog->filecrc = CRC_Block((unsigned char *)dprograms, filesize);
2090
2091// byte swap the header
2092 prog->progs_version = LittleLong(dprograms->version);
2093 prog->progs_crc = LittleLong(dprograms->crc);
2094 if (prog->progs_version == 7)
2095 {
2096 dprograms_v7_t *v7 = (dprograms_v7_t*)dprograms;
2097 structtype = LittleLong(v7->secondaryversion);
2098 if (structtype == PROG_SECONDARYVERSION16 ||
2099 structtype == PROG_SECONDARYVERSION32) // barely supported
2100 Con_Printf(CON_WARN "WARNING: %s: %s targets FTEQW, for which support is incomplete. Proceed at your own risk.\n", prog->name, filename);
2101 else
2102 prog->error_cmd("%s: %s targets unknown engine", prog->name, filename);
2103
2104 if (v7->numbodylessfuncs != 0 || v7->numtypes != 0 || v7->blockscompressed != 0)
2105 prog->error_cmd("%s: %s uses unsupported features.", prog->name, filename);
2106 }
2107 else if (prog->progs_version != PROG_VERSION)
2108 prog->error_cmd("%s: %s has wrong version number (%i should be %i)", prog->name, filename, prog->progs_version, PROG_VERSION);
2109 instatements16 = (dstatement16_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_statements));
2110 instatements32 = (dstatement32_t *)instatements16;
2111 prog->progs_numstatements = LittleLong(dprograms->numstatements);
2112 inglobaldefs16 = (ddef16_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_globaldefs));
2113 inglobaldefs32 = (ddef32_t *)inglobaldefs16;
2114 prog->progs_numglobaldefs = LittleLong(dprograms->numglobaldefs);
2115 infielddefs16 = (ddef16_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_fielddefs));
2116 infielddefs32 = (ddef32_t *)infielddefs16;
2117 prog->progs_numfielddefs = LittleLong(dprograms->numfielddefs);
2118 infunctions = (dfunction_t *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_functions));
2119 prog->progs_numfunctions = LittleLong(dprograms->numfunctions);
2120 instrings = (char *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_strings));
2121 prog->progs_numstrings = LittleLong(dprograms->numstrings);
2122 inglobals = (int *)((unsigned char *)dprograms + LittleLong(dprograms->ofs_globals));
2123 prog->progs_numglobals = LittleLong(dprograms->numglobals);
2124 prog->progs_entityfields = LittleLong(dprograms->entityfields);
2125
2126 prog->numstatements = prog->progs_numstatements;
2127 prog->numglobaldefs = prog->progs_numglobaldefs;
2128 prog->numfielddefs = prog->progs_numfielddefs;
2129 prog->numfunctions = prog->progs_numfunctions;
2130 prog->numstrings = prog->progs_numstrings;
2131 prog->numglobals = prog->progs_numglobals;
2132 prog->entityfields = prog->progs_entityfields;
2133
2134 if (LittleLong(dprograms->ofs_strings) + prog->progs_numstrings > (int)filesize)
2135 prog->error_cmd("%s: %s strings go past end of file", prog->name, filename);
2136 prog->strings = (char *)Mem_Alloc(prog->progs_mempool, prog->progs_numstrings);
2137 memcpy(prog->strings, instrings, prog->progs_numstrings);
2138 prog->stringssize = prog->progs_numstrings;
2139
2140 prog->numknownstrings = 0;
2141 prog->maxknownstrings = 0;
2142 prog->knownstrings = NULL;
2143 prog->knownstrings_flags = NULL;
2144
2146
2147 // we need to expand the globaldefs and fielddefs to include engine defs
2148 prog->globaldefs = (mdef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobaldefs + numrequiredglobals) * sizeof(mdef_t));
2149 prog->globals.fp = (prvm_vec_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numglobals + requiredglobalspace + 2) * sizeof(prvm_vec_t));
2150 // + 2 is because of an otherwise occurring overrun in RETURN instruction
2151 // when trying to return the last or second-last global
2152 // (RETURN always returns a vector, there is no RETURN_F instruction)
2153 prog->fielddefs = (mdef_t *)Mem_Alloc(prog->progs_mempool, (prog->progs_numfielddefs + numrequiredfields) * sizeof(mdef_t));
2154 // we need to convert the statements to our memory format
2156 // allocate space for profiling statement usage
2157 prog->statement_profile = (double *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof(*prog->statement_profile));
2158 prog->explicit_profile = (double *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof(*prog->statement_profile));
2159 // functions need to be converted to the memory format
2161
2162 for (i = 0;i < prog->progs_numfunctions;i++)
2163 {
2164 prog->functions[i].first_statement = LittleLong(infunctions[i].first_statement);
2165 prog->functions[i].parm_start = LittleLong(infunctions[i].parm_start);
2166 prog->functions[i].s_name = LittleLong(infunctions[i].s_name);
2167 prog->functions[i].s_file = LittleLong(infunctions[i].s_file);
2168 prog->functions[i].numparms = LittleLong(infunctions[i].numparms);
2169 prog->functions[i].locals = LittleLong(infunctions[i].locals);
2170 memcpy(prog->functions[i].parm_size, infunctions[i].parm_size, sizeof(infunctions[i].parm_size));
2171 if(prog->functions[i].first_statement >= prog->numstatements)
2172 prog->error_cmd("%s: out of bounds function statement (function %d) in %s", __func__, i, prog->name);
2173 // TODO bounds check parm_start, s_name, s_file, numparms, locals, parm_size
2174 }
2175
2176 // copy the globaldefs to the new globaldefs list
2177 switch(structtype)
2178 {
2180 for (i=0 ; i<prog->numglobaldefs ; i++)
2181 {
2182 prog->globaldefs[i].type = LittleLong(inglobaldefs32[i].type);
2183 prog->globaldefs[i].ofs = LittleLong(inglobaldefs32[i].ofs);
2184 prog->globaldefs[i].s_name = LittleLong(inglobaldefs32[i].s_name);
2185 // TODO bounds check ofs, s_name
2186 }
2187 break;
2188 default:
2189 for (i=0 ; i<prog->numglobaldefs ; i++)
2190 {
2191 prog->globaldefs[i].type = (unsigned short)LittleShort(inglobaldefs16[i].type);
2192 prog->globaldefs[i].ofs = (unsigned short)LittleShort(inglobaldefs16[i].ofs);
2193 prog->globaldefs[i].s_name = LittleLong(inglobaldefs16[i].s_name);
2194 // TODO bounds check ofs, s_name
2195 }
2196 break;
2197 }
2198
2199 // append the required globals
2200 for (i = 0;i < numrequiredglobals;i++)
2201 {
2202 prog->globaldefs[prog->numglobaldefs].type = required_global[i].type;
2203 prog->globaldefs[prog->numglobaldefs].ofs = prog->numglobals;
2204 prog->globaldefs[prog->numglobaldefs].s_name = PRVM_SetEngineString(prog, required_global[i].name);
2205 if (prog->globaldefs[prog->numglobaldefs].type == ev_vector)
2206 prog->numglobals += 3;
2207 else
2208 prog->numglobals++;
2209 prog->numglobaldefs++;
2210 }
2211
2212 // copy the progs fields to the new fields list
2213 switch(structtype)
2214 {
2216 for (i = 0;i < prog->numfielddefs;i++)
2217 {
2218 prog->fielddefs[i].type = LittleLong(infielddefs32[i].type);
2219 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
2220 prog->error_cmd("%s: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", __func__, prog->name);
2221 prog->fielddefs[i].ofs = LittleLong(infielddefs32[i].ofs);
2222 prog->fielddefs[i].s_name = LittleLong(infielddefs32[i].s_name);
2223 // TODO bounds check ofs, s_name
2224 }
2225 break;
2226 default:
2227 for (i = 0;i < prog->numfielddefs;i++)
2228 {
2229 prog->fielddefs[i].type = (unsigned short)LittleShort(infielddefs16[i].type);
2230 if (prog->fielddefs[i].type & DEF_SAVEGLOBAL)
2231 prog->error_cmd("%s: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", __func__, prog->name);
2232 prog->fielddefs[i].ofs = (unsigned short)LittleShort(infielddefs16[i].ofs);
2233 prog->fielddefs[i].s_name = LittleLong(infielddefs16[i].s_name);
2234 // TODO bounds check ofs, s_name
2235 }
2236 break;
2237 }
2238
2239 // append the required fields
2240 for (i = 0;i < numrequiredfields;i++)
2241 {
2242 prog->fielddefs[prog->numfielddefs].type = required_field[i].type;
2243 prog->fielddefs[prog->numfielddefs].ofs = prog->entityfields;
2244 prog->fielddefs[prog->numfielddefs].s_name = PRVM_SetEngineString(prog, required_field[i].name);
2245 if (prog->fielddefs[prog->numfielddefs].type == ev_vector)
2246 prog->entityfields += 3;
2247 else
2248 prog->entityfields++;
2249 prog->numfielddefs++;
2250 }
2251
2252 // LadyHavoc: TODO: reorder globals to match engine struct
2253 // LadyHavoc: TODO: reorder fields to match engine struct
2254 // divVerent: note that when ever doing any remapping, globaldefs with pre-initialized global pointers need to also be identified and remapped
2255#define remapglobal(index) (index)
2256#define remapfield(index) (index)
2257
2258 // copy globals
2259 // FIXME: LadyHavoc: this uses a crude way to identify integer constants, rather than checking for matching globaldefs and checking their type
2260 for (i = 0;i < prog->progs_numglobals;i++)
2261 {
2262 u.i = LittleLong(inglobals[i]);
2263 // most globals are 0, we only need to deal with the ones that are not
2264 if (u.i)
2265 {
2266 d = u.i & 0xFF800000;
2267 if ((d == 0xFF800000) || (d == 0))
2268 {
2269 // Looks like an integer (expand to int64)
2270 prog->globals.ip[remapglobal(i)] = u.i;
2271 }
2272 else
2273 {
2274 // Looks like a float (expand to double)
2275 prog->globals.fp[remapglobal(i)] = u.f;
2276 }
2277 }
2278 }
2279
2280 // copy, remap globals in statements, bounds check
2281 for (i = 0;i < prog->progs_numstatements;i++)
2282 {
2283 switch(structtype)
2284 {
2286 op = (opcode_t)LittleLong(instatements32[i].op);
2287 a = (unsigned int)LittleLong(instatements32[i].a);
2288 b = (unsigned int)LittleLong(instatements32[i].b);
2289 c = (unsigned int)LittleLong(instatements32[i].c);
2290 break;
2291 default:
2292 op = (opcode_t)LittleShort(instatements16[i].op);
2293 a = (unsigned short)LittleShort(instatements16[i].a);
2294 b = (unsigned short)LittleShort(instatements16[i].b);
2295 c = (unsigned short)LittleShort(instatements16[i].c);
2296 break;
2297 }
2298 switch (op)
2299 {
2300 case OP_IF:
2301 case OP_IFNOT:
2302 b = (short)b;
2303 if (a >= prog->progs_numglobals || b + i < 0 || b + i >= prog->progs_numstatements)
2304 prog->error_cmd("%s: out of bounds IF/IFNOT (statement %d) in %s", __func__, i, prog->name);
2305 if (c)
2306 Con_DPrintf("%s: unexpected offset on binary opcode in %s\n", __func__, prog->name);
2307 prog->statements[i].op = op;
2308 prog->statements[i].operand[0] = remapglobal(a);
2309 prog->statements[i].operand[1] = b;
2310 prog->statements[i].operand[2] = -1;
2311 break;
2312 case OP_GOTO:
2313 a = (short)a;
2314 if (a + i < 0 || a + i >= prog->progs_numstatements)
2315 prog->error_cmd("%s: out of bounds GOTO (statement %d) in %s", __func__, i, prog->name);
2316 if (b || c)
2317 Con_DPrintf("%s: unexpected offset on unary opcode in %s\n", __func__, prog->name);
2318 prog->statements[i].op = op;
2319 prog->statements[i].operand[0] = a;
2320 prog->statements[i].operand[1] = -1;
2321 prog->statements[i].operand[2] = -1;
2322 break;
2323 default:
2324 Con_DPrintf("%s: unknown opcode %d at statement %d in %s\n", __func__, (int)op, i, prog->name);
2325
2326 //make sure its something well defined.
2327 prog->statements[i].op = OP_BOUNDCHECK;
2328 prog->statements[i].operand[0] = 0;
2329 prog->statements[i].operand[1] =
2330 prog->statements[i].operand[2] = op;
2331 break;
2332 // global global global
2333 case OP_ADD_I:
2334 case OP_ADD_FI:
2335 case OP_ADD_IF:
2336 case OP_SUB_I:
2337 case OP_SUB_FI:
2338 case OP_SUB_IF:
2339 case OP_CONV_ITOF:
2340 case OP_CONV_FTOI:
2341 case OP_LOAD_I:
2342 case OP_BITAND_I:
2343 case OP_BITOR_I:
2344 case OP_MUL_I:
2345 case OP_DIV_I:
2346 case OP_EQ_I:
2347 case OP_NE_I:
2348 case OP_NOT_I:
2349 case OP_DIV_VF:
2350 case OP_LE_I:
2351 case OP_GE_I:
2352 case OP_LT_I:
2353 case OP_GT_I:
2354 case OP_LE_IF:
2355 case OP_GE_IF:
2356 case OP_LT_IF:
2357 case OP_GT_IF:
2358 case OP_LE_FI:
2359 case OP_GE_FI:
2360 case OP_LT_FI:
2361 case OP_GT_FI:
2362 case OP_EQ_IF:
2363 case OP_EQ_FI:
2364 case OP_MUL_IF:
2365 case OP_MUL_FI:
2366 case OP_MUL_VI:
2367 case OP_DIV_IF:
2368 case OP_DIV_FI:
2369 case OP_BITAND_IF:
2370 case OP_BITOR_IF:
2371 case OP_BITAND_FI:
2372 case OP_BITOR_FI:
2373 case OP_AND_I:
2374 case OP_OR_I:
2375 case OP_AND_IF:
2376 case OP_OR_IF:
2377 case OP_AND_FI:
2378 case OP_OR_FI:
2379 case OP_NE_IF:
2380 case OP_NE_FI:
2381 case OP_GSTOREP_I:
2382 case OP_GSTOREP_F:
2383 case OP_GSTOREP_ENT:
2384 case OP_GSTOREP_FLD:
2385 case OP_GSTOREP_S:
2386 case OP_GSTOREP_FNC:
2387 case OP_GSTOREP_V:
2388// case OP_GADDRESS:
2389 case OP_GLOAD_I:
2390 case OP_GLOAD_F:
2391 case OP_GLOAD_FLD:
2392 case OP_GLOAD_ENT:
2393 case OP_GLOAD_S:
2394 case OP_GLOAD_FNC:
2395 case OP_BOUNDCHECK:
2396 case OP_GLOAD_V:
2397 case OP_ADD_F:
2398 case OP_ADD_V:
2399 case OP_SUB_F:
2400 case OP_SUB_V:
2401 case OP_MUL_F:
2402 case OP_MUL_V:
2403 case OP_MUL_FV:
2404 case OP_MUL_VF:
2405 case OP_DIV_F:
2406 case OP_BITAND_F:
2407 case OP_BITOR_F:
2408 case OP_GE_F:
2409 case OP_LE_F:
2410 case OP_GT_F:
2411 case OP_LT_F:
2412 case OP_AND_F:
2413 case OP_OR_F:
2414 case OP_EQ_F:
2415 case OP_EQ_V:
2416 case OP_EQ_S:
2417 case OP_EQ_E:
2418 case OP_EQ_FNC:
2419 case OP_NE_F:
2420 case OP_NE_V:
2421 case OP_NE_S:
2422 case OP_NE_E:
2423 case OP_NE_FNC:
2424 case OP_ADDRESS:
2425 case OP_LOAD_F:
2426 case OP_LOAD_FLD:
2427 case OP_LOAD_ENT:
2428 case OP_LOAD_S:
2429 case OP_LOAD_FNC:
2430 case OP_LOAD_V:
2431 case OP_LOAD_P:
2432 case OP_ADD_PIW:
2433 case OP_GLOBALADDRESS:
2434 case OP_LOADA_F:
2435 case OP_LOADA_V:
2436 case OP_LOADA_S:
2437 case OP_LOADA_ENT:
2438 case OP_LOADA_FLD:
2439 case OP_LOADA_FNC:
2440 case OP_LOADA_I:
2441 case OP_LOADP_F:
2442 case OP_LOADP_V:
2443 case OP_LOADP_S:
2444 case OP_LOADP_ENT:
2445 case OP_LOADP_FLD:
2446 case OP_LOADP_FNC:
2447 case OP_LOADP_I:
2448 case OP_STOREP_F:
2449 case OP_STOREP_ENT:
2450 case OP_STOREP_FLD:
2451 case OP_STOREP_S:
2452 case OP_STOREP_FNC:
2453 case OP_STOREP_V:
2454 case OP_STOREP_I:
2455 case OP_RSHIFT_I:
2456 case OP_LSHIFT_I:
2457 case OP_LE_U:
2458 case OP_LT_U:
2459 case OP_DIV_U:
2460 case OP_RSHIFT_U:
2461 if (a >= prog->progs_numglobals || b >= prog->progs_numglobals || c >= prog->progs_numglobals)
2462 prog->error_cmd("%s: out of bounds global index (statement %d)", __func__, i);
2463 prog->statements[i].op = op;
2464 prog->statements[i].operand[0] = remapglobal(a);
2465 prog->statements[i].operand[1] = remapglobal(b);
2466 prog->statements[i].operand[2] = remapglobal(c);
2467 break;
2468 // global none global
2469 case OP_NOT_F:
2470 case OP_NOT_V:
2471 case OP_NOT_S:
2472 case OP_NOT_FNC:
2473 case OP_NOT_ENT:
2474 if (a >= prog->progs_numglobals || c >= prog->progs_numglobals)
2475 prog->error_cmd("%s: out of bounds global index (statement %d) in %s", __func__, i, prog->name);
2476 if (b)
2477 Con_DPrintf("%s: unexpected offset on binary opcode in %s\n", __func__, prog->name);
2478 prog->statements[i].op = op;
2479 prog->statements[i].operand[0] = remapglobal(a);
2480 prog->statements[i].operand[1] = -1;
2481 prog->statements[i].operand[2] = remapglobal(c);
2482 break;
2483 // global global none
2484 case OP_STORE_F:
2485 case OP_STORE_ENT:
2486 case OP_STORE_FLD:
2487 case OP_STORE_S:
2488 case OP_STORE_FNC:
2489 case OP_STORE_V:
2490 case OP_STORE_I:
2491 case OP_STORE_P:
2492 case OP_STATE:
2493 if (a >= prog->progs_numglobals || b >= prog->progs_numglobals)
2494 prog->error_cmd("%s: out of bounds global index (statement %d) in %s", __func__, i, prog->name);
2495 if (c)
2496 Con_DPrintf("%s: unexpected offset on binary opcode in %s\n", __func__, prog->name);
2497 prog->statements[i].op = op;
2498 prog->statements[i].operand[0] = remapglobal(a);
2499 prog->statements[i].operand[1] = remapglobal(b);
2500 prog->statements[i].operand[2] = -1;
2501 break;
2502 // 1 global
2503 case OP_CALL0:
2504 if ( a < prog->progs_numglobals)
2505 if ( prog->globals.ip[remapglobal(a)] >= 0 )
2506 if ( prog->globals.ip[remapglobal(a)] < prog->progs_numfunctions )
2507 if ( prog->functions[prog->globals.ip[remapglobal(a)]].first_statement == -642 )
2509 case OP_CALL1:
2510 case OP_CALL2:
2511 case OP_CALL3:
2512 case OP_CALL4:
2513 case OP_CALL5:
2514 case OP_CALL6:
2515 case OP_CALL7:
2516 case OP_CALL8:
2517 case OP_DONE:
2518 case OP_RETURN:
2519 if ( a >= prog->progs_numglobals)
2520 prog->error_cmd("%s: out of bounds global index (statement %d) in %s", __func__, i, prog->name);
2521 if (b || c) //Spike -- added this check just as a diagnostic...
2522 Con_DPrintf("%s: unexpected offset on call opcode in %s. Hexen2 format is not supported\n", __func__, prog->name);
2523 prog->statements[i].op = op;
2524 prog->statements[i].operand[0] = remapglobal(a);
2525 prog->statements[i].operand[1] = -1;
2526 prog->statements[i].operand[2] = -1;
2527 break;
2528 }
2529
2530 // Warn about deprecated instructions.
2531 switch (op)
2532 {
2533 case OP_GSTOREP_I:
2534 case OP_GSTOREP_F:
2535 case OP_GSTOREP_ENT:
2536 case OP_GSTOREP_FLD:
2537 case OP_GSTOREP_S:
2538 case OP_GSTOREP_FNC:
2539 case OP_GSTOREP_V:
2540 //case OP_GADDRESS:
2541 case OP_GLOAD_I:
2542 case OP_GLOAD_F:
2543 case OP_GLOAD_FLD:
2544 case OP_GLOAD_ENT:
2545 case OP_GLOAD_S:
2546 case OP_GLOAD_FNC:
2547 case OP_GLOAD_V:
2548 if (!gaddress_warned) {
2549 Con_Printf(CON_WARN "WARNING: %s: %s uses deprecated OP_G* instructions, which are unlikely to be used correctly. Proceed at your own risk.\n", prog->name, filename);
2550 gaddress_warned = true;
2551 }
2552 break;
2553 default:
2554 break;
2555 }
2556 }
2557 if(prog->numstatements < 1)
2558 {
2559 prog->error_cmd("%s: empty program in %s", __func__, prog->name);
2560 }
2561 else switch(prog->statements[prog->numstatements - 1].op)
2562 {
2563 case OP_RETURN:
2564 case OP_GOTO:
2565 case OP_DONE:
2566 break;
2567 default:
2568 prog->error_cmd("%s: program may fall off the edge (does not end with RETURN, GOTO or DONE) in %s", __func__, prog->name);
2569 break;
2570 }
2571
2572 // we're done with the file now
2573 if(!data)
2574 Mem_Free(dprograms);
2575 dprograms = NULL;
2576
2577 prog->flag = 0;
2578 // expected to not return (call prog->error_cmd) if checks fail
2579 CheckRequiredFuncs(prog, filename);
2580
2581 PRVM_LoadLNO(prog, filename);
2582
2583 PRVM_Init_Exec(prog);
2584
2585 if(*prvm_language.string)
2586 // in CSQC we really shouldn't be able to change how stuff works... sorry for now
2587 // later idea: include a list of authorized .po file checksums with the csprogs
2588 {
2589 qbool deftrans = prog == CLVM_prog;
2590 const char *realfilename = (prog != CLVM_prog ? filename : csqc_progname.string);
2591 if(deftrans) // once we have dotranslate_ strings, ALWAYS use the opt-in method!
2592 {
2593 for (i=0 ; i<prog->numglobaldefs ; i++)
2594 {
2595 const char *name;
2596 name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
2597 if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
2598 if(name && !strncmp(name, "dotranslate_", 12))
2599 {
2600 deftrans = false;
2601 break;
2602 }
2603 }
2604 }
2605 if(!strcmp(prvm_language.string, "dump"))
2606 {
2607 qfile_t *f = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.pot", realfilename), "w", false);
2608 Con_Printf("Dumping to %s.pot\n", realfilename);
2609 if(f)
2610 {
2611 for (i=0 ; i<prog->numglobaldefs ; i++)
2612 {
2613 const char *name;
2614 name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
2615 if(deftrans ? (!name || strncmp(name, "notranslate_", 12)) : (name && !strncmp(name, "dotranslate_", 12)))
2616 if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
2617 {
2619 const char *value = PRVM_GetString(prog, val->string);
2620 if(*value)
2621 {
2622 char buf[MAX_INPUTLINE];
2624 FS_Printf(f, "msgid \"%s\"\nmsgstr \"\"\n\n", buf);
2625 }
2626 }
2627 }
2628 FS_Close(f);
2629 }
2630 }
2631 else
2632 {
2633 po_t *po = PRVM_PO_Load(
2634 va(vabuf, sizeof(vabuf), "%s.%s.po", realfilename, prvm_language.string),
2635 va(vabuf2, sizeof(vabuf2), "common.%s.po", prvm_language.string),
2636 prog->progs_mempool);
2637 if(po)
2638 {
2639 for (i=0 ; i<prog->numglobaldefs ; i++)
2640 {
2641 const char *name;
2642 name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
2643 if(deftrans ? (!name || strncmp(name, "notranslate_", 12)) : (name && !strncmp(name, "dotranslate_", 12)))
2644 if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
2645 {
2647 const char *value = PRVM_GetString(prog, val->string);
2648 if(*value)
2649 {
2650 value = PRVM_PO_Lookup(po, value);
2651 if(value)
2652 val->string = PRVM_SetEngineString(prog, value);
2653 }
2654 }
2655 }
2656 }
2657 }
2658 }
2659
2660 for (cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next)
2661 cvar->globaldefindex[prog - prvm_prog_list] = -1;
2662
2663 for (i=0 ; i<prog->numglobaldefs ; i++)
2664 {
2665 const char *name;
2666 name = PRVM_GetString(prog, prog->globaldefs[i].s_name);
2667 //Con_Printf("found var %s\n", name);
2668 if(name
2669 && !strncmp(name, "autocvar_", 9)
2670 && !(strlen(name) > 1 && name[strlen(name)-2] == '_' && (name[strlen(name)-1] == 'x' || name[strlen(name)-1] == 'y' || name[strlen(name)-1] == 'z'))
2671 )
2672 {
2674 cvar = Cvar_FindVar(prog->console_cmd->cvars, name + 9, prog->console_cmd->cvars_flagsmask);
2675 //Con_Printf("%s: autocvar global %s in %s, processing...\n", __func__, name, prog->name);
2676 if(!cvar)
2677 {
2678 const char *value;
2679 char buf[128];
2680 int prec[3];
2681 float f;
2682 Con_DPrintf("%s: no cvar for autocvar global %s in %s, creating...\n", __func__, name, prog->name);
2683 switch(prog->globaldefs[i].type & ~DEF_SAVEGLOBAL)
2684 {
2685 case ev_float:
2686 if((float)((int)(val->_float)) == val->_float)
2687 dpsnprintf(buf, sizeof(buf), "%i", (int)(val->_float));
2688 else
2689 {
2690 // ftos_slow
2691 f = val->_float;
2692 for (int precision = 7; precision <= 9; ++precision) {
2693 dpsnprintf(buf, sizeof(buf), "%.*g", precision, f);
2694 if ((float)atof(buf) == f) {
2695 break;
2696 }
2697 }
2698 }
2699 value = buf;
2700 break;
2701 case ev_vector:
2702 for (i = 0; i < 3; ++i)
2703 {
2704 prec[i] = 9;
2705 f = val->vector[i];
2706 for (int precision = 7; precision <= 9; ++precision) {
2707 dpsnprintf(buf, sizeof(buf), "%.*g", precision, f);
2708 if ((float)atof(buf) == f) {
2709 prec[i] = precision;
2710 break;
2711 }
2712 }
2713 }
2714 dpsnprintf(buf, sizeof(buf), "%.*g %.*g %.*g", prec[0], val->vector[0], prec[1], val->vector[1], prec[2], val->vector[2]);
2715 value = buf;
2716 break;
2717 case ev_string:
2718 value = PRVM_GetString(prog, val->string);
2719 break;
2720 default:
2721 Con_Printf("%s: invalid type of autocvar global %s in %s\n", __func__, name, prog->name);
2722 goto fail;
2723 }
2724 cvar = Cvar_Get(prog->console_cmd->cvars, name + 9, value, prog->console_cmd->cvars_flagsmask, NULL);
2725 if((prog->globaldefs[i].type & ~DEF_SAVEGLOBAL) == ev_string)
2726 {
2727 val->string = PRVM_SetEngineString(prog, cvar->string);
2728 cvar->globaldefindex_stringno[prog - prvm_prog_list] = val->string;
2729 }
2730 if(!cvar)
2731 prog->error_cmd("%s: could not create cvar for autocvar global %s in %s", __func__, name, prog->name);
2732 cvar->globaldefindex[prog - prvm_prog_list] = i;
2733 }
2734 else if((cvar->flags & CF_PRIVATE) == 0)
2735 {
2736 // MUST BE SYNCED WITH cvar.c Cvar_Set
2737 int j;
2738 const char *s;
2739 switch(prog->globaldefs[i].type & ~DEF_SAVEGLOBAL)
2740 {
2741 case ev_float:
2742 val->_float = cvar->value;
2743 break;
2744 case ev_vector:
2745 s = cvar->string;
2746 VectorClear(val->vector);
2747 for (j = 0;j < 3;j++)
2748 {
2749 while (*s && ISWHITESPACE(*s))
2750 s++;
2751 if (!*s)
2752 break;
2753 val->vector[j] = atof(s);
2754 while (!ISWHITESPACE(*s))
2755 s++;
2756 if (!*s)
2757 break;
2758 }
2759 break;
2760 case ev_string:
2761 val->string = PRVM_SetEngineString(prog, cvar->string);
2762 cvar->globaldefindex_stringno[prog - prvm_prog_list] = val->string;
2763 break;
2764 default:
2765 Con_Printf("%s: invalid type of autocvar global %s in %s\n", __func__, name, prog->name);
2766 goto fail;
2767 }
2768 cvar->globaldefindex[prog - prvm_prog_list] = i;
2769 }
2770 else
2771 Con_Printf("%s: private cvar for autocvar global %s in %s\n", __func__, name, prog->name);
2772 }
2773fail:
2774 ;
2775 }
2776
2777 prog->loaded = true;
2778
2780
2781 // set flags & mdef_ts in prog
2782
2783 PRVM_FindOffsets(prog);
2784
2785 // Do not allow more than 2^31 total entityfields. Achieve this by limiting maximum edict count.
2786 // TODO: For PRVM_64, this can be relaxes. May require changing some types away from int.
2787 max_safe_edicts = ((1 << 31) - prog->numglobals) / prog->entityfields;
2788 if (prog->limit_edicts > max_safe_edicts)
2789 {
2790 Con_Printf("%s: reducing maximum entity count to %d to avoid address overflow in %s\n", __func__, max_safe_edicts, prog->name);
2791 prog->limit_edicts = max_safe_edicts;
2792 }
2793
2794 prog->init_cmd(prog);
2795
2796 // init mempools
2797 PRVM_MEM_Alloc(prog);
2798
2799 Con_Printf("%s: program loaded (crc %i, size %iK)%s\n", prog->name, prog->filecrc, (int)(filesize/1024),
2800 prog == CLVM_prog ? (prog->flag & PRVM_CSQC_SIMPLE ? " CSQC_SIMPLE" : " EXT_CSQC") : "");
2801
2802 // Inittime is at least the time when this function finished. However,
2803 // later events may bump it.
2804 prog->inittime = host.realtime;
2805}
cvar_t csqc_progname
Definition cl_main.c:35
#define CF_PRIVATE
cvar should not be $ expanded or sent to the server under any circumstances (rcon_password,...
Definition cmd.h:59
#define LittleShort(l)
Definition common.h:90
#define CON_WARN
Definition console.h:101
void Crypto_LoadKeys(void)
Definition crypto.c:855
vector size
qfile_t * FS_OpenRealFile(const char *filepath, const char *mode, qbool quiet)
Definition fs.c:2902
int FS_Close(qfile_t *file)
Definition fs.c:2971
GLsizei const GLfloat * value
Definition glquake.h:740
void Host_LockSession(void)
Definition host.c:331
#define VectorClear(a)
Definition mathlib.h:97
#define PROG_VERSION
Definition pr_comp.h:425
opcode_t
Definition pr_comp.h:46
@ OP_SUB_FI
Definition pr_comp.h:168
@ OP_STOREP_S
Definition pr_comp.h:87
@ OP_NE_E
Definition pr_comp.h:66
@ OP_LOADA_ENT
Definition pr_comp.h:196
@ OP_AND_I
Definition pr_comp.h:237
@ OP_LE_FI
Definition pr_comp.h:217
@ OP_ADD_I
Definition pr_comp.h:164
@ OP_GSTOREP_FLD
Definition pr_comp.h:248
@ OP_STORE_V
Definition pr_comp.h:80
@ OP_GSTOREP_FNC
Definition pr_comp.h:250
@ OP_RSHIFT_U
Definition pr_comp.h:276
@ OP_SUB_F
Definition pr_comp.h:56
@ OP_LOAD_ENT
Definition pr_comp.h:75
@ OP_LOAD_F
Definition pr_comp.h:72
@ OP_LT_FI
Definition pr_comp.h:219
@ OP_GE_I
Definition pr_comp.h:210
@ OP_DIV_I
Definition pr_comp.h:181
@ OP_LT_I
Definition pr_comp.h:211
@ OP_IF
Definition pr_comp.h:97
@ OP_LOAD_FLD
Definition pr_comp.h:76
@ OP_MUL_VI
Definition pr_comp.h:229
@ OP_BITOR_F
Definition pr_comp.h:113
@ OP_STOREP_V
Definition pr_comp.h:86
@ OP_GLOAD_ENT
Definition pr_comp.h:256
@ OP_GLOAD_F
Definition pr_comp.h:254
@ OP_EQ_FI
Definition pr_comp.h:222
@ OP_GSTOREP_I
Definition pr_comp.h:245
@ OP_MUL_VF
Definition pr_comp.h:52
@ OP_ADD_IF
Definition pr_comp.h:166
@ OP_GLOAD_FLD
Definition pr_comp.h:255
@ OP_NOT_I
Definition pr_comp.h:186
@ OP_LOADA_I
Definition pr_comp.h:199
@ OP_GSTOREP_F
Definition pr_comp.h:246
@ OP_CALL8
Definition pr_comp.h:107
@ OP_CONV_ITOF
Definition pr_comp.h:170
@ OP_DIV_F
Definition pr_comp.h:53
@ OP_GT_F
Definition pr_comp.h:71
@ OP_DIV_IF
Definition pr_comp.h:231
@ OP_MUL_I
Definition pr_comp.h:180
@ OP_OR_FI
Definition pr_comp.h:242
@ OP_CALL6
Definition pr_comp.h:105
@ OP_ADD_V
Definition pr_comp.h:55
@ OP_STOREP_ENT
Definition pr_comp.h:88
@ OP_STOREP_FNC
Definition pr_comp.h:90
@ OP_AND_IF
Definition pr_comp.h:239
@ OP_CALL5
Definition pr_comp.h:104
@ OP_LOADP_V
Definition pr_comp.h:203
@ OP_NE_FNC
Definition pr_comp.h:67
@ OP_NE_S
Definition pr_comp.h:65
@ OP_BITOR_FI
Definition pr_comp.h:236
@ OP_LT_IF
Definition pr_comp.h:215
@ OP_STORE_P
Definition pr_comp.h:200
@ OP_CONV_FTOI
Definition pr_comp.h:171
@ OP_LOADA_FNC
Definition pr_comp.h:198
@ OP_LOADP_ENT
Definition pr_comp.h:205
@ OP_STORE_I
Definition pr_comp.h:161
@ OP_SUB_V
Definition pr_comp.h:57
@ OP_BITAND_FI
Definition pr_comp.h:235
@ OP_NOT_ENT
Definition pr_comp.h:95
@ OP_GSTOREP_S
Definition pr_comp.h:249
@ OP_GLOAD_I
Definition pr_comp.h:253
@ OP_OR_IF
Definition pr_comp.h:240
@ OP_STOREP_I
Definition pr_comp.h:175
@ OP_DIV_FI
Definition pr_comp.h:232
@ OP_EQ_FNC
Definition pr_comp.h:62
@ OP_LE_U
Definition pr_comp.h:273
@ OP_STOREP_FLD
Definition pr_comp.h:89
@ OP_MUL_FV
Definition pr_comp.h:51
@ OP_LOAD_P
Definition pr_comp.h:201
@ OP_NE_V
Definition pr_comp.h:64
@ OP_STORE_FLD
Definition pr_comp.h:83
@ OP_GLOBALADDRESS
Definition pr_comp.h:191
@ OP_ADD_PIW
Definition pr_comp.h:192
@ OP_CALL1
Definition pr_comp.h:100
@ OP_EQ_I
Definition pr_comp.h:182
@ OP_EQ_V
Definition pr_comp.h:59
@ OP_STORE_ENT
Definition pr_comp.h:82
@ OP_MUL_IF
Definition pr_comp.h:227
@ OP_GSTOREP_ENT
Definition pr_comp.h:247
@ OP_GT_IF
Definition pr_comp.h:216
@ OP_NE_IF
Definition pr_comp.h:243
@ OP_ADD_F
Definition pr_comp.h:54
@ OP_LT_F
Definition pr_comp.h:70
@ OP_RSHIFT_I
Definition pr_comp.h:189
@ OP_LOADP_S
Definition pr_comp.h:204
@ OP_MUL_FI
Definition pr_comp.h:228
@ OP_LOADA_F
Definition pr_comp.h:193
@ OP_GE_F
Definition pr_comp.h:69
@ OP_GE_IF
Definition pr_comp.h:214
@ OP_DIV_U
Definition pr_comp.h:275
@ OP_LE_I
Definition pr_comp.h:209
@ OP_LE_F
Definition pr_comp.h:68
@ OP_LOADP_I
Definition pr_comp.h:208
@ OP_BITAND_F
Definition pr_comp.h:112
@ OP_LE_IF
Definition pr_comp.h:213
@ OP_ADD_FI
Definition pr_comp.h:165
@ OP_GE_FI
Definition pr_comp.h:218
@ OP_AND_F
Definition pr_comp.h:110
@ OP_CALL0
Definition pr_comp.h:99
@ OP_LOADP_FLD
Definition pr_comp.h:206
@ OP_NE_F
Definition pr_comp.h:63
@ OP_NOT_F
Definition pr_comp.h:92
@ OP_STORE_S
Definition pr_comp.h:81
@ OP_LOAD_S
Definition pr_comp.h:74
@ OP_OR_I
Definition pr_comp.h:238
@ OP_CALL4
Definition pr_comp.h:103
@ OP_EQ_E
Definition pr_comp.h:61
@ OP_DIV_VF
Definition pr_comp.h:187
@ OP_STOREP_F
Definition pr_comp.h:85
@ OP_SUB_IF
Definition pr_comp.h:169
@ OP_LSHIFT_I
Definition pr_comp.h:190
@ OP_CALL2
Definition pr_comp.h:101
@ OP_GLOAD_V
Definition pr_comp.h:264
@ OP_MUL_V
Definition pr_comp.h:50
@ OP_GLOAD_S
Definition pr_comp.h:257
@ OP_LOADA_FLD
Definition pr_comp.h:197
@ OP_SUB_I
Definition pr_comp.h:167
@ OP_NE_FI
Definition pr_comp.h:244
@ OP_LOADP_F
Definition pr_comp.h:202
@ OP_STATE
Definition pr_comp.h:108
@ OP_GT_I
Definition pr_comp.h:212
@ OP_LOAD_I
Definition pr_comp.h:174
@ OP_LOADA_V
Definition pr_comp.h:194
@ OP_LOADA_S
Definition pr_comp.h:195
@ OP_CALL3
Definition pr_comp.h:102
@ OP_RETURN
Definition pr_comp.h:91
@ OP_OR_F
Definition pr_comp.h:111
@ OP_ADDRESS
Definition pr_comp.h:78
@ OP_EQ_IF
Definition pr_comp.h:221
@ OP_BITAND_I
Definition pr_comp.h:178
@ OP_EQ_F
Definition pr_comp.h:58
@ OP_DONE
Definition pr_comp.h:48
@ OP_NOT_V
Definition pr_comp.h:93
@ OP_BOUNDCHECK
Definition pr_comp.h:259
@ OP_AND_FI
Definition pr_comp.h:241
@ OP_GSTOREP_V
Definition pr_comp.h:251
@ OP_EQ_S
Definition pr_comp.h:60
@ OP_BITOR_IF
Definition pr_comp.h:234
@ OP_LOAD_FNC
Definition pr_comp.h:77
@ OP_NE_I
Definition pr_comp.h:183
@ OP_GT_FI
Definition pr_comp.h:220
@ OP_NOT_FNC
Definition pr_comp.h:96
@ OP_LOAD_V
Definition pr_comp.h:73
@ OP_GOTO
Definition pr_comp.h:109
@ OP_GLOAD_FNC
Definition pr_comp.h:258
@ OP_BITAND_IF
Definition pr_comp.h:233
@ OP_CALL7
Definition pr_comp.h:106
@ OP_STORE_FNC
Definition pr_comp.h:84
@ OP_LT_U
Definition pr_comp.h:274
@ OP_BITOR_I
Definition pr_comp.h:179
@ OP_MUL_F
Definition pr_comp.h:49
@ OP_LOADP_FNC
Definition pr_comp.h:207
@ OP_NOT_S
Definition pr_comp.h:94
@ OP_STORE_F
Definition pr_comp.h:79
@ OP_IFNOT
Definition pr_comp.h:98
#define PROG_SECONDARYVERSION32
Definition pr_comp.h:470
#define PROG_SECONDARYVERSION16
Definition pr_comp.h:469
void PRVM_Init_Exec(prvm_prog_t *prog)
Definition prvm_exec.c:892
#define PRVM_CSQC_SIMPLE
Definition progsvm.h:239
static po_t * PRVM_PO_Load(const char *filename, const char *filename2, mempool_t *pool)
static void PRVM_FindOffsets(prvm_prog_t *prog)
#define remapglobal(index)
int PRVM_SetEngineString(prvm_prog_t *prog, const char *s)
static const char * PRVM_PO_Lookup(po_t *po, const char *str)
static void PRVM_MEM_Alloc(prvm_prog_t *prog)
Definition prvm_edict.c:70
static void PRVM_LoadLNO(prvm_prog_t *prog, const char *progname)
static void PRVM_PO_UnparseString(char *out, const char *in, size_t outsize)
dp_FragColor b
ret a
uint32_t numstrings
Definition pr_comp.h:445
uint32_t numstatements
Definition pr_comp.h:433
uint32_t numfielddefs
Definition pr_comp.h:439
int32_t crc
Definition pr_comp.h:429
uint32_t numglobals
Definition pr_comp.h:448
uint32_t numglobaldefs
Definition pr_comp.h:436
uint32_t ofs_strings
Definition pr_comp.h:444
uint32_t ofs_globals
Definition pr_comp.h:447
uint32_t ofs_statements
Definition pr_comp.h:432
int32_t version
Definition pr_comp.h:428
uint32_t ofs_fielddefs
Definition pr_comp.h:438
uint32_t ofs_functions
Definition pr_comp.h:441
uint32_t entityfields
Definition pr_comp.h:450
uint32_t ofs_globaldefs
Definition pr_comp.h:435
uint32_t numfunctions
Definition pr_comp.h:442
uint32_t numbodylessfuncs
Definition pr_comp.h:462
uint32_t blockscompressed
Definition pr_comp.h:466
uint32_t numtypes
Definition pr_comp.h:465
int32_t secondaryversion
Definition pr_comp.h:468
int32_t first_statement
Definition pr_comp.h:393
int32_t s_file
Definition pr_comp.h:410
uint8_t parm_size[MAX_PARMS]
Definition pr_comp.h:413
int32_t numparms
Definition pr_comp.h:412
int32_t locals
Definition pr_comp.h:395
int32_t parm_start
Definition pr_comp.h:394
opcode_t op
Definition pr_comp.h:419
int operand[3]
Definition pr_comp.h:420
unsigned short filecrc
Definition progsvm.h:631
int progs_numfunctions
Definition progsvm.h:557
int progs_entityfields
Definition progsvm.h:560
int progs_crc
Definition progsvm.h:553
int numstrings
Definition progsvm.h:567
int progs_version
Definition progsvm.h:552
unsigned flag
flag - used to store general flags like PRVM_GE_SELF, etc.
Definition progsvm.h:703
double * explicit_profile
only incremented if prvm_statementprofiling is on
Definition progsvm.h:575
int progs_numstrings
Definition progsvm.h:558
double * statement_profile
only incremented if prvm_statementprofiling is on
Definition progsvm.h:573
int numstatements
Definition progsvm.h:563
mstatement_t * statements
Definition progsvm.h:547
int numexplicitcoveragestatements
Definition progsvm.h:577
void(* init_cmd)(struct prvm_prog_s *prog)
[INIT] used by PRVM_InitProg
Definition progsvm.h:744
double profiletime
system time when last PRVM_CallProfile was called (or PRVM_Prog_Load initially)
Definition progsvm.h:540
double Sys_DirtyTime(void)
Definition sys_shared.c:417
void Mem_ExpandableArray_NewArray(memexpandablearray_t *l, mempool_t *mempool, size_t recordsize, int numrecordsperarray)
Definition zone.c:675

References prvm_eval_t::_float, a, b, dprograms_v7_t::blockscompressed, buf, CF_PRIVATE, CLVM_prog, Con_DPrintf(), Con_Printf(), CON_WARN, prvm_prog_t::console_cmd, dprograms_t::crc, CRC_Block(), Crypto_LoadKeys(), csqc_progname, cvar(), Cvar_FindVar(), Cvar_Get(), data, DEF_SAVEGLOBAL, dpsnprintf(), dprograms_t::entityfields, prvm_prog_t::entityfields, prvm_prog_t::error_cmd, ev_float, ev_string, ev_vector, prvm_prog_t::explicit_profile, f, prvm_prog_t::fielddefs, prvm_prog_t::filecrc, mfunction_t::first_statement, prvm_prog_t::flag, prvm_prog_t::fp, FS_Close(), FS_LoadFile(), FS_OpenRealFile(), FS_Printf(), prvm_prog_t::functions, prvm_prog_t::globaldefs, prvm_prog_t::globals, host, Host_LockSession(), prvm_prog_t::init_cmd, prvm_prog_t::inittime, int(), prvm_prog_t::ip, ISWHITESPACE, prvm_prog_t::knownstrings, prvm_prog_t::knownstrings_flags, prvm_prog_t::limit_edicts, LittleLong, LittleShort, prvm_prog_t::loaded, mfunction_t::locals, MAX_INPUTLINE, prvm_prog_t::maxknownstrings, Mem_Alloc, Mem_ExpandableArray_NewArray(), Mem_Free, name, prvm_prog_t::name, NULL, dprograms_v7_t::numbodylessfuncs, prvm_prog_t::numexplicitcoveragestatements, dprograms_t::numfielddefs, prvm_prog_t::numfielddefs, dprograms_t::numfunctions, prvm_prog_t::numfunctions, dprograms_t::numglobaldefs, prvm_prog_t::numglobaldefs, dprograms_t::numglobals, prvm_prog_t::numglobals, prvm_prog_t::numknownstrings, mfunction_t::numparms, dprograms_t::numstatements, prvm_prog_t::numstatements, dprograms_t::numstrings, prvm_prog_t::numstrings, dprograms_v7_t::numtypes, mdef_t::ofs, ofs, dprograms_t::ofs_fielddefs, dprograms_t::ofs_functions, dprograms_t::ofs_globaldefs, dprograms_t::ofs_globals, dprograms_t::ofs_statements, dprograms_t::ofs_strings, mstatement_t::op, OP_ADD_F, OP_ADD_FI, OP_ADD_I, OP_ADD_IF, OP_ADD_PIW, OP_ADD_V, OP_ADDRESS, OP_AND_F, OP_AND_FI, OP_AND_I, OP_AND_IF, OP_BITAND_F, OP_BITAND_FI, OP_BITAND_I, OP_BITAND_IF, OP_BITOR_F, OP_BITOR_FI, OP_BITOR_I, OP_BITOR_IF, OP_BOUNDCHECK, OP_CALL0, OP_CALL1, OP_CALL2, OP_CALL3, OP_CALL4, OP_CALL5, OP_CALL6, OP_CALL7, OP_CALL8, OP_CONV_FTOI, OP_CONV_ITOF, OP_DIV_F, OP_DIV_FI, OP_DIV_I, OP_DIV_IF, OP_DIV_U, OP_DIV_VF, OP_DONE, OP_EQ_E, OP_EQ_F, OP_EQ_FI, OP_EQ_FNC, OP_EQ_I, OP_EQ_IF, OP_EQ_S, OP_EQ_V, OP_GE_F, OP_GE_FI, OP_GE_I, OP_GE_IF, OP_GLOAD_ENT, OP_GLOAD_F, OP_GLOAD_FLD, OP_GLOAD_FNC, OP_GLOAD_I, OP_GLOAD_S, OP_GLOAD_V, OP_GLOBALADDRESS, OP_GOTO, OP_GSTOREP_ENT, OP_GSTOREP_F, OP_GSTOREP_FLD, OP_GSTOREP_FNC, OP_GSTOREP_I, OP_GSTOREP_S, OP_GSTOREP_V, OP_GT_F, OP_GT_FI, OP_GT_I, OP_GT_IF, OP_IF, OP_IFNOT, OP_LE_F, OP_LE_FI, OP_LE_I, OP_LE_IF, OP_LE_U, OP_LOAD_ENT, OP_LOAD_F, OP_LOAD_FLD, OP_LOAD_FNC, OP_LOAD_I, OP_LOAD_P, OP_LOAD_S, OP_LOAD_V, OP_LOADA_ENT, OP_LOADA_F, OP_LOADA_FLD, OP_LOADA_FNC, OP_LOADA_I, OP_LOADA_S, OP_LOADA_V, OP_LOADP_ENT, OP_LOADP_F, OP_LOADP_FLD, OP_LOADP_FNC, OP_LOADP_I, OP_LOADP_S, OP_LOADP_V, OP_LSHIFT_I, OP_LT_F, OP_LT_FI, OP_LT_I, OP_LT_IF, OP_LT_U, OP_MUL_F, OP_MUL_FI, OP_MUL_FV, OP_MUL_I, OP_MUL_IF, OP_MUL_V, OP_MUL_VF, OP_MUL_VI, OP_NE_E, OP_NE_F, OP_NE_FI, OP_NE_FNC, OP_NE_I, OP_NE_IF, OP_NE_S, OP_NE_V, OP_NOT_ENT, OP_NOT_F, OP_NOT_FNC, OP_NOT_I, OP_NOT_S, OP_NOT_V, OP_OR_F, OP_OR_FI, OP_OR_I, OP_OR_IF, OP_RETURN, OP_RSHIFT_I, OP_RSHIFT_U, OP_STATE, OP_STORE_ENT, OP_STORE_F, OP_STORE_FLD, OP_STORE_FNC, OP_STORE_I, OP_STORE_P, OP_STORE_S, OP_STORE_V, OP_STOREP_ENT, OP_STOREP_F, OP_STOREP_FLD, OP_STOREP_FNC, OP_STOREP_I, OP_STOREP_S, OP_STOREP_V, OP_SUB_F, OP_SUB_FI, OP_SUB_I, OP_SUB_IF, OP_SUB_V, mstatement_t::operand, dfunction_t::parm_size, mfunction_t::parm_size, mfunction_t::parm_start, prvm_prog_t::profiletime, PROG_SECONDARYVERSION16, PROG_SECONDARYVERSION32, PROG_VERSION, prvm_prog_t::progs_crc, prvm_prog_t::progs_entityfields, prvm_prog_t::progs_mempool, prvm_prog_t::progs_numfielddefs, prvm_prog_t::progs_numfunctions, prvm_prog_t::progs_numglobaldefs, prvm_prog_t::progs_numglobals, prvm_prog_t::progs_numstatements, prvm_prog_t::progs_numstrings, prvm_prog_t::progs_version, PRVM_CSQC_SIMPLE, PRVM_FindOffsets(), PRVM_GetString(), PRVM_GLOBALFIELDVALUE, PRVM_Init_Exec(), prvm_language, PRVM_LoadLNO(), PRVM_MEM_Alloc(), PRVM_PO_Load(), PRVM_PO_Lookup(), PRVM_PO_UnparseString(), prvm_prog_list, PRVM_SetEngineString(), PRVM_UpdateBreakpoints(), remapglobal, mfunction_t::s_file, mdef_t::s_name, mfunction_t::s_name, dprograms_v7_t::secondaryversion, size, prvm_prog_t::starttime, prvm_prog_t::statement_profile, prvm_prog_t::statements, prvm_eval_t::string, prvm_prog_t::stringbuffersarray, prvm_prog_t::strings, prvm_prog_t::stringssize, strlen(), Sys_DirtyTime(), mdef_t::type, prvm_required_field_t::type, type, va(), value, prvm_eval_t::vector, VectorClear, and dprograms_t::version.

Referenced by CL_VM_Init(), MP_Init(), and SV_VM_Setup().

◆ PRVM_Prog_Reset()

void PRVM_Prog_Reset ( prvm_prog_t * prog)

Definition at line 1950 of file prvm_edict.c.

1951{
1952 if (prog->loaded)
1953 {
1954 if(prog->tempstringsbuf.cursize)
1956 prog->tempstringsbuf.cursize = 0;
1957 PRVM_LeakTest(prog);
1958 prog->reset_cmd(prog);
1960 if(prog->po)
1961 PRVM_PO_Destroy((po_t *) prog->po);
1962 }
1963 memset(prog,0,sizeof(prvm_prog_t));
1964 prog->break_statement = -1;
1965 prog->watch_global_type = ev_void;
1966 prog->watch_field_type = ev_void;
1967}
void PRVM_LeakTest(prvm_prog_t *prog)
static void PRVM_PO_Destroy(po_t *po)
void(* reset_cmd)(struct prvm_prog_s *prog)
[INIT] used by PRVM_ResetProg
Definition progsvm.h:745
etype_t watch_field_type
Definition progsvm.h:617
int break_statement
Definition progsvm.h:610
etype_t watch_global_type
Definition progsvm.h:613
void * po
translation buffer (only needs to be freed on unloading progs, type is private to prvm_edict....
Definition progsvm.h:714
#define Mem_FreePool(pool)
Definition zone.h:105

References prvm_prog_t::break_statement, sizebuf_t::cursize, sizebuf_t::data, ev_void, prvm_prog_t::loaded, Mem_Free, Mem_FreePool, prvm_prog_t::po, prvm_prog_t::progs_mempool, PRVM_LeakTest(), PRVM_PO_Destroy(), prvm_prog_t::reset_cmd, prvm_prog_t::tempstringsbuf, prvm_prog_t::watch_field_type, and prvm_prog_t::watch_global_type.

Referenced by CL_VM_ShutDown(), MP_Shutdown(), PRVM_Crash(), PRVM_Prog_Init(), and SV_VM_Shutdown().

◆ PRVM_ProgFromString()

prvm_prog_t * PRVM_ProgFromString ( const char * str)

Definition at line 166 of file prvm_edict.c.

167{
168 if (!strcmp(str, "server"))
169 return SVVM_prog;
170 if (!strcmp(str, "client"))
171 return CLVM_prog;
172#ifdef CONFIG_MENU
173 if (!strcmp(str, "menu"))
174 return MVM_prog;
175#endif
176 return NULL;
177}

References CLVM_prog, NULL, and SVVM_prog.

Referenced by PRVM_Breakpoint_f(), PRVM_EdictWatchpoint_f(), PRVM_FriendlyProgFromString(), and PRVM_GlobalWatchpoint_f().

◆ PRVM_SetEngineString()

int PRVM_SetEngineString ( prvm_prog_t * prog,
const char * s )

Definition at line 3425 of file prvm_edict.c.

3426{
3427 int i;
3428 if (!s)
3429 return 0;
3430 if (s >= prog->strings && s <= prog->strings + prog->stringssize)
3431 prog->error_cmd("PRVM_SetEngineString: s in prog->strings area");
3432 // if it's in the tempstrings area, use a reserved range
3433 // (otherwise we'd get millions of useless string offsets cluttering the database)
3434 if (s >= (char *)prog->tempstringsbuf.data && s < (char *)prog->tempstringsbuf.data + prog->tempstringsbuf.maxsize)
3435 return prog->stringssize + (s - (char *)prog->tempstringsbuf.data);
3436 // see if it's a known string address
3437 for (i = 0;i < prog->numknownstrings;i++)
3438 if (prog->knownstrings[i] == s)
3439 return PRVM_KNOWNSTRINGBASE + i;
3440 // new unknown engine string
3441 if (developer_insane.integer)
3442 Con_DPrintf("new engine string %p = \"%s\"\n", (void *)s, s);
3443 for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
3444 if (!prog->knownstrings[i])
3445 break;
3447 return PRVM_KNOWNSTRINGBASE + i;
3448}
cvar_t developer_insane
Definition host.c:50

References Con_DPrintf(), sizebuf_t::data, developer_insane, prvm_prog_t::error_cmd, prvm_prog_t::firstfreeknownstring, KNOWNSTRINGFLAG_ENGINE, KNOWNSTRINGFLAG_GCMARK, prvm_prog_t::knownstrings, sizebuf_t::maxsize, prvm_prog_t::numknownstrings, PRVM_KNOWNSTRINGBASE, PRVM_NewKnownString(), prvm_prog_t::strings, prvm_prog_t::stringssize, and prvm_prog_t::tempstringsbuf.

Referenced by CL_VM_Init(), PRVM_Prog_Load(), PRVM_SetTempString(), SV_Name(), SV_Playermodel_f(), SV_Playerskin_f(), SV_SpawnServer(), SV_UpdateToReliableMessages(), SVVM_init_edict(), VM_CL_modelnameforindex(), VM_CL_setmodel(), VM_CL_setmodelindex(), VM_SV_modelnameforindex(), VM_SV_setmodel(), and VM_SV_setmodelindex().

◆ PRVM_SetTempString()

int PRVM_SetTempString ( prvm_prog_t * prog,
const char * s,
size_t slen )

Takes an strlen (not a buffer size).

Definition at line 3458 of file prvm_edict.c.

3459{
3460 size_t size;
3461 char *t;
3462
3463 if (!s || slen >= VM_TEMPSTRING_MAXSIZE)
3464 return 0;
3465 size = slen + 1;
3466 if (developer_insane.integer)
3467 Con_DPrintf("PRVM_SetTempString %s: cursize %i, new tempstring size %lu\n", prog->name, prog->tempstringsbuf.cursize, (unsigned long)size);
3468 if ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
3469 {
3470 sizebuf_t old = prog->tempstringsbuf;
3471 if (prog->tempstringsbuf.cursize + size >= 1<<28)
3472 prog->error_cmd("PRVM_SetTempString %s: ran out of tempstring memory! (refusing to grow tempstring buffer over 256MB, cursize %i, new tempstring size %lu)\n", prog->name, prog->tempstringsbuf.cursize, (unsigned long)size);
3473 prog->tempstringsbuf.maxsize = max(prog->tempstringsbuf.maxsize, 65536);
3474 while ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
3475 prog->tempstringsbuf.maxsize *= 2;
3476 if (prog->tempstringsbuf.maxsize != old.maxsize || prog->tempstringsbuf.data == NULL)
3477 {
3478 Con_DPrintf("PRVM_SetTempString %s: enlarging tempstrings buffer (%iKB -> %iKB)\n", prog->name, old.maxsize/1024, prog->tempstringsbuf.maxsize/1024);
3479 prog->tempstringsbuf.data = (unsigned char *) Mem_Alloc(prog->progs_mempool, prog->tempstringsbuf.maxsize);
3480 if (old.data)
3481 {
3482 if (old.cursize)
3483 memcpy(prog->tempstringsbuf.data, old.data, old.cursize);
3484 Mem_Free(old.data);
3485 }
3486 }
3487 }
3488 t = (char *)prog->tempstringsbuf.data + prog->tempstringsbuf.cursize;
3489 memcpy(t, s, size);
3490 prog->tempstringsbuf.cursize += size;
3491 return PRVM_SetEngineString(prog, t);
3492}
#define VM_TEMPSTRING_MAXSIZE
Definition prvm_cmds.h:215

References Con_DPrintf(), sizebuf_t::cursize, sizebuf_t::data, developer_insane, prvm_prog_t::error_cmd, max, sizebuf_t::maxsize, Mem_Alloc, Mem_Free, prvm_prog_t::name, NULL, prvm_prog_t::progs_mempool, PRVM_SetEngineString(), size, prvm_prog_t::tempstringsbuf, and VM_TEMPSTRING_MAXSIZE.

Referenced by CL_VM_Event_Sound(), CL_VM_Parse_CenterPrint(), CL_VM_Parse_Print(), CL_VM_Parse_StuffCmd(), PRVM_ConsoleCommand(), PRVM_GameCommand(), SV_ReadClientMessage(), uri_to_string_callback(), VM_altstr_get(), VM_altstr_ins(), VM_altstr_prepare(), VM_altstr_set(), VM_buf_implode(), VM_bufstr_get(), VM_chr(), VM_chr2str(), VM_CL_getextresponse(), VM_CL_getplayerkey(), VM_CL_getstats(), VM_CL_gettaginfo(), VM_CL_ReadPicture(), VM_CL_ReadString(), VM_CL_serverkey(), VM_CL_skel_get_bonename(), VM_cvar_defstring(), VM_cvar_description(), VM_cvar_string(), VM_digest_hex(), VM_entityfieldname(), VM_etos(), VM_fgets(), VM_findkeysforcommand(), VM_ftos(), VM_getentityfieldstring(), VM_getkeybind(), VM_getsurfacetexture(), VM_infoadd(), VM_infoget(), VM_keynumtostring(), VM_M_crypto_getencryptlevel(), VM_M_crypto_getidfp(), VM_M_crypto_getkeyfp(), VM_M_crypto_getmyidfp(), VM_M_crypto_getmykeyfp(), VM_M_getgamedirinfo(), VM_M_getserverliststring(), VM_netaddress_resolve(), VM_search_getfilename(), VM_SetTraceGlobals(), VM_sprintf(), VM_strcat(), VM_strconv(), VM_strdecolorize(), VM_strftime(), VM_strireplace(), VM_strpad(), VM_strreplace(), VM_strtolower(), VM_strtoupper(), VM_substring(), VM_SV_getextresponse(), VM_SV_gettaginfo(), VM_SV_serverkey(), VM_SV_skel_get_bonename(), VM_tokenize(), VM_tokenize_console(), VM_tokenizebyseparator(), VM_uncolorstring(), VM_uri_escape(), VM_uri_unescape(), VM_vtos(), and VM_whichpack().

◆ PRVM_UglyValueString()

char * PRVM_UglyValueString ( prvm_prog_t * prog,
etype_t type,
prvm_eval_t * val,
char * line,
size_t linelength )

Definition at line 513 of file prvm_edict.c.

514{
515 int i;
516 const char *s;
517 mdef_t *def;
518 mfunction_t *f;
519
520 type = (etype_t)((int)type & ~DEF_SAVEGLOBAL);
521
522 switch (type)
523 {
524 case ev_string:
525 // Parse the string a bit to turn special characters
526 // (like newline, specifically) into escape codes,
527 // this fixes saving games from various mods
528 s = PRVM_GetString (prog, val->string);
529 for (i = 0;i < (int)linelength - 2 && *s;)
530 {
531 if (*s == '\n')
532 {
533 line[i++] = '\\';
534 line[i++] = 'n';
535 }
536 else if (*s == '\r')
537 {
538 line[i++] = '\\';
539 line[i++] = 'r';
540 }
541 else if (*s == '\\')
542 {
543 line[i++] = '\\';
544 line[i++] = '\\';
545 }
546 else if (*s == '"')
547 {
548 line[i++] = '\\';
549 line[i++] = '"';
550 }
551 else
552 line[i++] = *s;
553 s++;
554 }
555 line[i] = '\0';
556 break;
557 case ev_entity:
558 i = val->edict;
559 dpsnprintf (line, linelength, "%i", i);
560 break;
561 case ev_function:
562 if ((unsigned int)val->function < (unsigned int)prog->progs_numfunctions)
563 {
564 f = prog->functions + val->function;
565 dp_strlcpy (line, PRVM_GetString (prog, f->s_name), linelength);
566 }
567 else
568 dpsnprintf (line, linelength, "bad function %" PRVM_PRIi " (invalid!)", val->function);
569 break;
570 case ev_field:
571 def = PRVM_ED_FieldAtOfs ( prog, val->_int );
572 if (def != NULL)
573 dpsnprintf (line, linelength, ".%s", PRVM_GetString(prog, def->s_name));
574 else
575 dpsnprintf (line, linelength, "field %" PRVM_PRIi "(invalid!)", val->_int );
576 break;
577 case ev_void:
578 dpsnprintf (line, linelength, "void");
579 break;
580 case ev_float:
581 dpsnprintf (line, linelength, PRVM_FLOAT_LOSSLESS_FORMAT, val->_float);
582 break;
583 case ev_vector:
584 dpsnprintf (line, linelength, PRVM_VECTOR_LOSSLESS_FORMAT, val->vector[0], val->vector[1], val->vector[2]);
585 break;
586 default:
587 dpsnprintf (line, linelength, "bad type %i", type);
588 break;
589 }
590
591 return line;
592}
#define PRVM_VECTOR_LOSSLESS_FORMAT
Definition progs.h:37
#define PRVM_FLOAT_LOSSLESS_FORMAT
Definition progs.h:36
mdef_t * PRVM_ED_FieldAtOfs(prvm_prog_t *prog, unsigned int ofs)
Definition prvm_edict.c:357
#define PRVM_PRIi
Definition qtypes.h:58

References prvm_eval_t::_float, prvm_eval_t::_int, DEF_SAVEGLOBAL, dp_strlcpy, dpsnprintf(), prvm_eval_t::edict, ev_entity, ev_field, ev_float, ev_function, ev_string, ev_vector, ev_void, f, prvm_eval_t::function, prvm_prog_t::functions, int(), NULL, prvm_prog_t::progs_numfunctions, PRVM_ED_FieldAtOfs(), PRVM_FLOAT_LOSSLESS_FORMAT, PRVM_GetString(), PRVM_PRIi, PRVM_VECTOR_LOSSLESS_FORMAT, mdef_t::s_name, prvm_eval_t::string, type, and prvm_eval_t::vector.

Referenced by PRVM_ED_EdictGet_f(), PRVM_ED_GlobalGet_f(), PRVM_ED_Write(), PRVM_ED_WriteGlobals(), PRVM_Watchpoint(), and VM_getentityfieldstring().

◆ PRVM_UpdateBreakpoints()

void PRVM_UpdateBreakpoints ( prvm_prog_t * prog)
static

Definition at line 3060 of file prvm_edict.c.

3061{
3062 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3063 if (!prog->loaded)
3064 return;
3065 if (debug->break_statement[0])
3066 {
3067 if (debug->break_statement[0] >= '0' && debug->break_statement[0] <= '9')
3068 {
3069 prog->break_statement = atoi(debug->break_statement);
3070 prog->break_stack_index = 0;
3071 }
3072 else
3073 {
3074 mfunction_t *func;
3075 func = PRVM_ED_FindFunction (prog, debug->break_statement);
3076 if (!func)
3077 {
3078 Con_Printf("%s progs: no function or statement named %s to break on!\n", prog->name, debug->break_statement);
3079 prog->break_statement = -1;
3080 }
3081 else
3082 {
3083 prog->break_statement = func->first_statement;
3084 prog->break_stack_index = 1;
3085 }
3086 }
3087 if (prog->break_statement >= -1)
3088 Con_Printf("%s progs: breakpoint is at statement %d\n", prog->name, prog->break_statement);
3089 }
3090 else
3091 prog->break_statement = -1;
3092
3093 if (debug->watch_global[0])
3094 {
3095 mdef_t *global = PRVM_ED_FindGlobal( prog, debug->watch_global );
3096 if( !global )
3097 {
3098 Con_Printf( "%s progs: no global named '%s' to watch!\n", prog->name, debug->watch_global );
3099 prog->watch_global_type = ev_void;
3100 }
3101 else
3102 {
3103 size_t sz = sizeof(prvm_vec_t) * ((global->type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
3104 prog->watch_global = global->ofs;
3105 prog->watch_global_type = (etype_t)global->type;
3106 memcpy(&prog->watch_global_value, PRVM_GLOBALFIELDVALUE(prog->watch_global), sz);
3107 }
3108 if (prog->watch_global_type != ev_void)
3109 Con_Printf("%s progs: global watchpoint is at global index %d\n", prog->name, prog->watch_global);
3110 }
3111 else
3112 prog->watch_global_type = ev_void;
3113
3114 if (debug->watch_field[0])
3115 {
3116 mdef_t *field = PRVM_ED_FindField( prog, debug->watch_field );
3117 if( !field )
3118 {
3119 Con_Printf( "%s progs: no field named '%s' to watch!\n", prog->name, debug->watch_field );
3120 prog->watch_field_type = ev_void;
3121 }
3122 else
3123 {
3124 size_t sz = sizeof(prvm_vec_t) * ((field->type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
3125 prog->watch_edict = debug->watch_edict;
3126 prog->watch_field = field->ofs;
3127 prog->watch_field_type = (etype_t)field->type;
3128 if (prog->watch_edict < prog->num_edicts)
3130 else
3131 memset(&prog->watch_edictfield_value, 0, sz);
3132 }
3133 if (prog->watch_edict != ev_void)
3134 Con_Printf("%s progs: edict field watchpoint is at edict %d field index %d\n", prog->name, prog->watch_edict, prog->watch_field);
3135 }
3136 else
3137 prog->watch_field_type = ev_void;
3138}
#define PRVM_EDICTFIELDVALUE(ed, fieldoffset)
Definition progsvm.h:209
prvm_eval_t watch_global_value
Definition progsvm.h:614
int watch_global
Definition progsvm.h:612
int break_stack_index
Definition progsvm.h:611
int watch_edict
Definition progsvm.h:615
int watch_field
Definition progsvm.h:616
prvm_eval_t watch_edictfield_value
Definition progsvm.h:618

References prvm_prog_t::break_stack_index, debug_data_t::break_statement, prvm_prog_t::break_statement, Con_Printf(), debug_data, DEF_SAVEGLOBAL, ev_vector, ev_void, mfunction_t::first_statement, prvm_prog_t::loaded, prvm_prog_t::name, prvm_prog_t::num_edicts, mdef_t::ofs, PRVM_ED_FindField(), PRVM_ED_FindFunction(), PRVM_ED_FindGlobal(), PRVM_EDICT_NUM, PRVM_EDICTFIELDVALUE, PRVM_GLOBALFIELDVALUE, prvm_prog_list, mdef_t::type, debug_data_t::watch_edict, prvm_prog_t::watch_edict, prvm_prog_t::watch_edictfield_value, debug_data_t::watch_field, prvm_prog_t::watch_field, prvm_prog_t::watch_field_type, debug_data_t::watch_global, prvm_prog_t::watch_global, prvm_prog_t::watch_global_type, and prvm_prog_t::watch_global_value.

Referenced by PRVM_Breakpoint_f(), PRVM_EdictWatchpoint_f(), PRVM_GlobalWatchpoint_f(), and PRVM_Prog_Load().

◆ PRVM_ValueString()

char * PRVM_ValueString ( prvm_prog_t * prog,
etype_t type,
prvm_eval_t * val,
char * line,
size_t linelength )
static

Definition at line 447 of file prvm_edict.c.

448{
449 mdef_t *def;
450 mfunction_t *f;
451 int n;
452
453 type = (etype_t)((int) type & ~DEF_SAVEGLOBAL);
454
455 switch (type)
456 {
457 case ev_string:
458 dp_strlcpy (line, PRVM_GetString (prog, val->string), linelength);
459 break;
460 case ev_entity:
461 n = val->edict;
462 if (n < 0 || n >= prog->max_edicts)
463 dpsnprintf (line, linelength, "entity %i (invalid!)", n);
464 else
465 dpsnprintf (line, linelength, "entity %i", n);
466 break;
467 case ev_function:
468 if ((unsigned int)val->function < (unsigned int)prog->progs_numfunctions)
469 {
470 f = prog->functions + val->function;
471 dpsnprintf (line, linelength, "%s()", PRVM_GetString(prog, f->s_name));
472 }
473 else
474 dpsnprintf (line, linelength, "function %" PRVM_PRIi "() (invalid!)", val->function);
475 break;
476 case ev_field:
477 def = PRVM_ED_FieldAtOfs ( prog, val->_int );
478 if (def != NULL)
479 dpsnprintf (line, linelength, ".%s", PRVM_GetString(prog, def->s_name));
480 else
481 dpsnprintf (line, linelength, "field %" PRVM_PRIi " (invalid!)", val->_int );
482 break;
483 case ev_void:
484 dpsnprintf (line, linelength, "void");
485 break;
486 case ev_float:
487 // LadyHavoc: changed from %5.1f to %10.4f
488 dpsnprintf (line, linelength, PRVM_FLOAT_LOSSLESS_FORMAT, val->_float);
489 break;
490 case ev_vector:
491 // LadyHavoc: changed from %5.1f to %10.4f
492 dpsnprintf (line, linelength, "'" PRVM_VECTOR_LOSSLESS_FORMAT "'", val->vector[0], val->vector[1], val->vector[2]);
493 break;
494 case ev_pointer:
495 dpsnprintf (line, linelength, "pointer");
496 break;
497 default:
498 dpsnprintf (line, linelength, "bad type %i", (int) type);
499 break;
500 }
501
502 return line;
503}

References prvm_eval_t::_float, prvm_eval_t::_int, DEF_SAVEGLOBAL, dp_strlcpy, dpsnprintf(), prvm_eval_t::edict, ev_entity, ev_field, ev_float, ev_function, ev_pointer, ev_string, ev_vector, ev_void, f, prvm_eval_t::function, prvm_prog_t::functions, prvm_prog_t::max_edicts, n, NULL, prvm_prog_t::progs_numfunctions, PRVM_ED_FieldAtOfs(), PRVM_FLOAT_LOSSLESS_FORMAT, PRVM_GetString(), PRVM_PRIi, PRVM_VECTOR_LOSSLESS_FORMAT, mdef_t::s_name, prvm_eval_t::string, type, and prvm_eval_t::vector.

Referenced by PRVM_ED_Print(), PRVM_Global_f(), and PRVM_GlobalString().

◆ PRVM_Watchpoint()

void PRVM_Watchpoint ( prvm_prog_t * prog,
int stack_index,
const char * text,
etype_t type,
prvm_eval_t * o,
prvm_eval_t * n )

Definition at line 3044 of file prvm_edict.c.

3045{
3046 size_t sz = sizeof(prvm_vec_t) * ((type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
3047 if (memcmp(o, n, sz))
3048 {
3049 char buf[1024];
3050 char valuebuf_o[128];
3051 char valuebuf_n[128];
3052 PRVM_UglyValueString(prog, type, o, valuebuf_o, sizeof(valuebuf_o));
3053 PRVM_UglyValueString(prog, type, n, valuebuf_n, sizeof(valuebuf_n));
3054 dpsnprintf(buf, sizeof(buf), "%s: %s -> %s", text, valuebuf_o, valuebuf_n);
3055 PRVM_Breakpoint(prog, stack_index, buf);
3056 memcpy(o, n, sz);
3057 }
3058}
void PRVM_Breakpoint(prvm_prog_t *prog, int stack_index, const char *text)

References buf, DEF_SAVEGLOBAL, dpsnprintf(), ev_vector, n, PRVM_Breakpoint(), PRVM_UglyValueString(), and type.

Referenced by while().

Variable Documentation

◆ debug_data

◆ prvm_backtraceforwarnings

cvar_t prvm_backtraceforwarnings = {CF_CLIENT | CF_SERVER, "prvm_backtraceforwarnings", "0", "print a backtrace for warnings too"}

Definition at line 40 of file prvm_edict.c.

40{CF_CLIENT | CF_SERVER, "prvm_backtraceforwarnings", "0", "print a backtrace for warnings too"};
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48

Referenced by PRVM_Init(), and VM_Warning().

◆ prvm_badvalue

prvm_eval_t prvm_badvalue

Definition at line 31 of file prvm_edict.c.

◆ prvm_breakpointdump

cvar_t prvm_breakpointdump = {CF_CLIENT | CF_SERVER, "prvm_breakpointdump", "0", "write a savegame on breakpoint to breakpoint-server.dmp"}

Definition at line 45 of file prvm_edict.c.

45{CF_CLIENT | CF_SERVER, "prvm_breakpointdump", "0", "write a savegame on breakpoint to breakpoint-server.dmp"};

Referenced by PRVM_Breakpoint(), and PRVM_Init().

◆ prvm_coverage

cvar_t prvm_coverage = {CF_CLIENT | CF_SERVER, "prvm_coverage", "0", "report and count coverage events (1: per-function, 2: coverage() builtin, 4: per-statement)"}

Definition at line 39 of file prvm_edict.c.

39{CF_CLIENT | CF_SERVER, "prvm_coverage", "0", "report and count coverage events (1: per-function, 2: coverage() builtin, 4: per-statement)"};

Referenced by CLVM_ExecuteProgram(), PRVM_ChildProfile_f(), PRVM_Init(), PRVM_PrintFunctionStatements(), PRVM_Profile_f(), SVVM_ExecuteProgram(), VM_coverage(), and while().

◆ prvm_errordump

cvar_t prvm_errordump = {CF_CLIENT | CF_SERVER, "prvm_errordump", "0", "write a savegame on crash to crash-server.dmp"}

Definition at line 44 of file prvm_edict.c.

44{CF_CLIENT | CF_SERVER, "prvm_errordump", "0", "write a savegame on crash to crash-server.dmp"};

Referenced by PRVM_Crash(), and PRVM_Init().

◆ prvm_gameplayfix_div0is0

cvar_t prvm_gameplayfix_div0is0 = {CF_SERVER, "prvm_gameplayfix_div0is0", "0", "When set to 1, floating point division by 0 will return zero instead of returning the IEEE standardized result (likely nan or inf). Other ways of getting non-finite values are not affected, and the warning will still print."}

Definition at line 57 of file prvm_edict.c.

57{CF_SERVER, "prvm_gameplayfix_div0is0", "0", "When set to 1, floating point division by 0 will return zero instead of returning the IEEE standardized result (likely nan or inf). Other ways of getting non-finite values are not affected, and the warning will still print."};

Referenced by PRVM_Init(), and while().

◆ prvm_garbagecollection_enable

cvar_t prvm_garbagecollection_enable = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_enable", "1", "automatically scan for and free resources that are not referenced by the code being executed in the VM"}

Definition at line 48 of file prvm_edict.c.

48{CF_CLIENT | CF_SERVER, "prvm_garbagecollection_enable", "1", "automatically scan for and free resources that are not referenced by the code being executed in the VM"};

Referenced by PRVM_GarbageCollection(), PRVM_Init(), and while().

◆ prvm_garbagecollection_notify

cvar_t prvm_garbagecollection_notify = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_notify", "0", "print out a notification for each resource freed by garbage collection (set developer >= 1 to see these)"}

Definition at line 49 of file prvm_edict.c.

49{CF_CLIENT | CF_SERVER, "prvm_garbagecollection_notify", "0", "print out a notification for each resource freed by garbage collection (set developer >= 1 to see these)"};

Referenced by PRVM_GarbageCollection(), and PRVM_Init().

◆ prvm_garbagecollection_scan_limit

cvar_t prvm_garbagecollection_scan_limit = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_scan_limit", "50000", "scan this many fields or resources per second to free up unreferenced resources"}

At 50k in Xonotic with 8 bots scans take about: 24s server, 25s menu, 9s client.

At 50k in Quake 1.5: 2.2s server, 0.14s client. At 50k impact on high FPS benchmarks is negligible, at 100k impact is low but measurable.

Definition at line 53 of file prvm_edict.c.

53{CF_CLIENT | CF_SERVER, "prvm_garbagecollection_scan_limit", "50000", "scan this many fields or resources per second to free up unreferenced resources"};

Referenced by PRVM_GarbageCollection(), and PRVM_Init().

◆ prvm_garbagecollection_strings

cvar_t prvm_garbagecollection_strings = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_strings", "1", "automatically call strunzone() on strings that are not referenced"}

Definition at line 54 of file prvm_edict.c.

54{CF_CLIENT | CF_SERVER, "prvm_garbagecollection_strings", "1", "automatically call strunzone() on strings that are not referenced"};

Referenced by PRVM_GarbageCollection(), and PRVM_Init().

◆ prvm_language

cvar_t prvm_language = {CF_CLIENT | CF_SERVER | CF_ARCHIVE, "prvm_language", "", "when set, loads PROGSFILE.LANGUAGENAME.po and common.LANGUAGENAME.po for string translations; when set to dump, PROGSFILE.pot is written from the strings in the progs"}

Definition at line 33 of file prvm_edict.c.

33{CF_CLIENT | CF_SERVER | CF_ARCHIVE, "prvm_language", "", "when set, loads PROGSFILE.LANGUAGENAME.po and common.LANGUAGENAME.po for string translations; when set to dump, PROGSFILE.pot is written from the strings in the progs"};
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53

Referenced by PRVM_Init(), and PRVM_Prog_Load().

◆ prvm_leaktest

cvar_t prvm_leaktest = {CF_CLIENT | CF_SERVER, "prvm_leaktest", "0", "try to detect memory leaks in strings or entities"}

Definition at line 41 of file prvm_edict.c.

41{CF_CLIENT | CF_SERVER, "prvm_leaktest", "0", "try to detect memory leaks in strings or entities"};

Referenced by PRVM_Init(), and PRVM_Prog_Init().

◆ prvm_leaktest_follow_targetname

cvar_t prvm_leaktest_follow_targetname = {CF_CLIENT | CF_SERVER, "prvm_leaktest_follow_targetname", "0", "if set, target/targetname links are considered when leak testing; this should normally not be required, as entities created during startup - e.g. info_notnull - are never considered leaky"}

Definition at line 42 of file prvm_edict.c.

42{CF_CLIENT | CF_SERVER, "prvm_leaktest_follow_targetname", "0", "if set, target/targetname links are considered when leak testing; this should normally not be required, as entities created during startup - e.g. info_notnull - are never considered leaky"};

Referenced by PRVM_Init(), and PRVM_IsEdictReferenced().

◆ prvm_leaktest_ignore_classnames

cvar_t prvm_leaktest_ignore_classnames = {CF_CLIENT | CF_SERVER, "prvm_leaktest_ignore_classnames", "", "classnames of entities to NOT leak check because they are found by find(world, classname, ...) but are actually spawned by QC code (NOT map entities)"}

Definition at line 43 of file prvm_edict.c.

43{CF_CLIENT | CF_SERVER, "prvm_leaktest_ignore_classnames", "", "classnames of entities to NOT leak check because they are found by find(world, classname, ...) but are actually spawned by QC code (NOT map entities)"};

Referenced by PRVM_Init(), and PRVM_IsEdictRelevant().

◆ prvm_prog_list

◆ prvm_reuseedicts_always_allow

double prvm_reuseedicts_always_allow = 0
static

Definition at line 59 of file prvm_edict.c.

Referenced by PRVM_ED_CanAlloc(), and PRVM_ED_LoadFromFile().

◆ prvm_reuseedicts_neverinsameframe

cvar_t prvm_reuseedicts_neverinsameframe = {CF_CLIENT | CF_SERVER, "prvm_reuseedicts_neverinsameframe", "1", "never allows re-use of freed entity slots during same frame"}

Definition at line 47 of file prvm_edict.c.

47{CF_CLIENT | CF_SERVER, "prvm_reuseedicts_neverinsameframe", "1", "never allows re-use of freed entity slots during same frame"};

Referenced by PRVM_ED_CanAlloc(), and PRVM_Init().

◆ prvm_reuseedicts_startuptime

cvar_t prvm_reuseedicts_startuptime = {CF_CLIENT | CF_SERVER, "prvm_reuseedicts_startuptime", "2", "allows immediate re-use of freed entity slots during start of new level (value in seconds)"}

Definition at line 46 of file prvm_edict.c.

46{CF_CLIENT | CF_SERVER, "prvm_reuseedicts_startuptime", "2", "allows immediate re-use of freed entity slots during start of new level (value in seconds)"};

Referenced by PRVM_ED_CanAlloc(), and PRVM_Init().

◆ prvm_runawaycheck

qbool prvm_runawaycheck = true

Definition at line 60 of file prvm_edict.c.

Referenced by Cbuf_Execute(), PRVM_Init(), and while().

◆ prvm_statementprofiling

cvar_t prvm_statementprofiling = {CF_CLIENT | CF_SERVER, "prvm_statementprofiling", "0", "counts how many times each QuakeC statement has been executed, these counts are displayed in prvm_printfunction output (if enabled)"}

Definition at line 37 of file prvm_edict.c.

37{CF_CLIENT | CF_SERVER, "prvm_statementprofiling", "0", "counts how many times each QuakeC statement has been executed, these counts are displayed in prvm_printfunction output (if enabled)"};

Referenced by PRVM_Init(), and PRVM_PrintStatement().

◆ prvm_stringdebug

cvar_t prvm_stringdebug = {CF_CLIENT | CF_SERVER, "prvm_stringdebug", "0", "Print debug and warning messages related to strings"}

Definition at line 55 of file prvm_edict.c.

55{CF_CLIENT | CF_SERVER, "prvm_stringdebug", "0", "Print debug and warning messages related to strings"};

Referenced by PRVM_GetString(), and PRVM_Init().

◆ prvm_timeprofiling

cvar_t prvm_timeprofiling = {CF_CLIENT | CF_SERVER, "prvm_timeprofiling", "0", "counts how long each function has been executed, these counts are displayed in prvm_profile output (if enabled)"}

Definition at line 38 of file prvm_edict.c.

38{CF_CLIENT | CF_SERVER, "prvm_timeprofiling", "0", "counts how long each function has been executed, these counts are displayed in prvm_profile output (if enabled)"};

Referenced by CLVM_ExecuteProgram(), PRVM_Init(), PRVM_Profile(), and SVVM_ExecuteProgram().

◆ prvm_traceqc

cvar_t prvm_traceqc = {CF_CLIENT | CF_SERVER, "prvm_traceqc", "0", "prints every QuakeC statement as it is executed (only for really thorough debugging!)"}

Definition at line 35 of file prvm_edict.c.

35{CF_CLIENT | CF_SERVER, "prvm_traceqc", "0", "prints every QuakeC statement as it is executed (only for really thorough debugging!)"};

Referenced by CLVM_ExecuteProgram(), PRVM_Init(), and SVVM_ExecuteProgram().

◆ prvm_type_size

int prvm_type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4}

for consistency : I think a goal of this sub-project is to make the new vm mostly independent from the old one, thus if it's necessary, I copy everything

Definition at line 29 of file prvm_edict.c.

29{1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
int string_t
Definition pr_comp.h:27

Referenced by PRVM_ED_Print(), PRVM_ED_Write(), PRVM_Fields_f(), and VM_getentityfieldstring().

◆ sv_entfields_noescapes

cvar_t sv_entfields_noescapes = {CF_SERVER, "sv_entfields_noescapes", "wad", "Space-separated list of fields in which backslashes won't be parsed as escapes when loading entities from .bsp or .ent files. This is a workaround for buggy maps with unescaped backslashes used as path separators (only forward slashes are allowed in Quake VFS paths)."}

Definition at line 56 of file prvm_edict.c.

56{CF_SERVER, "sv_entfields_noescapes", "wad", "Space-separated list of fields in which backslashes won't be parsed as escapes when loading entities from .bsp or .ent files. This is a workaround for buggy maps with unescaped backslashes used as path separators (only forward slashes are allowed in Quake VFS paths)."};

Referenced by PRVM_ED_ParseEdict(), and PRVM_Init().