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__ */