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 1688 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 *field)
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 *function)
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 *global)
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 3459 of file prvm_edict.c.

3460{
3461 int i;
3462 char *s;
3463 if (!bufferlength)
3464 {
3465 if (pointer)
3466 *pointer = NULL;
3467 return 0;
3468 }
3469 for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
3470 if (!prog->knownstrings[i])
3471 break;
3472 s = (char *)PRVM_Alloc(bufferlength);
3474 if(prog->leaktest_active)
3476 if (pointer)
3477 *pointer = (char *)(prog->knownstrings[i]);
3478 return PRVM_KNOWNSTRINGBASE + i;
3479}
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
int i
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, i, 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 3000 of file prvm_edict.c.

3001{
3002 char vabuf[1024];
3003 Con_Printf("PRVM_Breakpoint: %s\n", text);
3004 PRVM_PrintState(prog, stack_index);
3006 SV_Savegame_to(prog, va(vabuf, sizeof(vabuf), "breakpoint-%s.dmp", prog->name));
3007}
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
int integer
Definition cvar.h:73
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
Definition progsvm.h:700

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

Referenced by PRVM_Watchpoint(), and while().

◆ PRVM_Breakpoint_f()

static void PRVM_Breakpoint_f ( cmd_state_t * cmd)
static

Definition at line 3105 of file prvm_edict.c.

3106{
3107 prvm_prog_t *prog;
3108
3109 if( Cmd_Argc(cmd) == 2 ) {
3110 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
3111 return;
3112 {
3113 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3114 debug->break_statement[0] = 0;
3115 }
3117 return;
3118 }
3119 if( Cmd_Argc(cmd) != 3 ) {
3120 Con_Printf( "prvm_breakpoint <program name> <function name | statement>\n" );
3121 return;
3122 }
3123
3124 if (!(prog = PRVM_ProgFromString(Cmd_Argv(cmd, 1))))
3125 return;
3126
3127 {
3128 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3129 dp_strlcpy(debug->break_statement, Cmd_Argv(cmd, 2), sizeof(debug->break_statement));
3130 }
3132}
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,...)
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
prvm_prog_t prvm_prog_list[PRVM_PROG_MAX]
Definition prvm_edict.c:27
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 3345 of file prvm_edict.c.

3346{
3347 const char *old;
3349 if (i < 0 || i >= prog->numknownstrings)
3350 prog->error_cmd("PRVM_ChangeEngineString: string index %i is out of bounds", i);
3351 else if ((prog->knownstrings_flags[i] & KNOWNSTRINGFLAG_ENGINE) == 0)
3352 prog->error_cmd("PRVM_ChangeEngineString: string index %i is not an engine string", i);
3353 old = prog->knownstrings[i];
3354 prog->knownstrings[i] = s;
3355 return old;
3356}
#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, i, 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, i, 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 1484 of file prvm_edict.c.

1485{
1486 if(!ent->free)
1487 if (PRVM_serverfunction(SV_OnEntityPostSpawnFunction))
1488 {
1489 // self = ent
1492 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPostSpawnFunction), "QC function SV_OnEntityPostSpawnFunction is missing");
1493 }
1494}
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
double time
Definition server.h:76

References prvm_prog_t::ExecuteProgram, prvm_edict_t::free, PRVM_EDICT_TO_PROG, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, server_t::time, 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 1389 of file prvm_edict.c.

1390{
1391 if (PRVM_serverfunction(SV_OnEntityPreSpawnFunction))
1392 {
1393 // self = ent
1396 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityPreSpawnFunction), "QC function SV_OnEntityPreSpawnFunction is missing");
1397 }
1398}

References prvm_prog_t::ExecuteProgram, PRVM_EDICT_TO_PROG, PRVM_serverfunction, PRVM_serverglobaledict, PRVM_serverglobalfloat, self, sv, server_t::time, 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 1400 of file prvm_edict.c.

1401{
1402 const char *funcname;
1403 mfunction_t *func;
1404 prvm_eval_t *fulldata = NULL;
1405 char vabuf[1024];
1406
1407//
1408// immediately call spawn function, but only if there is a self global and a classname
1409//
1410 if (!ent->free)
1411 {
1412 if (!PRVM_alledictstring(ent, classname))
1413 {
1414 Con_Print("No classname for:\n");
1415 PRVM_ED_Print(prog, ent, NULL);
1416 PRVM_ED_Free (prog, ent);
1417 return false;
1418 }
1419 /*
1420 * This is required for FTE compatibility (FreeCS).
1421 * It copies the key/value pairs themselves into a
1422 * global for QC to parse on its own.
1423 */
1424 else if (data && start)
1425 {
1426 if((fulldata = PRVM_ED_FindGlobalEval(prog, "__fullspawndata")))
1427 {
1428 const char *in;
1429 char *spawndata;
1430 fulldata->string = PRVM_AllocString(prog, data - start + 1, &spawndata);
1431 for(in = start; in < data; )
1432 {
1433 char c = *in++;
1434 if(c == '\n')
1435 *spawndata++ = '\t';
1436 else
1437 *spawndata++ = c;
1438 }
1439 *spawndata = 0;
1440 }
1441 }
1442
1443 // look for the spawn function
1444 funcname = PRVM_GetString(prog, PRVM_alledictstring(ent, classname));
1445 func = PRVM_ED_FindFunction (prog, va(vabuf, sizeof(vabuf), "spawnfunc_%s", funcname));
1446 if(!func)
1447 if(!PRVM_allglobalfloat(require_spawnfunc_prefix))
1448 func = PRVM_ED_FindFunction (prog, funcname);
1449
1450 if (!func)
1451 {
1452 // check for OnEntityNoSpawnFunction
1453 if (PRVM_serverfunction(SV_OnEntityNoSpawnFunction))
1454 {
1455 // self = ent
1458 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_OnEntityNoSpawnFunction), "QC function SV_OnEntityNoSpawnFunction is missing");
1459 }
1460 else
1461 {
1462
1463 Con_DPrint("No spawn function for:\n");
1464 if (developer.integer > 0) // don't confuse non-developers with errors
1465 PRVM_ED_Print(prog, ent, NULL);
1466
1467 PRVM_ED_Free (prog, ent);
1468 return false; // not included in "inhibited" count
1469 }
1470 }
1471 else
1472 {
1473 // self = ent
1476 prog->ExecuteProgram(prog, func - prog->functions, "");
1477 }
1478 return true;
1479 }
1480 PRVM_ED_Free(prog, ent);
1481 return false;
1482}
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, cvar_t::integer, 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, server_t::time, 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;
248 return true;
250 return false; // never allow reuse in same frame (causes networking trouble)
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
float value
Definition cvar.h:74
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h: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, cvar_t::integer, prvm_reuseedicts_always_allow, prvm_reuseedicts_neverinsameframe, prvm_reuseedicts_startuptime, host_static_t::realtime, prvm_prog_t::starttime, and cvar_t::value.

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;
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::@30 fields
union prvm_edict_t::@29 priv
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(), host_static_t::realtime, 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()

static 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()

