1866 lines
45 KiB
C++
1866 lines
45 KiB
C++
// ScriptSystem.cpp: implementation of the CScriptSystem class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "ScriptSystem.h"
|
|
#include "ScriptObject.h"
|
|
#include "RecycleAllocator.h"
|
|
#include "StackGuard.h"
|
|
|
|
#include <ISystem.h> // For warning and errors.
|
|
// needed for crypak
|
|
#include <ICryPak.h>
|
|
#include <IConsole.h>
|
|
#include <ILog.h>
|
|
#include <IDataProbe.h>
|
|
|
|
extern "C"
|
|
{
|
|
#define LUA_PRIVATE
|
|
#include "lua.h"
|
|
#include "lualib.h"
|
|
#include "luadebug.h"
|
|
}
|
|
|
|
#if defined(_DEBUG) && !defined(LINUX)
|
|
#include <crtdbg.h>
|
|
#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( "<ScriptSystem> 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("<<unknown>>");
|
|
}
|
|
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("<<unknown>>");
|
|
}
|
|
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 <m_stkScriptObjectsPool.size(); i++)
|
|
{
|
|
delete m_stkScriptObjectsPool[i];
|
|
}
|
|
m_stkScriptObjectsPool.clear();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
extern "C" {
|
|
int vl_initvectorlib(lua_State *L);
|
|
}
|
|
|
|
bool CScriptSystem::Init(IScriptSystemSink *pSink, IScriptDebugSink *pDebugSink, bool bStdLibs, int nStackSize)
|
|
{
|
|
m_pSink = pSink;
|
|
m_pLS = lua_open(0);
|
|
if (pDebugSink)
|
|
{
|
|
m_bDebug = true;
|
|
m_pDebugSink = pDebugSink;
|
|
}
|
|
else
|
|
{
|
|
m_pDebugSink = NULL;
|
|
m_bDebug = false;
|
|
}
|
|
if (m_pLS && m_bDebug)
|
|
{
|
|
lua_dblibopen(m_pLS);
|
|
lua_setlinehook(m_pLS, linehook);
|
|
lua_setcallhook(m_pLS, callhook);
|
|
}
|
|
if (bStdLibs)
|
|
{
|
|
lua_baselibopen(m_pLS);
|
|
lua_strlibopen(m_pLS);
|
|
lua_mathlibopen(m_pLS);
|
|
lua_iolibopen(m_pLS);
|
|
lua_bitlibopen(m_pLS);
|
|
}
|
|
vl_initvectorlib(m_pLS);
|
|
lua_setuserptr(m_pLS,this);
|
|
lua_iolibopen(m_pLS);
|
|
RegisterErrorHandler(m_bDebug);
|
|
RegisterTagHandlers();
|
|
|
|
//initvectortag(m_pLS);
|
|
return m_pLS?true:false;
|
|
}
|
|
|
|
void CScriptSystem::PostInit()
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Register console vars.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (GetISystem()->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( "<ScriptSystem> 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()<SCRIPT_OBJECT_POOL_SIZE){
|
|
m_stkScriptObjectsPool.push_back(p);
|
|
}
|
|
else
|
|
{
|
|
char sTemp[100];
|
|
sprintf(sTemp,"chached>> 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();
|
|
}
|
|
}
|
|
|