// ScriptSystem.cpp: implementation of the CScriptSystem class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #include #include "ScriptSystem.h" #include "ScriptObject.h" #include "RecycleAllocator.h" #include "StackGuard.h" #include // For warning and errors. // needed for crypak #include #include #include #include extern "C" { #define LUA_PRIVATE #include "lua.h" #include "lualib.h" #include "luadebug.h" } #if defined(_DEBUG) && !defined(LINUX) #include #define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_CLIENTBLOCK #endif #include "LuaCryPakIo.h" //#ifndef WIN64 // experimental #define USE_RAW_CALL //#endif #ifdef _DEBUG #define BEGIN_CHECK_STACK \ int __nStack = lua_stackspace(m_pLS); /* #define END_CHECK_STACK \ { \ char sTemp[120]; \ if (__nStack != lua_stackspace(m_pLS)) \ {DEBUG_BREAK;} \ sprintf(sTemp, "STACK=%d\n", __nStack); \ ::OutputDebugString(sTemp); \ } */ #define END_CHECK_STACK \ { \ if (__nStack != lua_stackspace(m_pLS)) \ {CryError( " END_CHECK_STACK Failed." );} \ } #else #define BEGIN_CHECK_STACK #define END_CHECK_STACK #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// static int I = 0; extern "C" int g_dumpStackOnAlloc = 0; // used in .c file. //static int64 g_numScriptSystemValidations = 0; inline void CScriptSystem::Validate() { //#if defined(WIN64) && defined(_DEBUG) //++g_numScriptSystemValidations; //assert ((g_numScriptSystemValidations <135000) || IsHeapValid()); //#endif } /*LUA_API void alberto_pushfunc(lua_State *L, HSCRIPTFUNCTION func) { L->top->value.cl =(struct Closure *) func; ttype(L->top) = LUA_TFUNCTION; incr_top;//(L); }*/ IScriptObject *CScriptSystem::GetLocalVariables(int nLevel) { Validate(); IScriptObject *pObj; lua_Debug ar; nLevel=0; const char *name; lua_newtable(m_pLS); int nTable=lua_ref(m_pLS,1); lua_getref(m_pLS,nTable); pObj=CreateEmptyObject(); pObj->Attach(); while(lua_getstack(m_pLS, nLevel, &ar) != 0) { //return 0; /* failure: no such level in the stack */ //create a table and fill it with the local variables (name,value) int i = 1; while ((name = lua_getlocal(m_pLS, &ar, i)) != NULL) { lua_getref(m_pLS,nTable); lua_pushstring(m_pLS,name); //::OutputDebugString(name); //::OutputDebugString("\n"); lua_pushvalue(m_pLS,-3); lua_rawset(m_pLS,-3); //pop table and value lua_pop(m_pLS,2); i++; } nLevel++; } Validate(); return pObj; } #define LEVELS1 12 /* size of the first part of the stack */ #define LEVELS2 10 /* size of the second part of the stack */ IScriptObject *CScriptSystem::GetCallsStack() { Validate(); IScriptObject *pStackTrace=CreateObject(); int level = 0; int firstpart = 1; /* still before eventual `...' */ lua_Debug ar; while (lua_getstack(m_pLS, level++, &ar)) { l_char buff[120]; /* enough to fit following `sprintf's */ if (level == 2) { //luaL_addstring(&b, l_s("stack traceback:\n")); } else if (level > LEVELS1 && firstpart) { /* no more than `LEVELS2' more levels? */ if (!lua_getstack(m_pLS, level+LEVELS2, &ar)) level--; /* keep going */ else { // luaL_addstring(&b, l_s(" ...\n")); /* too many levels */ while (lua_getstack(m_pLS, level+LEVELS2, &ar)) /* find last levels */ level++; } firstpart = 0; continue; } IScriptObject *pEntry=CreateObject(); sprintf(buff, l_s("%4d: "), level-1); lua_getinfo(m_pLS, l_s("Snl"), &ar); switch (*ar.namewhat) { case 'g': case 'l': /* global, local */ sprintf(buff, "function `%.50s'", ar.name); break; case 'f': /* field */ sprintf(buff, "method `%.50s'", ar.name); break; case 't': /* tag method */ sprintf(buff, "`%.50s' tag method", ar.name); break; default: { if (*ar.what == 'm') /* main? */ sprintf(buff, "main of %.70s", ar.short_src); else if (*ar.what == 'C') /* C function? */ sprintf(buff, "%.70s", ar.short_src); else sprintf(buff, "function <%d:%.70s>", ar.linedefined, ar.short_src); } } pEntry->SetValue("description",buff); pEntry->SetValue("line",ar.currentline); if (ar.source) { pEntry->SetValue("sourcefile",ar.source); } pStackTrace->PushBack(pEntry); pEntry->Release(); } Validate(); return pStackTrace; } int listvars(lua_State *L, int level) { CScriptSystem::Validate(); char sTemp[1000]; lua_Debug ar; int i = 1; const char *name; if (lua_getstack(L, level, &ar) == 0) return 0; /* failure: no such level in the stack */ while ((name = lua_getlocal(L, &ar, i)) != NULL) { sprintf(sTemp, "%s =", name); OutputDebugString(sTemp); if (lua_isnumber(L, i)) { int n = (int)lua_tonumber(L, i); itoa(n, sTemp, 10); OutputDebugString(sTemp); } else if (lua_isstring(L, i)) { OutputDebugString(lua_tostring(L, i)); }else if (lua_isnil(L, i)) { OutputDebugString("nil"); } else { OutputDebugString("<>"); } OutputDebugString("\n"); i++; lua_pop(L, 1); /* remove variable value */ } /*lua_getglobals(L); i = 1; while ((name = lua_getlocal(L, &ar, i)) != NULL) { sprintf(sTemp, "%s =", name); OutputDebugString(sTemp); if (lua_isnumber(L, i)) { int n = (int)lua_tonumber(L, i); itoa(n, sTemp, 10); OutputDebugString(sTemp); } else if (lua_isstring(L, i)) { OutputDebugString(lua_tostring(L, i)); }else if (lua_isnil(L, i)) { OutputDebugString("nil"); } else { OutputDebugString("<>"); } OutputDebugString("\n"); i++; lua_pop(L, 1); }*/ CScriptSystem::Validate(); return 1; } static void callhook(lua_State *L, lua_Debug *ar) { CScriptSystem *pSS=(CScriptSystem *)lua_getuserptr(L); if(pSS->m_bsBreakState!=bsStepInto)return; lua_getinfo(L, "Sl", ar); ScriptDebugInfo sdi; pSS->m_sLastBreakSource = sdi.sSourceName = ar->source; pSS->m_nLastBreakLine = sdi.nCurrentLine = ar->currentline; pSS->m_pDebugSink->OnExecuteLine(sdi); } static void linehook(lua_State *L, lua_Debug *ar) { CScriptSystem *pSS=(CScriptSystem *)lua_getuserptr(L); if(pSS->m_bsBreakState!=bsNoBreak) { switch(pSS->m_bsBreakState) { case bsContinue: if(pSS->m_BreakPoint.nLine==ar->currentline) { lua_getinfo(L, "Sl", ar); if(ar->source) { if(stricmp(ar->source,pSS->m_BreakPoint.sSourceFile.c_str())==0) break; } } return; case bsStepNext: case bsStepInto: if(pSS->m_BreakPoint.nLine!=ar->currentline) { lua_getinfo(L, "Sl", ar); if((stricmp(pSS->m_sLastBreakSource.c_str(),ar->source)==0)){ break; } } return; /*lua_getinfo(L, "S", ar); if(ar->source) { if(pSS->m_BreakPoint.nLine!=ar->currentline && (stricmp(pSS->m_sLastBreakSource.c_str(),ar->source)!=0)) break; } return;*/ default: return; }; ScriptDebugInfo sdi; pSS->m_sLastBreakSource = sdi.sSourceName = ar->source; pSS->m_nLastBreakLine = sdi.nCurrentLine = ar->currentline; pSS->m_pDebugSink->OnExecuteLine(sdi); } } string& FormatPath( const string &sPath ) { static string strTemp; static char sLowerName[300]; strcpy(sLowerName, sPath.c_str()); int i = 0; while (sLowerName[i] != 0) { if (sLowerName[i] == '\\') sLowerName[i] = '/'; i++; } strTemp = _strlwr(sLowerName); return strTemp; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// CScriptSystem::CScriptSystem() { m_nObjCreationNumber=1; m_pLS = NULL; m_bDebug = false; m_pSink = NULL; m_pDebugSink = NULL; m_nGCTag=0; m_bsBreakState=bsNoBreak; m_BreakPoint.nLine=0; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// CScriptSystem::~CScriptSystem() { /* while (!m_stkPooledWeakObjects.empty()) { delete m_stkPooledWeakObjects.top(); m_stkPooledWeakObjects.pop(); } while (!m_stkPooledWeakObjectsEmpty.empty()) { delete m_stkPooledWeakObjectsEmpty.top(); m_stkPooledWeakObjectsEmpty.pop(); } */ if (m_pLS) { lua_close(m_pLS); m_pLS = NULL; } #ifdef _DEBUG recycle_cleanup(); #endif for (int i = 0; i GetIConsole()) { GetISystem()->GetIConsole()->Register( "lua_stackonmalloc",&g_dumpStackOnAlloc,0 ); } } ////////////////////////////////////////////////////////////////////////// void CScriptSystem::EnableDebugger(IScriptDebugSink *pDebugSink) { m_pDebugSink = pDebugSink; if(pDebugSink) { m_bDebug=true; lua_dblibopen(m_pLS); lua_setlinehook(m_pLS, linehook); lua_setcallhook(m_pLS, callhook); lua_setuserptr(m_pLS,this); RegisterErrorHandler(true); } else { m_bDebug=false; lua_setlinehook(m_pLS, NULL); lua_setcallhook(m_pLS, NULL); RegisterErrorHandler(false); } } ////////////////////////////////////////////////////////////////////////// extern "C" void DumpCallStack( lua_State *L ) { lua_Debug ar; int nRes; int iCurrentLine=-1; // no line number info memset(&ar,0,sizeof(lua_Debug)); static int counter = 0; counter++; int level = 0; GetISystem()->GetILog()->Log( "\001--- Lua Call Stack Trace N%d\n",counter ); while (lua_getstack(L, level++, &ar)) { nRes = lua_getinfo(L, "lnS", &ar); iCurrentLine=ar.currentline; GetISystem()->GetILog()->Log( "\001%s, %s (%d)\n",ar.name,ar.source,ar.currentline ); } } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::ErrorHandler(lua_State *L) { const char *sFuncName = NULL; const char *sSourceFile = NULL; lua_Debug ar; int nRes; int iCurrentLine=-1; // no line number info CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); memset(&ar,0,sizeof(lua_Debug)); lua_pop(L, 1); if (lua_isstring(L, 1)) { const char *sErr = lua_tostring(L, 1); nRes = lua_getstack(L, 1, &ar); if (nRes != 0) { nRes = lua_getinfo(L, "lnS", &ar); iCurrentLine=ar.currentline; sFuncName = ar.name; sSourceFile = ar.source; } if (!sFuncName) sFuncName = "undefined"; if (!sSourceFile) sSourceFile= "undefined"; pThis->m_pSink->OnScriptError(sSourceFile, sFuncName, iCurrentLine, sErr); } return 0; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::SetGlobalTagHandlerString(lua_State *L) { CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); const char *sName = lua_tostring(L, 1); if (!pThis->CanSetGlobal(sName)) return 0; char *var = (char *) lua_touserdata(L, 2); const char *val = (const char *) lua_tostring(L, 3); if (var && val) strcpy(var, val); pThis->NotifySetGlobal(sName); return 0; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::SetGlobalTagHandlerInt(lua_State *L) { CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); const char *sName = lua_tostring(L, 1); if (!pThis->CanSetGlobal(sName)) return 0; int* var = (int*) lua_touserdata(L, 2); int val = (int) lua_tonumber(L, 3); *var = val; pThis->NotifySetGlobal(sName); return 0; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::SetGlobalTagHandlerFloat(lua_State *L) { CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); const char *sName = lua_tostring(L, 1); if (!pThis->CanSetGlobal(sName)) return 0; float* var = (float*) lua_touserdata(L, 2); float val = (float) lua_tonumber(L, 3); *var = val; pThis->NotifySetGlobal(sName); return 0; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::GetGlobalTagHandlerString(lua_State *L) { CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); const char *sName = lua_tostring(L, 1); const char *var = (const char *) lua_touserdata(L, 2); lua_pushstring(L, var); return 1; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::GetGlobalTagHandlerFloat(lua_State *L) { CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); const char *sName = lua_tostring(L, 1); float* var = (float*) lua_touserdata(L, 2); lua_pushnumber(L, *var); return 1; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::GetGlobalTagHandlerInt(lua_State *L) { CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); const char *sName = lua_tostring(L, 1); int* var = (int*) lua_touserdata(L, 2); lua_pushnumber(L, (lua_Number)*var); return 1; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::NotifySetGlobal(const char *sVarName) { if (m_pSink) m_pSink->OnSetGlobal(sVarName); } bool CScriptSystem::CanSetGlobal (const char *sVarName) { return !m_pSink || m_pSink->CanSetGlobal(sVarName); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// extern "C" int errorfb (lua_State *L); void CScriptSystem::RegisterErrorHandler(bool bDebugger) { /*lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::ErrorHandler, 1); lua_setglobal(m_pLS, LUA_ERRORMESSAGE);*/ if(bDebugger) { lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::ErrorHandler, 1); lua_setglobal(m_pLS, LUA_ERRORMESSAGE); } else { lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::ErrorHandler, 1); lua_setglobal(m_pLS, LUA_ALERT); lua_pushcclosure(m_pLS, errorfb, 0); lua_setglobal(m_pLS, LUA_ERRORMESSAGE); } } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::RegisterTagHandlers() { static int prova = 50; static char sprova[256]; m_nFloatTag = lua_newtag(m_pLS); m_nIntTag = lua_newtag(m_pLS); m_nStringTag = lua_newtag(m_pLS); m_nGCTag = lua_newtag(m_pLS); lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::GCTagHandler, 1); lua_settagmethod(m_pLS, m_nGCTag, "gc"); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// HTAG CScriptSystem::CreateTaggedValue(const char *sKey, int *pVal) { int nTag = lua_newtag(m_pLS); lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::SetGlobalTagHandlerInt, 1); lua_settagmethod(m_pLS, nTag, "setglobal"); lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::GetGlobalTagHandlerInt, 1); lua_settagmethod(m_pLS, nTag, "getglobal"); lua_newuserdatabox(m_pLS, pVal); lua_settag(m_pLS, nTag); lua_setglobal(m_pLS, sKey); return nTag; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// HTAG CScriptSystem::CreateTaggedValue(const char *sKey, float *pVal) { int nTag = lua_newtag(m_pLS); lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::SetGlobalTagHandlerFloat, 1); lua_settagmethod(m_pLS, nTag, "setglobal"); lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::GetGlobalTagHandlerFloat, 1); lua_settagmethod(m_pLS, nTag, "getglobal"); lua_newuserdatabox(m_pLS, pVal); lua_settag(m_pLS, nTag); lua_setglobal(m_pLS, sKey); return nTag; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// HTAG CScriptSystem::CreateTaggedValue(const char *sKey, char *pVal) { int nTag = lua_newtag(m_pLS); lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::SetGlobalTagHandlerString, 1); lua_settagmethod(m_pLS, nTag, "setglobal"); lua_newuserdatabox(m_pLS, this); lua_pushcclosure(m_pLS, CScriptSystem::GetGlobalTagHandlerString, 1); lua_settagmethod(m_pLS, nTag, "getglobal"); lua_newuserdatabox(m_pLS, pVal); lua_settag(m_pLS, nTag); lua_setglobal(m_pLS, sKey); return nTag; } void CScriptSystem::RemoveTaggedValue(HTAG htag) { lua_pushnil(m_pLS); lua_settagmethod(m_pLS, htag, "setglobal"); lua_pushnil(m_pLS); lua_settagmethod(m_pLS, htag, "getglobal"); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::FormatAndRaiseError(int nErr) { const char *sFuncName = NULL; switch (nErr) { case 0: /*GetLog()->Log("ScriptSystem:Success!!!\n"); */ break; case LUA_ERRRUN: sFuncName = "undefined"; m_pSink->OnScriptError("", sFuncName, -1, "ScriptSystem:error while running the chunk"); break; case LUA_ERRSYNTAX: m_pSink->OnScriptError("", "", -1, "ScriptSystem:precompiling the file"); break; case LUA_ERRMEM: m_pSink->OnScriptError("", "", -1, "ScriptSystem:memory allocation error in"); break; case LUA_ERRERR: m_pSink->OnScriptError("", "", -1, "error while running _ERRORMESSAGE"); break; case LUA_ERRFILE: m_pSink->OnScriptError(m_strCurrentFile.c_str(), "", -1, "Error opening/parsing file "); break; default: break; }; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// IFunctionHandler *CScriptSystem::GetFunctionHandler() { return &m_feFuntionHandler; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// IScriptObject *CScriptSystem::CreateEmptyObject() { BEGIN_CHECK_STACK CScriptObject *pObj = CreateScriptObject(); if (!pObj->CreateEmpty(this)) { pObj->Release(); END_CHECK_STACK return NULL; }; END_CHECK_STACK return pObj; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// IScriptObject *CScriptSystem::CreateObject() { BEGIN_CHECK_STACK CScriptObject *pObj = CreateScriptObject(); if (!pObj->Create(this)) { pObj->Release(); END_CHECK_STACK return NULL; }; //pObj->SetThis(pThis); END_CHECK_STACK return pObj; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// IScriptObject* CScriptSystem::CreateGlobalObject(const char *sName) { BEGIN_CHECK_STACK CScriptObject *pObj = CreateScriptObject(); if (!pObj->CreateGlobal(this, sName)) { pObj->Release(); END_CHECK_STACK return NULL; }; // pObj->SetThis(pThis); END_CHECK_STACK return pObj; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::_ExecuteFile(const char *sFileName, bool bRaiseError) { FILE *pFile = NULL; m_strCurrentFile = sFileName; //#ifdef USE_CRYPAK ICryPak *pPak=GetISystem()->GetIPak(); pFile = pPak->FOpen(sFileName, "rb"); //#else // pFile = fxopen(sFileName, "rb"); //#endif if (!pFile) { if (bRaiseError) RaiseError("Unable to open %s", sFileName); return false; } int nSize=0; //#ifdef USE_CRYPAK pPak->FSeek(pFile, 0, SEEK_END); nSize = pPak->FTell(pFile); pPak->FSeek(pFile, 0, SEEK_SET); if (nSize==0) { pPak->FClose(pFile); return (false); } /* #else fseek(pFile, 0, SEEK_END); nSize = ftell(pFile); fseek(pFile, 0, SEEK_SET); if (nSize == 0) { fclose(pFile); return false; } #endif */ char *pBuffer; pBuffer = new char[nSize]; //#ifdef USE_CRYPAK if (pPak->FRead(pBuffer, nSize, 1, pFile) == 0) { delete [] pBuffer; pPak->FClose(pFile); return false; } pPak->FClose(pFile); /* #else if (fread(pBuffer, nSize, 1, pFile) == 0) { fclose(pFile); return false; } fclose(pFile); #endif */ char script_decr_key[32] = "3CE2698701289029F3926DF0191189A"; ////////////////////////////////////////////////////////////////////////// // Check if it is encrypted script. ////////////////////////////////////////////////////////////////////////// string CRY_ENCRYPT_FILE_HEADER = string("")+"c"+"r"+"y"+"e"+"h"+"d"+"r"; if (nSize > CRY_ENCRYPT_FILE_HEADER.size()) { if (memcmp(pBuffer,CRY_ENCRYPT_FILE_HEADER.c_str(),CRY_ENCRYPT_FILE_HEADER.size()) == 0) { // Decrypt this buffer. GetISystem()->GetIDataProbe()->AESDecryptBuffer( pBuffer,nSize,pBuffer,nSize,script_decr_key ); } } ////////////////////////////////////////////////////////////////////////// if (m_bDebug && m_pDebugSink) { m_pDebugSink->OnLoadSource(sFileName,(unsigned char*) pBuffer, nSize); } //int nRes = lua_dofile(m_pLS, sFileName); char szFileName[_MAX_PATH + 1]; szFileName[0] = '@'; strcpy(&szFileName[1], sFileName); int nRes=lua_dobuffer(m_pLS,pBuffer,nSize,/*sFileName*/ szFileName); delete [] pBuffer; if (nRes) { if (bRaiseError) { FormatAndRaiseError(nRes); } return false; } return true; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::ExecuteFile(const char *sFileName, bool bRaiseError,bool bForceReload) { if (strlen(sFileName) <= 0) return false; string sTemp; sTemp = FormatPath(sFileName); //ScriptFileListItor itor = std::find(m_dqLoadedFiles.begin(), m_dqLoadedFiles.end(), sTemp.c_str()); ScriptFileListItor itor = m_dqLoadedFiles.find(sTemp); if (itor == m_dqLoadedFiles.end() || bForceReload) { if (!_ExecuteFile(sTemp.c_str(), bRaiseError)) { #if defined(_DEBUG) && (defined(WIN64) || defined(LINUX64)) char szBuf[0x800]; _snprintf (szBuf, sizeof(szBuf), "Can't execute script %s : %s\n", sFileName, sTemp.c_str()); OutputDebugString (szBuf); #endif return false; } if(itor == m_dqLoadedFiles.end()) m_dqLoadedFiles.insert(sTemp); } #if defined(_DEBUG) && (defined(WIN64) || defined(LINUX64)) char szBuf[0x800]; _snprintf (szBuf, sizeof(szBuf), "Script %s executed\n", sFileName); OutputDebugString (szBuf); #endif return true; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::UnloadScript(const char *sFileName) { if (strlen(sFileName) <= 0) return; string sTemp; sTemp = FormatPath(sFileName); //ScriptFileListItor itor = std::find(m_dqLoadedFiles.begin(), m_dqLoadedFiles.end(), sTemp.c_str()); ScriptFileListItor itor = m_dqLoadedFiles.find(sTemp); if (itor != m_dqLoadedFiles.end()) { #if !defined(LINUX) ::OutputDebugString("ERASE : "); ::OutputDebugString(sTemp.c_str()); ::OutputDebugString("\n"); #endif m_dqLoadedFiles.erase(itor); } } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::UnloadScripts() { m_dqLoadedFiles.clear(); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::ReloadScripts() { ScriptFileListItor itor; itor = m_dqLoadedFiles.begin(); while (itor != m_dqLoadedFiles.end()) { ReloadScript(itor->c_str(), true); ++itor; } return true; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::ReloadScript(const char *sFileName, bool bRaiseError) { string strTemp = FormatPath(sFileName); ScriptFileListItor itor = m_dqLoadedFiles.find(strTemp);//std::find(m_dqLoadedFiles.begin(), m_dqLoadedFiles.end(), strTemp); if (itor == m_dqLoadedFiles.end()) { RaiseError("Error reloading \"%s\" the file was not loaded", sFileName); return false; } return _ExecuteFile(strTemp.c_str(), bRaiseError); } void CScriptSystem::DumpLoadedScripts() { ScriptFileListItor itor; itor = m_dqLoadedFiles.begin(); while (itor != m_dqLoadedFiles.end()) { m_pSink->OnLoadedScriptDump(itor->c_str()); ++itor; } } /* void CScriptSystem::GetScriptHashFunction( IScriptObject &Current, unsigned int &dwHash) { unsigned int *pCode=0; int iSize=0; if(pCurrent.GetCurrentFuncData(pCode,iSize)) // function ? { if(pCode) // lua function ? GetScriptHashFunction(pCode,iSize,dwHash); } } */ void CScriptSystem::GetScriptHash( const char *sPath, const char *szKey, unsigned int &dwHash ) { // IScriptObject *pCurrent; // GetGlobalValue(szKey,pCurrent); // if(!pCurrent) // is not a table // { // } /* else if(lua_isfunction(m_pLS, -1)) { GetScriptHashFunction(*pCurrent,dwHash); return; } else { lua_pop(m_pLS, 1); return; } */ /* pCurrent->BeginIteration(); while(pCurrent->MoveNext()) { char *szKeyName; if(!pCurrent->GetCurrentKey(szKeyName)) szKeyName="NO"; ScriptVarType type=pCurrent->GetCurrentType(); if(type==svtObject) // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject { void *pVis; pCurrent->GetCurrentPtr(pVis); GetISystem()->GetILog()->Log(" table '%s/%s'",sPath.c_str(),szKeyName); if(setVisited.count(pVis)!=0) { GetISystem()->GetILog()->Log(" .. already processed .."); continue; } setVisited.insert(pVis); { IScriptObject *pNewObject = m_pScriptSystem->CreateEmptyObject(); pCurrent->GetCurrent(pNewObject); Debug_Full_recursive(pNewObject,sPath+string("/")+szKeyName,setVisited); pNewObject->Release(); } } else if(type==svtFunction) // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject { GetScriptHashFunction(*pCurrent,dwHash); } } pCurrent->EndIteration(); */ } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::ExecuteBuffer(const char *sBuffer, size_t nSize) { int nRes = lua_dobuffer(m_pLS, sBuffer, nSize, "__script_buffer__"); if (nRes) { FormatAndRaiseError(nRes); return false; } return (true); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::Release() { #ifdef _DEBUG char sTemp[100]; int nCreationNumber; #endif while(!m_stkScriptObjectsPool.empty()) { CScriptObject *pObj=m_stkScriptObjectsPool.back(); #ifdef _DEBUG nCreationNumber=pObj->m_nCreationNumber; #endif delete pObj; m_stkScriptObjectsPool.pop_back(); #ifdef _DEBUG sprintf(sTemp,"delete[%d] obj Pool size %d new\n",nCreationNumber,m_stkScriptObjectsPool.size()); ::OutputDebugString(sTemp); #endif } delete this; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::BeginCall(HSCRIPTFUNCTION hFunc) { // alberto_pushfunc(m_pLS,hFunc); m_nTempTop = lua_gettop(m_pLS); if(hFunc==0) { RaiseError("(BeginCall) failed NULL parameter"); m_nTempArg = -1; return 0; } if(!lua_getref(m_pLS, (int)hFunc)) { m_nTempArg = -1; return 0; } if(!lua_isfunction(m_pLS,-1)) { RaiseError("Function Ptr:%d not found",hFunc); m_nTempArg = -1; return 0; } m_nTempArg = 0; return 1; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::BeginCall(const char *sTableName, const char *sFuncName) { lua_getglobal(m_pLS, sTableName); if(!lua_istable(m_pLS,-1)) { RaiseError("(BeginCall)Tried to call %s:%s(), Table %s not found (check for syntax errors or if the file wasn't loaded)",sTableName,sFuncName,sTableName); m_nTempArg = -1; lua_pop(m_pLS,1); return 0; } lua_pushstring(m_pLS, sFuncName); lua_rawget(m_pLS, - 2); lua_remove(m_pLS, - 2); // Remove table global. m_nTempArg = 0; if(!lua_isfunction(m_pLS,-1)) { RaiseError("Function %s:%s not found(check for syntax errors or if the file wasn't loaded)",sTableName,sFuncName); m_nTempArg = -1; return 0; } return 1; } int CScriptSystem::BeginCall(const char *sFuncName) { lua_getglobal(m_pLS, sFuncName); m_nTempArg = 0; #ifdef _DEBUG if(!lua_isfunction(m_pLS,-1)) { RaiseError("Function %s not found(check for syntax errors or if the file wasn't loaded)",sFuncName); m_nTempArg = -1; return 0; } #endif return 1; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// HSCRIPTFUNCTION CScriptSystem::GetFunctionPtr(const char *sFuncName) { _GUARD_STACK(m_pLS); HSCRIPTFUNCTION func; lua_getglobal(m_pLS, sFuncName); if (lua_isnil(m_pLS, -1) ||(!lua_isfunction(m_pLS, -1))) { lua_pop(m_pLS, 1); return NULL; } func = (HSCRIPTFUNCTION)lua_ref(m_pLS, 0); return func; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// HSCRIPTFUNCTION CScriptSystem::GetFunctionPtr(const char *sTableName, const char *sFuncName) { _GUARD_STACK(m_pLS); HSCRIPTFUNCTION func; lua_getglobal(m_pLS, sTableName); if(!lua_istable(m_pLS,-1)) { // RaiseError("(GetFunctionPtr)Table %s: not found(check for syntax errors or if the file wasn't loaded)", sTableName); lua_pop(m_pLS,1); return 0; } lua_pushstring(m_pLS, sFuncName); lua_gettable(m_pLS, - 2); lua_remove(m_pLS, - 2); // Remove table global. if (lua_isnil(m_pLS, -1) ||(!lua_isfunction(m_pLS, -1))) { lua_pop(m_pLS, 1); return FALSE; } func = (HSCRIPTFUNCTION)lua_ref(m_pLS, 0); return func; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::EndCall() { Validate(); if(m_nTempArg==-1) return; #ifdef USE_RAW_CALL int nRes = lua_call(m_pLS, m_nTempArg, 0); if (nRes) FormatAndRaiseError(nRes); #else lua_rawcall(m_pLS, m_nTempArg, 0); #endif Validate(); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::EndCall(int &nRet) { Validate(); if(m_nTempArg==-1) return; #ifdef USE_RAW_CALL int nRes = lua_call(m_pLS, m_nTempArg, 1); if (nRes) FormatAndRaiseError(nRes); #else lua_rawcall(m_pLS, m_nTempArg, 1); #endif Validate(); if(lua_gettop(m_pLS)) { if (lua_isnumber(m_pLS, -1)) { nRet = (int)lua_tonumber(m_pLS, -1); } lua_pop(m_pLS, 1); } Validate(); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::EndCall(float &fRet) { Validate(); if(m_nTempArg==-1) return; #ifdef USE_RAW_CALL int nRes = lua_call(m_pLS, m_nTempArg, 1); if (nRes) FormatAndRaiseError(nRes); #else lua_rawcall(m_pLS, m_nTempArg, 1); #endif Validate(); if(lua_gettop(m_pLS)) { if (lua_isnumber(m_pLS, -1)) { fRet = lua_tonumber(m_pLS, -1); } lua_pop(m_pLS, 1); } Validate(); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::EndCall(const char *&sRet) { Validate(); if(m_nTempArg==-1) return; #ifdef USE_RAW_CALL int nRes = lua_call(m_pLS, m_nTempArg, 1); if (nRes) FormatAndRaiseError(nRes); #else lua_rawcall(m_pLS, m_nTempArg, 1); #endif Validate(); if(lua_gettop(m_pLS)) { if (lua_isstring(m_pLS, -1)) { sRet = lua_tostring(m_pLS, -1); } lua_pop(m_pLS, 1); } Validate(); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::EndCall(bool &bRet) { Validate(); if(m_nTempArg==-1) return; #ifdef USE_RAW_CALL int nRes = lua_call(m_pLS, m_nTempArg, 1); if (nRes) FormatAndRaiseError(nRes); #else lua_rawcall(m_pLS, m_nTempArg, 1); #endif Validate(); if (lua_gettop(m_pLS)) { if (lua_isnil(m_pLS, -1)) bRet = false; else bRet = true; lua_pop(m_pLS, 1); } Validate(); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::EndCall(IScriptObject *pObj) { Validate(); if(m_nTempArg==-1) return; #ifdef USE_RAW_CALL int nRes = lua_call(m_pLS, m_nTempArg, 1); if (nRes) FormatAndRaiseError(nRes); #else lua_rawcall(m_pLS, m_nTempArg, 1); #endif Validate(); if (lua_gettop(m_pLS)) { if (lua_istable(m_pLS, -1)) { //int nRef = lua_ref(m_pLS, 1); pObj->Attach(); } else { lua_pop(m_pLS, 1); } } Validate(); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::PushFuncParam(int nVal) { Validate(); if(m_nTempArg==-1) return; lua_pushnumber(m_pLS, (lua_Number)nVal); m_nTempArg++; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::PushFuncParam(float fVal) { Validate(); if(m_nTempArg==-1) return; lua_pushnumber(m_pLS, fVal); m_nTempArg++; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::PushFuncParam(const char *sVal) { Validate(); if(m_nTempArg==-1) return; lua_pushstring(m_pLS, sVal); m_nTempArg++; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::PushFuncParam(bool bVal) { Validate(); if(m_nTempArg==-1) return; if (bVal) { lua_pushnumber(m_pLS, 1); } else { lua_pushnil(m_pLS); } m_nTempArg++; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::PushFuncParam(IScriptObject *pVal) { Validate(); if(m_nTempArg==-1) return; if(!lua_xgetref(m_pLS, pVal->GetRef())) { lua_pushnil(m_pLS); } m_nTempArg++; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::SetGlobalToNull(const char *sKey) { Validate(); lua_pushnil(m_pLS); lua_setglobal(m_pLS, sKey); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::SetGlobalValue(const char *sKey, int nVal) { Validate(); lua_pushnumber(m_pLS, (lua_Number)nVal); lua_setglobal(m_pLS, sKey); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::SetGlobalValue(const char *sKey, float fVal) { Validate(); lua_pushnumber(m_pLS, fVal); lua_setglobal(m_pLS, sKey); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::SetGlobalValue(const char *sKey, const char *sVal) { Validate(); lua_pushstring(m_pLS, sVal); lua_setglobal(m_pLS, sKey); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::SetGlobalValue(const char *sKey, IScriptObject *pObj) { Validate(); lua_xgetref(m_pLS, pObj->GetRef()); lua_setglobal(m_pLS, sKey); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// IScriptObject *CScriptSystem::GetGlobalObject() { Validate(); CScriptObject *pObj = CreateScriptObject(); lua_getglobals(m_pLS); pObj->CreateEmpty(this); pObj->Attach(); return pObj; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::GetGlobalValue(const char *sKey, int &nVal) { Validate(); lua_getglobal(m_pLS, sKey); if (lua_isnumber(m_pLS, -1)) { nVal =(int)(lua_tonumber(m_pLS, 1)); } else { lua_pop(m_pLS, 1); return false; } lua_pop(m_pLS, 1); return true; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::GetGlobalValue(const char *sKey, float &fVal) { Validate(); lua_getglobal(m_pLS, sKey); if (lua_isnumber(m_pLS, -1)) { fVal =(float)(lua_tonumber(m_pLS, 1)); } else { lua_pop(m_pLS, 1); return false; } lua_pop(m_pLS, 1); return true; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::GetGlobalValue(const char *sKey, const char * &sVal) { Validate(); lua_getglobal(m_pLS, sKey); if (lua_isstring(m_pLS, -1)) { sVal =(lua_tostring(m_pLS, -1)); if(sVal==NULL) { //this cannot happen if it does call alberto lua_pop(m_pLS, 1); CryError( " CScriptSystem::GetGlobalValue: Key %s cannot be converted to string.",sKey ); return false; } } else { lua_pop(m_pLS, 1); return false; } lua_pop(m_pLS, 1); return true; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// bool CScriptSystem::GetGlobalValue(const char *sKey, IScriptObject *pObj) { Validate(); lua_getglobal(m_pLS, sKey); if (lua_istable(m_pLS, -1)) { pObj->Attach(); } else { lua_pop(m_pLS, 1); return false; } return true; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::ForceGarbageCollection() { /*char sTemp[200]; lua_StateStats lss; lua_getstatestats(m_pLS,&lss); sprintf(sTemp,"protos=%d closures=%d tables=%d udata=%d strings=%d\n",lss.nProto,lss.nClosure,lss.nHash,lss.nUdata,lss.nString); OutputDebugString("BEFORE GC STATS :"); OutputDebugString(sTemp);*/ Validate(); lua_setgcthreshold(m_pLS, 0); Validate(); /*lua_getstatestats(m_pLS,&lss); sprintf(sTemp,"protos=%d closures=%d tables=%d udata=%d strings=%d\n",lss.nProto,lss.nClosure,lss.nHash,lss.nUdata,lss.nString); OutputDebugString("AFTER GC STATS :"); OutputDebugString(sTemp);*/ } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// int CScriptSystem::GetCGCount() { Validate(); return lua_getgccount(m_pLS); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::SetGCThreshhold(int nKb) { Validate(); lua_setgcthreshold(m_pLS, nKb); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void CScriptSystem::RaiseError(const char *sErr,...) { Validate(); va_list arglist; char sBuf[2048]; lua_Debug ar; int nRes; int iCurrentLine=-1; // no line number info const char *sFuncName = NULL; const char *sSourceFile = NULL; va_start(arglist, sErr); vsprintf(sBuf, sErr, arglist); va_end(arglist); nRes = lua_getstack(m_pLS, 1, &ar); if (nRes != 0) { nRes = lua_getinfo(m_pLS, "lnS", &ar); iCurrentLine=ar.currentline; sFuncName = ar.name; sSourceFile = ar.source; } if (!sFuncName) sFuncName = "undefined"; if (!sSourceFile) sSourceFile= "undefined"; if (sBuf) m_pSink->OnScriptError(sSourceFile, sFuncName, iCurrentLine, sBuf); } int CScriptSystem::GCTagHandler(lua_State *L) { Validate(); CScriptSystem *pThis = (CScriptSystem *)lua_touserdata(L, - 1); USER_DATA_CHUNK *udc=(USER_DATA_CHUNK *)lua_touserdata(L,1); if(pThis && pThis->m_pSink && udc) { //pThis->m_mapUserData.erase(udc->nVal); pThis->m_pSink->OnCollectUserData(udc->nVal,udc->nCookie); lua_unref(L,(int)udc->nRef); udc->nVal=udc->nCookie=0xDEADBEEF; } return 0; } USER_DATA CScriptSystem::CreateUserData(INT_PTR nVal,int nCookie) //AMD Port { Validate(); // UserDataMapItor itor=m_mapUserData.find(nVal); int nRef=0; // if(itor==m_mapUserData.end()) // { USER_DATA_CHUNK *pUDC=(USER_DATA_CHUNK *)lua_newuserdata(m_pLS,sizeof(USER_DATA_CHUNK)); pUDC->nVal=nVal; pUDC->nCookie=nCookie; lua_settag(m_pLS, m_nGCTag); pUDC->nRef=lua_ref(m_pLS,0); //m_mapUserData.insert(UserDataMapItor::value_type(nVal,nRef)); // } // else // { //::OutputDebugString("Reusing pointer\n"); //nRef=itor->second; // } Validate(); return pUDC->nRef; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // Pointer to Global ISystem. static ISystem* gISystem = 0; ISystem* GetISystem() { return gISystem; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// IScriptSystem *CreateScriptSystem(ISystem *pSystem,IScriptSystemSink *pSink, IScriptDebugSink *pDebugSink, bool bStdLibs) { gISystem = pSystem; CScriptSystem *pScriptSystem = new CScriptSystem; pScriptSystem->Validate(); if (!pScriptSystem->Init(pSink, pDebugSink, bStdLibs, 1024)) { pScriptSystem->Release(); } return pScriptSystem; } CScriptObject *CScriptSystem::CreateScriptObject() { Validate(); //char sTemp[100]; if(m_stkScriptObjectsPool.empty()) { //sprintf(sTemp,"Pool size %d new\n",m_stkScriptObjectsPool.size()); //::OutputDebugString(sTemp); // if(m_nObjCreationNumber==42) // DEBUG_BREAK; return new CScriptObject(m_nObjCreationNumber++); } else { CScriptObject *pObj; // sprintf(sTemp,"Pool size %d cached\n",m_stkScriptObjectsPool.size()); //::OutputDebugString(sTemp); pObj = m_stkScriptObjectsPool.back(); pObj->Recreate(); m_stkScriptObjectsPool.pop_back(); return pObj; } } void CScriptSystem::ReleaseScriptObject(CScriptObject *p) { Validate(); if(m_stkScriptObjectsPool.size()> Pool size %d\n",m_stkScriptObjectsPool.size()); ::OutputDebugString(sTemp); delete p; Validate(); } } void CScriptSystem::UnbindUserdata() { Validate(); lua_pushnil(m_pLS); lua_settagmethod(m_pLS,m_nGCTag,"gc"); } void CScriptSystem::UnrefFunction (HSCRIPTFUNCTION hFunc) { lua_unref (m_pLS, hFunc); } HBREAKPOINT CScriptSystem::AddBreakPoint(const char *sFile,int nLineNumber) { m_BreakPoint.sSourceFile=sFile; m_BreakPoint.nLine=nLineNumber; DebugContinue(); return 0; } IScriptObject *CScriptSystem::GetBreakPoints() { Validate(); IScriptObject *pBreakPoints=CreateObject(); if(m_BreakPoint.sSourceFile.length()) { IScriptObject *pBP=CreateObject(); pBP->SetValue("line",m_BreakPoint.nLine); pBP->SetValue("sourcefile",m_BreakPoint.sSourceFile.c_str()); pBreakPoints->PushBack(pBP); pBP->Release(); Validate(); } return pBreakPoints; } void CScriptSystem::ReleaseFunc(HSCRIPTFUNCTION f) { if(f) { lua_unref(m_pLS,f); Validate(); } }