static 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:416
uint32_t type
Definition pr_comp.h:414

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_Init().

◆ PRVM_ED_EdictSet_f()

static 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) != 5)
1256 {
1257 Con_Print("prvm_edictset <program name> <edict number> <field> <value>\n");
1258 return;
1259 }
1260
1261 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
1262 return;
1263
1264 ed = PRVM_EDICT_NUM(atoi(Cmd_Argv(cmd, 2)));
1265
1266 if((key = PRVM_ED_FindField(prog, Cmd_Argv(cmd, 3))) == 0)
1267 Con_Printf("Key %s not found!\n", Cmd_Argv(cmd, 3));
1268 else
1269 PRVM_ED_ParseEpair(prog, ed, key, Cmd_Argv(cmd, 4), true);
1270}
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

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), 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, i, 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:417

References prvm_prog_t::fielddefs, i, 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:460
int numfunctions
Definition progsvm.h:566

References prvm_prog_t::functions, i, 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, i, 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::@31 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, host_static_t::realtime, 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()

static 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, i, NULL, prvm_prog_t::numglobaldefs, mdef_t::ofs, and ofs.

Referenced by PRVM_GlobalString(), and PRVM_GlobalStringNoContents().

◆ PRVM_ED_GlobalGet_f()

static 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 1511 of file prvm_edict.c.

1512{
1513 prvm_edict_t *ent;
1514 const char *start;
1515 int parsed, inhibited, spawned, died;
1516
1517 parsed = 0;
1518 inhibited = 0;
1519 spawned = 0;
1520 died = 0;
1521
1523
1524 // parse ents
1525 while (1)
1526 {
1527 start = data;
1528
1529 // parse the opening brace
1530 if (!COM_ParseToken_Simple(&data, false, false, true))
1531 break;
1532 if (com_token[0] != '{')
1533 prog->error_cmd("PRVM_ED_LoadFromFile: %s: found %s when expecting {", prog->name, com_token);
1534
1535 // CHANGED: this is not conform to PR_LoadFromFile
1536 if(prog->loadintoworld)
1537 {
1538 prog->loadintoworld = false;
1539 ent = PRVM_EDICT_NUM(0);
1540 }
1541 else
1542 ent = PRVM_ED_Alloc(prog);
1543
1544 // clear it
1545 if (ent != prog->edicts) // hack
1546 memset (ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
1547
1548 data = PRVM_ED_ParseEdict (prog, data, ent, false);
1549 parsed++;
1550
1551 // remove the entity ?
1552 if(!prog->load_edict(prog, ent))
1553 {
1554 PRVM_ED_Free(prog, ent);
1555 inhibited++;
1556 continue;
1557 }
1558
1560
1561 if(ent->free)
1562 {
1563 inhibited++;
1564 continue;
1565 }
1566
1567 SV_LinkEdict(ent);
1568
1569 if(!PRVM_ED_CallSpawnFunction(prog, ent, data, start))
1570 continue;
1571
1573
1574 spawned++;
1575 if (ent->free)
1576 died++;
1577 }
1578
1579 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);
1580
1582}
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, host_static_t::realtime, 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 1281 of file prvm_edict.c.

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

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, cvar_t::integer, n, prvm_prog_t::name, PRVM_ED_FindField(), PRVM_ED_ParseEpair(), host_static_t::realtime, cvar_t::string, 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);
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:421
@ 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
#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, i, 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
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
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, cvar_t::integer, 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
692 type = d->type & ~DEF_SAVEGLOBAL;
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
#define PRVM_NUM_FOR_EDICT(e)
Definition progsvm.h:870
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
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(), dp_strlcat, dpsnprintf(), prvm_prog_t::fielddefs, prvm_edict_t::fields, prvm_edict_t::fp, prvm_edict_t::free, i, 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()

static 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(), i, 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}

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

Referenced by PRVM_Init().

◆ 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
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
772 type = d->type & ~DEF_SAVEGLOBAL;
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:3273
int FS_Print(qfile_t *file, const char *msg)
Definition fs.c:3261
const char * statestring
printed together with backtraces
Definition progsvm.h:717

References Con_Printf(), developer_entityparsing, f, prvm_prog_t::fielddefs, prvm_edict_t::fields, prvm_edict_t::fp, prvm_edict_t::free, FS_Print(), FS_Printf(), i, cvar_t::integer, 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;
917 type &= ~DEF_SAVEGLOBAL;
918
919 if (type != ev_string && type != ev_float && type != ev_entity)
920 continue;
921
922 name = PRVM_GetString(prog, def->s_name);
923
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, i, cvar_t::integer, 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 3275 of file prvm_edict.c.

3276{
3277 prog->error_cmd("PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", prog->name, n, filename, fileline);
3278 return 0;
3279}

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

◆ PRVM_EdictWatchpoint_f()

static void PRVM_EdictWatchpoint_f ( cmd_state_t * cmd)
static

Definition at line 3163 of file prvm_edict.c.

3164{
3165 prvm_prog_t *prog;
3166
3167 if( Cmd_Argc(cmd) == 2 ) {
3168 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
3169 return;
3170 {
3171 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3172 debug->watch_field[0] = 0;
3173 }
3175 return;
3176 }
3177 if( Cmd_Argc(cmd) != 4 ) {
3178 Con_Printf( "prvm_edictwatchpoint <program name> <edict number> <field name>\n" );
3179 return;
3180 }
3181
3182 if (!(prog = PRVM_ProgFromString(Cmd_Argv(cmd, 1))))
3183 return;
3184
3185 {
3186 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3187 debug->watch_edict = atoi(Cmd_Argv(cmd, 2));
3188 dp_strlcpy(debug->watch_field, Cmd_Argv(cmd, 3), sizeof(debug->watch_field));
3189 }
3191}
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()

static void PRVM_Fields_f ( cmd_state_t * cmd)
static

Definition at line 2773 of file prvm_edict.c.

