Script_Interpreter.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #ifndef __SCRIPT_INTERPRETER_H__
  21. #define __SCRIPT_INTERPRETER_H__
  22. #define MAX_STACK_DEPTH 64
  23. #define LOCALSTACK_SIZE 6144
  24. typedef struct prstack_s {
  25. int s;
  26. const function_t *f;
  27. int stackbase;
  28. } prstack_t;
  29. class idInterpreter {
  30. private:
  31. prstack_t callStack[ MAX_STACK_DEPTH ];
  32. int callStackDepth;
  33. int maxStackDepth;
  34. byte localstack[ LOCALSTACK_SIZE ];
  35. int localstackUsed;
  36. int localstackBase;
  37. int maxLocalstackUsed;
  38. const function_t *currentFunction;
  39. int instructionPointer;
  40. int popParms;
  41. const idEventDef *multiFrameEvent;
  42. idEntity *eventEntity;
  43. idThread *thread;
  44. void PopParms( int numParms );
  45. void PushString( const char *string );
  46. void Push( int value );
  47. const char *FloatToString( float value );
  48. void AppendString( idVarDef *def, const char *from );
  49. void SetString( idVarDef *def, const char *from );
  50. const char *GetString( idVarDef *def );
  51. varEval_t GetVariable( idVarDef *def );
  52. idEntity *GetEntity( int entnum ) const;
  53. idScriptObject *GetScriptObject( int entnum ) const;
  54. void NextInstruction( int position );
  55. void LeaveFunction( idVarDef *returnDef );
  56. void CallEvent( const function_t *func, int argsize );
  57. void CallSysEvent( const function_t *func, int argsize );
  58. public:
  59. bool doneProcessing;
  60. bool threadDying;
  61. bool terminateOnExit;
  62. bool debug;
  63. idInterpreter();
  64. // save games
  65. void Save( idSaveGame *savefile ) const; // archives object for save game file
  66. void Restore( idRestoreGame *savefile ); // unarchives object from save game file
  67. void SetThread( idThread *pThread );
  68. void StackTrace() const;
  69. int CurrentLine() const;
  70. const char *CurrentFile() const;
  71. void Error( VERIFY_FORMAT_STRING const char *fmt, ... ) const;
  72. void Warning( VERIFY_FORMAT_STRING const char *fmt, ... ) const;
  73. void DisplayInfo() const;
  74. bool BeginMultiFrameEvent( idEntity *ent, const idEventDef *event );
  75. void EndMultiFrameEvent( idEntity *ent, const idEventDef *event );
  76. bool MultiFrameEventInProgress() const;
  77. void ThreadCall( idInterpreter *source, const function_t *func, int args );
  78. void EnterFunction( const function_t *func, bool clearStack );
  79. void EnterObjectFunction( idEntity *self, const function_t *func, bool clearStack );
  80. bool Execute();
  81. void Reset();
  82. bool GetRegisterValue( const char *name, idStr &out, int scopeDepth );
  83. int GetCallstackDepth() const;
  84. const prstack_t *GetCallstack() const;
  85. const function_t *GetCurrentFunction() const;
  86. idThread *GetThread() const;
  87. };
  88. /*
  89. ====================
  90. idInterpreter::PopParms
  91. ====================
  92. */
  93. ID_INLINE void idInterpreter::PopParms( int numParms ) {
  94. // pop our parms off the stack
  95. if ( localstackUsed < numParms ) {
  96. Error( "locals stack underflow\n" );
  97. }
  98. localstackUsed -= numParms;
  99. }
  100. /*
  101. ====================
  102. idInterpreter::Push
  103. ====================
  104. */
  105. ID_INLINE void idInterpreter::Push( int value ) {
  106. if ( localstackUsed + sizeof( int ) > LOCALSTACK_SIZE ) {
  107. Error( "Push: locals stack overflow\n" );
  108. }
  109. *( int * )&localstack[ localstackUsed ] = value;
  110. localstackUsed += sizeof( int );
  111. }
  112. /*
  113. ====================
  114. idInterpreter::PushString
  115. ====================
  116. */
  117. ID_INLINE void idInterpreter::PushString( const char *string ) {
  118. if ( localstackUsed + MAX_STRING_LEN > LOCALSTACK_SIZE ) {
  119. Error( "PushString: locals stack overflow\n" );
  120. }
  121. idStr::Copynz( ( char * )&localstack[ localstackUsed ], string, MAX_STRING_LEN );
  122. localstackUsed += MAX_STRING_LEN;
  123. }
  124. /*
  125. ====================
  126. idInterpreter::FloatToString
  127. ====================
  128. */
  129. ID_INLINE const char *idInterpreter::FloatToString( float value ) {
  130. static char text[ 32 ];
  131. if ( value == ( float )( int )value ) {
  132. sprintf( text, "%d", ( int )value );
  133. } else {
  134. sprintf( text, "%f", value );
  135. }
  136. return text;
  137. }
  138. /*
  139. ====================
  140. idInterpreter::AppendString
  141. ====================
  142. */
  143. ID_INLINE void idInterpreter::AppendString( idVarDef *def, const char *from ) {
  144. if ( def->initialized == idVarDef::stackVariable ) {
  145. idStr::Append( ( char * )&localstack[ localstackBase + def->value.stackOffset ], MAX_STRING_LEN, from );
  146. } else {
  147. idStr::Append( def->value.stringPtr, MAX_STRING_LEN, from );
  148. }
  149. }
  150. /*
  151. ====================
  152. idInterpreter::SetString
  153. ====================
  154. */
  155. ID_INLINE void idInterpreter::SetString( idVarDef *def, const char *from ) {
  156. if ( def->initialized == idVarDef::stackVariable ) {
  157. idStr::Copynz( ( char * )&localstack[ localstackBase + def->value.stackOffset ], from, MAX_STRING_LEN );
  158. } else {
  159. idStr::Copynz( def->value.stringPtr, from, MAX_STRING_LEN );
  160. }
  161. }
  162. /*
  163. ====================
  164. idInterpreter::GetString
  165. ====================
  166. */
  167. ID_INLINE const char *idInterpreter::GetString( idVarDef *def ) {
  168. if ( def->initialized == idVarDef::stackVariable ) {
  169. return ( char * )&localstack[ localstackBase + def->value.stackOffset ];
  170. } else {
  171. return def->value.stringPtr;
  172. }
  173. }
  174. /*
  175. ====================
  176. idInterpreter::GetVariable
  177. ====================
  178. */
  179. ID_INLINE varEval_t idInterpreter::GetVariable( idVarDef *def ) {
  180. if ( def->initialized == idVarDef::stackVariable ) {
  181. varEval_t val;
  182. val.intPtr = ( int * )&localstack[ localstackBase + def->value.stackOffset ];
  183. return val;
  184. } else {
  185. return def->value;
  186. }
  187. }
  188. /*
  189. ================
  190. idInterpreter::GetEntity
  191. ================
  192. */
  193. ID_INLINE idEntity *idInterpreter::GetEntity( int entnum ) const{
  194. assert( entnum <= MAX_GENTITIES );
  195. if ( ( entnum > 0 ) && ( entnum <= MAX_GENTITIES ) ) {
  196. return gameLocal.entities[ entnum - 1 ];
  197. }
  198. return NULL;
  199. }
  200. /*
  201. ================
  202. idInterpreter::GetScriptObject
  203. ================
  204. */
  205. ID_INLINE idScriptObject *idInterpreter::GetScriptObject( int entnum ) const {
  206. idEntity *ent;
  207. assert( entnum <= MAX_GENTITIES );
  208. if ( ( entnum > 0 ) && ( entnum <= MAX_GENTITIES ) ) {
  209. ent = gameLocal.entities[ entnum - 1 ];
  210. if ( ent && ent->scriptObject.data ) {
  211. return &ent->scriptObject;
  212. }
  213. }
  214. return NULL;
  215. }
  216. /*
  217. ====================
  218. idInterpreter::NextInstruction
  219. ====================
  220. */
  221. ID_INLINE void idInterpreter::NextInstruction( int position ) {
  222. // Before we execute an instruction, we increment instructionPointer,
  223. // therefore we need to compensate for that here.
  224. instructionPointer = position - 1;
  225. }
  226. #endif /* !__SCRIPT_INTERPRETER_H__ */