33cvar_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"};
42cvar_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"};
56cvar_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)."};
57cvar_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."};
168 if (!strcmp(str,
"server"))
170 if (!strcmp(str,
"client"))
173 if (!strcmp(str,
"menu"))
189 Con_Printf(
"%s: unknown program name\n", str);
194 Con_Printf(
"%s: program is not loaded\n", str);
290 prog->
error_cmd(
"%s: PRVM_ED_Alloc: no free edicts", prog->
name);
463 dpsnprintf (line, linelength,
"entity %i (invalid!)",
n);
529 for (i = 0;i < (
int)linelength - 2 && *s;)
684 if(wildcard_fieldname)
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;
709 dp_strlcat(tempstring,
" ",
sizeof(tempstring));
710 dp_strlcat(tempstring,
" ",
sizeof(tempstring));
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;
721 dp_strlcat(tempstring,
"\n",
sizeof(tempstring));
722 if (
strlen(tempstring) >=
sizeof(tempstring)/2)
780 prog->
statestring =
va(vabuf,
sizeof(vabuf),
"PRVM_ED_Write, ent=%d, name=%s", i,
name);
804 const char *wildcard_fieldname;
808 Con_Print(
"prvm_edicts <program name> <optional field name wildcard>\n");
818 wildcard_fieldname =
NULL;
836 const char *wildcard_fieldname;
840 Con_Print(
"prvm_edict <program name> <edict number> <optional field name wildcard>\n");
858 wildcard_fieldname =
NULL;
877 Con_Print(
"prvm_count <program name>\n");
927 prog->
statestring =
va(vabuf,
sizeof(vabuf),
"PRVM_ED_WriteGlobals, name=%s",
name);
949 prog->
error_cmd(
"PRVM_ED_ParseGlobals: EOF without closing brace");
960 prog->
error_cmd(
"PRVM_ED_ParseGlobals: EOF without closing brace");
966 prog->
error_cmd(
"PRVM_ED_ParseGlobals: closing brace without data");
976 prog->
error_cmd(
"PRVM_ED_ParseGlobals: parse error");
1008 for (i = 0;i < l;i++)
1010 if (s[i] ==
'\\' && s[i+1] && parsebackslash)
1015 else if (s[i] ==
'r')
1032 for (i = 0;i < 3;i++)
1038 val->
vector[i] = atof(s);
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);
1063 Con_DPrintf(
"PRVM_ED_ParseEpair: Bogus field name %s in %s\n", s, prog->
name);
1069 Con_DPrintf(
"PRVM_ED_ParseEpair: Can't find field %s in %s\n", s, prog->
name);
1079 Con_Printf(
"PRVM_ED_ParseEpair: Can't find function %s in %s\n", s, prog->
name);
1122 Con_Printf(
"%s program do not support GameCommand!\n", whichprogs);
1126 int restorevm_tempstringsbuf_cursize;
1168 Con_Print(
"prvm_edictget <program name> <edict number> <field> [<cvar>]\n");
1211 Con_Print(
"prvm_globalget <program name> <global> [<cvar>]\n");
1263 Con_Print(
"prvm_edictset <program name> <edict number> <field> <value>\n");
1292 qbool parsebackslash =
true;
1301 prog->
error_cmd(
"PRVM_ED_ParseEdict: EOF without closing brace");
1324 while (
n && keyname[
n-1] ==
' ')
1340 parsebackslash =
false;
1350 prog->
error_cmd(
"PRVM_ED_ParseEdict: EOF without closing brace");
1355 prog->
error_cmd(
"PRVM_ED_ParseEdict: closing brace without data");
1365 if (keyname[0] ==
'_')
1383 prog->
error_cmd(
"PRVM_ED_ParseEdict: parse error");
1408 const char *funcname;
1430 else if (
data && start)
1437 for(in = start; in <
data; )
1441 *spawndata++ =
'\t';
1521 int parsed, inhibited, spawned, died;
1585 Con_DPrintf(
"%s: %i new entities parsed, %i new inhibited, %i (%i new) spawned (whereas %i removed self, %i stayed)\n", prog->
name, parsed, inhibited, prog->
num_edicts, spawned, died, spawned - died);
1597#define PRVM_DECLARE_serverglobalfloat(x)
1598#define PRVM_DECLARE_serverglobalvector(x)
1599#define PRVM_DECLARE_serverglobalstring(x)
1600#define PRVM_DECLARE_serverglobaledict(x)
1601#define PRVM_DECLARE_serverglobalfunction(x)
1602#define PRVM_DECLARE_clientglobalfloat(x)
1603#define PRVM_DECLARE_clientglobalvector(x)
1604#define PRVM_DECLARE_clientglobalstring(x)
1605#define PRVM_DECLARE_clientglobaledict(x)
1606#define PRVM_DECLARE_clientglobalfunction(x)
1607#define PRVM_DECLARE_menuglobalfloat(x)
1608#define PRVM_DECLARE_menuglobalvector(x)
1609#define PRVM_DECLARE_menuglobalstring(x)
1610#define PRVM_DECLARE_menuglobaledict(x)
1611#define PRVM_DECLARE_menuglobalfunction(x)
1612#define PRVM_DECLARE_serverfieldfloat(x)
1613#define PRVM_DECLARE_serverfieldvector(x)
1614#define PRVM_DECLARE_serverfieldstring(x)
1615#define PRVM_DECLARE_serverfieldedict(x)
1616#define PRVM_DECLARE_serverfieldfunction(x)
1617#define PRVM_DECLARE_clientfieldfloat(x)
1618#define PRVM_DECLARE_clientfieldvector(x)
1619#define PRVM_DECLARE_clientfieldstring(x)
1620#define PRVM_DECLARE_clientfieldedict(x)
1621#define PRVM_DECLARE_clientfieldfunction(x)
1622#define PRVM_DECLARE_menufieldfloat(x)
1623#define PRVM_DECLARE_menufieldvector(x)
1624#define PRVM_DECLARE_menufieldstring(x)
1625#define PRVM_DECLARE_menufieldedict(x)
1626#define PRVM_DECLARE_menufieldfunction(x)
1627#define PRVM_DECLARE_serverfunction(x)
1628#define PRVM_DECLARE_clientfunction(x)
1629#define PRVM_DECLARE_menufunction(x)
1630#define PRVM_DECLARE_field(x) prog->fieldoffsets.x = PRVM_ED_FindFieldOffset(prog, #x);
1631#define PRVM_DECLARE_global(x) prog->globaloffsets.x = PRVM_ED_FindGlobalOffset(prog, #x);
1632#define PRVM_DECLARE_function(x) prog->funcoffsets.x = PRVM_ED_FindFunctionOffset(prog, #x);
1634#undef PRVM_DECLARE_serverglobalfloat
1635#undef PRVM_DECLARE_serverglobalvector
1636#undef PRVM_DECLARE_serverglobalstring
1637#undef PRVM_DECLARE_serverglobaledict
1638#undef PRVM_DECLARE_serverglobalfunction
1639#undef PRVM_DECLARE_clientglobalfloat
1640#undef PRVM_DECLARE_clientglobalvector
1641#undef PRVM_DECLARE_clientglobalstring
1642#undef PRVM_DECLARE_clientglobaledict
1643#undef PRVM_DECLARE_clientglobalfunction
1644#undef PRVM_DECLARE_menuglobalfloat
1645#undef PRVM_DECLARE_menuglobalvector
1646#undef PRVM_DECLARE_menuglobalstring
1647#undef PRVM_DECLARE_menuglobaledict
1648#undef PRVM_DECLARE_menuglobalfunction
1649#undef PRVM_DECLARE_serverfieldfloat
1650#undef PRVM_DECLARE_serverfieldvector
1651#undef PRVM_DECLARE_serverfieldstring
1652#undef PRVM_DECLARE_serverfieldedict
1653#undef PRVM_DECLARE_serverfieldfunction
1654#undef PRVM_DECLARE_clientfieldfloat
1655#undef PRVM_DECLARE_clientfieldvector
1656#undef PRVM_DECLARE_clientfieldstring
1657#undef PRVM_DECLARE_clientfieldedict
1658#undef PRVM_DECLARE_clientfieldfunction
1659#undef PRVM_DECLARE_menufieldfloat
1660#undef PRVM_DECLARE_menufieldvector
1661#undef PRVM_DECLARE_menufieldstring
1662#undef PRVM_DECLARE_menufieldedict
1663#undef PRVM_DECLARE_menufieldfunction
1664#undef PRVM_DECLARE_serverfunction
1665#undef PRVM_DECLARE_clientfunction
1666#undef PRVM_DECLARE_menufunction
1667#undef PRVM_DECLARE_field
1668#undef PRVM_DECLARE_global
1669#undef PRVM_DECLARE_function
1694#define PO_HASHSIZE 16384
1695typedef struct po_string_s
1715 case '\a':
if(outsize >= 2) { *out++ =
'\\'; *out++ =
'a'; outsize -= 2; }
break;
1716 case '\b':
if(outsize >= 2) { *out++ =
'\\'; *out++ =
'b'; outsize -= 2; }
break;
1717 case '\t':
if(outsize >= 2) { *out++ =
'\\'; *out++ =
't'; outsize -= 2; }
break;
1718 case '\r':
if(outsize >= 2) { *out++ =
'\\'; *out++ =
'r'; outsize -= 2; }
break;
1719 case '\n':
if(outsize >= 2) { *out++ =
'\\'; *out++ =
'n'; outsize -= 2; }
break;
1720 case '\\':
if(outsize >= 2) { *out++ =
'\\'; *out++ =
'\\'; outsize -= 2; }
break;
1721 case '"':
if(outsize >= 2) { *out++ =
'\\'; *out++ =
'"'; outsize -= 2; }
break;
1723 if(*in >= 0 && *in <= 0x1F)
1728 *out++ =
'0' + ((*in & 0700) >> 6);
1729 *out++ =
'0' + ((*in & 0070) >> 3);
1730 *out++ =
'0' + (*in & 0007) ;
1760 case 'a':
if(outsize > 0) { *out++ =
'\a'; --outsize; }
break;
1761 case 'b':
if(outsize > 0) { *out++ =
'\b'; --outsize; }
break;
1762 case 't':
if(outsize > 0) { *out++ =
'\t'; --outsize; }
break;
1763 case 'r':
if(outsize > 0) { *out++ =
'\r'; --outsize; }
break;
1764 case 'n':
if(outsize > 0) { *out++ =
'\n'; --outsize; }
break;
1765 case '\\':
if(outsize > 0) { *out++ =
'\\'; --outsize; }
break;
1766 case '"':
if(outsize > 0) { *out++ =
'"'; --outsize; }
break;
1767 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
1771 if(*in >=
'0' && *in <=
'7')
1774 *out = (*out << 3) | (*in -
'0');
1777 if(*in >=
'0' && *in <=
'7')
1780 *out = (*out << 3) | (*in -
'0');
1791 if(outsize > 0) { *out++ = *in; --outsize; }
1818 for (i = 0; i < 2; ++i)
1820 const char *
buf = (
const char *)
1832 memset(po, 0,
sizeof(*po));
1835 memset(&thisstr, 0,
sizeof(thisstr));
1843 p = strchr(p,
'\n');
1849 if(*p ==
'\r' || *p ==
'\n')
1854 if(!strncmp(p,
"msgid \"", 7))
1859 else if(!strncmp(p,
"msgstr \"", 8))
1866 p = strchr(p,
'\n');
1876 q = strchr(p,
'\n');
1883 if((
size_t)(q - p) >= (
size_t)
sizeof(inbuf))
1885 memcpy(inbuf, p, q - p - 1);
1886 inbuf[q - p - 1] =
'\0';
1888 decodedpos +=
strlen(decodedbuf + decodedpos);
1900 memcpy(thisstr.
key, decodedbuf, decodedpos + 1);
1902 else if(decodedpos > 0 && thisstr.
key)
1905 memcpy(thisstr.
value, decodedbuf, decodedpos + 1);
1909 memcpy(po->
hashtable[hashindex], &thisstr,
sizeof(thisstr));
1910 memset(&thisstr, 0,
sizeof(thisstr));
1925 if(!strcmp(str, p->
key))
1977 unsigned int *header;
1981 dp_strlcat( filename,
".lno",
sizeof( filename ) );
2003 header = (
unsigned int *) lno;
2004 if (memcmp(lno,
"LNOF", 4) == 0
2037 ddef16_t *infielddefs16;
2038 ddef32_t *infielddefs32;
2039 ddef16_t *inglobaldefs16;
2040 ddef32_t *inglobaldefs32;
2046 int requiredglobalspace;
2062 int max_safe_edicts;
2063 bool gaddress_warned =
false;
2066 prog->
error_cmd(
"%s: there is already a %s program loaded!", __func__, prog->
name);
2079 prog->
error_cmd(
"%s: couldn't load \"%s\" for %s", __func__, filename, prog->
name);
2085 requiredglobalspace = 0;
2086 for (i = 0;i < numrequiredglobals;i++)
2087 requiredglobalspace += required_global[i].
type ==
ev_vector ? 3 : 1;
2100 Con_Printf(
CON_WARN "WARNING: %s: %s targets FTEQW, for which support is incomplete. Proceed at your own risk.\n", prog->
name, filename);
2102 prog->
error_cmd(
"%s: %s targets unknown engine", prog->
name, filename);
2105 prog->
error_cmd(
"%s: %s uses unsupported features.", prog->
name, filename);
2113 inglobaldefs32 = (ddef32_t *)inglobaldefs16;
2116 infielddefs32 = (ddef32_t *)infielddefs16;
2135 prog->
error_cmd(
"%s: %s strings go past end of file", prog->
name, filename);
2172 prog->
error_cmd(
"%s: out of bounds function statement (function %d) in %s", __func__, i, prog->
name);
2200 for (i = 0;i < numrequiredglobals;i++)
2220 prog->
error_cmd(
"%s: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", __func__, prog->
name);
2231 prog->
error_cmd(
"%s: prog->fielddefs[i].type & DEF_SAVEGLOBAL in %s", __func__, prog->
name);
2240 for (i = 0;i < numrequiredfields;i++)
2255#define remapglobal(index) (index)
2256#define remapfield(index) (index)
2266 d = u.i & 0xFF800000;
2267 if ((d == 0xFF800000) || (d == 0))
2295 c = (
unsigned short)
LittleShort(instatements16[i].c);
2304 prog->
error_cmd(
"%s: out of bounds IF/IFNOT (statement %d) in %s", __func__, i, prog->
name);
2306 Con_DPrintf(
"%s: unexpected offset on binary opcode in %s\n", __func__, prog->
name);
2315 prog->
error_cmd(
"%s: out of bounds GOTO (statement %d) in %s", __func__, i, prog->
name);
2317 Con_DPrintf(
"%s: unexpected offset on unary opcode in %s\n", __func__, prog->
name);
2324 Con_DPrintf(
"%s: unknown opcode %d at statement %d in %s\n", __func__, (
int)op, i, prog->
name);
2462 prog->
error_cmd(
"%s: out of bounds global index (statement %d)", __func__, i);
2475 prog->
error_cmd(
"%s: out of bounds global index (statement %d) in %s", __func__, i, prog->
name);
2477 Con_DPrintf(
"%s: unexpected offset on binary opcode in %s\n", __func__, prog->
name);
2494 prog->
error_cmd(
"%s: out of bounds global index (statement %d) in %s", __func__, i, prog->
name);
2496 Con_DPrintf(
"%s: unexpected offset on binary opcode in %s\n", __func__, prog->
name);
2520 prog->
error_cmd(
"%s: out of bounds global index (statement %d) in %s", __func__, i, prog->
name);
2522 Con_DPrintf(
"%s: unexpected offset on call opcode in %s. Hexen2 format is not supported\n", __func__, prog->
name);
2548 if (!gaddress_warned) {
2549 Con_Printf(
CON_WARN "WARNING: %s: %s uses deprecated OP_G* instructions, which are unlikely to be used correctly. Proceed at your own risk.\n", prog->
name, filename);
2550 gaddress_warned =
true;
2559 prog->
error_cmd(
"%s: empty program in %s", __func__, prog->
name);
2568 prog->
error_cmd(
"%s: program may fall off the edge (does not end with RETURN, GOTO or DONE) in %s", __func__, prog->
name);
2579 CheckRequiredFuncs(prog, filename);
2598 if(
name && !strncmp(
name,
"dotranslate_", 12))
2607 qfile_t *
f =
FS_OpenRealFile(
va(vabuf,
sizeof(vabuf),
"%s.pot", realfilename),
"w",
false);
2608 Con_Printf(
"Dumping to %s.pot\n", realfilename);
2615 if(deftrans ? (!
name || strncmp(
name,
"notranslate_", 12)) : (
name && !strncmp(
name,
"dotranslate_", 12)))
2634 va(vabuf,
sizeof(vabuf),
"%s.%s.po", realfilename,
prvm_language.string),
2643 if(deftrans ? (!
name || strncmp(
name,
"notranslate_", 12)) : (
name && !strncmp(
name,
"dotranslate_", 12)))
2669 && !strncmp(
name,
"autocvar_", 9)
2682 Con_DPrintf(
"%s: no cvar for autocvar global %s in %s, creating...\n", __func__,
name, prog->
name);
2692 for (
int precision = 7; precision <= 9; ++precision) {
2694 if ((
float)atof(
buf) ==
f) {
2702 for (i = 0; i < 3; ++i)
2706 for (
int precision = 7; precision <= 9; ++precision) {
2708 if ((
float)atof(
buf) ==
f) {
2709 prec[i] = precision;
2721 Con_Printf(
"%s: invalid type of autocvar global %s in %s\n", __func__,
name, prog->
name);
2731 prog->
error_cmd(
"%s: could not create cvar for autocvar global %s in %s", __func__,
name, prog->
name);
2747 for (j = 0;j < 3;j++)
2753 val->
vector[j] = atof(s);
2765 Con_Printf(
"%s: invalid type of autocvar global %s in %s\n", __func__,
name, prog->
name);
2771 Con_Printf(
"%s: private cvar for autocvar global %s in %s\n", __func__,
name, prog->
name);
2790 Con_Printf(
"%s: reducing maximum entity count to %d to avoid address overflow in %s\n", __func__, max_safe_edicts, prog->
name);
2799 Con_Printf(
"%s: program loaded (crc %i, size %iK)%s\n", prog->
name, prog->
filecrc, (
int)(filesize/1024),
2811 int i, j, ednum, used, usedamount;
2830 Con_Print(
"prvm_fields <program name>\n");
2838 for (ednum = 0;ednum < prog->
max_edicts;ednum++)
2873 dp_strlcat(tempstring,
"string ",
sizeof(tempstring));
2876 dp_strlcat(tempstring,
"entity ",
sizeof(tempstring));
2879 dp_strlcat(tempstring,
"function ",
sizeof(tempstring));
2882 dp_strlcat(tempstring,
"field ",
sizeof(tempstring));
2885 dp_strlcat(tempstring,
"void ",
sizeof(tempstring));
2888 dp_strlcat(tempstring,
"float ",
sizeof(tempstring));
2891 dp_strlcat(tempstring,
"vector ",
sizeof(tempstring));
2894 dp_strlcat(tempstring,
"pointer ",
sizeof(tempstring));
2898 dp_strlcat(tempstring, tempstring2,
sizeof(tempstring));
2903 memcpy (tempstring2,
name,
sizeof(tempstring2)-4);
2904 tempstring2[
sizeof(tempstring2)-4] = tempstring2[
sizeof(tempstring2)-3] = tempstring2[
sizeof(tempstring2)-2] =
'.';
2905 tempstring2[
sizeof(tempstring2)-1] = 0;
2910 dp_strlcat(tempstring,
" ",
sizeof(tempstring));
2911 dpsnprintf(tempstring2,
sizeof(tempstring2),
"%5d", counts[i]);
2912 dp_strlcat(tempstring, tempstring2,
sizeof(tempstring));
2913 dp_strlcat(tempstring,
"\n",
sizeof(tempstring));
2914 if (
strlen(tempstring) >=
sizeof(tempstring)/2)
2926 Con_Printf(
"%s: %i entity fields (%i in use), totalling %i bytes per edict (%i in use), %i edicts allocated, %i bytes total spent on edict fields (%i needed)\n", prog->
name, prog->
entityfields, used, prog->
entityfields * 4, usedamount * 4, prog->
max_edicts, prog->
entityfields * 4 * prog->
max_edicts, usedamount * 4 * prog->
max_edicts);
2933 const char *wildcard;
2944 Con_Print(
"prvm_globals <program name> <optional name wildcard>\n");
2982 Con_Printf(
"prvm_global <program name> <global name>\n" );
3006 Con_Printf(
"prvm_globalset <program name> <global name> <value>\n" );
3047 if (memcmp(o,
n, sz))
3050 char valuebuf_o[128];
3051 char valuebuf_n[128];
3054 dpsnprintf(
buf,
sizeof(
buf),
"%s: %s -> %s", text, valuebuf_o, valuebuf_n);
3155 Con_Printf(
"prvm_breakpoint <program name> <function name | statement>\n" );
3184 Con_Printf(
"prvm_globalwatchpoint <program name> <global name>\n" );
3213 Con_Printf(
"prvm_edictwatchpoint <program name> <edict number> <field name>\n" );
3241 Cmd_AddCommand(
CF_SHARED,
"prvm_childprofile",
PRVM_ChildProfile_f,
"prints execution statistics about the most used QuakeC functions in the selected VM (server, client, menu), sorted by time taken in function with child calls");
3243 Cmd_AddCommand(
CF_SHARED,
"prvm_fields",
PRVM_Fields_f,
"prints usage statistics on properties (how many entities have non-zero values) in the selected VM (server, client, menu)");
3248 Cmd_AddCommand(
CF_SHARED,
"prvm_edictget",
PRVM_ED_EdictGet_f,
"retrieves the value of a specified property of a specified entity in the selected VM (server, client menu) into a cvar or to the console");
3254 Cmd_AddCommand(
CF_SHARED,
"prvm_breakpoint",
PRVM_Breakpoint_f,
"marks a statement or function as breakpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear breakpoint");
3255 Cmd_AddCommand(
CF_SHARED,
"prvm_globalwatchpoint",
PRVM_GlobalWatchpoint_f,
"marks a global as watchpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear watchpoint");
3256 Cmd_AddCommand(
CF_SHARED,
"prvm_edictwatchpoint",
PRVM_EdictWatchpoint_f,
"marks an entity field as watchpoint (when this is executed, a stack trace is printed); to actually halt and investigate state, combine this with a gdb breakpoint on PRVM_Breakpoint, or with prvm_breakpointdump; run with just progs name to clear watchpoint");
3285 Con_DPrintf(
"\nQuakeC extensions for server and client:");
3312 prog->
error_cmd(
"PRVM_EDICT_NUM: %s: bad number %i (called at %s:%i)", prog->
name,
n, filename, fileline);
3316#define PRVM_KNOWNSTRINGBASE 0x40000000
3324 VM_Warning(prog,
"PRVM_GetString: Invalid string offset (%i < 0)\n", num);
3327 else if (num < prog->stringssize)
3336 if (num < prog->tempstringsbuf.cursize)
3349 if (num >= 0 && num < prog->numknownstrings)
3354 VM_Warning(prog,
"PRVM_GetString: Invalid zone-string offset (%i has been freed)\n", num);
3375 VM_Warning(prog,
"PRVM_GetString: Invalid constant-string offset (%i >= %i prog->stringssize)\n", num, prog->
stringssize);
3385 prog->
error_cmd(
"PRVM_ChangeEngineString: string index %i is out of bounds", i);
3387 prog->
error_cmd(
"PRVM_ChangeEngineString: string index %i is not an engine string", i);
3431 prog->
error_cmd(
"PRVM_SetEngineString: s in prog->strings area");
3442 Con_DPrintf(
"new engine string %p = \"%s\"\n", (
void *)s, s);
3472 prog->
error_cmd(
"PRVM_SetTempString %s: ran out of tempstring memory! (refusing to grow tempstring buffer over 256MB, cursize %i, new tempstring size %lu)\n", prog->
name, prog->
tempstringsbuf.
cursize, (
unsigned long)
size);
3519 prog->
error_cmd(
"PRVM_FreeString %s: attempt to free a NULL string", prog->
name);
3520 else if (num >= 0 && num < prog->stringssize)
3521 prog->
error_cmd(
"PRVM_FreeString %s: attempt to free a constant string", prog->
name);
3526 prog->
error_cmd(
"PRVM_FreeString %s: attempt to free a non-existent or already freed string", prog->
name);
3528 prog->
error_cmd(
"PRVM_FreeString %s: attempt to free a string owned by the engine", prog->
name);
3538 prog->
error_cmd(
"PRVM_FreeString %s: invalid string offset %i", prog->
name, num);
3714 Con_DPrintf(
"leak check used %d stages to find all references\n", stage);
3720 qbool leaked =
false;
3763 Con_Printf(
"Open string buffer handle found!\n Allocated at: %s\n", stringbuffer->
origin);
3789 Con_Printf(
"Congratulations. No leaks found.\n");
3856 Con_DPrintf(
"PRVM_GarbageCollection: Found bogus strzone reference in edict %i field %i (field name: \"%s\"), erasing reference", entityindex, d->
ofs,
PRVM_GetString(prog, d->
s_name));
3894 Con_DPrintf(
"prvm_garbagecollection_notify: %s: freeing unreferenced string %i: \"%s\"\n", prog->
name, num, prog->
knownstrings[num]);
3912 memset(gc, 0,
sizeof(*gc));
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...
#define CF_SERVER
cvar/command that only the server can change/execute
static int Cmd_Argc(cmd_state_t *cmd)
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...
#define CF_CLIENT
cvar/command that only the client can change/execute
static const char * Cmd_Args(cmd_state_t *cmd)
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
#define CF_PRIVATE
cvar should not be $ expanded or sent to the server under any circumstances (rcon_password,...
unsigned short CRC_Block(const unsigned char *data, size_t size)
char com_token[MAX_INPUTLINE]
char * va(char *buf, size_t buflen, const char *format,...)
qbool COM_ParseToken_Console(const char **datapointer)
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
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 ...
#define dp_strlcat(dst, src, dsize)
#define dp_strlcpy(dst, src, dsize)
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
void Con_DPrint(const char *msg)
A Con_Print that only shows up if the "developer" cvar is set.
void Crypto_LoadKeys(void)
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
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.
cvar_t * Cvar_FindVar(cvar_state_t *cvars, const char *var_name, unsigned neededflags)
qbool Cvar_Readonly(cvar_t *var, const char *cmd_name)
int matchpattern(const char *in, const char *pattern, int caseinsensitive)
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
qfile_t * FS_OpenRealFile(const char *filepath, const char *mode, qbool quiet)
static int(ZEXPORT *qz_inflate)(z_stream *strm
void FS_StripExtension(const char *in, char *out, size_t size_out)
int FS_Close(qfile_t *file)
int FS_Printf(qfile_t *file, const char *format,...)
int FS_Print(qfile_t *file, const char *msg)
GLsizei const GLfloat * value
GLsizeiptr const GLvoid * data
GLenum GLuint GLenum GLsizei const GLchar * buf
void Host_LockSession(void)
cvar_t developer_entityparsing
#define bound(min, num, max)
const char * vm_m_extensions[]
#define PROG_SECONDARYVERSION32
#define PROG_SECONDARYVERSION16
#define PRVM_VECTOR_LOSSLESS_FORMAT
#define PRVM_FLOAT_LOSSLESS_FORMAT
#define KNOWNSTRINGFLAG_ENGINE
void PRVM_Profile_f(struct cmd_state_s *cmd)
#define PRVM_alledictstring(ed, fieldname)
void VM_Warning(prvm_prog_t *prog, const char *fmt,...) DP_FUNC_PRINTF(2)
#define PRVM_serverglobaledict(fieldname)
void PRVM_Init_Exec(prvm_prog_t *prog)
void PRVM_ChildProfile_f(struct cmd_state_s *cmd)
#define PRVM_EDICT_TO_PROG(e)
#define PRVM_MAX_OPENFILES
const char * vm_sv_extensions[]
client also uses this
void PRVM_ED_PrintNum(prvm_prog_t *prog, int ent, const char *wildcard_fieldname)
#define PRVM_Alloc(buffersize)
#define PRVM_EDICT_NUM(n)
const char * PRVM_GetString(prvm_prog_t *prog, int num)
#define PRVM_clientedictstring(ed, fieldname)
#define PRVM_EDICTFIELDEDICT(ed, fieldoffset)
#define PRVM_allfunction(funcname)
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...
#define PRVM_EDICTFIELDSTRING(ed, fieldoffset)
#define PRVM_NUM_FOR_EDICT(e)
#define PRVM_Free(buffer)
#define PRVM_clientedictfunction(ed, fieldname)
void PRVM_CallProfile_f(struct cmd_state_s *cmd)
void PRVM_PrintFunction_f(struct cmd_state_s *cmd)
@ PRVM_GC_KNOWNSTRINGS_SWEEP
#define PRVM_serverglobalfloat(fieldname)
#define PRVM_serveredictfloat(ed, fieldname)
#define PRVM_MAX_OPENSEARCHES
#define PRVM_serverfunction(funcname)
#define PRVM_clientedictfloat(ed, fieldname)
#define KNOWNSTRINGFLAG_GCPRUNE
#define PRVM_GLOBALFIELDSTRING(fieldoffset)
#define PRVM_serveredictstring(ed, fieldname)
#define PRVM_serveredictfunction(ed, fieldname)
#define PRVM_GLOBALFIELDVALUE(fieldoffset)
void PRVM_ED_PrintEdicts_f(struct cmd_state_s *cmd)
#define PRVM_allglobaledict(fieldname)
#define PRVM_EDICTFIELDVALUE(ed, fieldoffset)
void PRVM_PrintState(prvm_prog_t *prog, int stack_index)
#define KNOWNSTRINGFLAG_GCMARK
#define PRVM_GLOBALFIELDEDICT(fieldoffset)
prvm_eval_t prvm_badvalue
#define PRVM_allglobalfloat(fieldname)
void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize)
prvm_prog_t prvm_prog_list[PRVM_PROG_MAX]
cvar_t prvm_backtraceforwarnings
#define VM_TEMPSTRING_MAXSIZE
static void PRVM_GameCommand_Client_f(cmd_state_t *cmd)
cvar_t prvm_reuseedicts_neverinsameframe
void PRVM_ED_LoadFromFile(prvm_prog_t *prog, const char *data)
static void PRVM_EdictWatchpoint_f(cmd_state_t *cmd)
static void PRVM_Global_f(cmd_state_t *cmd)
static void PRVM_ED_EdictSet_f(cmd_state_t *cmd)
void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e)
int PRVM_SetTempString(prvm_prog_t *prog, const char *s, size_t slen)
Takes an strlen (not a buffer size).
cvar_t prvm_gameplayfix_div0is0
void PRVM_ED_CallPostspawnFunction(prvm_prog_t *prog, prvm_edict_t *ent)
void PRVM_Watchpoint(prvm_prog_t *prog, int stack_index, const char *text, etype_t type, prvm_eval_t *o, prvm_eval_t *n)
static void PRVM_GlobalSet_f(cmd_state_t *cmd)
static void PRVM_GlobalWatchpoint_f(cmd_state_t *cmd)
static void PRVM_PO_ParseString(char *out, const char *in, size_t outsize)
char * PRVM_UglyValueString(prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
static po_t * PRVM_PO_Load(const char *filename, const char *filename2, mempool_t *pool)
cvar_t prvm_timeprofiling
static void PRVM_FindOffsets(prvm_prog_t *prog)
void PRVM_Prog_Init(prvm_prog_t *prog, cmd_state_t *cmd)
mdef_t * PRVM_ED_FindGlobal(prvm_prog_t *prog, const char *name)
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)
static void PRVM_GameCommand_Menu_f(cmd_state_t *cmd)
static void PRVM_NewKnownString(prvm_prog_t *prog, int i, int flags, const char *s)
#define remapglobal(index)
mfunction_t * PRVM_ED_FindFunction(prvm_prog_t *prog, const char *name)
const char * PRVM_ChangeEngineString(prvm_prog_t *prog, int i, const char *s)
int PRVM_SetEngineString(prvm_prog_t *prog, const char *s)
void PRVM_ED_PrintNum(prvm_prog_t *prog, int ent, const char *wildcard_fieldname)
static debug_data_t debug_data[PRVM_PROG_MAX]
static void PRVM_ED_PrintEdict_f(cmd_state_t *cmd)
static void PRVM_ED_GlobalGet_f(cmd_state_t *cmd)
void PRVM_ED_Write(prvm_prog_t *prog, qfile_t *f, prvm_edict_t *ed)
void PRVM_FreeString(prvm_prog_t *prog, int num)
qbool PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, mdef_t *key, const char *s, qbool parsebackslash)
void PRVM_ED_PrintEdicts_f(cmd_state_t *cmd)
const char * PRVM_ED_ParseEdict(prvm_prog_t *prog, const char *data, prvm_edict_t *ent, qbool saveload)
prvm_prog_t * PRVM_ProgFromString(const char *str)
int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer)
unsigned int PRVM_EDICT_NUM_ERROR(prvm_prog_t *prog, unsigned int n, const char *filename, int fileline)
const char * PRVM_GetString(prvm_prog_t *prog, int num)
prvm_eval_t * PRVM_ED_FindGlobalEval(prvm_prog_t *prog, const char *name)
void PRVM_Prog_Reset(prvm_prog_t *prog)
static mdef_t * PRVM_ED_GlobalAtOfs(prvm_prog_t *prog, unsigned int ofs)
static double prvm_reuseedicts_always_allow
static char * PRVM_ValueString(prvm_prog_t *prog, etype_t type, prvm_eval_t *val, char *line, size_t linelength)
cvar_t prvm_garbagecollection_notify
void PRVM_Breakpoint(prvm_prog_t *prog, int stack_index, const char *text)
static qbool PRVM_IsEdictRelevant(prvm_prog_t *prog, prvm_edict_t *edict)
static const char * PRVM_PO_Lookup(po_t *po, const char *str)
static void PRVM_Fields_f(cmd_state_t *cmd)
cvar_t prvm_statementprofiling
void PRVM_LeakTest(prvm_prog_t *prog)
cvar_t prvm_garbagecollection_enable
void PRVM_GarbageCollection(prvm_prog_t *prog)
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 ...
void PRVM_ED_ParseGlobals(prvm_prog_t *prog, const char *data)
static void PRVM_MEM_Alloc(prvm_prog_t *prog)
cvar_t prvm_garbagecollection_scan_limit
At 50k in Xonotic with 8 bots scans take about: 24s server, 25s menu, 9s client.
void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog)
mdef_t * PRVM_ED_FindField(prvm_prog_t *prog, const char *name)
int PRVM_ED_FindGlobalOffset(prvm_prog_t *prog, const char *global)
void PRVM_ED_WriteGlobals(prvm_prog_t *prog, qfile_t *f)
#define PRVM_KNOWNSTRINGBASE
static void PRVM_GameCommand(cmd_state_t *cmd, const char *whichprogs, const char *whichcmd)
static void PRVM_LoadLNO(prvm_prog_t *prog, const char *progname)
static void PRVM_MarkReferencedEdicts(prvm_prog_t *prog)
static void PRVM_Globals_f(cmd_state_t *cmd)
static void PRVM_PO_UnparseString(char *out, const char *in, size_t outsize)
char * PRVM_GlobalString(prvm_prog_t *prog, int ofs, char *line, size_t linelength)
cvar_t prvm_breakpointdump
static void PRVM_PO_Destroy(po_t *po)
cvar_t prvm_garbagecollection_strings
qbool PRVM_ED_CallSpawnFunction(prvm_prog_t *prog, prvm_edict_t *ent, const char *data, const char *start)
cvar_t sv_entfields_noescapes
char * PRVM_GlobalStringNoContents(prvm_prog_t *prog, int ofs, char *line, size_t linelength)
static void PRVM_ED_Count_f(cmd_state_t *cmd)
cvar_t prvm_leaktest_follow_targetname
cvar_t prvm_leaktest_ignore_classnames
static void PRVM_Breakpoint_f(cmd_state_t *cmd)
void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed)
static qbool PRVM_IsStringReferenced(prvm_prog_t *prog, string_t string)
void PRVM_ED_Print(prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname)
static void PRVM_GameCommand_Server_f(cmd_state_t *cmd)
mdef_t * PRVM_ED_FieldAtOfs(prvm_prog_t *prog, unsigned int ofs)
func_t PRVM_ED_FindFunctionOffset(prvm_prog_t *prog, const char *function)
void PRVM_ED_CallPrespawnFunction(prvm_prog_t *prog, prvm_edict_t *ent)
cvar_t prvm_reuseedicts_startuptime
static qbool PRVM_IsEdictReferenced(prvm_prog_t *prog, prvm_edict_t *edict, int mark)
static void PRVM_ED_EdictGet_f(cmd_state_t *cmd)
int PRVM_ED_FindFieldOffset(prvm_prog_t *prog, const char *field)
const char * PRVM_AllocationOrigin(prvm_prog_t *prog)
static void PRVM_UpdateBreakpoints(prvm_prog_t *prog)
prvm_edict_t * PRVM_ED_Alloc(prvm_prog_t *prog)
qbool PRVM_ED_CanAlloc(prvm_prog_t *prog, prvm_edict_t *e)
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
void SV_LinkEdict(prvm_edict_t *ent)
void SV_Savegame_to(prvm_prog_t *prog, const char *name)
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
char break_statement[256]
uint8_t parm_size[MAX_PARMS]
uint32_t numbodylessfuncs
uint32_t blockscompressed
uint8_t parm_size[MAX_PARMS]
struct po_string_s * nextonhashchain
po_string_t * hashtable[PO_HASHSIZE]
int mark
mark for the leak detector
const char * allocation_origin
place in the code where it was allocated (for the leak detector)
qbool free
true if this edict is unused
double freetime
sv.time when the object was freed (to prevent early reuse which could mess up client interpolation or...
union prvm_edict_t::@123106147040330276163271355201011305114267000315 priv
union prvm_edict_t::@130370055076073023136252053272156300303324036224 fields
prvm_edict_private_t * required
int knownstrings_sweep_progress
int globals_mark_progress
int fields_mark_progress_entity
const char * statestring
printed together with backtraces
prvm_eval_t watch_global_value
int * statement_linenums
NULL if not available.
void(* reset_cmd)(struct prvm_prog_s *prog)
[INIT] used by PRVM_ResetProg
int entityfields
number of vec_t fields in progs (some variables are 3)
struct qfile_s * openfiles[PRVM_MAX_OPENFILES]
int entityfieldsarea
LadyHavoc: equal to max_edicts * entityfields (for bounds checking)
qbool loaded
used to indicate whether a prog is loaded
prvm_prog_funcoffsets_t funcoffsets
unsigned char * knownstrings_flags
int edictprivate_size
size of the engine private struct
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
void(* begin_increase_edicts)(struct prvm_prog_s *prog)
[INIT] used by PRVM_MEM_Increase_Edicts
void(* free_edict)(struct prvm_prog_s *prog, prvm_edict_t *ed)
[INIT] used by PRVM_ED_Free
const char ** knownstrings
void(* error_cmd)(const char *format,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
[INIT]
int num_edicts
copies of some vars that were former read from sv
prvm_prog_fieldoffsets_t fieldoffsets
void(* count_edicts)(struct prvm_prog_s *prog)
[INIT] used by PRVM_ED_Count_f
double inittime
system time when QC initialization code finished (any entity created before is not a leak)
const char * opensearches_origin[PRVM_MAX_OPENSEARCHES]
union prvm_prog_t::@154363101014374065374200170016167302241050246021 globals
int limit_edicts
used instead of the constant MAX_EDICTS
prvm_prog_globaloffsets_t globaloffsets
unsigned flag
flag - used to store general flags like PRVM_GE_SELF, etc.
void(* init_edict)(struct prvm_prog_s *prog, prvm_edict_t *edict)
[INIT] used by PRVM_ED_ClearEdict
double * explicit_profile
only incremented if prvm_statementprofiling is on
double * statement_profile
only incremented if prvm_statementprofiling is on
mempool_t * progs_mempool
all memory allocations related to this vm_prog (code, edicts, strings)
union prvm_prog_t::@327125214102202150166162221173336172250075227076 edictsfields
struct fssearch_s * opensearches[PRVM_MAX_OPENSEARCHES]
etype_t watch_global_type
memexpandablearray_t stringbuffersarray
struct cmd_state_s * console_cmd
points to the relevant console command interpreter for this vm (cmd_local or &cmd_server),...
int max_edicts
number of edicts for which space has been (should be) allocated
void * po
translation buffer (only needs to be freed on unloading progs, type is private to prvm_edict....
mstatement_t * statements
void(* ExecuteProgram)(struct prvm_prog_s *prog, func_t fnum, const char *errormessage)
pointer to one of the *VM_ExecuteProgram functions
qbool(* load_edict)(struct prvm_prog_s *prog, prvm_edict_t *ent)
[INIT] used by PRVM_ED_LoadFromFile
const char ** knownstrings_origin
sizebuf_t tempstringsbuf
buffer for storing all tempstrings created during one invocation of ExecuteProgram
int firstfreeknownstring
this is updated whenever a string is removed or added (simple optimization of the free string search)
const char * openfiles_origin[PRVM_MAX_OPENFILES]
prvm_prog_garbagecollection_state_t gc
garbage collection status
int numexplicitcoveragestatements
prvm_eval_t watch_edictfield_value
void(* init_cmd)(struct prvm_prog_s *prog)
[INIT] used by PRVM_InitProg
double profiletime
system time when last PRVM_CallProfile was called (or PRVM_Prog_Load initially)
int * statement_columnnums
NULL if not available.
void(* end_increase_edicts)(struct prvm_prog_s *prog)
[INIT]
double starttime
system time when PRVM_Prog_Load was called
int reserved_edicts
number of reserved edicts (allocated from 1)
double Sys_DirtyTime(void)
int Sys_CheckParm(const char *parm)
size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l)
void Mem_ExpandableArray_NewArray(memexpandablearray_t *l, mempool_t *mempool, size_t recordsize, int numrecordsperarray)
void * Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index)
#define Mem_FreePool(pool)
#define Mem_Alloc(pool, size)
#define Mem_Realloc(pool, data, size)