2774{
2775 prvm_prog_t *prog;
2776 int i, j, ednum, used, usedamount;
2777 int *counts;
2778 char tempstring[MAX_INPUTLINE], tempstring2[260];
2779 const char *name;
2780 prvm_edict_t *ed;
2781 mdef_t *d;
2782 prvm_eval_t *val;
2783
2784 // TODO
2785 /*
2786 if (!sv.active)
2787 {
2788 Con_Print("no progs loaded\n");
2789 return;
2790 }
2791 */
2792
2793 if(Cmd_Argc(cmd) != 2)
2794 {
2795 Con_Print("prvm_fields <program name>\n");
2796 return;
2797 }
2798
2799 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
2800 return;
2801
2802 counts = (int *)Mem_Alloc(tempmempool, prog->numfielddefs * sizeof(int));
2803 for (ednum = 0;ednum < prog->max_edicts;ednum++)
2804 {
2805 ed = PRVM_EDICT_NUM(ednum);
2806 if (ed->free)
2807 continue;
2808 for (i = 1;i < prog->numfielddefs;i++)
2809 {
2810 d = &prog->fielddefs[i];
2811 name = PRVM_GetString(prog, d->s_name);
2812 if (name[strlen(name)-2] == '_')
2813 continue; // skip _x, _y, _z vars
2814 val = (prvm_eval_t *)(ed->fields.fp + d->ofs);
2815 // if the value is still all 0, skip the field
2816 for (j = 0;j < prvm_type_size[d->type & ~DEF_SAVEGLOBAL];j++)
2817 {
2818 if (val->ivector[j])
2819 {
2820 counts[i]++;
2821 break;
2822 }
2823 }
2824 }
2825 }
2826 used = 0;
2827 usedamount = 0;
2828 tempstring[0] = 0;
2829 for (i = 0;i < prog->numfielddefs;i++)
2830 {
2831 d = &prog->fielddefs[i];
2832 name = PRVM_GetString(prog, d->s_name);
2833 if (name[strlen(name)-2] == '_')
2834 continue; // skip _x, _y, _z vars
2835 switch(d->type & ~DEF_SAVEGLOBAL)
2836 {
2837 case ev_string:
2838 dp_strlcat(tempstring, "string ", sizeof(tempstring));
2839 break;
2840 case ev_entity:
2841 dp_strlcat(tempstring, "entity ", sizeof(tempstring));
2842 break;
2843 case ev_function:
2844 dp_strlcat(tempstring, "function ", sizeof(tempstring));
2845 break;
2846 case ev_field:
2847 dp_strlcat(tempstring, "field ", sizeof(tempstring));
2848 break;
2849 case ev_void:
2850 dp_strlcat(tempstring, "void ", sizeof(tempstring));
2851 break;
2852 case ev_float:
2853 dp_strlcat(tempstring, "float ", sizeof(tempstring));
2854 break;
2855 case ev_vector:
2856 dp_strlcat(tempstring, "vector ", sizeof(tempstring));
2857 break;
2858 case ev_pointer:
2859 dp_strlcat(tempstring, "pointer ", sizeof(tempstring));
2860 break;
2861 default:
2862 dpsnprintf (tempstring2, sizeof(tempstring2), "bad type %i ", d->type & ~DEF_SAVEGLOBAL);
2863 dp_strlcat(tempstring, tempstring2, sizeof(tempstring));
2864 break;
2865 }
2866 if (strlen(name) > sizeof(tempstring2)-4)
2867 {
2868 memcpy (tempstring2, name, sizeof(tempstring2)-4);
2869 tempstring2[sizeof(tempstring2)-4] = tempstring2[sizeof(tempstring2)-3] = tempstring2[sizeof(tempstring2)-2] = '.';
2870 tempstring2[sizeof(tempstring2)-1] = 0;
2871 name = tempstring2;
2872 }
2873 dp_strlcat(tempstring, name, sizeof(tempstring));
2874 for (j = (int)strlen(name);j < 25;j++)
2875 dp_strlcat(tempstring, " ", sizeof(tempstring));
2876 dpsnprintf(tempstring2, sizeof(tempstring2), "%5d", counts[i]);
2877 dp_strlcat(tempstring, tempstring2, sizeof(tempstring));
2878 dp_strlcat(tempstring, "\n", sizeof(tempstring));
2879 if (strlen(tempstring) >= sizeof(tempstring)/2)
2880 {
2881 Con_Print(tempstring);
2882 tempstring[0] = 0;
2883 }
2884 if (counts[i])
2885 {
2886 used++;
2887 usedamount += prvm_type_size[d->type & ~DEF_SAVEGLOBAL];
2888 }
2889 }
2890 Mem_Free(counts);
2891 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);
2892}
@ 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, i, 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()

static void PRVM_FindOffsets ( prvm_prog_t * prog)
static

Definition at line 1584 of file prvm_edict.c.

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

3482{
3483 if (num == 0)
3484 prog->error_cmd("PRVM_FreeString %s: attempt to free a NULL string", prog->name);
3485 else if (num >= 0 && num < prog->stringssize)
3486 prog->error_cmd("PRVM_FreeString %s: attempt to free a constant string", prog->name);
3487 else if (num >= PRVM_KNOWNSTRINGBASE && num < PRVM_KNOWNSTRINGBASE + prog->numknownstrings)
3488 {
3489 num = num - PRVM_KNOWNSTRINGBASE;
3490 if (!prog->knownstrings[num])
3491 prog->error_cmd("PRVM_FreeString %s: attempt to free a non-existent or already freed string", prog->name);
3492 if (!prog->knownstrings_flags[num])
3493 prog->error_cmd("PRVM_FreeString %s: attempt to free a string owned by the engine", prog->name);
3494 PRVM_Free((char *)prog->knownstrings[num]);
3495 if(prog->leaktest_active)
3496 if(prog->knownstrings_origin[num])
3497 PRVM_Free((char *)prog->knownstrings_origin[num]);
3498 prog->knownstrings[num] = NULL;
3499 prog->knownstrings_flags[num] = 0;
3500 prog->firstfreeknownstring = min(prog->firstfreeknownstring, num);
3501 }
3502 else
3503 prog->error_cmd("PRVM_FreeString %s: invalid string offset %i", prog->name, num);
3504}
#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()

static 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()

static 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()

static 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()

static 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 3757 of file prvm_edict.c.

