Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1502 lines
34 KiB

  1. //========== Copyright � 2008, Valve Corporation, All rights reserved. ========
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include <stdio.h>
  7. #if defined(POSIX)
  8. #include <curses.h>
  9. #include <unistd.h>
  10. #else
  11. #include <io.h>
  12. #include <conio.h>
  13. #include <direct.h>
  14. #endif
  15. #include "platform.h"
  16. #if !defined(OSX) && !defined(POSIX)
  17. extern "C"
  18. {
  19. #endif
  20. #include "lua.h"
  21. #include "lauxlib.h"
  22. #include "lualib.h"
  23. #ifdef getstr // Already defined in curses.h on linux
  24. #undef getstr
  25. #endif
  26. #include "lobject.h"
  27. #include "lstate.h"
  28. #include "ldo.h"
  29. #if !defined(OSX) && !defined(POSIX)
  30. }
  31. #endif
  32. #include "vec3.h"
  33. #include "tier1/utlmap.h"
  34. #include "datamap.h"
  35. #include "tier1/functors.h"
  36. #include "tier1/utlvector.h"
  37. #include "tier1/utlhash.h"
  38. #include "tier1/utlbuffer.h"
  39. #include "tier1/fmtstr.h"
  40. #include "tier1/convar.h"
  41. #include "mathlib/vector.h"
  42. #include "vstdlib/random.h"
  43. #include "vscript/ivscript.h"
  44. #include <string>
  45. //#include "init_nut.h"
  46. #include "memdbgon.h"
  47. #ifdef VLUA_DEBUG_SERIALIZATION
  48. static int lastType;
  49. #endif
  50. //-------------------------------------------------------------------------
  51. // Helpers
  52. //-------------------------------------------------------------------------
  53. static const char *FieldTypeToString( int type )
  54. {
  55. switch( type )
  56. {
  57. case FIELD_VOID: return "void";
  58. case FIELD_FLOAT: return "float";
  59. case FIELD_CSTRING: return "string";
  60. case FIELD_VECTOR: return "Vector";
  61. case FIELD_INTEGER: return "int";
  62. case FIELD_BOOLEAN: return "bool";
  63. case FIELD_CHARACTER: return "char";
  64. case FIELD_HSCRIPT: return "handle";
  65. default: return "<unknown>";
  66. }
  67. }
  68. static const char *LUATypeToString( int nLUAType )
  69. {
  70. switch( nLUAType )
  71. {
  72. case LUA_TNUMBER: return "FLOAT";
  73. case LUA_TBOOLEAN: return "BOOL";
  74. case LUA_TSTRING: return "STRING";
  75. case LUA_TNIL: return "NULL";
  76. case LUA_TTABLE: return "TABLE";
  77. case LUA_TUSERDATA: return "USERDATA";
  78. case LUA_TTHREAD: return "THREAD";
  79. }
  80. return "<unknown>";
  81. }
  82. class CLuaVM : public IScriptVM
  83. {
  84. lua_State *m_LuaState;
  85. ScriptOutputFunc_t m_OutputFunc;
  86. ScriptErrorFunc_t m_ErrorFunc;
  87. int64 m_iUniqueIdSerialNumber;
  88. // CUtlHashFast<SQClass *, CUtlHashFastGenericHash> m_TypeMap;
  89. struct InstanceContext_t
  90. {
  91. void *pInstance;
  92. ScriptClassDesc_t *pClassDesc;
  93. char szName[ 64 ];
  94. };
  95. public:
  96. CLuaVM( lua_State *pState = NULL )
  97. {
  98. m_LuaState = pState;
  99. m_iUniqueIdSerialNumber = 0;
  100. m_OutputFunc = NULL;
  101. m_ErrorFunc = NULL;
  102. // m_TypeMap.Init( 256 );
  103. }
  104. static int PrintFunc( lua_State *pState )
  105. {
  106. ScriptOutputFunc_t m_OutputFunc = *( ( ScriptOutputFunc_t * )lua_touserdata( pState, lua_upvalueindex( 1 ) ) );
  107. CUtlString Output;
  108. int n = lua_gettop( pState ); /* number of arguments */
  109. int i;
  110. lua_getglobal( pState, "towstring" );
  111. lua_getglobal( pState, "tostring" );
  112. for ( i=1; i <= n; i++ )
  113. {
  114. const char *s = NULL;
  115. lua_pushvalue( pState, -1 ); /* function to be called */
  116. lua_pushvalue( pState, i ); /* value to print */
  117. lua_call( pState, 1, 1 );
  118. s = lua_tostring( pState, -1 ); /* get result */
  119. if ( s == NULL )
  120. {
  121. return luaL_error( pState, LUA_QL( "tostring" ) " must return a string to " LUA_QL( "print" ) );
  122. }
  123. if ( i > 1 )
  124. {
  125. Output += "\t";
  126. }
  127. if ( s )
  128. {
  129. Output += s;
  130. }
  131. lua_pop( pState, 1 ); /* pop result */
  132. }
  133. if ( m_OutputFunc )
  134. {
  135. m_OutputFunc( Output );
  136. }
  137. else
  138. {
  139. Msg( "%s\n", Output.Get() );
  140. }
  141. return 0;
  142. }
  143. void HandleError( const char *pszErrorText )
  144. {
  145. if ( m_ErrorFunc )
  146. {
  147. m_ErrorFunc( SCRIPT_LEVEL_WARNING, pszErrorText );
  148. }
  149. else
  150. {
  151. Msg( pszErrorText );
  152. }
  153. }
  154. static int FatalErrorHandler( lua_State *pState )
  155. {
  156. const char *err = lua_tostring( pState, 1 );
  157. throw( err );
  158. }
  159. void FatalError( const char *pszError )
  160. {
  161. if ( m_ErrorFunc )
  162. {
  163. m_ErrorFunc( SCRIPT_LEVEL_ERROR, pszError );
  164. }
  165. else
  166. {
  167. Msg( pszError );
  168. }
  169. }
  170. int GetStackSize( )
  171. {
  172. return ( ( char * )m_LuaState->stack_last - ( char * )m_LuaState->top ) / sizeof( TValue );
  173. }
  174. static void stackDump (lua_State *L)
  175. {
  176. int i;
  177. int top = lua_gettop(L);
  178. for (i = 1; i <= top; i++) { /* repeat for each level */
  179. int t = lua_type(L, i);
  180. switch (t) {
  181. case LUA_TSTRING: /* strings */
  182. printf("`%s'", lua_tostring(L, i));
  183. break;
  184. case LUA_TBOOLEAN: /* booleans */
  185. printf(lua_toboolean(L, i) ? "true" : "false");
  186. break;
  187. case LUA_TNUMBER: /* numbers */
  188. printf("%g", lua_tonumber(L, i));
  189. break;
  190. default: /* other values */
  191. printf("%s", lua_typename(L, t));
  192. break;
  193. }
  194. printf(" "); /* put a separator */
  195. }
  196. printf("\n"); /* end the listing */
  197. }
  198. //-------------------------------------------------------------
  199. //
  200. //-------------------------------------------------------------
  201. static void PushVariant( lua_State *pState, const ScriptVariant_t &value )
  202. {
  203. switch ( value.m_type )
  204. {
  205. case FIELD_VOID:
  206. lua_pushnil( pState );
  207. break;
  208. case FIELD_FLOAT:
  209. lua_pushnumber( pState, value.m_float );
  210. break;
  211. case FIELD_CSTRING:
  212. lua_pushstring( pState, value );
  213. break;
  214. case FIELD_VECTOR:
  215. lua_newvec3( pState, value.m_pVector );
  216. break;
  217. case FIELD_INTEGER:
  218. lua_pushinteger( pState, value.m_int );
  219. break;
  220. case FIELD_BOOLEAN:
  221. lua_pushboolean( pState, value.m_bool );
  222. break;
  223. case FIELD_CHARACTER:
  224. {
  225. char sz[2];
  226. sz[0] = value.m_char;
  227. sz[1] = 0;
  228. lua_pushlstring( pState, sz, 1 );
  229. break;
  230. }
  231. case FIELD_HSCRIPT:
  232. if ( value.m_hScript == NULL )
  233. {
  234. lua_pushnil( pState );
  235. }
  236. else
  237. {
  238. lua_rawgeti( pState, LUA_REGISTRYINDEX, size_cast< int > ( ( intp )value.m_hScript ) );
  239. Assert( lua_isnil( pState, -1 ) == false );
  240. }
  241. break;
  242. }
  243. }
  244. //-------------------------------------------------------------
  245. //
  246. //-------------------------------------------------------------
  247. static bool ConvertToVariant( int nStackIndex, lua_State *pState, ScriptVariant_t *pReturn )
  248. {
  249. switch ( lua_type( pState, nStackIndex ) )
  250. {
  251. case LUA_TNIL:
  252. pReturn->m_type = FIELD_VOID;
  253. break;
  254. case LUA_TNUMBER:
  255. *pReturn = ( float )lua_tonumber( pState, nStackIndex );
  256. break;
  257. case LUA_TBOOLEAN:
  258. *pReturn = ( lua_toboolean( pState, nStackIndex ) != 0 );
  259. break;
  260. case LUA_TSTRING:
  261. {
  262. int size = strlen( lua_tostring( pState, nStackIndex ) ) + 1;
  263. pReturn->m_type = FIELD_CSTRING;
  264. pReturn->m_pszString = new char[ size ];
  265. memcpy( (void *)pReturn->m_pszString, lua_tostring( pState, nStackIndex ), size );
  266. pReturn->m_flags |= SV_FREE;
  267. }
  268. break;
  269. #if 0
  270. case OT_INSTANCE:
  271. {
  272. SQUserPointer pVector;
  273. sq_pushobject( m_hVM, object );
  274. SQRESULT getResult = sq_getinstanceup( m_hVM, -1, &pVector, TYPETAG_VECTOR );
  275. sq_poptop( m_hVM );
  276. if ( getResult == SQ_OK )
  277. {
  278. pReturn->m_type = FIELD_VECTOR;
  279. pReturn->m_pVector = new Vector( *((Vector *)pVector) );
  280. pReturn->m_flags |= SV_FREE;
  281. break;
  282. }
  283. }
  284. // fall through
  285. #endif
  286. default:
  287. {
  288. Assert( nStackIndex == -1 );
  289. pReturn->m_type = FIELD_HSCRIPT;
  290. pReturn->m_hScript = ( HSCRIPT )( intp )luaL_ref( pState, LUA_REGISTRYINDEX );
  291. }
  292. }
  293. return true;
  294. }
  295. static void ReleaseVariant( lua_State *pState, ScriptVariant_t &value )
  296. {
  297. if ( value.m_type == FIELD_HSCRIPT )
  298. {
  299. luaL_unref( pState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )value.m_hScript ) );
  300. }
  301. else
  302. {
  303. value.Free();
  304. }
  305. value.m_type = FIELD_VOID;
  306. }
  307. virtual bool Init( )
  308. {
  309. m_LuaState = luaL_newstate();
  310. luaL_openlibs( m_LuaState );
  311. luaopen_vec3( m_LuaState );
  312. lua_atpanic( m_LuaState, FatalErrorHandler );
  313. SetOutputCallback( NULL );
  314. return true;
  315. }
  316. virtual void Shutdown()
  317. {
  318. if ( m_LuaState )
  319. {
  320. lua_close( m_LuaState );
  321. m_LuaState = NULL;
  322. }
  323. // m_TypeMap.Purge();
  324. }
  325. virtual bool ConnectDebugger()
  326. {
  327. Assert( 0 );
  328. return false;
  329. }
  330. virtual void DisconnectDebugger()
  331. {
  332. Assert( 0 );
  333. }
  334. virtual ScriptLanguage_t GetLanguage()
  335. {
  336. return SL_LUA;
  337. }
  338. virtual const char *GetLanguageName()
  339. {
  340. return "Lua";
  341. }
  342. virtual void AddSearchPath( const char *pszSearchPath )
  343. {
  344. lua_getfield( m_LuaState, LUA_GLOBALSINDEX, "package" );
  345. if ( !lua_istable( m_LuaState, -1 ) )
  346. {
  347. Assert( 0 );
  348. lua_pop( m_LuaState, 1 );
  349. return;
  350. }
  351. lua_getfield( m_LuaState, -1, "path" );
  352. if ( !lua_isstring( m_LuaState, -1 ) )
  353. {
  354. Assert( 0 );
  355. lua_pop( m_LuaState, 1 );
  356. return;
  357. }
  358. CUtlString szNewPath;
  359. szNewPath = lua_tostring( m_LuaState, -1 );
  360. szNewPath += ";";
  361. szNewPath += pszSearchPath;
  362. szNewPath += "\\?.lua";
  363. lua_pushstring( m_LuaState, szNewPath );
  364. lua_setfield( m_LuaState, -3, "path" );
  365. lua_pop( m_LuaState, 2 );
  366. }
  367. virtual bool Frame( float simTime )
  368. {
  369. if ( m_LuaState )
  370. {
  371. Msg( "Garbage Collecting...\n" );
  372. lua_gc( m_LuaState, LUA_GCCOLLECT, 0 );
  373. }
  374. #if 0
  375. if ( m_hDbg )
  376. {
  377. sq_rdbg_update( m_hDbg );
  378. if ( !m_hDbg->IsConnected() )
  379. DisconnectDebugger();
  380. }
  381. #endif
  382. return true;
  383. }
  384. virtual ScriptStatus_t Run( const char *pszScript, bool bWait = true )
  385. {
  386. Assert( 0 );
  387. return SCRIPT_ERROR;
  388. }
  389. virtual HSCRIPT CompileScript( const char *pszScript, const char *pszId = NULL )
  390. {
  391. int nResult = luaL_loadbuffer( m_LuaState, pszScript, strlen( pszScript ), pszId );
  392. if ( nResult == 0 )
  393. {
  394. int func_ref = luaL_ref( m_LuaState, LUA_REGISTRYINDEX );
  395. // lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, func_ref );
  396. // lua_call( m_LuaState, 0, 0 );
  397. return ( HSCRIPT )( intp )func_ref;
  398. }
  399. else
  400. {
  401. const char *pszErrorText = lua_tostring( m_LuaState, -1 );
  402. HandleError( pszErrorText );
  403. }
  404. return INVALID_HSCRIPT;
  405. }
  406. virtual void ReleaseScript( HSCRIPT hScript)
  407. {
  408. luaL_unref( m_LuaState, LUA_REGISTRYINDEX, size_cast< int > ( ( intp )hScript ) );
  409. }
  410. virtual ScriptStatus_t Run( HSCRIPT hScript, HSCRIPT hScope = NULL, bool bWait = true )
  411. {
  412. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScript ) );
  413. int nResult = lua_pcall( m_LuaState, 0, LUA_MULTRET, 0 );
  414. switch( nResult )
  415. {
  416. case LUA_ERRRUN:
  417. {
  418. const char *pszErrorText = lua_tostring( m_LuaState, -1 );
  419. HandleError( pszErrorText );
  420. return SCRIPT_ERROR;
  421. }
  422. case LUA_ERRMEM:
  423. {
  424. const char *pszErrorText = lua_tostring( m_LuaState, -1 );
  425. HandleError( pszErrorText );
  426. return SCRIPT_ERROR;
  427. }
  428. case LUA_ERRERR:
  429. {
  430. const char *pszErrorText = lua_tostring( m_LuaState, -1 );
  431. HandleError( pszErrorText );
  432. return SCRIPT_ERROR;
  433. }
  434. }
  435. return SCRIPT_DONE;
  436. }
  437. virtual ScriptStatus_t Run( HSCRIPT hScript, bool bWait )
  438. {
  439. Assert( 0 );
  440. return SCRIPT_ERROR;
  441. }
  442. // stack good
  443. virtual HSCRIPT CreateScope( const char *pszScope, HSCRIPT hParent = NULL )
  444. {
  445. return NULL;
  446. }
  447. virtual void ReleaseScope( HSCRIPT hScript )
  448. {
  449. }
  450. // stack good
  451. virtual HSCRIPT LookupFunction( const char *pszFunction, HSCRIPT hScope = NULL )
  452. {
  453. if ( hScope )
  454. {
  455. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  456. if ( lua_isnil( m_LuaState, -1 ) )
  457. {
  458. Assert( 0 );
  459. lua_pop( m_LuaState, 1 );
  460. return NULL;
  461. }
  462. lua_getfield( m_LuaState, -1, pszFunction );
  463. if ( lua_isnil( m_LuaState, -1 ) || !lua_isfunction( m_LuaState, -1 ) )
  464. {
  465. lua_pop( m_LuaState, 2 );
  466. return NULL;
  467. }
  468. int func_ref = luaL_ref( m_LuaState, LUA_REGISTRYINDEX );
  469. lua_pop( m_LuaState, 1 );
  470. return ( HSCRIPT )( intp )func_ref;
  471. }
  472. else
  473. {
  474. lua_getfield( m_LuaState, LUA_GLOBALSINDEX, pszFunction );
  475. if ( lua_isnil( m_LuaState, -1 ) || !lua_isfunction( m_LuaState, -1 ) )
  476. {
  477. lua_pop( m_LuaState, 1 );
  478. return NULL;
  479. }
  480. int func_ref = luaL_ref( m_LuaState, LUA_REGISTRYINDEX );
  481. return ( HSCRIPT )( intp )func_ref;
  482. }
  483. }
  484. // stack good
  485. virtual void ReleaseFunction( HSCRIPT hScript )
  486. {
  487. luaL_unref( m_LuaState, LUA_REGISTRYINDEX, size_cast<int>( ( intp )hScript ) );
  488. }
  489. // stack good
  490. virtual ScriptStatus_t ExecuteFunction( HSCRIPT hFunction, ScriptVariant_t *pArgs, int nArgs, ScriptVariant_t *pReturn, HSCRIPT hScope, bool bWait )
  491. {
  492. if ( hScope == INVALID_HSCRIPT )
  493. {
  494. DevWarning( "ExecuteFunction: Invalid scope handed to script VM\n" );
  495. return SCRIPT_ERROR;
  496. }
  497. #if 0
  498. if ( m_hDbg )
  499. {
  500. extern bool g_bSqDbgTerminateScript;
  501. if ( g_bSqDbgTerminateScript )
  502. {
  503. DisconnectDebugger();
  504. g_bSqDbgTerminateScript = false;
  505. }
  506. }
  507. #endif
  508. Assert( bWait );
  509. try
  510. {
  511. if ( hFunction )
  512. {
  513. int nStackSize = GetStackSize();
  514. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hFunction ) );
  515. int nTopStack = lua_gettop( m_LuaState );
  516. if ( hScope )
  517. {
  518. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  519. }
  520. for ( int i = 0; i < nArgs; i++ )
  521. {
  522. PushVariant( m_LuaState, pArgs[i] );
  523. }
  524. lua_call( m_LuaState, lua_gettop( m_LuaState ) - nTopStack, ( pReturn ? 1 : 0 ) );
  525. if ( pReturn )
  526. {
  527. ConvertToVariant( -1, m_LuaState, pReturn );
  528. }
  529. lua_pop( m_LuaState, nStackSize - GetStackSize() );
  530. return SCRIPT_DONE;
  531. }
  532. if ( pReturn )
  533. {
  534. pReturn->m_type = FIELD_VOID;
  535. }
  536. }
  537. catch( const char *pszString )
  538. {
  539. FatalError( pszString );
  540. }
  541. return SCRIPT_ERROR;
  542. }
  543. // stack good
  544. static int TranslateCall( lua_State *pState )
  545. {
  546. int nActualParams = lua_gettop( pState );
  547. ScriptFunctionBinding_t *pVMScriptFunction = ( ScriptFunctionBinding_t * )lua_touserdata( pState, lua_upvalueindex( 1 ) );
  548. int nFormalParams = pVMScriptFunction->m_desc.m_Parameters.Count();
  549. CUtlVectorFixed<ScriptVariant_t, 14> params;
  550. ScriptVariant_t returnValue;
  551. bool bCallFree = false;
  552. params.SetSize( nFormalParams );
  553. void *pObject = NULL;
  554. if ( nActualParams )
  555. {
  556. int nOffset = 1;
  557. if ( ( pVMScriptFunction->m_flags & SF_MEMBER_FUNC ) )
  558. {
  559. InstanceContext_t *pInstanceContext = ( InstanceContext_t * )lua_touserdata( pState, nOffset );
  560. pObject = pInstanceContext->pInstance;
  561. if ( pInstanceContext->pClassDesc->pHelper )
  562. {
  563. pObject = pInstanceContext->pClassDesc->pHelper->GetProxied( pObject );
  564. }
  565. if ( !pObject )
  566. {
  567. // sq_throwerror( hVM, "Accessed null instance" );
  568. return SCRIPT_ERROR;
  569. }
  570. nOffset++;
  571. nActualParams--;
  572. }
  573. int iLimit = ( nActualParams < nFormalParams ? nActualParams : nFormalParams );
  574. ScriptDataType_t *pCurParamType = pVMScriptFunction->m_desc.m_Parameters.Base();
  575. for ( int i = 0; i < iLimit; i++, pCurParamType++ )
  576. {
  577. switch ( *pCurParamType )
  578. {
  579. case FIELD_FLOAT:
  580. params[ i ] = ( float )lua_tonumber( pState, i + nOffset );
  581. break;
  582. case FIELD_CSTRING:
  583. params[ i ] = lua_tostring( pState, i + nOffset );
  584. break;
  585. case FIELD_VECTOR:
  586. {
  587. params[ i ] = lua_getvec3( pState, i + nOffset );
  588. break;
  589. }
  590. case FIELD_INTEGER:
  591. params[ i ] = ( int )lua_tonumber( pState, i + nOffset );
  592. break;
  593. case FIELD_BOOLEAN:
  594. params[ i ] = ( lua_toboolean( pState, i + nOffset ) != 0 );
  595. break;
  596. case FIELD_CHARACTER:
  597. params[ i ] = lua_tostring( pState, i + nOffset )[0];
  598. break;
  599. case FIELD_HSCRIPT:
  600. {
  601. lua_pushvalue( pState, i + nOffset );
  602. params[ i ] = ( HSCRIPT )( intp )luaL_ref( pState, LUA_REGISTRYINDEX );
  603. // params[ i ].m_flags |= SV_FREE;
  604. bCallFree = true;
  605. break;
  606. }
  607. default:
  608. break;
  609. }
  610. }
  611. }
  612. (*pVMScriptFunction->m_pfnBinding)( pVMScriptFunction->m_pFunction, pObject, params.Base(), params.Count(), ( pVMScriptFunction->m_desc.m_ReturnType != FIELD_VOID ) ? &returnValue : NULL );
  613. if ( pVMScriptFunction->m_desc.m_ReturnType != FIELD_VOID )
  614. {
  615. PushVariant( pState, returnValue );
  616. }
  617. if ( bCallFree )
  618. {
  619. for ( int i = 0; i < params.Count(); i++ )
  620. {
  621. ReleaseVariant( pState, params[ i ] );
  622. // params[i].Free();
  623. }
  624. }
  625. return ( ( pVMScriptFunction->m_desc.m_ReturnType != FIELD_VOID ) ? 1 : 0 ) ;
  626. }
  627. //-------------------------------------------------------------
  628. //
  629. //-------------------------------------------------------------
  630. // stack good
  631. void RegisterFunctionGuts( ScriptFunctionBinding_t *pScriptFunction, HSCRIPT pOwningClass = NULL )
  632. {
  633. char szTypeMask[ 64 ];
  634. if ( pScriptFunction->m_desc.m_Parameters.Count() > ARRAYSIZE(szTypeMask) - 1 )
  635. {
  636. AssertMsg1( 0, "Too many agruments for script function %s\n", pScriptFunction->m_desc.m_pszFunction );
  637. return;
  638. }
  639. szTypeMask[0] = '.';
  640. char *pCurrent = &szTypeMask[1];
  641. for ( int i = 0; i < pScriptFunction->m_desc.m_Parameters.Count(); i++, pCurrent++ )
  642. {
  643. switch ( pScriptFunction->m_desc.m_Parameters[i] )
  644. {
  645. case FIELD_CSTRING:
  646. *pCurrent = 's';
  647. break;
  648. case FIELD_FLOAT:
  649. case FIELD_INTEGER:
  650. *pCurrent = 'n';
  651. break;
  652. case FIELD_BOOLEAN:
  653. *pCurrent = 'b';
  654. break;
  655. case FIELD_VECTOR:
  656. *pCurrent = 'x';
  657. break;
  658. case FIELD_HSCRIPT:
  659. *pCurrent = '.';
  660. break;
  661. case FIELD_CHARACTER:
  662. default:
  663. *pCurrent = FIELD_VOID;
  664. AssertMsg( 0 , "Not supported" );
  665. break;
  666. }
  667. }
  668. int nStackIndex = LUA_GLOBALSINDEX;
  669. if ( pOwningClass )
  670. {
  671. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )pOwningClass ) );
  672. if ( !lua_isnil( m_LuaState, -1 ) )
  673. {
  674. nStackIndex = lua_gettop( m_LuaState );
  675. }
  676. }
  677. Assert( pCurrent - szTypeMask < ARRAYSIZE(szTypeMask) - 1 );
  678. *pCurrent = 0;
  679. lua_pushstring( m_LuaState, pScriptFunction->m_desc.m_pszScriptName );
  680. lua_pushlightuserdata( m_LuaState, pScriptFunction );
  681. lua_pushcclosure( m_LuaState, &TranslateCall, 1 );
  682. lua_settable( m_LuaState, nStackIndex );
  683. if ( pOwningClass )
  684. {
  685. lua_pop( m_LuaState, 1 );
  686. }
  687. if ( nStackIndex == LUA_GLOBALSINDEX )
  688. {
  689. Msg( "VLua: Registered GLOBAL function %s\n", pScriptFunction->m_desc.m_pszScriptName );
  690. }
  691. else
  692. {
  693. Msg( "VLua: Registered TABLE function %s\n", pScriptFunction->m_desc.m_pszScriptName );
  694. }
  695. #if 0
  696. if ( developer.GetInt() )
  697. {
  698. const char *pszHide = SCRIPT_HIDE;
  699. if ( !pScriptFunction->m_desc.m_pszDescription || *pScriptFunction->m_desc.m_pszDescription != *pszHide )
  700. {
  701. std::string name;
  702. std::string signature;
  703. if ( pClassDesc )
  704. {
  705. name += pClassDesc->m_pszScriptName;
  706. name += "::";
  707. }
  708. name += pScriptFunction->m_desc.m_pszScriptName;
  709. signature += FieldTypeToString( pScriptFunction->m_desc.m_ReturnType );
  710. signature += ' ';
  711. signature += name;
  712. signature += '(';
  713. for ( int i = 0; i < pScriptFunction->m_desc.m_Parameters.Count(); i++ )
  714. {
  715. if ( i != 0 )
  716. {
  717. signature += ", ";
  718. }
  719. signature+= FieldTypeToString( pScriptFunction->m_desc.m_Parameters[i] );
  720. }
  721. signature += ')';
  722. sq_pushobject( m_hVM, LookupObject( "RegisterFunctionDocumentation", NULL, false ) );
  723. sq_pushroottable( m_hVM );
  724. sq_pushobject( m_hVM, hFunction );
  725. sq_pushstring( m_hVM, name.c_str(), name.length() );
  726. sq_pushstring( m_hVM, signature.c_str(), signature.length() );
  727. sq_pushstring( m_hVM, pScriptFunction->m_desc.m_pszDescription, -1 );
  728. sq_call( m_hVM, 5, false, /*false*/ true );
  729. sq_pop( m_hVM, 1 );
  730. }
  731. }
  732. #endif
  733. }
  734. virtual void RegisterFunction( ScriptFunctionBinding_t *pScriptFunction )
  735. {
  736. RegisterFunctionGuts( pScriptFunction );
  737. }
  738. static int custom_index( lua_State *pState )
  739. {
  740. InstanceContext_t *pInstanceContext = ( ( InstanceContext_t * )lua_touserdata( pState, 1 ) );
  741. ScriptClassDesc_t *pVMScriptFunction = pInstanceContext->pClassDesc;
  742. const char *pszKey = luaL_checkstring( pState, 2 );
  743. while( pVMScriptFunction )
  744. {
  745. lua_getfield( pState, LUA_REGISTRYINDEX, pVMScriptFunction->m_pszClassname );
  746. if ( lua_isnil( pState, -1 ) )
  747. {
  748. break;
  749. }
  750. lua_pushstring( pState, pszKey );
  751. lua_rawget( pState, -2 );
  752. if ( lua_isnil( pState, -1 ) )
  753. {
  754. lua_pop( pState, 2 );
  755. pVMScriptFunction = pVMScriptFunction->m_pBaseDesc;
  756. }
  757. else
  758. {
  759. break;
  760. }
  761. }
  762. return 1;
  763. }
  764. /*
  765. static int custom_gc( lua_State *pState )
  766. {
  767. InstanceContext_t *pInstanceContext = ( ( InstanceContext_t * )lua_touserdata( pState, 1 ) );
  768. return 0;
  769. }
  770. */
  771. // stack good
  772. virtual bool RegisterClass( ScriptClassDesc_t *pClassDesc )
  773. {
  774. if ( luaL_newmetatable( m_LuaState, pClassDesc->m_pszScriptName ) == 0 )
  775. {
  776. lua_pop( m_LuaState, 1 );
  777. return true;
  778. }
  779. // lua_pushcclosure( m_LuaState, custom_gc, 0 );
  780. // lua_setfield( m_LuaState, -2, "__gc" );
  781. lua_pushcclosure( m_LuaState, custom_index, 0 );
  782. lua_setfield( m_LuaState, -2, "__index" );
  783. HSCRIPT ClassReference = ( HSCRIPT )( intp )luaL_ref( m_LuaState, LUA_REGISTRYINDEX );
  784. for ( int i = 0; i < pClassDesc->m_FunctionBindings.Count(); i++ )
  785. {
  786. RegisterFunctionGuts( &pClassDesc->m_FunctionBindings[i], ClassReference );
  787. }
  788. if ( pClassDesc->m_pBaseDesc )
  789. {
  790. RegisterClass( pClassDesc->m_pBaseDesc );
  791. }
  792. luaL_unref( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )ClassReference ) );
  793. return true;
  794. }
  795. // stack good
  796. virtual HSCRIPT RegisterInstance( ScriptClassDesc_t *pClassDesc, void *pInstance )
  797. {
  798. HSCRIPT Instance = NULL;
  799. if ( !RegisterClass( pClassDesc ) )
  800. {
  801. return NULL;
  802. }
  803. InstanceContext_t *pInstanceContext = ( InstanceContext_t * )lua_newuserdata( m_LuaState, sizeof( InstanceContext_t ) );
  804. pInstanceContext->pInstance = pInstance;
  805. pInstanceContext->pClassDesc = pClassDesc;
  806. luaL_getmetatable( m_LuaState, pClassDesc->m_pszScriptName );
  807. lua_setmetatable( m_LuaState, -2 );
  808. Instance = ( HSCRIPT )( intp )luaL_ref( m_LuaState, LUA_REGISTRYINDEX );
  809. return Instance;
  810. }
  811. // stack good
  812. virtual void SetInstanceUniqeId( HSCRIPT hInstance, const char *pszId )
  813. {
  814. #if 0
  815. TValue *pValue = ( TValue * )hInstance;
  816. if ( !hInstance )
  817. {
  818. Assert( 0 );
  819. return;
  820. }
  821. Assert( ttislightuserdata( pValue ) );
  822. InstanceContext_t *pInstanceContext = ( InstanceContext_t * )( pValue->value.p );
  823. if ( pInstanceContext == NULL )
  824. {
  825. Assert( 0 );
  826. return;
  827. }
  828. lua_getfield( m_LuaState, LUA_REGISTRYINDEX, pInstanceContext->szName ); //--
  829. strcpy( pInstanceContext->szName, pszId );
  830. lua_setfield( m_LuaState, LUA_REGISTRYINDEX, pInstanceContext->szName ); //--
  831. #endif
  832. Assert( 0 );
  833. }
  834. // stack good
  835. virtual void RemoveInstance( HSCRIPT hInstance )
  836. {
  837. #if 0
  838. TValue *pValue = ( TValue * )hInstance;
  839. if ( !pValue )
  840. {
  841. Assert( 0 );
  842. return;
  843. }
  844. Assert( ttislightuserdata( pValue ) );
  845. InstanceContext_t *pInstanceContext = ( InstanceContext_t * )( pValue->value.p );
  846. lua_pushnil( m_LuaState );
  847. lua_setfield( m_LuaState, LUA_REGISTRYINDEX, pInstanceContext->szName );
  848. // lua_pushnil( m_LuaState ); //--
  849. // lua_setfield( m_LuaState, LUA_GLOBALSINDEX, pInstanceContext->szName ); //--
  850. delete pInstanceContext;
  851. delete pValue;
  852. #endif
  853. Assert( 0 );
  854. }
  855. virtual void *GetInstanceValue( HSCRIPT hInstance, ScriptClassDesc_t *pExpectedType = NULL )
  856. {
  857. Assert( 0 );
  858. return NULL;
  859. }
  860. virtual bool GenerateUniqueKey( const char *pszRoot, char *pBuf, int nBufSize )
  861. {
  862. Assert( V_strlen(pszRoot) + 32 <= nBufSize );
  863. Q_snprintf( pBuf, nBufSize, "_%x%I64x_%s", RandomInt(0, 0xfff), m_iUniqueIdSerialNumber++, pszRoot ); // random to limit key compare when serial number gets large
  864. return true;
  865. }
  866. // stack good
  867. virtual bool ValueExists( HSCRIPT hScope, const char *pszKey )
  868. {
  869. Assert( hScope == NULL );
  870. lua_getfield( m_LuaState, LUA_GLOBALSINDEX, pszKey );
  871. bool bResult = ( lua_isnil( m_LuaState, -1 ) == false );
  872. lua_pop( m_LuaState, 1 );
  873. return bResult;
  874. }
  875. virtual bool SetValue( HSCRIPT hScope, const char *pszKey, const char *pszValue )
  876. {
  877. // Not supported yet.
  878. Assert(0);
  879. return false;
  880. }
  881. // stack good
  882. virtual bool SetValue( HSCRIPT hScope, const char *pszKey, const ScriptVariant_t &value )
  883. {
  884. if ( hScope )
  885. {
  886. // Msg( "SetValue: SCOPE %s\n", pszKey );
  887. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  888. lua_pushstring( m_LuaState, pszKey );
  889. PushVariant( m_LuaState, value );
  890. lua_settable( m_LuaState, -3 );
  891. lua_pop( m_LuaState, 1 );
  892. }
  893. else
  894. {
  895. // Msg( "SetValue: NORMAL %s\n", pszKey );
  896. lua_pushstring( m_LuaState, pszKey );
  897. PushVariant( m_LuaState, value );
  898. lua_settable( m_LuaState, LUA_GLOBALSINDEX );
  899. }
  900. return true;
  901. }
  902. virtual bool SetValue( HSCRIPT hScope, int nIndex, const ScriptVariant_t &value )
  903. {
  904. Assert( hScope );
  905. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  906. lua_pushinteger( m_LuaState, nIndex );
  907. PushVariant( m_LuaState, value );
  908. lua_settable( m_LuaState, -3 );
  909. return true;
  910. }
  911. virtual void CreateTable( ScriptVariant_t &Result )
  912. {
  913. lua_newtable( m_LuaState );
  914. ConvertToVariant( -1, m_LuaState, &Result );
  915. }
  916. // stack good
  917. virtual int GetNumTableEntries( HSCRIPT hScope )
  918. {
  919. // Should this also check for 0?
  920. if ( hScope == INVALID_HSCRIPT )
  921. return 0;
  922. int nCount = 0;
  923. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  924. // int count = lua_objlen( m_LuaState, -1 );
  925. lua_pushnil( m_LuaState ); /* first key */
  926. while ( lua_next( m_LuaState, -2 ) != 0 )
  927. {
  928. /* key is at index -2 and value at index -1 */
  929. // Msg ("%s - %s\n", lua_typename(m_LuaState, lua_type(m_LuaState, -2)), lua_typename(m_LuaState, lua_type(m_LuaState, -1)));
  930. nCount++;
  931. lua_pop( m_LuaState, 1 ); /* removes value; keeps key for next iteration */
  932. }
  933. lua_pop( m_LuaState, 1 ); /* removes value; keeps key for next iteration */
  934. return nCount;
  935. }
  936. // stack good
  937. virtual int GetKeyValue( HSCRIPT hScope, int nIterator, ScriptVariant_t *pKey, ScriptVariant_t *pValue )
  938. {
  939. int nCount = 0;
  940. int nStackSize = GetStackSize();
  941. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  942. // int count = lua_objlen( m_LuaState, -1 );
  943. lua_pushnil( m_LuaState ); /* first key */
  944. while ( lua_next( m_LuaState, -2 ) != 0 && nCount < nIterator )
  945. {
  946. nCount++;
  947. lua_pop( m_LuaState, 1 ); /* removes value; keeps key for next iteration */
  948. }
  949. // Msg ("%s - %s\n", lua_typename(m_LuaState, lua_type(m_LuaState, -2)), lua_typename(m_LuaState, lua_type(m_LuaState, -1)));
  950. ConvertToVariant( -2, m_LuaState, pKey );
  951. ConvertToVariant( -1, m_LuaState, pValue );
  952. lua_pop( m_LuaState, 3 ); /* removes value; keeps key for next iteration */
  953. lua_pop( m_LuaState, nStackSize - GetStackSize() );
  954. return nCount + 1;
  955. }
  956. virtual bool GetValue( HSCRIPT hScope, const char *pszKey, ScriptVariant_t *pValue )
  957. {
  958. int nStackSize = GetStackSize();
  959. if ( hScope )
  960. {
  961. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  962. lua_getfield( m_LuaState, -1, pszKey );
  963. if ( lua_isnil( m_LuaState, -1 ) )
  964. {
  965. lua_pop( m_LuaState, nStackSize - GetStackSize() );
  966. return false;
  967. }
  968. }
  969. else
  970. {
  971. lua_getfield( m_LuaState, LUA_GLOBALSINDEX, pszKey );
  972. if ( lua_isnil( m_LuaState, -1 ) )
  973. {
  974. lua_pop( m_LuaState, nStackSize - GetStackSize() );
  975. return false;
  976. }
  977. }
  978. ConvertToVariant( -1, m_LuaState, pValue );
  979. lua_pop( m_LuaState, nStackSize - GetStackSize() );
  980. return true;
  981. }
  982. virtual bool GetValue( HSCRIPT hScope, int nIndex, ScriptVariant_t *pValue )
  983. {
  984. if ( hScope )
  985. {
  986. int nStackSize = GetStackSize();
  987. lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, size_cast< int >( ( intp )hScope ) );
  988. lua_rawgeti( m_LuaState, -1, nIndex );
  989. if ( lua_isnil( m_LuaState, -1 ) )
  990. {
  991. lua_pop( m_LuaState, nStackSize - GetStackSize() );
  992. return false;
  993. }
  994. ConvertToVariant( -1, m_LuaState, pValue );
  995. lua_pop( m_LuaState, nStackSize - GetStackSize() );
  996. return true;
  997. }
  998. return false;
  999. }
  1000. virtual void ReleaseValue( ScriptVariant_t &value )
  1001. {
  1002. ReleaseVariant( m_LuaState, value );
  1003. }
  1004. virtual bool ClearValue( HSCRIPT hScope, const char *pszKey )
  1005. {
  1006. Assert( 0 );
  1007. return false;
  1008. }
  1009. virtual void WriteState( CUtlBuffer *pBuffer )
  1010. {
  1011. Assert( 0 );
  1012. }
  1013. virtual void ReadState( CUtlBuffer *pBuffer )
  1014. {
  1015. Assert( 0 );
  1016. }
  1017. virtual void RemoveOrphanInstances()
  1018. {
  1019. Assert( 0 );
  1020. }
  1021. virtual void DumpState()
  1022. {
  1023. Assert( 0 );
  1024. }
  1025. //-------------------------------------------------------------
  1026. //
  1027. //-------------------------------------------------------------
  1028. virtual bool RaiseException( const char *pszExceptionText )
  1029. {
  1030. return true;
  1031. }
  1032. virtual void SetOutputCallback( ScriptOutputFunc_t pFunc )
  1033. {
  1034. m_OutputFunc = pFunc;
  1035. lua_pushstring( m_LuaState, "print" );
  1036. ScriptOutputFunc_t *pOutputCallback = ( ScriptOutputFunc_t * )lua_newuserdata( m_LuaState, sizeof( ScriptOutputFunc_t ) );
  1037. *pOutputCallback = m_OutputFunc;
  1038. lua_pushcclosure( m_LuaState, PrintFunc, 1 );
  1039. lua_settable( m_LuaState, LUA_GLOBALSINDEX );
  1040. }
  1041. virtual void SetErrorCallback( ScriptErrorFunc_t pFunc )
  1042. {
  1043. m_ErrorFunc = pFunc;
  1044. }
  1045. };
  1046. //-----------------------------------------------------------------------------
  1047. //
  1048. //-----------------------------------------------------------------------------
  1049. IScriptVM *ScriptCreateLuaVM()
  1050. {
  1051. return new CLuaVM;
  1052. }
  1053. void ScriptDestroyLuaVM( IScriptVM *pVM )
  1054. {
  1055. CLuaVM *pLuaVM = assert_cast< CLuaVM * >( pVM );
  1056. delete pLuaVM;
  1057. }
  1058. //-----------------------------------------------------------------------------
  1059. //-----------------------------------------------------------------------------
  1060. //
  1061. //-----------------------------------------------------------------------------
  1062. //-----------------------------------------------------------------------------
  1063. #ifdef VLUA_TEST
  1064. CLuaVM g_LuaVM;
  1065. IScriptVM *g_pScriptVM = &g_LuaVM;
  1066. //-----------------------------------------------------------------------------
  1067. //
  1068. //-----------------------------------------------------------------------------
  1069. #include <time.h>
  1070. #include "fasttimer.h"
  1071. static void FromScript_AddBehavior( const char *pBehaviorName, HSCRIPT hTable )
  1072. {
  1073. ScriptVariant_t KeyVariant, ValueVariant;
  1074. Msg( "Behavior: %s\n", pBehaviorName );
  1075. int nInterator = 0;
  1076. int index = g_pScriptVM->GetNumTableEntries( hTable );
  1077. for( int i = 0; i < index; i++ )
  1078. {
  1079. nInterator = g_pScriptVM->GetKeyValue( hTable, nInterator, &KeyVariant, &ValueVariant );
  1080. Msg( " %d: %s / %s\n", i, KeyVariant.m_pszString, ValueVariant.m_pszString );
  1081. g_pScriptVM->ReleaseValue( KeyVariant );
  1082. g_pScriptVM->ReleaseValue( ValueVariant );
  1083. }
  1084. }
  1085. static Vector MyVectorAdd( Vector A, Vector B )
  1086. {
  1087. return A + B;
  1088. }
  1089. void TestOutput( const char *pszText )
  1090. {
  1091. Msg( "%s\n", pszText );
  1092. }
  1093. bool TestError( const char *pszText )
  1094. {
  1095. Msg( "%s\n", pszText );
  1096. return true;
  1097. }
  1098. class CMyClass
  1099. {
  1100. public:
  1101. bool Foo( int );
  1102. void Bar( HSCRIPT TableA, HSCRIPT TableB );
  1103. float FooBar( int, const char * );
  1104. float OverlyTechnicalName( bool );
  1105. };
  1106. bool CMyClass::Foo( int test )
  1107. {
  1108. return true;
  1109. }
  1110. void CMyClass::Bar( HSCRIPT TableA, HSCRIPT TableB )
  1111. {
  1112. ScriptVariant_t MyValue;
  1113. // g_pScriptVM->CreateTable( MyTable );
  1114. MyValue = 10;
  1115. g_pScriptVM->SetValue( TableA, 1, MyValue );
  1116. MyValue = 20;
  1117. g_pScriptVM->SetValue( TableA, 2, MyValue );
  1118. MyValue = 30;
  1119. g_pScriptVM->SetValue( TableA, 3, MyValue );
  1120. MyValue = 100;
  1121. g_pScriptVM->SetValue( TableB, 1, MyValue );
  1122. MyValue = 200;
  1123. g_pScriptVM->SetValue( TableB, 2, MyValue );
  1124. MyValue = 300;
  1125. g_pScriptVM->SetValue( TableB, 3, MyValue );
  1126. // return MyTable;
  1127. }
  1128. float CMyClass::FooBar( int test1, const char *test2 )
  1129. {
  1130. return 2.34f;
  1131. }
  1132. float CMyClass::OverlyTechnicalName( bool test )
  1133. {
  1134. return 4.56f;
  1135. }
  1136. BEGIN_SCRIPTDESC_ROOT_NAMED( CMyClass , "CMyClass", SCRIPT_SINGLETON "" )
  1137. DEFINE_SCRIPTFUNC( Foo, "" )
  1138. DEFINE_SCRIPTFUNC( Bar, "" )
  1139. DEFINE_SCRIPTFUNC( FooBar, "" )
  1140. DEFINE_SCRIPTFUNC_NAMED( OverlyTechnicalName, "SimpleMemberName", "" )
  1141. END_SCRIPTDESC();
  1142. class CMyDerivedClass : public CMyClass
  1143. {
  1144. public:
  1145. float DerivedFunc() const;
  1146. };
  1147. BEGIN_SCRIPTDESC( CMyDerivedClass, CMyClass, SCRIPT_SINGLETON "" )
  1148. DEFINE_SCRIPTFUNC( DerivedFunc, "" )
  1149. END_SCRIPTDESC();
  1150. float CMyDerivedClass::DerivedFunc() const
  1151. {
  1152. return 8.91f;
  1153. }
  1154. CMyDerivedClass derivedInstance;
  1155. void AnotherFunction()
  1156. {
  1157. // Manual class exposure
  1158. g_pScriptVM->RegisterClass( GetScriptDescForClass( CMyClass ) );
  1159. // Auto registration by instance
  1160. g_pScriptVM->RegisterInstance( &derivedInstance, "theInstance" );
  1161. }
  1162. int main( int argc, const char **argv)
  1163. {
  1164. if ( argc < 2 )
  1165. {
  1166. printf( "No script specified" );
  1167. return 1;
  1168. }
  1169. g_pScriptVM->Init();
  1170. g_pScriptVM->SetOutputCallback( TestOutput );
  1171. g_pScriptVM->SetErrorCallback( TestError );
  1172. AnotherFunction();
  1173. CCycleCount count;
  1174. count.Sample();
  1175. RandomSeed( time( NULL ) ^ count.GetMicroseconds() );
  1176. ScriptRegisterFunction( g_pScriptVM, RandomFloat, "" );
  1177. ScriptRegisterFunction( g_pScriptVM, RandomInt, "" );
  1178. ScriptRegisterFunction( g_pScriptVM, FromScript_AddBehavior, "" );
  1179. ScriptRegisterFunction( g_pScriptVM, MyVectorAdd, "" );
  1180. if ( argc == 3 && *argv[2] == 'd' )
  1181. {
  1182. g_pScriptVM->ConnectDebugger();
  1183. }
  1184. int key;
  1185. CScriptScope scope;
  1186. scope.Init( "TestScope" );
  1187. do
  1188. {
  1189. const char *pszScript = argv[1];
  1190. FILE *hFile = fopen( pszScript, "rb" );
  1191. if ( !hFile )
  1192. {
  1193. printf( "\"%s\" not found.\n", pszScript );
  1194. return 1;
  1195. }
  1196. int nFileLen = _filelength( _fileno( hFile ) );
  1197. char *pBuf = new char[nFileLen + 1];
  1198. fread( pBuf, 1, nFileLen, hFile );
  1199. pBuf[nFileLen] = 0;
  1200. fclose( hFile );
  1201. if (1)
  1202. {
  1203. printf( "Executing script \"%s\"\n----------------------------------------\n", pszScript );
  1204. HSCRIPT hScript = g_pScriptVM->CompileScript( pBuf, ( strrchr( pszScript, '\\' ) ? strrchr( pszScript, '\\' ) + 1 : pszScript ) );
  1205. if ( hScript )
  1206. {
  1207. if ( scope.Run( hScript ) != SCRIPT_ERROR )
  1208. {
  1209. printf( "----------------------------------------\n" );
  1210. printf("Script complete. Press q to exit, m to dump memory usage, enter to run again.\n");
  1211. }
  1212. else
  1213. {
  1214. printf( "----------------------------------------\n" );
  1215. printf("Script execution error. Press q to exit, m to dump memory usage, enter to run again.\n");
  1216. }
  1217. g_pScriptVM->ReleaseScript( hScript );
  1218. }
  1219. else
  1220. {
  1221. printf( "----------------------------------------\n" );
  1222. printf("Script failed to compile. Press q to exit, m to dump memory usage, enter to run again.\n");
  1223. }
  1224. }
  1225. key = _getch(); // Keypress before exit
  1226. if ( key == 'm' )
  1227. {
  1228. Msg( "%d\n", g_pMemAlloc->GetSize( NULL ) );
  1229. }
  1230. delete pBuf;
  1231. } while ( key != 'q' );
  1232. scope.Term();
  1233. // g_pScriptVM->DisconnectDebugger();
  1234. g_pScriptVM->Shutdown();
  1235. return 0;
  1236. }
  1237. #endif
  1238. // add a check stack auto class to each function