2004-08-23 01:38:21 +00:00
# define PROGSUSED
# include "progsint.h"
2005-04-17 02:22:51 +00:00
# include <stdlib.h>
2004-08-23 01:38:21 +00:00
typedef struct prmemb_s {
struct prmemb_s * prev ;
int level ;
} prmemb_t ;
void * PRHunkAlloc ( progfuncs_t * progfuncs , int ammount )
{
2005-03-28 00:11:59 +00:00
prmemb_t * mem ;
ammount = sizeof ( prmemb_t ) + ( ( ammount + 3 ) & ~ 3 ) ;
2008-05-11 12:55:53 +00:00
mem = memalloc ( ammount ) ;
2005-03-28 00:11:59 +00:00
memset ( mem , 0 , ammount ) ;
mem - > prev = memb ;
if ( ! memb )
mem - > level = 1 ;
else
mem - > level = ( ( prmemb_t * ) memb ) - > level + 1 ;
memb = mem ;
2004-08-23 01:38:21 +00:00
2005-03-28 00:11:59 +00:00
return ( ( char * ) mem ) + sizeof ( prmemb_t ) ;
2004-08-23 01:38:21 +00:00
}
int PRHunkMark ( progfuncs_t * progfuncs )
{
2005-03-28 00:11:59 +00:00
return ( ( prmemb_t * ) memb ) - > level ;
2004-08-23 01:38:21 +00:00
}
void PRHunkFree ( progfuncs_t * progfuncs , int mark )
{
2005-03-28 00:11:59 +00:00
prmemb_t * omem ;
while ( memb )
2004-08-23 01:38:21 +00:00
{
2005-03-28 00:11:59 +00:00
if ( memb - > level < = mark )
return ;
2004-08-23 01:38:21 +00:00
2005-03-28 00:11:59 +00:00
omem = memb ;
memb = memb - > prev ;
memfree ( omem ) ;
}
return ;
}
2011-10-27 16:16:29 +00:00
/*if we ran out of memory, the vm can allocate a new block, but doing so requires fixing up all sorts of pointers*/
void PRAddressableRelocate ( progfuncs_t * progfuncs , char * oldb , char * newb , int oldlen )
{
unsigned int i ;
edictrun_t * e ;
for ( i = 0 ; i < maxedicts ; i + + )
{
e = ( edictrun_t * ) ( prinst - > edicttable [ i ] ) ;
if ( e & & ( char * ) e - > fields > = oldb & & ( char * ) e - > fields < oldb + oldlen )
e - > fields = ( ( char * ) e - > fields - oldb ) + newb ;
}
if ( progfuncs - > stringtable > = oldb & & progfuncs - > stringtable < oldb + oldlen )
progfuncs - > stringtable = ( progfuncs - > stringtable - oldb ) + newb ;
for ( i = 0 ; i < maxprogs ; i + + )
{
if ( ( char * ) prinst - > progstate [ i ] . globals > = oldb & & ( char * ) prinst - > progstate [ i ] . globals < oldb + oldlen )
prinst - > progstate [ i ] . globals = ( float * ) ( ( ( char * ) prinst - > progstate [ i ] . globals - oldb ) + newb ) ;
if ( prinst - > progstate [ i ] . strings > = oldb & & prinst - > progstate [ i ] . strings < oldb + oldlen )
prinst - > progstate [ i ] . strings = ( prinst - > progstate [ i ] . strings - oldb ) + newb ;
}
for ( i = 0 ; i < numfields ; i + + )
{
if ( field [ i ] . name > = oldb & & field [ i ] . name < oldb + oldlen )
field [ i ] . name = ( field [ i ] . name - oldb ) + newb ;
}
externs - > addressablerelocated ( progfuncs , oldb , newb , oldlen ) ;
}
2005-03-28 00:11:59 +00:00
//for 64bit systems. :)
//addressable memory is memory available to the vm itself for writing.
//once allocated, it cannot be freed for the lifetime of the VM.
void * PRAddressableAlloc ( progfuncs_t * progfuncs , int ammount )
{
ammount = ( ammount + 4 ) & ~ 3 ; //round up to 4
if ( addressableused + ammount > addressablesize )
2011-10-27 16:16:29 +00:00
{
/*only do this if the caller states that it can cope with addressable-block relocations/resizes*/
if ( externs - > addressablerelocated )
{
# ifdef _WIN32
char * newblock ;
#if 0 //def _DEBUG
int oldtot = addressablesize ;
# endif
int newsize = ( addressableused + ammount + 4096 ) & ~ ( 4096 - 1 ) ;
newblock = VirtualAlloc ( NULL , addressablesize , MEM_RESERVE , PAGE_NOACCESS ) ;
if ( newblock )
{
VirtualAlloc ( newblock , addressableused , MEM_COMMIT , PAGE_READWRITE ) ;
memcpy ( newblock , addressablehunk , addressableused ) ;
#if 0 //def _DEBUG
VirtualAlloc ( addressablehunk , oldtot , MEM_RESERVE , PAGE_NOACCESS ) ;
# else
VirtualFree ( addressablehunk , 0 , MEM_RELEASE ) ;
# endif
PRAddressableRelocate ( progfuncs , addressablehunk , newblock , addressableused ) ;
addressablehunk = newblock ;
addressablesize = newsize ;
}
# else
char * newblock ;
2011-10-27 16:42:53 +00:00
int newsize = ( addressableused + ammount + 1024 * 1024 ) & ~ ( 1024 * 1024 - 1 ) ;
2011-10-27 16:16:29 +00:00
newblock = realloc ( newblock , addressablesize ) ;
if ( newblock )
{
PRAddressableRelocate ( progfuncs , addressablehunk , newblock , addressableused ) ;
addressablehunk = newblock ;
addressablesize = newsize ;
}
# endif
}
if ( addressableused + ammount > addressablesize )
Sys_Error ( " Not enough addressable memory for progs VM " ) ;
}
2005-03-28 00:11:59 +00:00
addressableused + = ammount ;
# ifdef _WIN32
if ( ! VirtualAlloc ( addressablehunk , addressableused , MEM_COMMIT , PAGE_READWRITE ) )
Sys_Error ( " VirtualAlloc failed. Blame windows. " ) ;
# endif
return & addressablehunk [ addressableused - ammount ] ;
}
2005-05-15 18:49:04 +00:00
2005-03-28 00:11:59 +00:00
void PRAddressableFlush ( progfuncs_t * progfuncs , int totalammount )
{
addressableused = 0 ;
if ( totalammount < 0 ) //flush
{
totalammount = addressablesize ;
// return;
2004-08-23 01:38:21 +00:00
}
2005-03-28 00:11:59 +00:00
# ifdef _WIN32
2011-07-30 14:14:56 +00:00
if ( addressablehunk & & addressablesize ! = totalammount )
{
VirtualFree ( addressablehunk , 0 , MEM_RELEASE ) ; //doesn't this look complicated? :p
addressablehunk = NULL ;
}
2011-12-23 03:12:29 +00:00
if ( ! addressablehunk )
addressablehunk = VirtualAlloc ( addressablehunk , totalammount , MEM_RESERVE , PAGE_NOACCESS ) ;
2005-03-28 00:11:59 +00:00
# else
2011-07-30 14:14:56 +00:00
if ( addressablehunk )
free ( addressablehunk ) ;
2005-03-28 00:11:59 +00:00
addressablehunk = malloc ( totalammount ) ; //linux will allocate-on-use anyway, which is handy.
2005-05-17 02:36:54 +00:00
// memset(addressablehunk, 0xff, totalammount);
2005-03-28 00:11:59 +00:00
# endif
2005-09-16 04:37:24 +00:00
if ( ! addressablehunk )
Sys_Error ( " Out of memory \n " ) ;
2005-03-28 00:11:59 +00:00
addressablesize = totalammount ;
2004-08-23 01:38:21 +00:00
}
int PR_InitEnts ( progfuncs_t * progfuncs , int max_ents )
{
maxedicts = max_ents ;
sv_num_edicts = 0 ;
2005-03-28 00:11:59 +00:00
max_fields_size = fields_size ;
2004-08-23 01:38:21 +00:00
prinst - > edicttable = PRHunkAlloc ( progfuncs , maxedicts * sizeof ( struct edicts_s * ) ) ;
2005-03-28 00:11:59 +00:00
sv_edicts = PRHunkAlloc ( progfuncs , externs - > edictsize ) ;
2004-08-23 01:38:21 +00:00
prinst - > edicttable [ 0 ] = sv_edicts ;
2005-03-28 00:11:59 +00:00
( ( edictrun_t * ) prinst - > edicttable [ 0 ] ) - > fields = PRAddressableAlloc ( progfuncs , max_fields_size ) ;
2009-11-04 21:16:50 +00:00
QC_ClearEdict ( progfuncs , sv_edicts ) ;
2004-08-23 01:38:21 +00:00
sv_num_edicts = 1 ;
2009-11-17 00:15:44 +00:00
if ( externs - > entspawn )
externs - > entspawn ( ( struct edict_s * ) sv_edicts , false ) ;
2005-03-28 00:11:59 +00:00
return max_fields_size ;
2004-08-23 01:38:21 +00:00
}
2005-06-14 04:52:10 +00:00
edictrun_t tempedict ; //used as a safty buffer
float tempedictfields [ 2048 ] ;
2005-03-28 00:11:59 +00:00
void PR_Configure ( progfuncs_t * progfuncs , int addressable_size , int max_progs ) //can be used to wipe all memory
2004-08-23 01:38:21 +00:00
{
2005-10-07 16:27:20 +00:00
unsigned int i ;
2004-08-23 01:38:21 +00:00
edictrun_t * e ;
2005-03-28 00:11:59 +00:00
max_fields_size = 0 ;
fields_size = 0 ;
2004-08-23 01:38:21 +00:00
progfuncs - > stringtable = 0 ;
QC_StartShares ( progfuncs ) ;
QC_InitShares ( progfuncs ) ;
for ( i = 1 ; i < maxedicts ; i + + )
{
2004-09-20 23:25:38 +00:00
e = ( edictrun_t * ) ( prinst - > edicttable [ i ] ) ;
2004-08-23 01:38:21 +00:00
prinst - > edicttable [ i ] = NULL ;
// e->entnum = i;
if ( e )
memfree ( e ) ;
}
PRHunkFree ( progfuncs , 0 ) ; //clear mem - our hunk may not be a real hunk.
2005-03-28 00:11:59 +00:00
if ( addressable_size < 0 )
addressable_size = 8 * 1024 * 1024 ;
PRAddressableFlush ( progfuncs , addressable_size ) ;
2004-08-23 01:38:21 +00:00
pr_progstate = PRHunkAlloc ( progfuncs , sizeof ( progstate_t ) * max_progs ) ;
/* for(a = 0; a < max_progs; a++)
{
pr_progstate [ a ] . progs = NULL ;
}
*/
maxprogs = max_progs ;
pr_typecurrent = - 1 ;
prinst - > reorganisefields = false ;
maxedicts = 1 ;
2005-06-14 04:52:10 +00:00
prinst - > edicttable = & sv_edicts ;
2004-08-23 01:38:21 +00:00
sv_num_edicts = 1 ; //set up a safty buffer so things won't go horribly wrong too often
2005-06-14 04:52:10 +00:00
sv_edicts = ( struct edict_s * ) & tempedict ;
tempedict . readonly = true ;
tempedict . fields = tempedictfields ;
tempedict . isfree = false ;
2004-08-23 01:38:21 +00:00
}
struct globalvars_s * PR_globals ( progfuncs_t * progfuncs , progsnum_t pnum )
{
if ( pnum < 0 )
2005-04-02 18:00:45 +00:00
{
if ( ! current_progstate )
2011-12-05 15:23:40 +00:00
{
static float fallback [ RESERVED_OFS ] ;
return ( struct globalvars_s * ) fallback ; //err.. you've not loaded one yet.
}
2004-08-23 01:38:21 +00:00
return ( struct globalvars_s * ) current_progstate - > globals ;
2005-04-02 18:00:45 +00:00
}
2004-08-23 01:38:21 +00:00
return ( struct globalvars_s * ) pr_progstate [ pnum ] . globals ;
}
struct entvars_s * PR_entvars ( progfuncs_t * progfuncs , struct edict_s * ed )
{
if ( ( ( edictrun_t * ) ed ) - > isfree )
return NULL ;
return ( struct entvars_s * ) edvars ( ed ) ;
}
2009-04-01 22:03:56 +00:00
int PR_GetFuncArgCount ( progfuncs_t * progfuncs , func_t func )
{
unsigned int pnum ;
unsigned int fnum ;
dfunction_t * f ;
pnum = ( func & 0xff000000 ) > > 24 ;
fnum = ( func & 0x00ffffff ) ;
if ( pnum > = ( unsigned ) maxprogs | | ! pr_progstate [ pnum ] . functions )
return - 1 ;
else if ( fnum > = pr_progstate [ pnum ] . progs - > numfunctions )
return - 1 ;
else
{
f = pr_progstate [ pnum ] . functions + fnum ;
return f - > numparms ;
}
}
2004-08-23 01:38:21 +00:00
func_t PR_FindFunc ( progfuncs_t * progfuncs , char * funcname , progsnum_t pnum )
{
dfunction_t * f = NULL ;
2005-04-02 18:00:45 +00:00
if ( pnum = = PR_ANY )
{
2005-10-07 16:27:20 +00:00
for ( pnum = 0 ; ( unsigned ) pnum < maxprogs ; pnum + + )
2005-04-02 18:00:45 +00:00
{
if ( ! pr_progstate [ pnum ] . progs )
continue ;
f = ED_FindFunction ( progfuncs , funcname , & pnum , pnum ) ;
if ( f )
break ;
}
}
else if ( pnum = = PR_ANYBACK ) //run backwards
2004-08-23 01:38:21 +00:00
{
2005-04-02 18:00:45 +00:00
for ( pnum = maxprogs - 1 ; pnum > = 0 ; pnum - - )
2004-08-23 01:38:21 +00:00
{
if ( ! pr_progstate [ pnum ] . progs )
continue ;
f = ED_FindFunction ( progfuncs , funcname , & pnum , pnum ) ;
if ( f )
break ;
}
}
else
f = ED_FindFunction ( progfuncs , funcname , & pnum , pnum ) ;
if ( ! f )
return 0 ;
{
ddef16_t * var16 ;
ddef32_t * var32 ;
2011-03-04 13:59:06 +00:00
switch ( pr_progstate [ pnum ] . structtype )
2004-08-23 01:38:21 +00:00
{
2011-03-04 13:59:06 +00:00
case PST_KKQWSV :
case PST_DEFAULT :
2004-08-23 01:38:21 +00:00
var16 = ED_FindTypeGlobalFromProgs16 ( progfuncs , funcname , pnum , ev_function ) ; //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
if ( ! var16 )
return ( f - pr_progstate [ pnum ] . functions ) | ( pnum < < 24 ) ;
2011-03-04 13:59:06 +00:00
return * ( int * ) & pr_progstate [ pnum ] . globals [ var16 - > ofs ] ;
case PST_QTEST :
case PST_FTE32 :
2004-08-23 01:38:21 +00:00
var32 = ED_FindTypeGlobalFromProgs32 ( progfuncs , funcname , pnum , ev_function ) ; //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
if ( ! var32 )
2005-04-02 18:00:45 +00:00
return ( f - pr_progstate [ pnum ] . functions ) | ( pnum < < 24 ) ;
2004-08-23 01:38:21 +00:00
return * ( int * ) & pr_progstate [ pnum ] . globals [ var32 - > ofs ] ;
}
Sys_Error ( " Error with def size (PR_FindFunc) " ) ;
}
return 0 ;
}
2011-05-20 04:10:46 +00:00
void QC_FindPrefixedGlobals ( progfuncs_t * progfuncs , char * prefix , void ( * found ) ( progfuncs_t * progfuncs , char * name , union eval_s * val , etype_t type ) )
{
unsigned int i ;
ddef16_t * def16 ;
ddef32_t * def32 ;
int len = strlen ( prefix ) ;
unsigned int pnum ;
for ( pnum = 0 ; pnum < maxprogs ; pnum + + )
{
if ( ! pr_progstate [ pnum ] . progs )
continue ;
switch ( pr_progstate [ pnum ] . structtype )
{
case PST_DEFAULT :
case PST_KKQWSV :
for ( i = 1 ; i < pr_progstate [ pnum ] . progs - > numglobaldefs ; i + + )
{
def16 = & pr_progstate [ pnum ] . globaldefs16 [ i ] ;
if ( ! strncmp ( def16 - > s_name + progfuncs - > stringtable , prefix , len ) )
found ( progfuncs , def16 - > s_name + progfuncs - > stringtable , ( eval_t * ) & pr_progstate [ pnum ] . globals [ def16 - > ofs ] , def16 - > type ) ;
}
break ;
case PST_QTEST :
case PST_FTE32 :
for ( i = 1 ; i < pr_progstate [ pnum ] . progs - > numglobaldefs ; i + + )
{
def32 = & pr_progstate [ pnum ] . globaldefs32 [ i ] ;
if ( ! strncmp ( def32 - > s_name + progfuncs - > stringtable , prefix , len ) )
found ( progfuncs , def32 - > s_name + progfuncs - > stringtable , ( eval_t * ) & pr_progstate [ pnum ] . globals [ def32 - > ofs ] , def32 - > type ) ;
}
break ;
}
}
}
eval_t * PR_FindGlobal ( progfuncs_t * progfuncs , char * globname , progsnum_t pnum , etype_t * type )
2004-08-23 01:38:21 +00:00
{
2005-10-07 16:27:20 +00:00
unsigned int i ;
2004-08-23 01:38:21 +00:00
ddef16_t * var16 ;
ddef32_t * var32 ;
2004-11-23 00:23:25 +00:00
if ( pnum = = PR_CURRENT )
pnum = pr_typecurrent ;
2005-07-14 01:57:34 +00:00
if ( pnum = = PR_ANY )
{
eval_t * ev ;
2005-10-07 16:27:20 +00:00
for ( i = 0 ; i < maxprogs ; i + + )
2005-07-14 01:57:34 +00:00
{
2005-10-07 16:27:20 +00:00
if ( ! pr_progstate [ i ] . progs )
2005-07-14 01:57:34 +00:00
continue ;
2011-05-20 04:10:46 +00:00
ev = PR_FindGlobal ( progfuncs , globname , i , type ) ;
2005-07-14 01:57:34 +00:00
if ( ev )
return ev ;
}
return NULL ;
}
2005-10-07 16:27:20 +00:00
if ( pnum < 0 | | ( unsigned ) pnum > = maxprogs | | ! pr_progstate [ pnum ] . progs )
2005-07-14 01:57:34 +00:00
return NULL ;
2011-03-04 13:59:06 +00:00
switch ( pr_progstate [ pnum ] . structtype )
2004-08-23 01:38:21 +00:00
{
2011-03-04 13:59:06 +00:00
case PST_DEFAULT :
case PST_KKQWSV :
2004-08-23 01:38:21 +00:00
if ( ! ( var16 = ED_FindGlobalFromProgs16 ( progfuncs , globname , pnum ) ) )
return NULL ;
2011-05-20 04:10:46 +00:00
if ( type )
* type = var16 - > type ;
2004-08-23 01:38:21 +00:00
return ( eval_t * ) & pr_progstate [ pnum ] . globals [ var16 - > ofs ] ;
2011-03-04 13:59:06 +00:00
case PST_QTEST :
case PST_FTE32 :
2004-08-23 01:38:21 +00:00
if ( ! ( var32 = ED_FindGlobalFromProgs32 ( progfuncs , globname , pnum ) ) )
return NULL ;
2011-05-20 04:10:46 +00:00
if ( type )
* type = var32 - > type ;
2004-08-23 01:38:21 +00:00
return ( eval_t * ) & pr_progstate [ pnum ] . globals [ var32 - > ofs ] ;
}
Sys_Error ( " Error with def size (PR_FindGlobal) " ) ;
return NULL ;
}
void SetGlobalEdict ( progfuncs_t * progfuncs , struct edict_s * ed , int ofs )
{
2005-03-28 00:11:59 +00:00
( ( int * ) pr_globals ) [ ofs ] = EDICT_TO_PROG ( progfuncs , ed ) ;
2004-08-23 01:38:21 +00:00
}
char * PR_VarString ( progfuncs_t * progfuncs , int first )
{
int i ;
static char out [ 1024 ] ;
char * s ;
out [ 0 ] = 0 ;
for ( i = first ; i < pr_argc ; i + + )
{
if ( G_STRING ( OFS_PARM0 + i * 3 ) )
{
2005-05-15 18:49:04 +00:00
s = G_STRING ( ( OFS_PARM0 + i * 3 ) ) + progfuncs - > stringtable ;
2011-01-29 19:53:38 +00:00
if ( strlen ( out ) + strlen ( s ) + 1 > = sizeof ( out ) )
return out ;
2005-05-15 18:49:04 +00:00
strcat ( out , s ) ;
2004-08-23 01:38:21 +00:00
}
}
return out ;
}
2008-01-23 01:31:01 +00:00
int PR_QueryField ( progfuncs_t * progfuncs , unsigned int fieldoffset , etype_t * type , char * * name , evalc_t * fieldcache )
{
fdef_t * var ;
var = ED_FieldAtOfs ( progfuncs , fieldoffset ) ;
if ( ! var )
return false ;
if ( type )
* type = var - > type & ~ ( DEF_SAVEGLOBAL | DEF_SHARED ) ;
if ( name )
* name = var - > name ;
if ( fieldcache )
{
fieldcache - > ofs32 = var ;
fieldcache - > varname = var - > name ;
}
return true ;
}
2004-08-23 01:38:21 +00:00
eval_t * GetEdictFieldValue ( progfuncs_t * progfuncs , struct edict_s * ed , char * name , evalc_t * cache )
{
fdef_t * var ;
if ( ! cache )
{
var = ED_FindField ( progfuncs , name ) ;
if ( ! var )
return NULL ;
2005-03-28 00:11:59 +00:00
return ( eval_t * ) & ( ( ( int * ) ( ( ( edictrun_t * ) ed ) - > fields ) ) [ var - > ofs ] ) ;
2004-08-23 01:38:21 +00:00
}
if ( ! cache - > varname )
{
cache - > varname = name ;
var = ED_FindField ( progfuncs , name ) ;
if ( ! var )
{
cache - > ofs32 = NULL ;
return NULL ;
}
cache - > ofs32 = var ;
2008-01-23 01:31:01 +00:00
cache - > varname = var - > name ;
if ( ! ed )
return ( void * ) ~ 0 ; //something not null
2005-03-28 00:11:59 +00:00
return ( eval_t * ) & ( ( ( int * ) ( ( ( edictrun_t * ) ed ) - > fields ) ) [ var - > ofs ] ) ;
2004-08-23 01:38:21 +00:00
}
if ( cache - > ofs32 = = NULL )
return NULL ;
2005-03-28 00:11:59 +00:00
return ( eval_t * ) & ( ( ( int * ) ( ( ( edictrun_t * ) ed ) - > fields ) ) [ cache - > ofs32 - > ofs ] ) ;
2004-08-23 01:38:21 +00:00
}
struct edict_s * ProgsToEdict ( progfuncs_t * progfuncs , int progs )
{
2005-10-07 16:27:20 +00:00
if ( ( unsigned ) progs > = ( unsigned ) maxedicts )
2008-11-09 22:29:28 +00:00
{
printf ( " Bad entity index %i \n " , progs ) ;
2005-08-03 23:14:59 +00:00
progs = 0 ;
2008-11-09 22:29:28 +00:00
}
2005-03-28 00:11:59 +00:00
return ( struct edict_s * ) PROG_TO_EDICT ( progfuncs , progs ) ;
2004-08-23 01:38:21 +00:00
}
int EdictToProgs ( progfuncs_t * progfuncs , struct edict_s * ed )
{
2005-03-28 00:11:59 +00:00
return EDICT_TO_PROG ( progfuncs , ed ) ;
2004-08-23 01:38:21 +00:00
}
2007-03-11 16:51:45 +00:00
string_t PR_StringToProgs ( progfuncs_t * progfuncs , char * str )
{
char * * ntable ;
int i , free = - 1 ;
if ( ! str )
return 0 ;
2012-01-25 04:40:10 +00:00
if ( str > = progfuncs - > stringtable & & str < progfuncs - > stringtable + addressableused )
2011-08-16 04:12:15 +00:00
return str - progfuncs - > stringtable ;
2007-03-11 16:51:45 +00:00
for ( i = prinst - > numallocedstrings - 1 ; i > = 0 ; i - - )
{
if ( prinst - > allocedstrings [ i ] = = str )
return ( string_t ) ( ( unsigned int ) i | 0x80000000 ) ;
if ( ! prinst - > allocedstrings [ i ] )
free = i ;
}
if ( free ! = - 1 )
{
i = free ;
prinst - > allocedstrings [ i ] = str ;
return ( string_t ) ( ( unsigned int ) i | 0x80000000 ) ;
}
prinst - > maxallocedstrings + = 1024 ;
2008-05-11 12:55:53 +00:00
ntable = memalloc ( sizeof ( char * ) * prinst - > maxallocedstrings ) ;
2007-03-11 16:51:45 +00:00
memcpy ( ntable , prinst - > allocedstrings , sizeof ( char * ) * prinst - > numallocedstrings ) ;
2008-05-14 17:27:57 +00:00
memset ( ntable + prinst - > numallocedstrings , 0 , sizeof ( char * ) * ( prinst - > maxallocedstrings - prinst - > numallocedstrings ) ) ;
2007-03-11 16:51:45 +00:00
prinst - > numallocedstrings = prinst - > maxallocedstrings ;
if ( prinst - > allocedstrings )
memfree ( prinst - > allocedstrings ) ;
prinst - > allocedstrings = ntable ;
for ( i = prinst - > numallocedstrings - 1 ; i > = 0 ; i - - )
{
if ( ! prinst - > allocedstrings [ i ] )
{
prinst - > allocedstrings [ i ] = str ;
return ( string_t ) ( ( unsigned int ) i | 0x80000000 ) ;
}
}
return 0 ;
}
2009-04-06 00:34:32 +00:00
char * PR_RemoveProgsString ( progfuncs_t * progfuncs , string_t str )
{
char * ret ;
//input string is expected to be an allocated string
//if its a temp, or a constant, just return NULL.
if ( ( unsigned int ) str & 0xc0000000 )
{
if ( ( unsigned int ) str & 0x80000000 )
{
int i = str & ~ 0x80000000 ;
if ( i > = prinst - > numallocedstrings )
{
pr_trace = 1 ;
return NULL ;
}
if ( prinst - > allocedstrings [ i ] )
{
ret = prinst - > allocedstrings [ i ] ;
prinst - > allocedstrings [ i ] = NULL ; //remove it
return ret ;
}
else
{
pr_trace = 1 ;
return NULL ; //urm, was freed...
}
}
}
pr_trace = 1 ;
return NULL ;
}
2010-12-18 17:02:47 +00:00
char * ASMCALL PR_StringToNative ( progfuncs_t * progfuncs , string_t str )
2007-03-11 16:51:45 +00:00
{
if ( ( unsigned int ) str & 0xc0000000 )
{
if ( ( unsigned int ) str & 0x80000000 )
{
int i = str & ~ 0x80000000 ;
if ( i > = prinst - > numallocedstrings )
2008-12-23 02:55:20 +00:00
{
2011-07-30 14:14:56 +00:00
printf ( " invalid string %x \n " , str ) ;
2011-10-03 02:45:44 +00:00
PR_StackTrace ( progfuncs ) ;
2008-12-23 02:55:20 +00:00
pr_trace = 1 ;
2007-03-11 16:51:45 +00:00
return " " ;
2008-12-23 02:55:20 +00:00
}
2007-03-11 16:51:45 +00:00
if ( prinst - > allocedstrings [ i ] )
return prinst - > allocedstrings [ i ] ;
else
2008-12-23 02:55:20 +00:00
{
2011-07-30 14:14:56 +00:00
printf ( " invalid string %x \n " , str ) ;
2011-10-03 02:45:44 +00:00
PR_StackTrace ( progfuncs ) ;
2008-12-23 02:55:20 +00:00
pr_trace = 1 ;
2007-03-11 16:51:45 +00:00
return " " ; //urm, was freed...
2008-12-23 02:55:20 +00:00
}
2007-03-11 16:51:45 +00:00
}
if ( ( unsigned int ) str & 0x40000000 )
{
int i = str & ~ 0x40000000 ;
if ( i > = prinst - > numtempstrings )
2008-12-23 02:55:20 +00:00
{
2011-07-30 14:14:56 +00:00
printf ( " invalid temp string %x \n " , str ) ;
2011-10-03 02:45:44 +00:00
PR_StackTrace ( progfuncs ) ;
2008-12-23 02:55:20 +00:00
pr_trace = 1 ;
2007-03-11 16:51:45 +00:00
return " " ;
2008-12-23 02:55:20 +00:00
}
2007-03-11 16:51:45 +00:00
return prinst - > tempstrings [ i ] ;
}
}
2011-08-16 04:12:15 +00:00
if ( str > = addressableused )
2008-12-23 02:55:20 +00:00
{
2011-07-30 14:14:56 +00:00
printf ( " invalid string offset %x \n " , str ) ;
2011-10-03 02:45:44 +00:00
PR_StackTrace ( progfuncs ) ;
2008-12-23 02:55:20 +00:00
pr_trace = 1 ;
2007-03-11 16:51:45 +00:00
return " " ;
2008-12-23 02:55:20 +00:00
}
2007-03-11 16:51:45 +00:00
return progfuncs - > stringtable + str ;
}
string_t PR_AllocTempString ( progfuncs_t * progfuncs , char * str )
{
char * * ntable ;
int newmax ;
int i ;
if ( ! str )
return 0 ;
if ( prinst - > numtempstrings = = prinst - > maxtempstrings )
{
newmax = prinst - > maxtempstrings + = 1024 ;
prinst - > maxtempstrings + = 1024 ;
ntable = memalloc ( sizeof ( char * ) * newmax ) ;
memcpy ( ntable , prinst - > tempstrings , sizeof ( char * ) * prinst - > numtempstrings ) ;
prinst - > maxtempstrings = newmax ;
if ( prinst - > tempstrings )
memfree ( prinst - > tempstrings ) ;
prinst - > tempstrings = ntable ;
}
i = prinst - > numtempstrings ;
if ( i = = 0x10000000 )
return 0 ;
prinst - > numtempstrings + + ;
prinst - > tempstrings [ i ] = memalloc ( strlen ( str ) + 1 ) ;
strcpy ( prinst - > tempstrings [ i ] , str ) ;
return ( string_t ) ( ( unsigned int ) i | 0x40000000 ) ;
}
2012-02-12 05:33:16 +00:00
string_t PR_AllocTempStringLen ( progfuncs_t * progfuncs , char * * str , unsigned int len )
2012-01-28 10:30:44 +00:00
{
char * * ntable ;
int newmax ;
int i ;
if ( ! str )
return 0 ;
if ( prinst - > numtempstrings = = prinst - > maxtempstrings )
{
newmax = prinst - > maxtempstrings + = 1024 ;
prinst - > maxtempstrings + = 1024 ;
ntable = memalloc ( sizeof ( char * ) * newmax ) ;
memcpy ( ntable , prinst - > tempstrings , sizeof ( char * ) * prinst - > numtempstrings ) ;
prinst - > maxtempstrings = newmax ;
if ( prinst - > tempstrings )
memfree ( prinst - > tempstrings ) ;
prinst - > tempstrings = ntable ;
}
i = prinst - > numtempstrings ;
if ( i = = 0x10000000 )
return 0 ;
prinst - > numtempstrings + + ;
prinst - > tempstrings [ i ] = memalloc ( len ) ;
* str = prinst - > tempstrings [ i ] ;
return ( string_t ) ( ( unsigned int ) i | 0x40000000 ) ;
}
2007-03-11 16:51:45 +00:00
void PR_FreeTemps ( progfuncs_t * progfuncs , int depth )
{
int i ;
if ( depth > prinst - > numtempstrings )
{
Sys_Error ( " QC Temp stack inverted \n " ) ;
return ;
}
for ( i = depth ; i < prinst - > numtempstrings ; i + + )
{
memfree ( prinst - > tempstrings [ i ] ) ;
}
prinst - > numtempstrings = depth ;
}
2004-08-23 01:38:21 +00:00
struct qcthread_s * PR_ForkStack ( progfuncs_t * progfuncs ) ;
void PR_ResumeThread ( progfuncs_t * progfuncs , struct qcthread_s * thread ) ;
void PR_AbortStack ( progfuncs_t * progfuncs ) ;
void RegisterBuiltin ( progfuncs_t * progfncs , char * name , builtin_t func ) ;
progfuncs_t deffuncs = {
PROGSTRUCT_VERSION ,
PR_Configure ,
PR_LoadProgs ,
PR_InitEnts ,
PR_ExecuteProgram ,
PR_SwitchProgs ,
PR_globals ,
PR_entvars ,
PR_RunError ,
ED_Print ,
ED_Alloc ,
ED_Free ,
EDICT_NUM ,
NUM_FOR_EDICT ,
SetGlobalEdict ,
PR_VarString ,
NULL ,
PR_FindFunc ,
# ifdef MINIMAL
NULL ,
NULL ,
# else
Comp_Begin ,
Comp_Continue ,
# endif
filefromprogs ,
2009-06-13 11:57:52 +00:00
NULL , //filefromnewprogs,
2004-08-23 01:38:21 +00:00
SaveEnts ,
LoadEnts ,
SaveEnt ,
RestoreEnt ,
PR_FindGlobal ,
ED_NewString ,
( void * ) PRHunkAlloc ,
GetEdictFieldValue ,
ProgsToEdict ,
EdictToProgs ,
EvaluateDebugString ,
NULL ,
PR_StackTrace ,
PR_ToggleBreakpoint ,
0 ,
NULL ,
# ifdef MINIMAL
NULL ,
# else
Decompile ,
# endif
NULL ,
NULL ,
RegisterBuiltin ,
0 ,
0 ,
PR_ForkStack ,
PR_ResumeThread ,
2004-09-01 00:05:04 +00:00
PR_AbortStack ,
2005-02-12 18:56:04 +00:00
0 ,
2005-05-20 03:32:53 +00:00
QC_RegisterFieldVar ,
0 ,
2007-03-11 16:51:45 +00:00
0 ,
PR_AllocTempString ,
PR_StringToProgs ,
2008-01-23 01:31:01 +00:00
PR_StringToNative ,
0 ,
2009-11-04 21:16:50 +00:00
PR_QueryField ,
2011-05-20 04:10:46 +00:00
QC_ClearEdict ,
2011-08-16 04:12:15 +00:00
QC_FindPrefixedGlobals ,
2012-01-28 10:30:44 +00:00
PRAddressableAlloc ,
PR_AllocTempStringLen
2004-08-23 01:38:21 +00:00
} ;
# undef printf
//defs incase following structure is not passed.
struct edict_s * safesv_edicts ;
int safesv_num_edicts ;
double safetime = 0 ;
progexterns_t defexterns = {
PROGSTRUCT_VERSION ,
NULL , //char *(*ReadFile) (char *fname, void *buffer, int len);
NULL , //int (*FileSize) (char *fname); //-1 if file does not exist
NULL , //bool (*WriteFile) (char *name, void *data, int len);
printf , //void (*printf) (char *, ...);
( void * ) exit , //void (*Sys_Error) (char *, ...);
NULL , //void (*Abort) (char *, ...);
sizeof ( edictrun_t ) , //int edictsize; //size of edict_t
NULL , //void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
NULL , //bool (*entcanfree) (struct edict_s *ent); //return true to stop ent from being freed
NULL , //void (*stateop) (float var, func_t func);
NULL ,
NULL ,
NULL ,
//used when loading a game
NULL , //builtin_t *(*builtinsfor) (int num); //must return a pointer to the builtins that were used before the state was saved.
NULL , //void (*loadcompleate) (int edictsize); //notification to reset any pointers.
2010-09-05 10:42:23 +00:00
NULL ,
2004-08-23 01:38:21 +00:00
( void * ) malloc , //void *(*memalloc) (int size); //small string allocation malloced and freed randomly by the executor. (use memalloc if you want)
free , //void (*memfree) (void * mem);
NULL , //builtin_t *globalbuiltins; //these are available to all progs
0 , //int numglobalbuiltins;
2005-02-28 07:16:19 +00:00
PR_NOCOMPILE ,
2004-08-23 01:38:21 +00:00
& safetime , //double *gametime;
& safesv_edicts , //struct edict_s **sv_edicts;
& safesv_num_edicts , //int *sv_num_edicts;
NULL , //int (*useeditor) (char *filename, int line, int nump, char **parms);
} ;
//progfuncs_t *progfuncs = NULL;
# undef memfree
# undef prinst
# undef extensionbuiltin
# undef field
# undef shares
# undef sv_num_edicts
# ifdef QCLIBDLL_EXPORTS
__declspec ( dllexport )
# endif
void CloseProgs ( progfuncs_t * inst )
{
2005-05-15 18:49:04 +00:00
// extensionbuiltin_t *eb;
2004-08-23 01:38:21 +00:00
void ( VARGS * f ) ( void * ) ;
2005-10-07 16:27:20 +00:00
unsigned int i ;
2004-08-23 01:38:21 +00:00
edictrun_t * e ;
f = inst - > parms - > memfree ;
for ( i = 1 ; i < inst - > maxedicts ; i + + )
{
2004-09-20 23:25:38 +00:00
e = ( edictrun_t * ) ( inst - > prinst - > edicttable [ i ] ) ;
2004-08-23 01:38:21 +00:00
inst - > prinst - > edicttable [ i ] = NULL ;
if ( e )
{
// e->entnum = i;
f ( e ) ;
}
}
PRHunkFree ( inst , 0 ) ;
2005-05-15 18:49:04 +00:00
2007-07-16 17:14:39 +00:00
# ifdef _WIN32
2007-07-23 13:32:17 +00:00
VirtualFree ( inst - > addressablehunk , 0 , MEM_RELEASE ) ; //doesn't this look complicated? :p
2007-07-16 17:14:39 +00:00
# else
free ( inst - > addressablehunk ) ;
# endif
2010-07-12 22:46:37 +00:00
if ( inst - > prinst - > allocedstrings )
2011-07-30 14:14:56 +00:00
f ( inst - > prinst - > allocedstrings ) ;
inst - > prinst - > allocedstrings = NULL ;
2010-07-12 22:46:37 +00:00
if ( inst - > prinst - > tempstrings )
f ( inst - > prinst - > tempstrings ) ;
inst - > prinst - > tempstrings = NULL ;
2005-05-15 18:49:04 +00:00
/*
2004-08-23 01:38:21 +00:00
while ( inst - > prinst - > extensionbuiltin )
{
eb = inst - > prinst - > extensionbuiltin - > prev ;
f ( inst - > prinst - > extensionbuiltin ) ;
inst - > prinst - > extensionbuiltin = eb ;
}
2005-05-15 18:49:04 +00:00
*/
2004-08-23 01:38:21 +00:00
if ( inst - > prinst - > field )
f ( inst - > prinst - > field ) ;
if ( inst - > prinst - > shares )
f ( inst - > prinst - > shares ) ; //free memory
f ( inst - > prinst ) ;
f ( inst ) ;
}
void RegisterBuiltin ( progfuncs_t * progfuncs , char * name , builtin_t func )
{
2005-05-15 18:49:04 +00:00
/*
2004-08-23 01:38:21 +00:00
extensionbuiltin_t * eb ;
eb = memalloc ( sizeof ( extensionbuiltin_t ) ) ;
eb - > prev = progfuncs - > prinst - > extensionbuiltin ;
progfuncs - > prinst - > extensionbuiltin = eb ;
eb - > name = name ;
eb - > func = func ;
2005-05-15 18:49:04 +00:00
*/
2004-08-23 01:38:21 +00:00
}
# ifndef WIN32
# define QCLIBINT //don't use dllspecifications
# endif
# if defined(QCLIBDLL_EXPORTS)
__declspec ( dllexport )
# endif
progfuncs_t * InitProgs ( progexterns_t * ext )
{
progfuncs_t * funcs ;
if ( ! ext )
ext = & defexterns ;
else
{
int i ;
if ( ext - > progsversion > PROGSTRUCT_VERSION )
return NULL ;
for ( i = 0 ; i < sizeof ( progexterns_t ) ; i + = 4 ) //make sure there are no items left out.
if ( ! * ( int * ) ( ( char * ) ext + i ) )
* ( int * ) ( ( char * ) ext + i ) = * ( int * ) ( ( char * ) & defexterns + i ) ;
}
# undef memalloc
# undef pr_trace
funcs = ext - > memalloc ( sizeof ( progfuncs_t ) ) ;
2005-03-28 00:11:59 +00:00
memcpy ( funcs , & deffuncs , sizeof ( progfuncs_t ) ) ;
2004-08-23 01:38:21 +00:00
funcs - > prinst = ext - > memalloc ( sizeof ( prinst_t ) ) ;
memset ( funcs - > prinst , 0 , sizeof ( prinst_t ) ) ;
funcs - > pr_trace = & funcs - > prinst - > pr_trace ;
funcs - > progstate = & funcs - > pr_progstate ;
funcs - > callargc = & funcs - > pr_argc ;
funcs - > parms = ext ;
2005-05-22 13:42:10 +00:00
SetEndian ( ) ;
2004-08-23 01:38:21 +00:00
return funcs ;
}
# ifdef QCC
void main ( int argc , char * * argv )
{
progexterns_t ext ;
progfuncs_t * funcs ;
funcs = InitProgs ( & ext ) ;
if ( funcs - > PR_StartCompile ( argc , argv ) )
while ( funcs - > PR_ContinueCompile ( ) ) ;
}
# endif