3758{
3762 return;
3763 // philosophy:
3764 // we like to limit how much scanning we do so it doesn't put a significant
3765 // burden on the cpu, so each of these are not complete scans, we also like
3766 // to have consistent cpu usage so we do a bit of work on each category of
3767 // leaked object every frame
3768 switch (gc->stage)
3769 {
3770 case PRVM_GC_START:
3771 gc->stage++;
3772 break;
3774 for (; gc->globals_mark_progress < prog->numglobaldefs && (limit--) > 0; gc->globals_mark_progress++)
3775 {
3776 mdef_t *d = &prog->globaldefs[gc->globals_mark_progress];
3777 switch (d->type)
3778 {
3779 case ev_string:
3780 {
3781 prvm_int_t s = prog->globals.ip[d->ofs];
3782 if (s & PRVM_KNOWNSTRINGBASE)
3783 {
3785 if (!prog->knownstrings[num])
3786 {
3787 // invalid
3788 Con_DPrintf("PRVM_GarbageCollection: Found bogus strzone reference in global %i (global name: \"%s\"), erasing reference", d->ofs, PRVM_GetString(prog, d->s_name));
3789 prog->globals.ip[d->ofs] = 0;
3790 continue;
3791 }
3793 }
3794 }
3795 break;
3796 default:
3797 break;
3798 }
3799 }
3800 if (gc->globals_mark_progress >= prog->numglobaldefs)
3801 gc->stage++;
3802 break;
3804 for (; gc->fields_mark_progress < prog->numfielddefs && limit > 0;)
3805 {
3806 mdef_t *d = &prog->fielddefs[gc->fields_mark_progress];
3807 switch (d->type)
3808 {
3809 case ev_string:
3810 //for (gc-> entityindex = 0; entityindex < prog->num_edicts; entityindex++)
3811 for (;gc->fields_mark_progress_entity < prog->num_edicts && (limit--) > 0;gc->fields_mark_progress_entity++)
3812 {
3813 int entityindex = gc->fields_mark_progress_entity;
3814 prvm_int_t s = prog->edictsfields.ip[entityindex * prog->entityfields + d->ofs];
3815 if (s & PRVM_KNOWNSTRINGBASE)
3816 {
3818 if (!prog->knownstrings[num])
3819 {
3820 // invalid
3821 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));
3822 prog->edictsfields.ip[entityindex * prog->entityfields + d->ofs] = 0;
3823 continue;
3824 }
3826 }
3827 }
3828 if (gc->fields_mark_progress_entity >= prog->num_edicts)
3829 {
3832 }
3833 break;
3834 default:
3837 break;
3838 }
3839 }
3840 if (gc->fields_mark_progress >= prog->numfielddefs)
3841 gc->stage++;
3842 break;
3844 // free any strzone'd strings that are not marked
3846 {
3847 gc->stage++;
3848 break;
3849 }
3850 for (;gc->knownstrings_sweep_progress < prog->numknownstrings && (limit--) > 0;gc->knownstrings_sweep_progress++)
3851 {
3852 int num = gc->knownstrings_sweep_progress;
3853 if (prog->knownstrings[num] && (prog->knownstrings_flags[num] & (KNOWNSTRINGFLAG_GCMARK | KNOWNSTRINGFLAG_ENGINE)) == 0)
3854 {
3856 {
3857 // string has been marked for pruning two passes in a row
3859 Con_DPrintf("prvm_garbagecollection_notify: %s: freeing unreferenced string %i: \"%s\"\n", prog->name, num, prog->knownstrings[num]);
3860 Mem_Free((char *)prog->knownstrings[num]);
3861 prog->knownstrings[num] = NULL;
3862 prog->knownstrings_flags[num] = 0;
3863 prog->firstfreeknownstring = min(prog->firstfreeknownstring, num);
3864 }
3865 else
3866 {
3867 // mark it for pruning next pass
3869 }
3870 }
3871 }
3873 gc->stage++;
3874 break;
3875 case PRVM_GC_RESET:
3876 default:
3877 memset(gc, 0, sizeof(*gc));
3878// 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);
3879 }
3880}
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
double realframetime
Definition client.h:871
union prvm_prog_t::@32 edictsfields
prvm_int_t * ip
Definition progsvm.h:581
prvm_prog_garbagecollection_state_t gc
garbage collection status
Definition progsvm.h:599
double frametime
Definition server.h:77

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, server_t::frametime, prvm_prog_t::gc, prvm_prog_t::globaldefs, prvm_prog_t::globals, prvm_prog_garbagecollection_state_t::globals_mark_progress, cvar_t::integer, 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, client_state_t::realframetime, 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 3283 of file prvm_edict.c.

3284{
3285 if (num < 0)
3286 {
3287 // invalid
3289 VM_Warning(prog, "PRVM_GetString: Invalid string offset (%i < 0)\n", num);
3290 return "";
3291 }
3292 else if (num < prog->stringssize)
3293 {
3294 // constant string from progs.dat
3295 return prog->strings + num;
3296 }
3297 else if (num <= prog->stringssize + prog->tempstringsbuf.maxsize)
3298 {
3299 // tempstring returned by engine to QC (becomes invalid after returning to engine)
3300 num -= prog->stringssize;
3301 if (num < prog->tempstringsbuf.cursize)
3302 return (char *)prog->tempstringsbuf.data + num;
3303 else
3304 {
3306 VM_Warning(prog, "PRVM_GetString: Invalid temp-string offset (%i >= %i prog->tempstringsbuf.cursize)\n", num, prog->tempstringsbuf.cursize);
3307 return "";
3308 }
3309 }
3310 else if (num & PRVM_KNOWNSTRINGBASE)
3311 {
3312 // allocated string
3313 num = num - PRVM_KNOWNSTRINGBASE;
3314 if (num >= 0 && num < prog->numknownstrings)
3315 {
3316 if (!prog->knownstrings[num])
3317 {
3319 VM_Warning(prog, "PRVM_GetString: Invalid zone-string offset (%i has been freed)\n", num);
3320 return "";
3321 }
3322 // refresh the garbage collection on the string - this guards
3323 // against a certain sort of repeated migration to earlier
3324 // points in the scan that could otherwise result in the string
3325 // being freed for being unused
3326 prog->knownstrings_flags[num] = (prog->knownstrings_flags[num] & ~KNOWNSTRINGFLAG_GCPRUNE) | KNOWNSTRINGFLAG_GCMARK;
3327 return prog->knownstrings[num];
3328 }
3329 else
3330 {
3332 VM_Warning(prog, "PRVM_GetString: Invalid zone-string offset (%i >= %i)\n", num, prog->numknownstrings);
3333 return "";
3334 }
3335 }
3336 else
3337 {
3338 // invalid string offset
3340 VM_Warning(prog, "PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)\n", num, prog->stringssize);
3341 return "";
3342 }
3343}
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, cvar_t::integer, KNOWNSTRINGFLAG_GCMARK, 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()

static void PRVM_Global_f ( cmd_state_t * cmd)
static

Definition at line 2941 of file prvm_edict.c.

2942{
2943 prvm_prog_t *prog;
2944 mdef_t *global;
2945 char valuebuf[MAX_INPUTLINE];
2946 if( Cmd_Argc(cmd) != 3 ) {
2947 Con_Printf( "prvm_global <program name> <global name>\n" );
2948 return;
2949 }
2950
2951 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
2952 return;
2953
2954 global = PRVM_ED_FindGlobal( prog, Cmd_Argv(cmd, 2) );
2955 if( !global )
2956 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(cmd, 2), Cmd_Argv(cmd, 1) );
2957 else
2958 Con_Printf( "%s: %s\n", Cmd_Argv(cmd, 2), PRVM_ValueString( prog, (etype_t)global->type, PRVM_GLOBALFIELDVALUE(global->ofs), valuebuf, sizeof(valuebuf) ) );
2959}
#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()

static void PRVM_Globals_f ( cmd_state_t * cmd)
static

Definition at line 2894 of file prvm_edict.c.

2895{
2896 prvm_prog_t *prog;
2897 int i;
2898 const char *wildcard;
2899 int numculled;
2900 numculled = 0;
2901 // TODO
2902 /*if (!sv.active)
2903 {
2904 Con_Print("no progs loaded\n");
2905 return;
2906 }*/
2907 if(Cmd_Argc (cmd) < 2 || Cmd_Argc(cmd) > 3)
2908 {
2909 Con_Print("prvm_globals <program name> <optional name wildcard>\n");
2910 return;
2911 }
2912
2913 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
2914 return;
2915
2916 if( Cmd_Argc(cmd) == 3)
2917 wildcard = Cmd_Argv(cmd, 2);
2918 else
2919 wildcard = NULL;
2920
2921 Con_Printf("%s :", prog->name);
2922
2923 for (i = 0;i < prog->numglobaldefs;i++)
2924 {
2925 if(wildcard)
2926 if( !matchpattern( PRVM_GetString(prog, prog->globaldefs[i].s_name), wildcard, 1) )
2927 {
2928 numculled++;
2929 continue;
2930 }
2931 Con_Printf("%s\n", PRVM_GetString(prog, prog->globaldefs[i].s_name));
2932 }
2933 Con_Printf("%i global variables, %i culled, totalling %i bytes\n", prog->numglobals, numculled, prog->numglobals * 4);
2934}
int numglobals
Definition progsvm.h:568

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), prvm_prog_t::globaldefs, i, 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()

