DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Script_Program.h (18888B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #ifndef __SCRIPT_PROGRAM_H__
     30 #define __SCRIPT_PROGRAM_H__
     31 
     32 class idScriptObject;
     33 class idEventDef;
     34 class idVarDef;
     35 class idTypeDef;
     36 class idEntity;
     37 class idThread;
     38 class idSaveGame;
     39 class idRestoreGame;
     40 
     41 #define MAX_STRING_LEN		128
     42 #define MAX_GLOBALS			296608			// in bytes
     43 #define MAX_STRINGS			1024
     44 
     45 #define MAX_FUNCS			3584
     46 
     47 #define MAX_STATEMENTS		131072			// statement_t - 18 bytes last I checked
     48 
     49 typedef enum {
     50 	ev_error = -1, ev_void, ev_scriptevent, ev_namespace, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_virtualfunction, ev_pointer, ev_object, ev_jumpoffset, ev_argsize, ev_boolean
     51 } etype_t;
     52 
     53 class function_t {
     54 public:
     55 						function_t();
     56 
     57 	size_t				Allocated() const;
     58 	void				SetName( const char *name );
     59 	const char			*Name() const;
     60 	void				Clear();
     61 
     62 private:
     63 	idStr 				name;
     64 public:
     65 	const idEventDef	*eventdef;
     66 	idVarDef			*def;
     67 	const idTypeDef		*type;
     68 	int 				firstStatement;
     69 	int 				numStatements;
     70 	int 				parmTotal;
     71 	int 				locals; 			// total ints of parms + locals
     72 	int					filenum; 			// source file defined in
     73 	idList<int, TAG_SCRIPT>			parmSize;
     74 };
     75 
     76 typedef union eval_s {
     77 	const char			*stringPtr;
     78 	float				_float;
     79 	float				vector[ 3 ];
     80 	function_t			*function;
     81 	int 				_int;
     82 	int 				entity;
     83 } eval_t;
     84 
     85 /***********************************************************************
     86 
     87 idTypeDef
     88 
     89 Contains type information for variables and functions.
     90 
     91 ***********************************************************************/
     92 
     93 class idTypeDef {
     94 private:
     95 	etype_t						type;
     96 	idStr 						name;
     97 	int							size;
     98 
     99 	// function types are more complex
    100 	idTypeDef					*auxType;					// return type
    101 	idList<idTypeDef *, TAG_SCRIPT>			parmTypes;
    102 	idStrList					parmNames;
    103 	idList<const function_t *, TAG_SCRIPT>	functions;
    104 
    105 public:
    106 	idVarDef					*def;						// a def that points to this type
    107 
    108 						idTypeDef( const idTypeDef &other );
    109 						idTypeDef( etype_t etype, idVarDef *edef, const char *ename, int esize, idTypeDef *aux );
    110 	void				operator=( const idTypeDef& other );
    111 	size_t				Allocated() const;
    112 
    113 	bool				Inherits( const idTypeDef *basetype ) const;
    114 	bool				MatchesType( const idTypeDef &matchtype ) const;
    115 	bool				MatchesVirtualFunction( const idTypeDef &matchfunc ) const;
    116 	void				AddFunctionParm( idTypeDef *parmtype, const char *name );
    117 	void				AddField( idTypeDef *fieldtype, const char *name );
    118 
    119 	void				SetName( const char *newname );
    120 	const char			*Name() const;
    121 
    122 	etype_t				Type() const;
    123 	int					Size() const;
    124 
    125 	idTypeDef			*SuperClass() const;
    126 	
    127 	idTypeDef			*ReturnType() const;
    128 	void				SetReturnType( idTypeDef *type );
    129 
    130 	idTypeDef			*FieldType() const;
    131 	void				SetFieldType( idTypeDef *type );
    132 
    133 	idTypeDef			*PointerType() const;
    134 	void				SetPointerType( idTypeDef *type );
    135 
    136 	int					NumParameters() const;
    137 	idTypeDef			*GetParmType( int parmNumber ) const;
    138 	const char			*GetParmName( int parmNumber ) const;
    139 
    140 	int					NumFunctions() const;
    141 	int					GetFunctionNumber( const function_t *func ) const;
    142 	const function_t	*GetFunction( int funcNumber ) const;
    143 	void				AddFunction( const function_t *func );
    144 };
    145 
    146 /***********************************************************************
    147 
    148 idScriptObject
    149 
    150 In-game representation of objects in scripts.  Use the idScriptVariable template
    151 (below) to access variables.
    152 
    153 ***********************************************************************/
    154 
    155 class idScriptObject {
    156 private:
    157 	idTypeDef					*type;
    158 	
    159 public:
    160 	byte						*data;
    161 
    162 								idScriptObject();
    163 								~idScriptObject();
    164 
    165 	void						Save( idSaveGame *savefile ) const;			// archives object for save game file
    166 	void						Restore( idRestoreGame *savefile );			// unarchives object from save game file
    167 
    168 	void						Free();
    169 	bool						SetType( const char *typeName );
    170 	void						ClearObject();
    171 	bool						HasObject() const;
    172 	idTypeDef					*GetTypeDef() const;
    173 	const char					*GetTypeName() const;
    174 	const function_t			*GetConstructor() const;
    175 	const function_t			*GetDestructor() const;
    176 	const function_t			*GetFunction( const char *name ) const;
    177 
    178 	byte						*GetVariable( const char *name, etype_t etype ) const;
    179 };
    180 
    181 /***********************************************************************
    182 
    183 idScriptVariable
    184 
    185 Helper template that handles looking up script variables stored in objects.
    186 If the specified variable doesn't exist, or is the wrong data type, idScriptVariable
    187 will cause an error.
    188 
    189 ***********************************************************************/
    190 
    191 template<class type, etype_t etype, class returnType>
    192 class idScriptVariable {
    193 private:
    194 	type				*data;
    195 
    196 public:
    197 						idScriptVariable();
    198 	bool				IsLinked() const;
    199 	void				Unlink();
    200 	void				LinkTo( idScriptObject &obj, const char *name );
    201 	idScriptVariable	&operator=( const returnType &value );
    202 						operator returnType() const;
    203 };
    204 
    205 template<class type, etype_t etype, class returnType>
    206 ID_INLINE idScriptVariable<type, etype, returnType>::idScriptVariable() {
    207 	data = NULL;
    208 }
    209 
    210 template<class type, etype_t etype, class returnType>
    211 ID_INLINE bool idScriptVariable<type, etype, returnType>::IsLinked() const {
    212 	return ( data != NULL );
    213 }
    214 
    215 template<class type, etype_t etype, class returnType>
    216 ID_INLINE void idScriptVariable<type, etype, returnType>::Unlink() {
    217 	data = NULL;
    218 }
    219 
    220 template<class type, etype_t etype, class returnType>
    221 ID_INLINE void idScriptVariable<type, etype, returnType>::LinkTo( idScriptObject &obj, const char *name ) {
    222 	data = ( type * )obj.GetVariable( name, etype );
    223 	if ( !data ) {
    224 		gameError( "Missing '%s' field in script object '%s'", name, obj.GetTypeName() );
    225 	}
    226 }
    227 
    228 template<class type, etype_t etype, class returnType>
    229 ID_INLINE idScriptVariable<type, etype, returnType> &idScriptVariable<type, etype, returnType>::operator=( const returnType &value ) {
    230 	// check if we attempt to access the object before it's been linked
    231 	assert( data );
    232 
    233 	// make sure we don't crash if we don't have a pointer
    234 	if ( data ) {
    235 		*data = ( type )value;
    236 	}
    237 	return *this;
    238 }
    239 
    240 template<class type, etype_t etype, class returnType>
    241 ID_INLINE idScriptVariable<type, etype, returnType>::operator returnType() const {
    242 	// check if we attempt to access the object before it's been linked
    243 	assert( data );
    244 
    245 	// make sure we don't crash if we don't have a pointer
    246 	if ( data ) {
    247 		return ( const returnType )*data;
    248 	} else {
    249 		// reasonably safe value
    250 		return ( const returnType )0;
    251 	}
    252 }
    253 
    254 /***********************************************************************
    255 
    256 Script object variable access template instantiations
    257 
    258 These objects will automatically handle looking up of the current value
    259 of a variable in a script object.  They can be stored as part of a class
    260 for up-to-date values of the variable, or can be used in functions to
    261 sample the data for non-dynamic values.
    262 
    263 ***********************************************************************/
    264 
    265 typedef idScriptVariable<int, ev_boolean, int>				idScriptBool;
    266 typedef idScriptVariable<float, ev_float, float>			idScriptFloat;
    267 typedef idScriptVariable<float, ev_float, int>				idScriptInt;
    268 typedef idScriptVariable<idVec3, ev_vector, idVec3>			idScriptVector;
    269 typedef idScriptVariable<idStr, ev_string, const char *>	idScriptString;
    270 
    271 /***********************************************************************
    272 
    273 idCompileError
    274 
    275 Causes the compiler to exit out of compiling the current function and
    276 display an error message with line and file info.
    277 
    278 ***********************************************************************/
    279 
    280 class idCompileError : public idException {
    281 public:
    282 	idCompileError( const char *text ) : idException( text ) {}
    283 };
    284 
    285 /***********************************************************************
    286 
    287 idVarDef
    288 
    289 Define the name, type, and location of variables, functions, and objects
    290 defined in script.
    291 
    292 ***********************************************************************/
    293 
    294 typedef union varEval_s {
    295 	idScriptObject			**objectPtrPtr;
    296 	char					*stringPtr;
    297 	float					*floatPtr;
    298 	idVec3					*vectorPtr;
    299 	function_t				*functionPtr;
    300 	int 					*intPtr;
    301 	byte					*bytePtr;
    302 	int 					*entityNumberPtr;
    303 	int						virtualFunction;
    304 	int						jumpOffset;
    305 	int						stackOffset;		// offset in stack for local variables
    306 	int						argSize;
    307 	varEval_s				*evalPtr;
    308 	int						ptrOffset;
    309 } varEval_t;
    310 
    311 class idVarDefName;
    312 
    313 class idVarDef {
    314 	friend class idVarDefName;
    315 
    316 public:
    317 	int						num;
    318 	varEval_t				value;
    319 	idVarDef *				scope; 			// function, namespace, or object the var was defined in
    320 	int						numUsers;		// number of users if this is a constant
    321 
    322 	typedef enum {
    323 		uninitialized, initializedVariable, initializedConstant, stackVariable
    324 	} initialized_t;
    325 
    326 	initialized_t			initialized;
    327 
    328 public:
    329 							idVarDef( idTypeDef *typeptr = NULL );
    330 							~idVarDef();
    331 
    332 	const char *			Name() const;
    333 	const char *			GlobalName() const;
    334 
    335 	void					SetTypeDef( idTypeDef *_type ) { typeDef = _type; }
    336 	idTypeDef *				TypeDef() const { return typeDef; }
    337 	etype_t					Type() const { return ( typeDef != NULL ) ? typeDef->Type() : ev_void; }
    338 
    339 	int						DepthOfScope( const idVarDef *otherScope ) const;
    340 
    341 	void					SetFunction( function_t *func );
    342 	void					SetObject( idScriptObject *object );
    343 	void					SetValue( const eval_t &value, bool constant );
    344 	void					SetString( const char *string, bool constant );
    345 
    346 	idVarDef *				Next() const { return next; }		// next var def with same name
    347 
    348 	void					PrintInfo( idFile *file, int instructionPointer ) const;
    349 
    350 private:
    351 	idTypeDef *				typeDef;
    352 	idVarDefName *			name;		// name of this var
    353 	idVarDef *				next;		// next var with the same name
    354 };
    355 
    356 /***********************************************************************
    357 
    358   idVarDefName
    359 
    360 ***********************************************************************/
    361 
    362 class idVarDefName {
    363 public:
    364 							idVarDefName() { defs = NULL; }
    365 							idVarDefName( const char *n ) { name = n; defs = NULL; }
    366 
    367 	const char *			Name() const { return name; }
    368 	idVarDef *				GetDefs() const { return defs; }
    369 
    370 	void					AddDef( idVarDef *def );
    371 	void					RemoveDef( idVarDef *def );
    372 
    373 private:
    374 	idStr					name;
    375 	idVarDef *				defs;
    376 };
    377 
    378 /***********************************************************************
    379 
    380   Variable and type defintions
    381 
    382 ***********************************************************************/
    383 
    384 extern	idTypeDef	type_void;
    385 extern	idTypeDef	type_scriptevent;
    386 extern	idTypeDef	type_namespace;
    387 extern	idTypeDef	type_string;
    388 extern	idTypeDef	type_float;
    389 extern	idTypeDef	type_vector;
    390 extern	idTypeDef	type_entity;
    391 extern  idTypeDef	type_field;
    392 extern	idTypeDef	type_function;
    393 extern	idTypeDef	type_virtualfunction;
    394 extern  idTypeDef	type_pointer;
    395 extern	idTypeDef	type_object;
    396 extern	idTypeDef	type_jumpoffset;	// only used for jump opcodes
    397 extern	idTypeDef	type_argsize;		// only used for function call and thread opcodes
    398 extern	idTypeDef	type_boolean;
    399 
    400 extern	idVarDef	def_void;
    401 extern	idVarDef	def_scriptevent;
    402 extern	idVarDef	def_namespace;
    403 extern	idVarDef	def_string;
    404 extern	idVarDef	def_float;
    405 extern	idVarDef	def_vector;
    406 extern	idVarDef	def_entity;
    407 extern	idVarDef	def_field;
    408 extern	idVarDef	def_function;
    409 extern	idVarDef	def_virtualfunction;
    410 extern	idVarDef	def_pointer;
    411 extern	idVarDef	def_object;
    412 extern	idVarDef	def_jumpoffset;		// only used for jump opcodes
    413 extern	idVarDef	def_argsize;		// only used for function call and thread opcodes
    414 extern	idVarDef	def_boolean;
    415 
    416 typedef struct statement_s {
    417 	unsigned short	op;
    418 	idVarDef		*a;
    419 	idVarDef		*b;
    420 	idVarDef		*c;
    421 	unsigned short	linenumber;
    422 	unsigned short	file;
    423 } statement_t;
    424 
    425 /***********************************************************************
    426 
    427 idProgram
    428 
    429 Handles compiling and storage of script data.  Multiple idProgram objects
    430 would represent seperate programs with no knowledge of each other.  Scripts
    431 meant to access shared data and functions should all be compiled by a
    432 single idProgram.
    433 
    434 ***********************************************************************/
    435 
    436 class idProgram {
    437 private:
    438 	idStrList									fileList;
    439 	idStr 										filename;
    440 	int											filenum;
    441 
    442 	int											numVariables;
    443 	byte										variables[ MAX_GLOBALS ];
    444 	idStaticList<byte,MAX_GLOBALS>				variableDefaults;
    445 	idStaticList<function_t,MAX_FUNCS>			functions;
    446 	idStaticList<statement_t,MAX_STATEMENTS>	statements;
    447 	idList<idTypeDef *, TAG_SCRIPT>				types;
    448 	idHashIndex									typesHash;
    449 	idList<idVarDefName *, TAG_SCRIPT>			varDefNames;
    450 	idHashIndex									varDefNameHash;
    451 	idList<idVarDef *, TAG_SCRIPT>				varDefs;
    452 
    453 	idVarDef									*sysDef;
    454 
    455 	int											top_functions;
    456 	int											top_statements;
    457 	int											top_types;
    458 	int											top_defs;
    459 	int											top_files;
    460 
    461 	void										CompileStats();
    462 
    463 public:
    464 	idVarDef									*returnDef;
    465 	idVarDef									*returnStringDef;
    466 
    467 												idProgram();
    468 												~idProgram();
    469 
    470 	// save games
    471 	void										Save( idSaveGame *savefile ) const;
    472 	bool										Restore( idRestoreGame *savefile );
    473 	int											CalculateChecksum() const;		// Used to insure program code has not
    474 																						//    changed between savegames
    475 
    476 	void										Startup( const char *defaultScript );
    477 	void										Restart();
    478 	bool										CompileText( const char *source, const char *text, bool console );
    479 	const function_t							*CompileFunction( const char *functionName, const char *text );
    480 	void										CompileFile( const char *filename );
    481 	void										BeginCompilation();
    482 	void										FinishCompilation();
    483 	void										DisassembleStatement( idFile *file, int instructionPointer ) const;
    484 	void										Disassemble() const;
    485 	void										FreeData();
    486 
    487 	const char									*GetFilename( int num );
    488 	int											GetFilenum( const char *name );
    489 	int											GetLineNumberForStatement( int index );
    490 	const char									*GetFilenameForStatement( int index );
    491 
    492 	idTypeDef									*AllocType( idTypeDef &type );
    493 	idTypeDef									*AllocType( etype_t etype, idVarDef *edef, const char *ename, int esize, idTypeDef *aux );
    494 	idTypeDef									*GetType( idTypeDef &type, bool allocate );
    495 	idTypeDef									*FindType( const char *name );
    496 
    497 	idVarDef									*AllocDef( idTypeDef *type, const char *name, idVarDef *scope, bool constant );
    498 	idVarDef									*GetDef( const idTypeDef *type, const char *name, const idVarDef *scope ) const;
    499 	void										FreeDef( idVarDef *d, const idVarDef *scope );
    500 	idVarDef									*FindFreeResultDef( idTypeDef *type, const char *name, idVarDef *scope, const idVarDef *a, const idVarDef *b );
    501 	idVarDef									*GetDefList( const char *name ) const;
    502 	void										AddDefToNameList( idVarDef *def, const char *name );
    503 
    504 	function_t									*FindFunction( const char *name ) const;						// returns NULL if function not found
    505 	function_t									*FindFunction( const char *name, const idTypeDef *type ) const;	// returns NULL if function not found
    506 	function_t									&AllocFunction( idVarDef *def );
    507 	function_t									*GetFunction( int index );
    508 	int											GetFunctionIndex( const function_t *func );
    509 
    510 	void										SetEntity( const char *name, idEntity *ent );
    511 
    512 	statement_t									*AllocStatement();
    513 	statement_t									&GetStatement( int index );
    514 	int											NumStatements() { return statements.Num(); }
    515 
    516 	int 										GetReturnedInteger();
    517 
    518 	void										ReturnFloat( float value );
    519 	void										ReturnInteger( int value );
    520 	void										ReturnVector( idVec3 const &vec );
    521 	void										ReturnString( const char *string );
    522 	void										ReturnEntity( idEntity *ent );
    523 	
    524 	int											NumFilenames() { return fileList.Num( ); }
    525 };
    526 
    527 /*
    528 ================
    529 idProgram::GetStatement
    530 ================
    531 */
    532 ID_INLINE statement_t &idProgram::GetStatement( int index ) {
    533 	return statements[ index ];
    534 }
    535 
    536 /*
    537 ================
    538 idProgram::GetFunction
    539 ================
    540 */
    541 ID_INLINE function_t *idProgram::GetFunction( int index ) {
    542 	return &functions[ index ];
    543 }
    544 
    545 /*
    546 ================
    547 idProgram::GetFunctionIndex
    548 ================
    549 */
    550 ID_INLINE int idProgram::GetFunctionIndex( const function_t *func ) {
    551 	return func - &functions[0];
    552 }
    553 
    554 /*
    555 ================
    556 idProgram::GetReturnedInteger
    557 ================
    558 */
    559 ID_INLINE int idProgram::GetReturnedInteger() {
    560 	return *returnDef->value.intPtr;
    561 }
    562 
    563 /*
    564 ================
    565 idProgram::ReturnFloat
    566 ================
    567 */
    568 ID_INLINE void idProgram::ReturnFloat( float value ) {
    569 	*returnDef->value.floatPtr = value;
    570 }
    571 
    572 /*
    573 ================
    574 idProgram::ReturnInteger
    575 ================
    576 */
    577 ID_INLINE void idProgram::ReturnInteger( int value ) {
    578 	*returnDef->value.intPtr = value;
    579 }
    580 
    581 /*
    582 ================
    583 idProgram::ReturnVector
    584 ================
    585 */
    586 ID_INLINE void idProgram::ReturnVector( idVec3 const &vec ) {
    587 	*returnDef->value.vectorPtr = vec;
    588 }
    589 
    590 /*
    591 ================
    592 idProgram::ReturnString
    593 ================
    594 */
    595 ID_INLINE void idProgram::ReturnString( const char *string ) {
    596 	idStr::Copynz( returnStringDef->value.stringPtr, string, MAX_STRING_LEN );
    597 }
    598 
    599 /*
    600 ================
    601 idProgram::GetFilename
    602 ================
    603 */
    604 ID_INLINE const char *idProgram::GetFilename( int num ) {
    605 	return fileList[ num ];
    606 }
    607 
    608 /*
    609 ================
    610 idProgram::GetLineNumberForStatement
    611 ================
    612 */
    613 ID_INLINE int idProgram::GetLineNumberForStatement( int index ) {
    614 	return statements[ index ].linenumber;
    615 }
    616 
    617 /*
    618 ================
    619 idProgram::GetFilenameForStatement
    620 ================
    621 */
    622 ID_INLINE const char *idProgram::GetFilenameForStatement( int index ) {
    623 	return GetFilename( statements[ index ].file );
    624 }
    625 
    626 #endif /* !__SCRIPT_PROGRAM_H__ */