static void PRVM_GlobalSet_f ( cmd_state_t * cmd)
static

Definition at line 2966 of file prvm_edict.c.

2967{
2968 prvm_prog_t *prog;
2969 mdef_t *global;
2970 if( Cmd_Argc(cmd) != 4 ) {
2971 Con_Printf( "prvm_globalset <program name> <global name> <value>\n" );
2972 return;
2973 }
2974
2975 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
2976 return;
2977
2978 global = PRVM_ED_FindGlobal( prog, Cmd_Argv(cmd, 2) );
2979 if( !global )
2980 Con_Printf( "No global '%s' in %s!\n", Cmd_Argv(cmd, 2), Cmd_Argv(cmd, 1) );
2981 else
2982 PRVM_ED_ParseEpair( prog, NULL, global, Cmd_Argv(cmd, 3), true );
2983}

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()

static void PRVM_GlobalWatchpoint_f ( cmd_state_t * cmd)
static

Definition at line 3134 of file prvm_edict.c.

3135{
3136 prvm_prog_t *prog;
3137
3138 if( Cmd_Argc(cmd) == 2 ) {
3139 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
3140 return;
3141 {
3142 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3143 debug->watch_global[0] = 0;
3144 }
3146 return;
3147 }
3148 if( Cmd_Argc(cmd) != 3 ) {
3149 Con_Printf( "prvm_globalwatchpoint <program name> <global name>\n" );
3150 return;
3151 }
3152
3153 if (!(prog = PRVM_ProgFromString(Cmd_Argv(cmd, 1))))
3154 return;
3155
3156 {
3157 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3158 dp_strlcpy(debug->watch_global, Cmd_Argv(cmd, 2), sizeof(debug->watch_global));
3159 }
3161}
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 3198 of file prvm_edict.c.

3199{
3200 unsigned int i;
3201
3202 Cmd_AddCommand(CF_SHARED, "prvm_edict", PRVM_ED_PrintEdict_f, "print all data about an entity number in the selected VM (server, client, menu)");
3203 Cmd_AddCommand(CF_SHARED, "prvm_edicts", PRVM_ED_PrintEdicts_f, "prints all data about all entities in the selected VM (server, client, menu)");
3204 Cmd_AddCommand(CF_SHARED, "prvm_edictcount", PRVM_ED_Count_f, "prints number of active entities in the selected VM (server, client, menu)");
3205 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)");
3206 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");
3207 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)");
3208 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)");
3209 Cmd_AddCommand(CF_SHARED, "prvm_globals", PRVM_Globals_f, "prints all global variables in the selected VM (server, client, menu)");
3210 Cmd_AddCommand(CF_SHARED, "prvm_global", PRVM_Global_f, "prints value of a specified global variable in the selected VM (server, client, menu)");
3211 Cmd_AddCommand(CF_SHARED, "prvm_globalset", PRVM_GlobalSet_f, "sets value of a specified global variable in the selected VM (server, client, menu)");
3212 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)");
3213 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");
3214 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");
3215 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)");
3216 Cmd_AddCommand(CF_SHARED, "cl_cmd", PRVM_GameCommand_Client_f, "calls the client QC function GameCommand with the supplied string as argument");
3217 Cmd_AddCommand(CF_SHARED, "menu_cmd", PRVM_GameCommand_Menu_f, "calls the menu QC function GameCommand with the supplied string as argument");
3218 Cmd_AddCommand(CF_SHARED, "sv_cmd", PRVM_GameCommand_Server_f, "calls the server QC function GameCommand with the supplied string as argument");
3219 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");
3220 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");
3221 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");
3222
3243
3244 // COMMANDLINEOPTION: PRVM: -norunaway disables the runaway loop check (it might be impossible to exit DarkPlaces if used!)
3245 prvm_runawaycheck = !Sys_CheckParm("-norunaway");
3246
3247 //VM_Cmd_Init();
3248
3249 // LadyHavoc: report supported extensions
3250 Con_DPrintf("\nQuakeC extensions for server and client:");
3251 for (i = 0; vm_sv_extensions[i]; i++)
3253 Con_DPrintf("\n");
3254#ifdef CONFIG_MENU
3255 Con_DPrintf("\nQuakeC extensions for menu:");
3256 for (i = 0; vm_m_extensions[i]; i++)
3257 Con_DPrintf(" %s", vm_m_extensions[i]);
3258 Con_DPrintf("\n");
3259#endif
3260}
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)
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)
cvar_t prvm_coverage
Definition prvm_edict.c:39
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)
void PRVM_ED_PrintEdicts_f(cmd_state_t *cmd)
Definition prvm_edict.c:800
cvar_t prvm_leaktest
Definition prvm_edict.c:41
qbool prvm_runawaycheck
Definition prvm_edict.c:60
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)
cvar_t prvm_backtraceforwarnings
Definition prvm_edict.c:40
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
static void PRVM_ED_EdictGet_f(cmd_state_t *cmd)
int Sys_CheckParm(const char *parm)
Definition sys_shared.c:327

References CF_SHARED, Cmd_AddCommand(), Con_DPrintf(), Cvar_RegisterVariable(), i, 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()

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

Definition at line 3589 of file prvm_edict.c.

3590{
3591 int i, j;
3592 int edictnum = PRVM_NUM_FOR_EDICT(edict);
3593 const char *targetname = NULL;
3594
3597
3598 if(targetname)
3599 if(!*targetname) // ""
3600 targetname = NULL;
3601
3602 for(j = 0; j < prog->num_edicts; ++j)
3603 {
3605 if (ed->priv.required->mark < mark)
3606 continue;
3607 if(ed == edict)
3608 continue;
3609 if(targetname)
3610 {
3611 const char *target = PRVM_GetString(prog, PRVM_serveredictstring(ed, target));
3612 if(target)
3613 if(!strcmp(target, targetname))
3614 return true;
3615 }
3616 for (i=0; i<prog->numfielddefs; ++i)
3617 {
3618 mdef_t *d = &prog->fielddefs[i];
3619 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
3620 continue;
3621 if(edictnum == PRVM_EDICTFIELDEDICT(ed, d->ofs))
3622 return true;
3623 }
3624 }
3625
3626 return false;
3627}
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, i, cvar_t::integer, 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()

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

Definition at line 3537 of file prvm_edict.c.

3538{
3539 char vabuf[1024];
3540 char vabuf2[1024];
3541 if(PRVM_NUM_FOR_EDICT(edict) <= prog->reserved_edicts)
3542 return true; // world or clients
3543 if (edict->freetime <= prog->inittime)
3544 return true; // created during startup
3545 if (prog == SVVM_prog)
3546 {
3547 if(PRVM_serveredictfloat(edict, solid)) // can block other stuff, or is a trigger?
3548 return true;
3549 if(PRVM_serveredictfloat(edict, modelindex)) // visible ent?
3550 return true;
3551 if(PRVM_serveredictfloat(edict, effects)) // particle effect?
3552 return true;
3553 if(PRVM_serveredictfunction(edict, think)) // has a think function?
3554 if(PRVM_serveredictfloat(edict, nextthink) > 0) // that actually will eventually run?
3555 return true;
3557 return true;
3559 {
3560 if(strstr(va(vabuf, sizeof(vabuf), " %s ", prvm_leaktest_ignore_classnames.string), va(vabuf2, sizeof(vabuf2), " %s ", PRVM_GetString(prog, PRVM_serveredictstring(edict, classname)))))
3561 return true;
3562 }
3563 }
3564 else if (prog == CLVM_prog)
3565 {
3566 // TODO someone add more stuff here
3567 if(PRVM_clientedictfloat(edict, entnum)) // csqc networked
3568 return true;
3569 if(PRVM_clientedictfloat(edict, modelindex)) // visible ent?
3570 return true;
3571 if(PRVM_clientedictfloat(edict, effects)) // particle effect?
3572 return true;
3573 if(PRVM_clientedictfunction(edict, think)) // has a think function?
3574 if(PRVM_clientedictfloat(edict, nextthink) > 0) // that actually will eventually run?
3575 return true;
3577 {
3578 if(strstr(va(vabuf, sizeof(vabuf), " %s ", prvm_leaktest_ignore_classnames.string), va(vabuf2, sizeof(vabuf2), " %s ", PRVM_GetString(prog, PRVM_clientedictstring(edict, classname)))))
3579 return true;
3580 }
3581 }
3582 else
3583 {
3584 // menu prog does not have classnames
3585 }
3586 return false;
3587}
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, cvar_t::string, SVVM_prog, takedamage, and va().

Referenced by PRVM_MarkReferencedEdicts().

◆ PRVM_IsStringReferenced()

static qbool PRVM_IsStringReferenced ( prvm_prog_t * prog,
string_t string )
static

Definition at line 3506 of file prvm_edict.c.

3507{
3508 int i, j;
3509
3510 for (i = 0;i < prog->numglobaldefs;i++)
3511 {
3512 mdef_t *d = &prog->globaldefs[i];
3513 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_string)
3514 continue;
3515 if(string == PRVM_GLOBALFIELDSTRING(d->ofs))
3516 return true;
3517 }
3518
3519 for(j = 0; j < prog->num_edicts; ++j)
3520 {
3522 if (ed->free)
3523 continue;
3524 for (i=0; i<prog->numfielddefs; ++i)
3525 {
3526 mdef_t *d = &prog->fielddefs[i];
3527 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_string)
3528 continue;
3529 if(string == PRVM_EDICTFIELDSTRING(ed, d->ofs))
3530 return true;
3531 }
3532 }
3533
3534 return false;
3535}
#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, i, 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 3682 of file prvm_edict.c.

3683{
3684 int i, j;
3685 qbool leaked = false;
3686
3687 if(!prog->leaktest_active)
3688 return;
3689
3690 // 1. Strings
3691 for (i = 0; i < prog->numknownstrings; ++i)
3692 {
3693 if(prog->knownstrings[i])
3694 if(prog->knownstrings_flags[i])
3695 if(prog->knownstrings_origin[i])
3697 {
3698 Con_Printf("Unreferenced string found!\n Value: %s\n Origin: %s\n", prog->knownstrings[i], prog->knownstrings_origin[i]);
3699 leaked = true;
3700 }
3701 }
3702
3703 // 2. Edicts
3705 for(j = 0; j < prog->num_edicts; ++j)
3706 {
3708 if(ed->free)
3709 continue;
3710 if(!ed->priv.required->mark)
3712 {
3713 Con_Printf("Unreferenced edict found!\n Allocated at: %s\n", ed->priv.required->allocation_origin);
3714 PRVM_ED_Print(prog, ed, NULL);
3715 Con_Print("\n");
3716 leaked = true;
3717 }
3718
3719 ed->priv.required->mark = 0; // clear marks again when done
3720 }
3721
3722 for (i = 0; i < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); ++i)
3723 {
3725 if(stringbuffer)
3726 if(stringbuffer->origin)
3727 {
3728 Con_Printf("Open string buffer handle found!\n Allocated at: %s\n", stringbuffer->origin);
3729 leaked = true;
3730 }
3731 }
3732
3733 for(i = 0; i < PRVM_MAX_OPENFILES; ++i)
3734 {
3735 if(prog->openfiles[i])
3736 if(prog->openfiles_origin[i])
3737 {
3738 Con_Printf("Open file handle found!\n Allocated at: %s\n", prog->openfiles_origin[i]);
3739 leaked = true;
3740 }
3741 }
3742
3743 for(i = 0; i < PRVM_MAX_OPENSEARCHES; ++i)
3744 {
3745 if(prog->opensearches[i])
3746 if(prog->opensearches_origin[i])
3747 {
3748 Con_Printf("Open search handle found!\n Allocated at: %s\n", prog->opensearches_origin[i]);
3749 leaked = true;
3750 }
3751 }
3752
3753 if(!leaked)
3754 Con_Printf("Congratulations. No leaks found.\n");
3755}
#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, i, 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()

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

Definition at line 1968 of file prvm_edict.c.

1968 {
1969 fs_offset_t filesize;
1970 unsigned char *lno;
1971 unsigned int *header;
1972 char filename[512];
1973
1974 FS_StripExtension( progname, filename, sizeof( filename ) );
1975 dp_strlcat( filename, ".lno", sizeof( filename ) );
1976
1977 lno = FS_LoadFile( filename, tempmempool, false, &filesize );
1978 if( !lno ) {
1979 return;
1980 }
1981
1982/*
1983<Spike> SafeWrite (h, &lnotype, sizeof(int));
1984<Spike> SafeWrite (h, &version, sizeof(int));
1985<Spike> SafeWrite (h, &numglobaldefs, sizeof(int));
1986<Spike> SafeWrite (h, &numpr_globals, sizeof(int));
1987<Spike> SafeWrite (h, &numfielddefs, sizeof(int));
1988<Spike> SafeWrite (h, &numstatements, sizeof(int));
1989<Spike> SafeWrite (h, statement_linenums, numstatements*sizeof(int));
1990*/
1991 if ((unsigned int)filesize < (6 + prog->progs_numstatements) * sizeof(int))
1992 {
1993 Mem_Free(lno);
1994 return;
1995 }
1996
1997 header = (unsigned int *) lno;
1998 if (memcmp(lno, "LNOF", 4) == 0
1999 && LittleLong( header[ 1 ] ) == 1
2000 && (unsigned int)LittleLong( header[ 2 ] ) == (unsigned int)prog->progs_numglobaldefs
2001 && (unsigned int)LittleLong( header[ 3 ] ) == (unsigned int)prog->progs_numglobals
2002 && (unsigned int)LittleLong( header[ 4 ] ) == (unsigned int)prog->progs_numfielddefs
2003 && (unsigned int)LittleLong( header[ 5 ] ) == (unsigned int)prog->progs_numstatements)
2004 {
2005 prog->statement_linenums = (int *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof( int ) );
2006 memcpy( prog->statement_linenums, header + 6, prog->progs_numstatements * sizeof( int ) );
2007
2008 /* gmqcc suports columnums */
2009 if ((unsigned int)filesize > ((6 + 2 * prog->progs_numstatements) * sizeof( int )))
2010 {
2011 prog->statement_columnnums = (int *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof( int ) );
2012 memcpy( prog->statement_columnnums, header + 6 + prog->progs_numstatements, prog->progs_numstatements * sizeof( int ) );
2013 }
2014 }
2015 Mem_Free( lno );
2016}
#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:3540
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3611
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()

static void PRVM_MarkReferencedEdicts ( prvm_prog_t * prog)
static

Definition at line 3629 of file prvm_edict.c.

3630{
3631 int i, j;
3632 qbool found_new;
3633 int stage;
3634
3635 // Stage 1: world, all entities that are relevant, and all entities that are referenced by globals.
3636 stage = 1;
3637 for(j = 0; j < prog->num_edicts; ++j)
3638 {
3640 if(ed->free)
3641 continue;
3642 ed->priv.required->mark = PRVM_IsEdictRelevant(prog, ed) ? stage : 0;
3643 }
3644 for (i = 0;i < prog->numglobaldefs;i++)
3645 {
3646 mdef_t *d = &prog->globaldefs[i];
3647 prvm_edict_t *ed;
3648 if((etype_t)((int) d->type & ~DEF_SAVEGLOBAL) != ev_entity)
3649 continue;
3650 j = PRVM_GLOBALFIELDEDICT(d->ofs);
3651 if (i < 0 || j >= prog->max_edicts) {
3652 Con_Printf("Invalid entity reference from global %s.\n", PRVM_GetString(prog, d->s_name));
3653 continue;
3654 }
3655 ed = PRVM_EDICT_NUM(j);;
3656 ed->priv.required->mark = stage;
3657 }
3658
3659 // Future stages: all entities that are referenced by an entity of the previous stage.
3660 do
3661 {
3662 found_new = false;
3663 for(j = 0; j < prog->num_edicts; ++j)
3664 {
3666 if(ed->free)
3667 continue;
3668 if(ed->priv.required->mark)
3669 continue;
3670 if(PRVM_IsEdictReferenced(prog, ed, stage))
3671 {
3672 ed->priv.required->mark = stage + 1;
3673 found_new = true;
3674 }
3675 }
3676 ++stage;
3677 }
3678 while(found_new);
3679 Con_DPrintf("leak check used %d stages to find all references\n", stage);
3680}
#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, i, 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()

static 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, i, 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, i, 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()

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

Definition at line 3358 of file prvm_edict.c.

3359{
3360 if (i >= prog->numknownstrings)
3361 {
3362 if (i >= prog->maxknownstrings)
3363 {
3364 const char **oldstrings = prog->knownstrings;
3365 const unsigned char *oldstrings_flags = prog->knownstrings_flags;
3366 const char **oldstrings_origin = prog->knownstrings_origin;
3367 prog->maxknownstrings += 128;
3368 prog->knownstrings = (const char **)PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
3369 prog->knownstrings_flags = (unsigned char *)PRVM_Alloc(prog->maxknownstrings * sizeof(unsigned char));
3370 if (prog->leaktest_active)
3371 prog->knownstrings_origin = (const char **)PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
3372 if (prog->numknownstrings)
3373 {
3374 memcpy((char **)prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
3375 memcpy((char **)prog->knownstrings_flags, oldstrings_flags, prog->numknownstrings * sizeof(unsigned char));
3376 if (prog->leaktest_active)
3377 memcpy((char **)prog->knownstrings_origin, oldstrings_origin, prog->numknownstrings * sizeof(char *));
3378 }
3379 }
3380 prog->numknownstrings++;
3381 }
3382 prog->firstfreeknownstring = i + 1;
3383 prog->knownstrings[i] = s;
3384 // it's in use right now, spare it until the next gc pass - that said, it is not freeable so this is probably moot
3385 prog->knownstrings_flags[i] = flags;
3386 if (prog->leaktest_active)
3387 prog->knownstrings_origin[i] = NULL;
3388}
float flags
int maxknownstrings
Definition progsvm.h:586

References prvm_prog_t::firstfreeknownstring, flags, i, 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()

static void PRVM_PO_Destroy ( po_t * po)
static

Definition at line 1925 of file prvm_edict.c.

1926{
1927 int i;
1928 for(i = 0; i < PO_HASHSIZE; ++i)
1929 {
1930 po_string_t *p = po->hashtable[i];
1931 while(p)
1932 {
1933 po_string_t *q = p;
1934 p = p->nextonhashchain;
1935 Mem_Free(q->key);
1936 Mem_Free(q->value);
1937 Mem_Free(q);
1938 }
1939 }
1940 Mem_Free(po);
1941}
#define PO_HASHSIZE
struct po_string_s * nextonhashchain
po_string_t * hashtable[PO_HASHSIZE]

References po_t::hashtable, i, 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()

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

Definition at line 1800 of file prvm_edict.c.

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

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

Definition at line 1913 of file prvm_edict.c.

1914{
1915 int hashindex = CRC_Block((const unsigned char *) str, strlen(str)) % PO_HASHSIZE;
1916 po_string_t *p = po->hashtable[hashindex];
1917 while(p)
1918 {
1919 if(!strcmp(str, p->key))
1920 return p->value;
1921 p = p->nextonhashchain;
1922 }
1923 return NULL;
1924}

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()

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

Definition at line 1741 of file prvm_edict.c.

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

Referenced by PRVM_PO_Load().

◆ PRVM_PO_UnparseString()

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

Definition at line 1700 of file prvm_edict.c.

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

Referenced by PRVM_Prog_Load().

◆ PRVM_Prog_Init()

void PRVM_Prog_Init ( prvm_prog_t * prog,
cmd_state_t * cmd )

Definition at line 3267 of file prvm_edict.c.

3268{
3269 PRVM_Prog_Reset(prog);
3271 prog->console_cmd = cmd;
3272}
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, cvar_t::integer, 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 2024 of file prvm_edict.c.

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

1945{
1946 if (prog->loaded)
1947 {
1948 if(prog->tempstringsbuf.cursize)
1950 prog->tempstringsbuf.cursize = 0;
1951 PRVM_LeakTest(prog);
1952 prog->reset_cmd(prog);
1954 if(prog->po)
1955 PRVM_PO_Destroy((po_t *) prog->po);
1956 }
1957 memset(prog,0,sizeof(prvm_prog_t));
1958 prog->break_statement = -1;
1959 prog->watch_global_type = ev_void;
1960 prog->watch_field_type = ev_void;
1961}
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 3390 of file prvm_edict.c.

3391{
3392 int i;
3393 if (!s)
3394 return 0;
3395 if (s >= prog->strings && s <= prog->strings + prog->stringssize)
3396 prog->error_cmd("PRVM_SetEngineString: s in prog->strings area");
3397 // if it's in the tempstrings area, use a reserved range
3398 // (otherwise we'd get millions of useless string offsets cluttering the database)
3399 if (s >= (char *)prog->tempstringsbuf.data && s < (char *)prog->tempstringsbuf.data + prog->tempstringsbuf.maxsize)
3400 return prog->stringssize + (s - (char *)prog->tempstringsbuf.data);
3401 // see if it's a known string address
3402 for (i = 0;i < prog->numknownstrings;i++)
3403 if (prog->knownstrings[i] == s)
3404 return PRVM_KNOWNSTRINGBASE + i;
3405 // new unknown engine string
3407 Con_DPrintf("new engine string %p = \"%s\"\n", (void *)s, s);
3408 for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
3409 if (!prog->knownstrings[i])
3410 break;
3412 return PRVM_KNOWNSTRINGBASE + i;
3413}
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, i, cvar_t::integer, 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 3423 of file prvm_edict.c.

3424{
3425 size_t size;
3426 char *t;
3427
3428 if (!s || slen >= VM_TEMPSTRING_MAXSIZE)
3429 return 0;
3430 size = slen + 1;
3432 Con_DPrintf("PRVM_SetTempString %s: cursize %i, new tempstring size %lu\n", prog->name, prog->tempstringsbuf.cursize, (unsigned long)size);
3433 if ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
3434 {
3435 sizebuf_t old = prog->tempstringsbuf;
3436 if (prog->tempstringsbuf.cursize + size >= 1<<28)
3437 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);
3438 prog->tempstringsbuf.maxsize = max(prog->tempstringsbuf.maxsize, 65536);
3439 while ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size)
3440 prog->tempstringsbuf.maxsize *= 2;
3441 if (prog->tempstringsbuf.maxsize != old.maxsize || prog->tempstringsbuf.data == NULL)
3442 {
3443 Con_DPrintf("PRVM_SetTempString %s: enlarging tempstrings buffer (%iKB -> %iKB)\n", prog->name, old.maxsize/1024, prog->tempstringsbuf.maxsize/1024);
3444 prog->tempstringsbuf.data = (unsigned char *) Mem_Alloc(prog->progs_mempool, prog->tempstringsbuf.maxsize);
3445 if (old.data)
3446 {
3447 if (old.cursize)
3448 memcpy(prog->tempstringsbuf.data, old.data, old.cursize);
3449 Mem_Free(old.data);
3450 }
3451 }
3452 }
3453 t = (char *)prog->tempstringsbuf.data + prog->tempstringsbuf.cursize;
3454 memcpy(t, s, size);
3455 prog->tempstringsbuf.cursize += size;
3456 return PRVM_SetEngineString(prog, t);
3457}
#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, cvar_t::integer, 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, i, 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()

static void PRVM_UpdateBreakpoints ( prvm_prog_t * prog)
static

Definition at line 3025 of file prvm_edict.c.

3026{
3027 debug_data_t *debug = &debug_data[prog - prvm_prog_list];
3028 if (!prog->loaded)
3029 return;
3030 if (debug->break_statement[0])
3031 {
3032 if (debug->break_statement[0] >= '0' && debug->break_statement[0] <= '9')
3033 {
3034 prog->break_statement = atoi(debug->break_statement);
3035 prog->break_stack_index = 0;
3036 }
3037 else
3038 {
3039 mfunction_t *func;
3040 func = PRVM_ED_FindFunction (prog, debug->break_statement);
3041 if (!func)
3042 {
3043 Con_Printf("%s progs: no function or statement named %s to break on!\n", prog->name, debug->break_statement);
3044 prog->break_statement = -1;
3045 }
3046 else
3047 {
3048 prog->break_statement = func->first_statement;
3049 prog->break_stack_index = 1;
3050 }
3051 }
3052 if (prog->break_statement >= -1)
3053 Con_Printf("%s progs: breakpoint is at statement %d\n", prog->name, prog->break_statement);
3054 }
3055 else
3056 prog->break_statement = -1;
3057
3058 if (debug->watch_global[0])
3059 {
3060 mdef_t *global = PRVM_ED_FindGlobal( prog, debug->watch_global );
3061 if( !global )
3062 {
3063 Con_Printf( "%s progs: no global named '%s' to watch!\n", prog->name, debug->watch_global );
3064 prog->watch_global_type = ev_void;
3065 }
3066 else
3067 {
3068 size_t sz = sizeof(prvm_vec_t) * ((global->type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
3069 prog->watch_global = global->ofs;
3070 prog->watch_global_type = (etype_t)global->type;
3071 memcpy(&prog->watch_global_value, PRVM_GLOBALFIELDVALUE(prog->watch_global), sz);
3072 }
3073 if (prog->watch_global_type != ev_void)
3074 Con_Printf("%s progs: global watchpoint is at global index %d\n", prog->name, prog->watch_global);
3075 }
3076 else
3077 prog->watch_global_type = ev_void;
3078
3079 if (debug->watch_field[0])
3080 {
3081 mdef_t *field = PRVM_ED_FindField( prog, debug->watch_field );
3082 if( !field )
3083 {
3084 Con_Printf( "%s progs: no field named '%s' to watch!\n", prog->name, debug->watch_field );
3085 prog->watch_field_type = ev_void;
3086 }
3087 else
3088 {
3089 size_t sz = sizeof(prvm_vec_t) * ((field->type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
3090 prog->watch_edict = debug->watch_edict;
3091 prog->watch_field = field->ofs;
3092 prog->watch_field_type = (etype_t)field->type;
3093 if (prog->watch_edict < prog->num_edicts)
3095 else
3096 memset(&prog->watch_edictfield_value, 0, sz);
3097 }
3098 if (prog->watch_edict != ev_void)
3099 Con_Printf("%s progs: edict field watchpoint is at edict %d field index %d\n", prog->name, prog->watch_edict, prog->watch_field);
3100 }
3101 else
3102 prog->watch_field_type = ev_void;
3103}
#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()

static 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 3009 of file prvm_edict.c.

3010{
3011 size_t sz = sizeof(prvm_vec_t) * ((type & ~DEF_SAVEGLOBAL) == ev_vector ? 3 : 1);
3012 if (memcmp(o, n, sz))
3013 {
3014 char buf[1024];
3015 char valuebuf_o[128];
3016 char valuebuf_n[128];
3017 PRVM_UglyValueString(prog, type, o, valuebuf_o, sizeof(valuebuf_o));
3018 PRVM_UglyValueString(prog, type, n, valuebuf_n, sizeof(valuebuf_n));
3019 dpsnprintf(buf, sizeof(buf), "%s: %s -> %s", text, valuebuf_o, valuebuf_n);
3020 PRVM_Breakpoint(prog, stack_index, buf);
3021 memcpy(o, n, sz);
3022 }
3023}
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().