diff --git a/code/nel/include/nel/gui/lua_helper.h b/code/nel/include/nel/gui/lua_helper.h new file mode 100644 index 000000000..52707eadc --- /dev/null +++ b/code/nel/include/nel/gui/lua_helper.h @@ -0,0 +1,388 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef RZ_LUA_HELPER_H +#define RZ_LUA_HELPER_H + + +#include "nel/misc/types_nl.h" +#include "nel/misc/smart_ptr.h" + +extern "C" +{ + #include "lua_loadlib.h" +} + +namespace NLGUI +{ + + class CLuaState; + + namespace LuaHelperStuff + { + void formatLuaStackContext( std::string &stackContext ); + std::string formatLuaErrorSysInfo( const std::string &error ); + std::string formatLuaErrorNlWarn( const std::string &error ); + } + + + // *************************************************************************** + /** Helper class to see if a stack is restored at its initial size (or with n return results). + * Check that the stack size remains unchanged when the object goes out of scope + */ + class CLuaStackChecker + { + public: + CLuaStackChecker(CLuaState *state, int numWantedResults = 0); + ~CLuaStackChecker(); + /** Increment exception context counter + * When an exception is thrown, lua stack checker do any assert bu will + * rather restore the lua stack at its original size, and will + * let the exception a chance to propagate + */ + static void incrementExceptionContextCounter(); + static void decrementExceptionContextCounter(); + + private: + CLuaState *_State; + int _FinalWantedSize; + static uint _ExceptionContextCounter; + + }; + + // ************************************************************************** + /** Helper class to restore the lua stack to the desired size when this object goes out of scope + */ + class CLuaStackRestorer + { + public: + CLuaStackRestorer(CLuaState *state, int finalSize); + ~CLuaStackRestorer(); + private: + int _FinalSize; + CLuaState *_State; + }; + + //////////////// + // EXCEPTIONS // + //////////////// + + class ELuaError : public NLMISC::Exception + { + public: + ELuaError() { CLuaStackChecker::incrementExceptionContextCounter(); } + virtual ~ELuaError() throw() { CLuaStackChecker::decrementExceptionContextCounter(); } + ELuaError(const std::string &reason) : Exception(reason) { CLuaStackChecker::incrementExceptionContextCounter(); } + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("LUAError: %s", what());} + }; + + // A parse error occured + class ELuaParseError : public ELuaError + { + public: + ELuaParseError() {} + ELuaParseError(const std::string &reason) : ELuaError(reason) {} + virtual ~ELuaParseError() throw() { } + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaParseError: %s", what());} + }; + + /** Exception thrown when something went wrong inside a wrapped function called by lua + */ + class ELuaWrappedFunctionException : public ELuaError + { + public: + ELuaWrappedFunctionException(CLuaState *luaState); + ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason); + ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...); + virtual ~ELuaWrappedFunctionException() throw() { } + virtual const char *what() const throw() {return _Reason.c_str();} + protected: + void init(CLuaState *ls, const std::string &reason); + protected: + std::string _Reason; + }; + + // A execution error occured + class ELuaExecuteError : public ELuaError + { + public: + ELuaExecuteError() {} + ELuaExecuteError(const std::string &reason) : ELuaError(reason) {} + virtual ~ELuaExecuteError() throw() { } + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaExecuteError: %s", what());} + }; + + // A bad cast occured when using lua_checkcast + class ELuaBadCast : public ELuaError + { + public: + ELuaBadCast() {} + ELuaBadCast(const std::string &reason) : ELuaError(reason) {} + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaBadCast: %s", what());} + }; + + // Error when trying to indexate an object that is not a table + class ELuaNotATable : public ELuaError + { + public: + ELuaNotATable() {} + ELuaNotATable(const std::string &reason) : ELuaError(reason) {} + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaNotATable: %s", what());} + }; + + + // *************************************************************************** + // a function to be used with a CLuaState instance + typedef int (* TLuaWrappedFunction) (CLuaState &ls); + + + // *************************************************************************** + /** C++ version of a lua state + */ + class CLuaState : public NLMISC::CRefCount + { + public: + typedef NLMISC::CRefPtr TRefPtr; + + // Create a new environement + CLuaState( bool debugger = false ); + ~CLuaState(); + + + /// \name Registering + // @{ + // register a wrapped function + void registerFunc(const char *name, TLuaWrappedFunction function); + // @} + + + /// \name Script execution + // @{ + + /** Parse a script and push as a function in top of the LUA stack + * \throw ELuaParseError + * \param dbgSrc is a string for debug. Should be a filename (preceded with '@'), or a short script. + */ + void loadScript(const std::string &code, const std::string &dbgSrc); + + /** Execute a script from a string, possibly throwing an exception if there's a parse error + * \throw ELuaParseError, ELuaExecuteError + */ + void executeScript(const std::string &code, int numRet = 0); + + /** Execute a script from a string. If an errors occurs it is printed in the log + * \return true if script execution was successful + */ + bool executeScriptNoThrow(const std::string &code, int numRet = 0); + + /** Load a Script from a File (maybe in a BNP), and execute it + * \return false if file not found + * \throw ELuaParseError, ELuaExecuteError + */ + bool executeFile(const std::string &pathName); + + /** execute a very Small Script (a function call for instance) + * It is different from doString() in such there is a cache (where the key is the script itself) + * so that the second time this script is executed, there is no parsing + * Note: I experienced optim with about 10 times faster than a executeScript() on a simple "a= a+1;" script + * \throw ELuaParseError, ELuaExecuteError + */ + void executeSmallScript(const std::string &script); + + // @} + + + /// \name Stack Manipulation + // @{ + // stack manipulation (indices start at 1) + void setTop(int index); // set new size of stack + void clear() { setTop(0); } + int getTop(); + bool empty() { return getTop() == 0; } + void pushValue(int index); // copie nth element of stack to the top of the stack + void remove(int index); // remove nth element of stack + void insert(int index); // insert last element of the stack before the given position + void replace(int index); // replace nth element of the stack with the top of the stack + void pop(int numElem = 1); // remove n elements from the top of the stack + // test the type of an element in the stack + // return one of the following values : + // LUA_TNIL + // LUA_TNUMBER + // LUA_TBOOLEAN + // LUA_TSTRING + // LUA_TTABLE + // LUA_TFUNCTION + // LUA_TUSERDATA + // LUA_TTHREAD + // LUA_TLIGHTUSERDATA + int type(int index = -1); + const char *getTypename(int type); + bool isNil(int index = -1); + bool isBoolean(int index = -1); + bool isNumber(int index = -1); + bool isString(int index = -1); + bool isTable(int index = -1); + bool isFunction(int index = -1); + bool isCFunction(int index = -1); + bool isUserData(int index = -1); + bool isLightUserData(int index = -1); + // converting then getting a value from the stack + bool toBoolean(int index = -1); + lua_Number toNumber(int index = -1); + const char *toString(int index = -1); + void toString(int index, std::string &str); // convert to a std::string, with a NULL check. + size_t strlen(int index = -1); + lua_CFunction toCFunction(int index = -1); + void *toUserData(int index = -1); + const void *toPointer(int index = -1); + /** Helper functions : get value of the wanted type in the top table after conversion + * A default value is used if the stack entry is NULL. + * If conversion fails then an exception is thrown (with optional msg) + */ + bool getTableBooleanValue(const char *name, bool defaultValue= false); + double getTableNumberValue(const char *name, double defaultValue= 0); + const char *getTableStringValue(const char *name, const char *defaultValue= NULL); + // pushing value onto the stack + void push(bool value); + void push(lua_Number value); + void push(const char *str); + void push(const char *str, int length); + void push(const std::string &str); + void pushNil(); + void push(lua_CFunction f); + void push(TLuaWrappedFunction function); + void pushLightUserData(void *); // push a light user data (use newUserData to push a full userdata) + // metatables + bool getMetaTable(int index = -1); + bool setMetaTable(int index = -1); // set the metatable at top of stack to the object at 'index' (usually -2), then pop the metatable + // even if asignment failed + // comparison + bool equal(int index1, int index2); + bool rawEqual(int index1, int index2); + bool lessThan(int index1, int index2); + // concatenation of the n element at the top of the stack (using lua semantic) + void concat(int numElem); + // tables + void newTable(); // create a new table at top of the stack + void getTable(int index); // get value from a table at index 'index' (key is at top) + void rawGet(int index); + void setTable(int index); // set (key, value) from top of the stack into the given table + // both key and value are poped + void rawSet(int index); + bool next(int index); // table traversal + // UserData + void *newUserData(uint size); + // seting value by int index in a table + void rawSetI(int index, int n); + void rawGetI(int index, int n); + /** Calling functions (it's up to the caller to clear the results) + * The function should have been pushed on the stack + */ + void call(int nargs, int nresults); + int pcall(int nargs, int nresults, int errfunc = 0); + /** Helper : Execute a function by name. Lookup for the function is done in the table at the index 'funcTableIndex' + * the behaviour is the same than with call of pcall. + */ + int pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex = LUA_GLOBALSINDEX, int errfunc = 0); + + // push a C closure (pop n element from the stack and associate with the function) + void pushCClosure(lua_CFunction function, int n); + // @} + + + /// \name Misc + // @{ + /** Retrieve pointer to a CLuaState environment from its lua_State pointer, or NULL + * if there no such environment + */ + static CLuaState *fromStatePointer(lua_State *state); + // Get state pointer. The state should not be closed (this object has ownership) + lua_State *getStatePointer() const {return _State;} + // check that an index is valid when accessing the stack + // an assertion is raised if the index is not valid + void checkIndex(int index); + + // registering C function to use with a lua state pointer + void registerFunc(const char *name, lua_CFunction function); + + // Garbage collector + int getGCCount(); // get memory in use in KB + int getGCThreshold(); // get max memory in KB + void setGCThreshold(int kb); // set max memory in KB (no-op with ref-counted version) + + // handle garbage collector for ref-counted version of lua (no-op with standard version, in which case gc handling is automatic) + void handleGC(); + + /** For Debug: get the Stack context of execution (filename / line) + * \param stackLevel: get the context of execution of the given stackLevel. + * 0 for the current function + * 1 for the function that called 0 + * 2 .... + * NB: if called from a C function called from LUA, remember that stackLevel 0 is the current function. + * Hence if you want to know what LUA context called you, pass stackLevel=1! + * \param ret string cleared if any error, else filled with formated FileName / LineNumber + */ + void getStackContext(std::string &ret, uint stackLevel); + // @} + + // for debug : dump the current content of the stack (no recursion) + void dumpStack(); + static void dumpStack(lua_State *ls); + void getStackAsString(std::string &dest); + + + private: + lua_State *_State; + + #ifdef LUA_NEVRAX_VERSION + int _GCThreshold; // if refcounted gc is used, then garbage collector is handled manually + #endif + // Small Script Cache + uint _SmallScriptPool; + typedef std::map TSmallScriptCache; + TSmallScriptCache _SmallScriptCache; + static const char * _NELSmallScriptTableName; + + private: + // this object isn't intended to be copied + CLuaState(const CLuaState &/* other */):NLMISC::CRefCount() { nlassert(0); } + CLuaState &operator=(const CLuaState &/* other */) { nlassert(0); return *this; } + + void executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet = 0); + + }; + + + // Access to lua function + // one should not include lua.h directly because if a debugger is present, lua + // function pointer will be taken from a dynamic library. + + + + //============================================================================================= + // include implementation + #define RZ_INCLUDE_LUA_HELPER_INLINE + #include "lua_helper_inline.h" + #undef RZ_INCLUDE_LUA_HELPER_INLINE + +} + +#endif diff --git a/code/ryzom/client/src/interface_v3/lua_helper_inline.h b/code/nel/include/nel/gui/lua_helper_inline.h similarity index 100% rename from code/ryzom/client/src/interface_v3/lua_helper_inline.h rename to code/nel/include/nel/gui/lua_helper_inline.h diff --git a/code/ryzom/client/src/interface_v3/lua_loadlib.h b/code/nel/include/nel/gui/lua_loadlib.h similarity index 100% rename from code/ryzom/client/src/interface_v3/lua_loadlib.h rename to code/nel/include/nel/gui/lua_loadlib.h diff --git a/code/nel/src/gui/lua_helper.cpp b/code/nel/src/gui/lua_helper.cpp new file mode 100644 index 000000000..1e67620d3 --- /dev/null +++ b/code/nel/src/gui/lua_helper.cpp @@ -0,0 +1,835 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/gui/lua_helper.h" +#include "nel/misc/file.h" + +#ifdef LUA_NEVRAX_VERSION + #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger +#endif + + +#include "nel/gui/lua_loadlib.h" + +// to get rid of you_must_not_use_assert___use_nl_assert___read_debug_h_file messages +#include +#ifdef assert + #undef assert +#endif + +#ifdef NL_DEBUG + #define assert(x) nlassert(x) +#else + #define assert(x) +#endif + +#include +#include +#include + +#ifdef NL_OS_WINDOWS +#include +#endif + +using namespace std; +using namespace NLMISC; + +namespace NLGUI +{ + + namespace LuaHelperStuff + { + void formatLuaStackContext( std::string &stackContext ) + { + stackContext = std::string( "@{FC8A}" ).append( stackContext ).append( "@{FC8F} " ); + } + + std::string formatLuaErrorSysInfo( const std::string &error ) + { + return std::string( "@{FC8F}" ).append( error ); + } + + std::string formatLuaErrorNlWarn( const std::string &error ) + { + // Remove color tags (see formatLuaErrorSC()) + std::string ret = error; + strFindReplace( ret, "@{FC8A}", "" ); + strFindReplace( ret, "@{FC8F}", "" ); + return ret; + } + } + + // *************************************************************************** + const char *CLuaState::_NELSmallScriptTableName= "NELSmallScriptTable"; + uint CLuaStackChecker::_ExceptionContextCounter = 0; + + // *************************************************************************** + void CLuaStackChecker::incrementExceptionContextCounter() + { + //H_AUTO(Lua_CLuaStackChecker_incrementExceptionContextCounter) + ++ _ExceptionContextCounter; + } + + // *************************************************************************** + void CLuaStackChecker::decrementExceptionContextCounter() + { + //H_AUTO(Lua_CLuaStackChecker_decrementExceptionContextCounter) + nlassert(_ExceptionContextCounter > 0); + -- _ExceptionContextCounter; + } + + + #ifdef LUA_NEVRAX_VERSION + ILuaIDEInterface *LuaDebuggerIDE = NULL; + static bool LuaDebuggerVisible = false; + #endif + + #ifdef NL_OS_WINDOWS + HMODULE LuaDebuggerModule = 0; + #endif + + void luaDebuggerMainLoop() + { + #ifdef LUA_NEVRAX_VERSION + if (!LuaDebuggerIDE) return; + if (!LuaDebuggerVisible) + { + LuaDebuggerIDE->showDebugger(true); + LuaDebuggerIDE->expandProjectTree(); + LuaDebuggerIDE->sortFiles(); + LuaDebuggerVisible = true; + } + LuaDebuggerIDE->doMainLoop(); + #endif + } + + + + static std::allocator l_stlAlloc; + + + static void l_free_func(void *block, int oldSize) + { + l_stlAlloc.deallocate((uint8 *) block, oldSize); + } + + static void *l_realloc_func(void *b, int os, int s) + { + if (os == s) return b; + void *newB = l_stlAlloc.allocate(s); + memcpy(newB, b, std::min(os, s)); + l_free_func(b, os); + return newB; + } + + + + const int MinGCThreshold = 128; // min value at which garbage collector will be triggered (in kilobytes) + // *************************************************************************** + CLuaState::CLuaState( bool debugger ) + { + _State = NULL; + + #ifdef LUA_NEVRAX_VERSION + _GCThreshold = MinGCThreshold; + #endif + + #ifdef NL_OS_WINDOWS + if( debugger ) + { + #ifndef LUA_NEVRAX_VERSION + static bool warningShown = false; + if (!warningShown) + { + nldebug( "Lua debugger was asked, but the static lua library against which the client was linked is too old. Please update to lua-5.0.2_nevrax. Debugging won't be available!" ); + //MessageBox (NULL, "Lua debugger was asked, but the static lua library against which the client was linked is too old. Please update to lua-5.0.2_nevrax. Debugging won't be available!", "Lua support", MB_OK); + warningShown = true; + } + #else + nlassert(LuaDebuggerIDE == NULL); // for now, only one debugger supported... + #ifdef NL_DEBUG + LuaDebuggerModule = ::LoadLibrary("lua_ide2_dll_d.dll"); + #else + LuaDebuggerModule = ::LoadLibrary("lua_ide2_dll_r.dll"); + #endif + if (LuaDebuggerModule) + { + TGetLuaIDEInterfaceVersion getVersion = (TGetLuaIDEInterfaceVersion) GetProcAddress(LuaDebuggerModule, "GetLuaIDEInterfaceVersion"); + nlassert(getVersion); + int dllInterfaceVersion = getVersion(); + if (dllInterfaceVersion > LUA_IDE_INTERFACE_VERSION) + { + MessageBox (NULL, "Lua debugger interface is newer than the application. Debugging will be disabled. Please update your client", "Lua support", MB_OK); + } + else if (dllInterfaceVersion < LUA_IDE_INTERFACE_VERSION) + { + MessageBox (NULL, "Lua debugger interface is too old. Lua debugging will be disabled. Please ask for a more recent dll.", "Lua support", MB_OK); + } + else + { + TGetLuaIDEInterface getter = (TGetLuaIDEInterface) GetProcAddress(LuaDebuggerModule, "GetLuaIDEInterface"); + nlassert(getter); + LuaDebuggerIDE = getter(); + LuaDebuggerIDE->prepareDebug("save\\___external_debug.lpr", l_realloc_func, l_free_func, Driver->getDisplay()); + _State = LuaDebuggerIDE->getLuaState(); + } + } + #endif + } + #endif + + if (!_State) + { + #ifdef LUA_NEVRAX_VERSION + _State = lua_open(l_realloc_func, l_free_func); + #else + _State = lua_open(); + #endif + nlassert(_State); + } + + // *** Load base libs + { + CLuaStackChecker lsc(this); + #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 + luaL_openlibs(_State); + #else + luaopen_base (_State); + luaopen_table (_State); + luaopen_io (_State); + luaopen_string (_State); + luaopen_math (_State); + luaopen_debug (_State); + #endif + + // open are buggy???? + clear(); + } + + // *** Register basics + CLuaStackChecker lsc(this); + + // do: LUA_REGISTRYINDEX.(lightuserdata*)this.classes= {} + pushLightUserData((void *) this); + newTable(); + push("classes"); + newTable(); // registry class + setTable(-3); + setTable(LUA_REGISTRYINDEX); + + // add pointer from lua state to this CLuaState object + // do: LUA_REGISTRYINDEX.(lightuserdata*)_State= this + pushLightUserData((void *) _State); // NB : as creator of the state, we make the assumption that + // no one will be using this pointer in the registry (cf. ref manual about registry) + pushLightUserData((void *) this); + setTable(LUA_REGISTRYINDEX); + + // Create the Table that contains Function cache for small script execution + push(_NELSmallScriptTableName); // 1:TableName + newTable(); // 1:TableName 2:table + setTable(LUA_REGISTRYINDEX); // ... + _SmallScriptPool= 0; + + // *** luabind init + luabind::open(_State); + } + + + // *************************************************************************** + CLuaStackRestorer::CLuaStackRestorer(CLuaState *state, int finalSize) : _FinalSize(finalSize), _State(state) + { + } + + // *************************************************************************** + CLuaStackRestorer::~CLuaStackRestorer() + { + nlassert(_State); + _State->setTop(_FinalSize); + } + + #ifdef NL_OS_WINDOWS + static int NoOpReportHook( int /* reportType */, char * /* message */, int * /* returnValue */ ) + { + return TRUE; + } + #endif + + + // *************************************************************************** + CLuaState::~CLuaState() + { + nlassert(_State); + + #ifdef LUA_NEVRAX_VERSION + if (!LuaDebuggerIDE) + #else + if (1) + #endif + { + lua_close(_State); + } + else + { + #ifdef LUA_NEVRAX_VERSION + LuaDebuggerIDE->stopDebug(); // this will also close the lua state + LuaDebuggerIDE = NULL; + LuaDebuggerVisible = false; + #ifdef NL_OS_WINDOWS + nlassert(LuaDebuggerModule) + _CrtSetReportHook(NoOpReportHook); // prevent dump of memory leaks at this point + //::FreeLibrary(LuaDebuggerModule); // don't free the library now (seems that it destroy, the main window, causing + // a crash when the app window is destroyed for real... + // -> FreeLibrary will be called when the application is closed + LuaDebuggerModule = 0; + #endif + #endif + } + + // Clear Small Script Cache + _SmallScriptPool= 0; + _SmallScriptCache.clear(); + } + + // *************************************************************************** + CLuaState *CLuaState::fromStatePointer(lua_State *state) + { + //H_AUTO(Lua_CLuaState_fromStatePointer) + nlassert(state); + int initialStackSize = lua_gettop(state); + lua_checkstack(state, initialStackSize + 2); + lua_pushlightuserdata(state, (void *) state); + lua_gettable(state, LUA_REGISTRYINDEX); + if (!lua_islightuserdata(state, -1)) + { + lua_pop(state, 1); + return NULL; + } + CLuaState *ls = (CLuaState *) lua_touserdata(state, -1); + lua_pop(state, 1); + nlassert(initialStackSize == lua_gettop(state)); + return ls; + } + + // *************************************************************************** + struct CLuaReader + { + const std::string *Str; + bool Done; + }; + + + + + void CLuaState::loadScript(const std::string &code, const std::string &dbgSrc) + { + //H_AUTO(Lua_CLuaState_loadScript) + if (code.empty()) return; + struct CHelper + { + static const char *luaChunkReaderFromString(lua_State * /* L */, void *ud, size_t *sz) + { + CLuaReader *rd = (CLuaReader *) ud; + if (!rd->Done) + { + rd->Done = true; + *sz = rd->Str->size(); + return rd->Str->c_str(); + } + else + { + *sz = 0; + return NULL; + } + } + }; + CLuaReader rd; + rd.Str = &code; + rd.Done = false; + + int result = lua_load(_State, CHelper::luaChunkReaderFromString, (void *) &rd, dbgSrc.c_str()); + if (result !=0) + { + // pop the error code + string err= toString(); + pop(); + // throw error + throw ELuaParseError(err); + } + } + + // *************************************************************************** + void CLuaState::executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet) + { + //H_AUTO(Lua_CLuaState_executeScriptInternal) + CLuaStackChecker lsc(this, numRet); + + // load the script + loadScript(code, dbgSrc); + + // execute + if (pcall(0, numRet) != 0) + { + // pop the error code + string err= toString(); + pop(); + // throw error + throw ELuaExecuteError(err); + } + } + + // *************************************************************************** + void CLuaState::executeScript(const std::string &code, int numRet) + { + //H_AUTO(Lua_CLuaState_executeScript) + // run the script, with dbgSrc==script + executeScriptInternal(code, code, numRet); + } + + // *************************************************************************** + bool CLuaState::executeScriptNoThrow(const std::string &code, int numRet) + { + //H_AUTO(Lua_CLuaState_executeScriptNoThrow) + try + { + executeScript(code, numRet); + } + catch (const ELuaError &e) + { + nlwarning(e.what()); + return false; + } + return true; + } + + // *************************************************************************** + bool CLuaState::executeFile(const std::string &pathName) + { + //H_AUTO(Lua_CLuaState_executeFile) + + CIFile inputFile; + if(!inputFile.open(pathName)) + return false; + + #ifdef LUA_NEVRAX_VERSION + if (LuaDebuggerIDE) + { + std::string path = NLMISC::CPath::getCurrentPath() + "/" + pathName.c_str(); + path = CPath::standardizeDosPath(path); + LuaDebuggerIDE->addFile(path.c_str()); + } + #endif + + // load the script text + string script; + /* + while(!inputFile.eof()) + { + char tmpBuff[5000]; + inputFile.getline(tmpBuff, 5000); + script+= tmpBuff; + script+= "\n"; + } + */ + script.resize(CFile::getFileSize(pathName)); + inputFile.serialBuffer((uint8 *) &script[0], (uint)script.size()); + + + // execute the script text, with dbgSrc==filename (use @ for lua internal purpose) + executeScriptInternal(script, string("@") + CFile::getFilename(pathName)); + + return true; + } + + // *************************************************************************** + void CLuaState::executeSmallScript(const std::string &script) + { + //H_AUTO(Lua_CLuaState_executeSmallScript) + if (script.empty()) return; + // *** if the small script has not already been called before, parse it now + TSmallScriptCache::iterator it= _SmallScriptCache.find(script); + if(it==_SmallScriptCache.end()) + { + CLuaStackChecker lsc(this); + + // add it to a function + loadScript(script, script); + + // Assign the method to the NEL table: NELSmallScriptTable[_SmallScriptPool]= function + push(_NELSmallScriptTableName); // 1:function 2:NelTableName + getTable(LUA_REGISTRYINDEX); // 1:function 2:NelTable + insert(-2); // 1:NelTable 2:function + rawSetI(-2, _SmallScriptPool); // 1:NelTable + pop(); + + // bkup in cache map + it= _SmallScriptCache.insert(make_pair(script, _SmallScriptPool)).first; + + // next allocated + _SmallScriptPool++; + } + + // *** Execute the function associated to the script + CLuaStackChecker lsc(this); + push(_NELSmallScriptTableName); // 1:NelTableName + getTable(LUA_REGISTRYINDEX); // 1:NelTable + // get the function at the given index in the "NELSmallScriptTable" table + rawGetI(-1, it->second); // 1:NelTable 2:function + + // execute + if (pcall(0, 0) != 0) + { + // Stack: 1: NelTable 2:errorcode + // pop the error code, and clear stack + string err= toString(); + pop(); // 1:NelTable + pop(); // .... + // throw error + throw ELuaExecuteError(err); + } + else + { + // Stack: 1:NelTable + pop(); // .... + } + + } + + // *************************************************************************** + void CLuaState::registerFunc(const char *name, lua_CFunction function) + { + //H_AUTO(Lua_CLuaState_registerFunc) + lua_register(_State, name, function); + } + + // *************************************************************************** + void CLuaState::pushCClosure(lua_CFunction function, int n) + { + //H_AUTO(Lua_CLuaState_pushCClosure) + nlassert(function); + nlassert(getTop() >= n); + lua_pushcclosure(_State, function, n); + } + + // *************************************************************************** + void CLuaState::push(TLuaWrappedFunction function) + { + //H_AUTO(Lua_CLuaState_push) + struct CForwarder + { + static int callFunc(lua_State *ls) + { + nlassert(ls); + TLuaWrappedFunction func = (TLuaWrappedFunction) lua_touserdata(ls, lua_upvalueindex(1)); + CLuaState *state = (CLuaState *) lua_touserdata(ls, lua_upvalueindex(2)); + nlassert(func); + nlassert(state); + // get real function pointer from the values in the closure + int numResults = 0; + int initialStackSize = state->getTop(); + try + { + // call the actual function + numResults = func(*state); + } + catch(const std::exception &e) + { + // restore stack to its initial size + state->setTop(initialStackSize); + lua_pushstring(ls, e.what()); + // TODO : see if this is safe to call lua error there" ... (it does a long jump) + lua_error(ls); + } + return numResults; + } + }; + pushLightUserData((void *) function); + pushLightUserData((void *) this); + pushCClosure(CForwarder::callFunc, 2); + } + + // *************************************************************************** + // Wrapped function + void CLuaState::registerFunc(const char *name, TLuaWrappedFunction function) + { + //H_AUTO(Lua_CLuaState_registerFunc) + nlassert(function); + CLuaStackChecker lsc(this); + push(name); + push(function); + setTable(LUA_GLOBALSINDEX); + } + + + // *************************************************************************** + bool CLuaState::getTableBooleanValue(const char *name, bool defaultValue) + { + //H_AUTO(Lua_CLuaState_getTableBooleanValue) + nlassert(name); + push(name); + getTable(-2); + if (isNil()) + { + pop(); + return defaultValue; + } + bool result = toBoolean(-1); + pop(); + return result; + } + + // *************************************************************************** + double CLuaState::getTableNumberValue(const char *name, double defaultValue) + { + //H_AUTO(Lua_CLuaState_getTableNumberValue) + nlassert(name); + push(name); + getTable(-2); + if (isNil()) + { + pop(); + return defaultValue; + } + double result = toNumber(-1); + pop(); + return result; + } + + // *************************************************************************** + const char *CLuaState::getTableStringValue(const char *name, const char *defaultValue) + { + //H_AUTO(Lua_CLuaState_getTableStringValue) + nlassert(name); + push(name); + getTable(-2); + if (isNil()) + { + pop(); + return defaultValue; + } + const char *result = toString(-1); + pop(); + return result; + } + + // *************************************************************************** + void CLuaState::getStackContext(string &ret, uint stackLevel) + { + //H_AUTO(Lua_CLuaState_getStackContext) + nlassert(_State); + ret.clear(); + lua_Debug dbg; + if(lua_getstack (_State, stackLevel, &dbg)) + { + if(lua_getinfo(_State, "lS", &dbg)) + { + ret= NLMISC::toString("%s:%d:", dbg.short_src, dbg.currentline); + } + } + } + + // *************************************************************************** + int CLuaState::pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex /*=LUA_GLOBALSINDEX*/, int errfunc /*= 0*/) + { + //H_AUTO(Lua_CLuaState_pcallByName) + int initialStackSize = getTop(); + nlassert(functionName); + nlassert(isTable(funcTableIndex)); + pushValue(funcTableIndex); + push(functionName); + getTable(-2); + remove(-2); // get rid of the table + nlassert(getTop() >= nargs); // not enough arguments on the stack + // insert function before its arguments + insert(- 1 - nargs); + int result = pcall(nargs, nresults, errfunc); + int currSize = getTop(); + if (result == 0) + { + nlassert(currSize == initialStackSize - nargs + nresults); + } + else + { + // errors, the stack contains a single string + if (errfunc == 0) + { + nlassert(currSize == initialStackSize - nargs + 1); + } + // else if there's an error handler, can't know the size of stack + } + return result; + } + + // *************************************************************************** + void CLuaState::dumpStack() + { + //H_AUTO(Lua_CLuaState_dumpStack) + nlinfo("LUA STACK CONTENT (size = %d)", getTop()); + nlinfo("================="); + CLuaStackChecker lsc(this); + for(int k = 1; k <= getTop(); ++k) + { + pushValue(k); + std::string value = toString(-1) ? toString(-1) : "?"; + nlinfo("Stack entry %d : type = %s, value = %s", k, getTypename(type(-1)), value.c_str()); + pop(); + } + } + + // *************************************************************************** + void CLuaState::getStackAsString(std::string &dest) + { + //H_AUTO(Lua_CLuaState_getStackAsString) + dest = NLMISC::toString("Stack size = %d\n", getTop()); + CLuaStackChecker lsc(this); + for(int k = 1; k <= getTop(); ++k) + { + pushValue(k); + std::string value = toString(-1) ? toString(-1) : "?"; + dest += NLMISC::toString("Stack entry %d : type = %s, value = %s\n", k, getTypename(type(-1)), value.c_str()); + pop(); + } + } + + //================================================================================ + CLuaStackChecker::~CLuaStackChecker() + { + nlassert(_State); + if (!_ExceptionContextCounter) + { + int currSize = _State->getTop(); + if (currSize != _FinalWantedSize) + { + static volatile bool assertWanted = true; + if (assertWanted) + { + nlwarning("Lua stack size error : expected size is %d, current size is %d", _FinalWantedSize, currSize); + _State->dumpStack(); + nlassert(0); + } + } + } + else + { + // this object dtor was called because an exception was thrown, so let the exception + // propagate (the stack must be broken, but because of the exception, not because of code error) + _State->setTop(_FinalWantedSize); + } + } + + // *************************************************************************** + void ELuaWrappedFunctionException::init(CLuaState *ls, const std::string &reason) + { + //H_AUTO(Lua_ELuaWrappedFunctionException_init) + // Print first Lua Stack Context + if(ls) + { + ls->getStackContext(_Reason, 1); // 1 because 0 is the current C function => return 1 for script called + // enclose with cool colors + LuaHelperStuff::formatLuaStackContext(_Reason); + } + + // Append the reason + _Reason+= reason; + } + + // *************************************************************************** + ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState) + { + //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) + init(luaState, ""); + } + + // *************************************************************************** + ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason) + { + //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) + init(luaState, reason); + } + + // *************************************************************************** + ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...) + { + //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) + std::string reason; + NLMISC_CONVERT_VARGS (reason, format, NLMISC::MaxCStringSize); + init(luaState, reason); + } + + //================================================================================ + void CLuaState::newTable() + { + //H_AUTO(Lua_CLuaState_newTable) + nlverify( lua_checkstack(_State, 1) ); + lua_newtable(_State); + } + + //================================================================================ + int CLuaState::getGCCount() + { + //H_AUTO(Lua_CLuaState_getGCCount) + return lua_getgccount(_State); + } + + //================================================================================ + int CLuaState::getGCThreshold() + { + //H_AUTO(Lua_CLuaState_getGCThreshold) + #ifdef LUA_NEVRAX_VERSION + return _GCThreshold; + #else + # if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 + return lua_gc(_State, LUA_GCCOUNT, 0); + # else + return lua_getgcthreshold(_State); + # endif + #endif + } + + //================================================================================ + void CLuaState::setGCThreshold(int kb) + { + //H_AUTO(Lua_CLuaState_setGCThreshold) + #ifdef LUA_NEVRAX_VERSION + _GCThreshold = kb; + handleGC(); + #else + # if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 + lua_gc(_State, LUA_GCCOLLECT, kb); + # else + lua_setgcthreshold(_State, kb); + # endif + #endif + } + + //================================================================================ + void CLuaState::handleGC() + { + //H_AUTO(Lua_CLuaState_handleGC) + #ifdef LUA_NEVRAX_VERSION + // must handle gc manually with the refcounted version + int gcCount = getGCCount(); + if (gcCount >= _GCThreshold) + { + nlwarning("Triggering GC : memory in use = %d kb, current threshold = %d kb", gcCount, _GCThreshold); + lua_setgcthreshold(_State, 0); + gcCount = getGCCount(); + _GCThreshold = std::max(MinGCThreshold, gcCount * 2); + nlwarning("After GC : memory in use = %d kb, threshold = %d kb", gcCount, _GCThreshold); + } + #endif + } + +} diff --git a/code/ryzom/client/src/interface_v3/lua_loadlib.c b/code/nel/src/gui/lua_loadlib.c similarity index 100% rename from code/ryzom/client/src/interface_v3/lua_loadlib.c rename to code/nel/src/gui/lua_loadlib.c diff --git a/code/ryzom/client/src/debug_client.cpp b/code/ryzom/client/src/debug_client.cpp index 70c138cb6..c12b2d6e0 100644 --- a/code/ryzom/client/src/debug_client.cpp +++ b/code/ryzom/client/src/debug_client.cpp @@ -40,7 +40,8 @@ #include "interface_v3/interface_manager.h" #include "interface_v3/sphrase_manager.h" #include "entities.h" -#include "interface_v3/lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; #include "character_cl.h" #include "r2/editor.h" #include "r2/dmc/client_edition_module.h" diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 313fc4300..d0445ce74 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -106,7 +106,12 @@ #include "chat_text_manager.h" #include "../npc_icon.h" -#include "lua_helper.h" +#include "nel/gui/lua_helper.h" +namespace NLGUI +{ + extern void luaDebuggerMainLoop(); +} +using namespace NLGUI; #include "lua_ihm.h" #include "add_on_manager.h" @@ -1359,7 +1364,6 @@ void CInterfaceManager::updateFrameEvents() pPM->update(); // if there's an external lua debugger, update it - extern void luaDebuggerMainLoop(); luaDebuggerMainLoop(); // handle gc for lua diff --git a/code/ryzom/client/src/interface_v3/interface_parser.cpp b/code/ryzom/client/src/interface_v3/interface_parser.cpp index 6e93779ab..f8371d8d2 100644 --- a/code/ryzom/client/src/interface_v3/interface_parser.cpp +++ b/code/ryzom/client/src/interface_v3/interface_parser.cpp @@ -105,7 +105,8 @@ #include "inventory_manager.h" #include "task_bar_manager.h" #include "../commands.h" -#include "lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; #include "lua_ihm.h" #include "../r2/editor.h" @@ -4661,7 +4662,7 @@ void CInterfaceParser::initLUA() // create a new LUA environnement nlassert(_LuaState==NULL); - _LuaState= new CLuaState; + _LuaState= new CLuaState( ClientCfg.LoadLuaDebugger ); #ifdef LUA_NEVRAX_VERSION extern ILuaIDEInterface *LuaDebuggerIDE; diff --git a/code/ryzom/client/src/interface_v3/interface_parser.h b/code/ryzom/client/src/interface_v3/interface_parser.h index 753432ddc..0c8b51940 100644 --- a/code/ryzom/client/src/interface_v3/interface_parser.h +++ b/code/ryzom/client/src/interface_v3/interface_parser.h @@ -25,7 +25,8 @@ #include "interface_link.h" #include "nel/misc/smart_ptr.h" #include "game_share/brick_types.h" -#include "lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; // *************************************************************************** class CInterfaceElement; diff --git a/code/ryzom/client/src/interface_v3/lua_helper.cpp b/code/ryzom/client/src/interface_v3/lua_helper.cpp deleted file mode 100644 index 0299e66cc..000000000 --- a/code/ryzom/client/src/interface_v3/lua_helper.cpp +++ /dev/null @@ -1,829 +0,0 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdpch.h" - -#include "lua_helper.h" -#include "nel/misc/file.h" -//#include "interface_manager.h" -#include "../client_cfg.h" - -#ifdef LUA_NEVRAX_VERSION - #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger -#endif - - -#include "lua_loadlib.h" - -// to get rid of you_must_not_use_assert___use_nl_assert___read_debug_h_file messages -#include -#ifdef assert - #undef assert -#endif - -#ifdef NL_DEBUG - #define assert(x) nlassert(x) -#else - #define assert(x) -#endif - -#include - -using namespace std; -using namespace NLMISC; - -namespace LuaHelperStuff -{ - void formatLuaStackContext( std::string &stackContext ) - { - stackContext = std::string( "@{FC8A}" ).append( stackContext ).append( "@{FC8F} " ); - } - - std::string formatLuaErrorSysInfo( const std::string &error ) - { - return std::string( "@{FC8F}" ).append( error ); - } - - std::string formatLuaErrorNlWarn( const std::string &error ) - { - // Remove color tags (see formatLuaErrorSC()) - std::string ret = error; - strFindReplace( ret, "@{FC8A}", "" ); - strFindReplace( ret, "@{FC8F}", "" ); - return ret; - } -} - -// *************************************************************************** -const char *CLuaState::_NELSmallScriptTableName= "NELSmallScriptTable"; -uint CLuaStackChecker::_ExceptionContextCounter = 0; - -// *************************************************************************** -void CLuaStackChecker::incrementExceptionContextCounter() -{ - //H_AUTO(Lua_CLuaStackChecker_incrementExceptionContextCounter) - ++ _ExceptionContextCounter; -} - -// *************************************************************************** -void CLuaStackChecker::decrementExceptionContextCounter() -{ - //H_AUTO(Lua_CLuaStackChecker_decrementExceptionContextCounter) - nlassert(_ExceptionContextCounter > 0); - -- _ExceptionContextCounter; -} - - -#ifdef LUA_NEVRAX_VERSION - ILuaIDEInterface *LuaDebuggerIDE = NULL; - static bool LuaDebuggerVisible = false; -#endif - -#ifdef NL_OS_WINDOWS - HMODULE LuaDebuggerModule = 0; -#endif - -void luaDebuggerMainLoop() -{ -#ifdef LUA_NEVRAX_VERSION - if (!LuaDebuggerIDE) return; - if (!LuaDebuggerVisible) - { - LuaDebuggerIDE->showDebugger(true); - LuaDebuggerIDE->expandProjectTree(); - LuaDebuggerIDE->sortFiles(); - LuaDebuggerVisible = true; - } - LuaDebuggerIDE->doMainLoop(); -#endif -} - - - -static std::allocator l_stlAlloc; - - -static void l_free_func(void *block, int oldSize) -{ - l_stlAlloc.deallocate((uint8 *) block, oldSize); -} - -static void *l_realloc_func(void *b, int os, int s) -{ - if (os == s) return b; - void *newB = l_stlAlloc.allocate(s); - memcpy(newB, b, std::min(os, s)); - l_free_func(b, os); - return newB; -} - - - -const int MinGCThreshold = 128; // min value at which garbage collector will be triggered (in kilobytes) -// *************************************************************************** -CLuaState::CLuaState() -{ - _State = NULL; - - #ifdef LUA_NEVRAX_VERSION - _GCThreshold = MinGCThreshold; - #endif - - #ifdef NL_OS_WINDOWS - if (ClientCfg.LoadLuaDebugger) - { - #ifndef LUA_NEVRAX_VERSION - static bool warningShown = false; - if (!warningShown) - { - MessageBox (NULL, "Lua debugger was asked, but the static lua library against which the client was linked is too old. Please update to lua-5.0.2_nevrax. Debugging won't be available!", "Lua support", MB_OK); - warningShown = true; - } - #else - nlassert(LuaDebuggerIDE == NULL); // for now, only one debugger supported... - #ifdef NL_DEBUG - LuaDebuggerModule = ::LoadLibrary("lua_ide2_dll_d.dll"); - #else - LuaDebuggerModule = ::LoadLibrary("lua_ide2_dll_r.dll"); - #endif - if (LuaDebuggerModule) - { - TGetLuaIDEInterfaceVersion getVersion = (TGetLuaIDEInterfaceVersion) GetProcAddress(LuaDebuggerModule, "GetLuaIDEInterfaceVersion"); - nlassert(getVersion); - int dllInterfaceVersion = getVersion(); - if (dllInterfaceVersion > LUA_IDE_INTERFACE_VERSION) - { - MessageBox (NULL, "Lua debugger interface is newer than the application. Debugging will be disabled. Please update your client", "Lua support", MB_OK); - } - else if (dllInterfaceVersion < LUA_IDE_INTERFACE_VERSION) - { - MessageBox (NULL, "Lua debugger interface is too old. Lua debugging will be disabled. Please ask for a more recent dll.", "Lua support", MB_OK); - } - else - { - TGetLuaIDEInterface getter = (TGetLuaIDEInterface) GetProcAddress(LuaDebuggerModule, "GetLuaIDEInterface"); - nlassert(getter); - LuaDebuggerIDE = getter(); - LuaDebuggerIDE->prepareDebug("save\\___external_debug.lpr", l_realloc_func, l_free_func, Driver->getDisplay()); - _State = LuaDebuggerIDE->getLuaState(); - } - } - #endif - } - #endif - - if (!_State) - { - #ifdef LUA_NEVRAX_VERSION - _State = lua_open(l_realloc_func, l_free_func); - #else - _State = lua_open(); - #endif - nlassert(_State); - } - - // *** Load base libs - { - CLuaStackChecker lsc(this); -#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 - luaL_openlibs(_State); -#else - luaopen_base (_State); - luaopen_table (_State); - luaopen_io (_State); - luaopen_string (_State); - luaopen_math (_State); - luaopen_debug (_State); -#endif - - // open are buggy???? - clear(); - } - - // *** Register basics - CLuaStackChecker lsc(this); - - // do: LUA_REGISTRYINDEX.(lightuserdata*)this.classes= {} - pushLightUserData((void *) this); - newTable(); - push("classes"); - newTable(); // registry class - setTable(-3); - setTable(LUA_REGISTRYINDEX); - - // add pointer from lua state to this CLuaState object - // do: LUA_REGISTRYINDEX.(lightuserdata*)_State= this - pushLightUserData((void *) _State); // NB : as creator of the state, we make the assumption that - // no one will be using this pointer in the registry (cf. ref manual about registry) - pushLightUserData((void *) this); - setTable(LUA_REGISTRYINDEX); - - // Create the Table that contains Function cache for small script execution - push(_NELSmallScriptTableName); // 1:TableName - newTable(); // 1:TableName 2:table - setTable(LUA_REGISTRYINDEX); // ... - _SmallScriptPool= 0; - - // *** luabind init - luabind::open(_State); -} - - -// *************************************************************************** -CLuaStackRestorer::CLuaStackRestorer(CLuaState *state, int finalSize) : _FinalSize(finalSize), _State(state) -{ -} - -// *************************************************************************** -CLuaStackRestorer::~CLuaStackRestorer() -{ - nlassert(_State); - _State->setTop(_FinalSize); -} - -#ifdef NL_OS_WINDOWS - static int NoOpReportHook( int /* reportType */, char * /* message */, int * /* returnValue */ ) - { - return TRUE; - } -#endif - - -// *************************************************************************** -CLuaState::~CLuaState() -{ - nlassert(_State); - - #ifdef LUA_NEVRAX_VERSION - if (!LuaDebuggerIDE) - #else - if (1) - #endif - { - lua_close(_State); - } - else - { - #ifdef LUA_NEVRAX_VERSION - LuaDebuggerIDE->stopDebug(); // this will also close the lua state - LuaDebuggerIDE = NULL; - LuaDebuggerVisible = false; - #ifdef NL_OS_WINDOWS - nlassert(LuaDebuggerModule) - _CrtSetReportHook(NoOpReportHook); // prevent dump of memory leaks at this point - //::FreeLibrary(LuaDebuggerModule); // don't free the library now (seems that it destroy, the main window, causing - // a crash when the app window is destroyed for real... - // -> FreeLibrary will be called when the application is closed - LuaDebuggerModule = 0; - #endif - #endif - } - - // Clear Small Script Cache - _SmallScriptPool= 0; - _SmallScriptCache.clear(); -} - -// *************************************************************************** -CLuaState *CLuaState::fromStatePointer(lua_State *state) -{ - //H_AUTO(Lua_CLuaState_fromStatePointer) - nlassert(state); - int initialStackSize = lua_gettop(state); - lua_checkstack(state, initialStackSize + 2); - lua_pushlightuserdata(state, (void *) state); - lua_gettable(state, LUA_REGISTRYINDEX); - if (!lua_islightuserdata(state, -1)) - { - lua_pop(state, 1); - return NULL; - } - CLuaState *ls = (CLuaState *) lua_touserdata(state, -1); - lua_pop(state, 1); - nlassert(initialStackSize == lua_gettop(state)); - return ls; -} - -// *************************************************************************** -struct CLuaReader -{ - const std::string *Str; - bool Done; -}; - - - - -void CLuaState::loadScript(const std::string &code, const std::string &dbgSrc) -{ - //H_AUTO(Lua_CLuaState_loadScript) - if (code.empty()) return; - struct CHelper - { - static const char *luaChunkReaderFromString(lua_State * /* L */, void *ud, size_t *sz) - { - CLuaReader *rd = (CLuaReader *) ud; - if (!rd->Done) - { - rd->Done = true; - *sz = rd->Str->size(); - return rd->Str->c_str(); - } - else - { - *sz = 0; - return NULL; - } - } - }; - CLuaReader rd; - rd.Str = &code; - rd.Done = false; - - int result = lua_load(_State, CHelper::luaChunkReaderFromString, (void *) &rd, dbgSrc.c_str()); - if (result !=0) - { - // pop the error code - string err= toString(); - pop(); - // throw error - throw ELuaParseError(err); - } -} - -// *************************************************************************** -void CLuaState::executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet) -{ - //H_AUTO(Lua_CLuaState_executeScriptInternal) - CLuaStackChecker lsc(this, numRet); - - // load the script - loadScript(code, dbgSrc); - - // execute - if (pcall(0, numRet) != 0) - { - // pop the error code - string err= toString(); - pop(); - // throw error - throw ELuaExecuteError(err); - } -} - -// *************************************************************************** -void CLuaState::executeScript(const std::string &code, int numRet) -{ - //H_AUTO(Lua_CLuaState_executeScript) - // run the script, with dbgSrc==script - executeScriptInternal(code, code, numRet); -} - -// *************************************************************************** -bool CLuaState::executeScriptNoThrow(const std::string &code, int numRet) -{ - //H_AUTO(Lua_CLuaState_executeScriptNoThrow) - try - { - executeScript(code, numRet); - } - catch (const ELuaError &e) - { - nlwarning(e.what()); - return false; - } - return true; -} - -// *************************************************************************** -bool CLuaState::executeFile(const std::string &pathName) -{ - //H_AUTO(Lua_CLuaState_executeFile) - - CIFile inputFile; - if(!inputFile.open(pathName)) - return false; - - #ifdef LUA_NEVRAX_VERSION - if (LuaDebuggerIDE) - { - std::string path = NLMISC::CPath::getCurrentPath() + "/" + pathName.c_str(); - path = CPath::standardizeDosPath(path); - LuaDebuggerIDE->addFile(path.c_str()); - } - #endif - - // load the script text - string script; - /* - while(!inputFile.eof()) - { - char tmpBuff[5000]; - inputFile.getline(tmpBuff, 5000); - script+= tmpBuff; - script+= "\n"; - } - */ - script.resize(CFile::getFileSize(pathName)); - inputFile.serialBuffer((uint8 *) &script[0], (uint)script.size()); - - - // execute the script text, with dbgSrc==filename (use @ for lua internal purpose) - executeScriptInternal(script, string("@") + CFile::getFilename(pathName)); - - return true; -} - -// *************************************************************************** -void CLuaState::executeSmallScript(const std::string &script) -{ - //H_AUTO(Lua_CLuaState_executeSmallScript) - if (script.empty()) return; - // *** if the small script has not already been called before, parse it now - TSmallScriptCache::iterator it= _SmallScriptCache.find(script); - if(it==_SmallScriptCache.end()) - { - CLuaStackChecker lsc(this); - - // add it to a function - loadScript(script, script); - - // Assign the method to the NEL table: NELSmallScriptTable[_SmallScriptPool]= function - push(_NELSmallScriptTableName); // 1:function 2:NelTableName - getTable(LUA_REGISTRYINDEX); // 1:function 2:NelTable - insert(-2); // 1:NelTable 2:function - rawSetI(-2, _SmallScriptPool); // 1:NelTable - pop(); - - // bkup in cache map - it= _SmallScriptCache.insert(make_pair(script, _SmallScriptPool)).first; - - // next allocated - _SmallScriptPool++; - } - - // *** Execute the function associated to the script - CLuaStackChecker lsc(this); - push(_NELSmallScriptTableName); // 1:NelTableName - getTable(LUA_REGISTRYINDEX); // 1:NelTable - // get the function at the given index in the "NELSmallScriptTable" table - rawGetI(-1, it->second); // 1:NelTable 2:function - - // execute - if (pcall(0, 0) != 0) - { - // Stack: 1: NelTable 2:errorcode - // pop the error code, and clear stack - string err= toString(); - pop(); // 1:NelTable - pop(); // .... - // throw error - throw ELuaExecuteError(err); - } - else - { - // Stack: 1:NelTable - pop(); // .... - } - -} - -// *************************************************************************** -void CLuaState::registerFunc(const char *name, lua_CFunction function) -{ - //H_AUTO(Lua_CLuaState_registerFunc) - lua_register(_State, name, function); -} - -// *************************************************************************** -void CLuaState::pushCClosure(lua_CFunction function, int n) -{ - //H_AUTO(Lua_CLuaState_pushCClosure) - nlassert(function); - nlassert(getTop() >= n); - lua_pushcclosure(_State, function, n); -} - -// *************************************************************************** -void CLuaState::push(TLuaWrappedFunction function) -{ - //H_AUTO(Lua_CLuaState_push) - struct CForwarder - { - static int callFunc(lua_State *ls) - { - nlassert(ls); - TLuaWrappedFunction func = (TLuaWrappedFunction) lua_touserdata(ls, lua_upvalueindex(1)); - CLuaState *state = (CLuaState *) lua_touserdata(ls, lua_upvalueindex(2)); - nlassert(func); - nlassert(state); - // get real function pointer from the values in the closure - int numResults = 0; - int initialStackSize = state->getTop(); - try - { - // call the actual function - numResults = func(*state); - } - catch(const std::exception &e) - { - // restore stack to its initial size - state->setTop(initialStackSize); - lua_pushstring(ls, e.what()); - // TODO : see if this is safe to call lua error there" ... (it does a long jump) - lua_error(ls); - } - return numResults; - } - }; - pushLightUserData((void *) function); - pushLightUserData((void *) this); - pushCClosure(CForwarder::callFunc, 2); -} - -// *************************************************************************** -// Wrapped function -void CLuaState::registerFunc(const char *name, TLuaWrappedFunction function) -{ - //H_AUTO(Lua_CLuaState_registerFunc) - nlassert(function); - CLuaStackChecker lsc(this); - push(name); - push(function); - setTable(LUA_GLOBALSINDEX); -} - - -// *************************************************************************** -bool CLuaState::getTableBooleanValue(const char *name, bool defaultValue) -{ - //H_AUTO(Lua_CLuaState_getTableBooleanValue) - nlassert(name); - push(name); - getTable(-2); - if (isNil()) - { - pop(); - return defaultValue; - } - bool result = toBoolean(-1); - pop(); - return result; -} - -// *************************************************************************** -double CLuaState::getTableNumberValue(const char *name, double defaultValue) -{ - //H_AUTO(Lua_CLuaState_getTableNumberValue) - nlassert(name); - push(name); - getTable(-2); - if (isNil()) - { - pop(); - return defaultValue; - } - double result = toNumber(-1); - pop(); - return result; -} - -// *************************************************************************** -const char *CLuaState::getTableStringValue(const char *name, const char *defaultValue) -{ - //H_AUTO(Lua_CLuaState_getTableStringValue) - nlassert(name); - push(name); - getTable(-2); - if (isNil()) - { - pop(); - return defaultValue; - } - const char *result = toString(-1); - pop(); - return result; -} - -// *************************************************************************** -void CLuaState::getStackContext(string &ret, uint stackLevel) -{ - //H_AUTO(Lua_CLuaState_getStackContext) - nlassert(_State); - ret.clear(); - lua_Debug dbg; - if(lua_getstack (_State, stackLevel, &dbg)) - { - if(lua_getinfo(_State, "lS", &dbg)) - { - ret= NLMISC::toString("%s:%d:", dbg.short_src, dbg.currentline); - } - } -} - -// *************************************************************************** -int CLuaState::pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex /*=LUA_GLOBALSINDEX*/, int errfunc /*= 0*/) -{ - //H_AUTO(Lua_CLuaState_pcallByName) - int initialStackSize = getTop(); - nlassert(functionName); - nlassert(isTable(funcTableIndex)); - pushValue(funcTableIndex); - push(functionName); - getTable(-2); - remove(-2); // get rid of the table - nlassert(getTop() >= nargs); // not enough arguments on the stack - // insert function before its arguments - insert(- 1 - nargs); - int result = pcall(nargs, nresults, errfunc); - int currSize = getTop(); - if (result == 0) - { - nlassert(currSize == initialStackSize - nargs + nresults); - } - else - { - // errors, the stack contains a single string - if (errfunc == 0) - { - nlassert(currSize == initialStackSize - nargs + 1); - } - // else if there's an error handler, can't know the size of stack - } - return result; -} - -// *************************************************************************** -void CLuaState::dumpStack() -{ - //H_AUTO(Lua_CLuaState_dumpStack) - nlinfo("LUA STACK CONTENT (size = %d)", getTop()); - nlinfo("================="); - CLuaStackChecker lsc(this); - for(int k = 1; k <= getTop(); ++k) - { - pushValue(k); - std::string value = toString(-1) ? toString(-1) : "?"; - nlinfo("Stack entry %d : type = %s, value = %s", k, getTypename(type(-1)), value.c_str()); - pop(); - } -} - -// *************************************************************************** -void CLuaState::getStackAsString(std::string &dest) -{ - //H_AUTO(Lua_CLuaState_getStackAsString) - dest = NLMISC::toString("Stack size = %d\n", getTop()); - CLuaStackChecker lsc(this); - for(int k = 1; k <= getTop(); ++k) - { - pushValue(k); - std::string value = toString(-1) ? toString(-1) : "?"; - dest += NLMISC::toString("Stack entry %d : type = %s, value = %s\n", k, getTypename(type(-1)), value.c_str()); - pop(); - } -} - -//================================================================================ -CLuaStackChecker::~CLuaStackChecker() -{ - nlassert(_State); - if (!_ExceptionContextCounter) - { - int currSize = _State->getTop(); - if (currSize != _FinalWantedSize) - { - static volatile bool assertWanted = true; - if (assertWanted) - { - nlwarning("Lua stack size error : expected size is %d, current size is %d", _FinalWantedSize, currSize); - _State->dumpStack(); - nlassert(0); - } - } - } - else - { - // this object dtor was called because an exception was thrown, so let the exception - // propagate (the stack must be broken, but because of the exception, not because of code error) - _State->setTop(_FinalWantedSize); - } -} - -// *************************************************************************** -void ELuaWrappedFunctionException::init(CLuaState *ls, const std::string &reason) -{ - //H_AUTO(Lua_ELuaWrappedFunctionException_init) - // Print first Lua Stack Context - if(ls) - { - ls->getStackContext(_Reason, 1); // 1 because 0 is the current C function => return 1 for script called - // enclose with cool colors - LuaHelperStuff::formatLuaStackContext(_Reason); - } - - // Append the reason - _Reason+= reason; -} - -// *************************************************************************** -ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState) -{ - //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) - init(luaState, ""); -} - -// *************************************************************************** -ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason) -{ - //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) - init(luaState, reason); -} - -// *************************************************************************** -ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...) -{ - //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) - std::string reason; - NLMISC_CONVERT_VARGS (reason, format, NLMISC::MaxCStringSize); - init(luaState, reason); -} - -//================================================================================ -void CLuaState::newTable() -{ - //H_AUTO(Lua_CLuaState_newTable) - nlverify( lua_checkstack(_State, 1) ); - lua_newtable(_State); -} - -//================================================================================ -int CLuaState::getGCCount() -{ - //H_AUTO(Lua_CLuaState_getGCCount) - return lua_getgccount(_State); -} - -//================================================================================ -int CLuaState::getGCThreshold() -{ - //H_AUTO(Lua_CLuaState_getGCThreshold) -#ifdef LUA_NEVRAX_VERSION - return _GCThreshold; -#else -# if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 - return lua_gc(_State, LUA_GCCOUNT, 0); -# else - return lua_getgcthreshold(_State); -# endif -#endif -} - -//================================================================================ -void CLuaState::setGCThreshold(int kb) -{ - //H_AUTO(Lua_CLuaState_setGCThreshold) -#ifdef LUA_NEVRAX_VERSION - _GCThreshold = kb; - handleGC(); -#else -# if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 - lua_gc(_State, LUA_GCCOLLECT, kb); -# else - lua_setgcthreshold(_State, kb); -# endif -#endif -} - -//================================================================================ -void CLuaState::handleGC() -{ - //H_AUTO(Lua_CLuaState_handleGC) - #ifdef LUA_NEVRAX_VERSION - // must handle gc manually with the refcounted version - int gcCount = getGCCount(); - if (gcCount >= _GCThreshold) - { - nlwarning("Triggering GC : memory in use = %d kb, current threshold = %d kb", gcCount, _GCThreshold); - lua_setgcthreshold(_State, 0); - gcCount = getGCCount(); - _GCThreshold = std::max(MinGCThreshold, gcCount * 2); - nlwarning("After GC : memory in use = %d kb, threshold = %d kb", gcCount, _GCThreshold); - } - #endif -} - - diff --git a/code/ryzom/client/src/interface_v3/lua_helper.h b/code/ryzom/client/src/interface_v3/lua_helper.h deleted file mode 100644 index 71a3efe17..000000000 --- a/code/ryzom/client/src/interface_v3/lua_helper.h +++ /dev/null @@ -1,385 +0,0 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RZ_LUA_HELPER_H -#define RZ_LUA_HELPER_H - - -#include "nel/misc/types_nl.h" -#include "nel/misc/smart_ptr.h" - - -extern "C" -{ - #include "lua_loadlib.h" -} - -class CLuaState; - -namespace LuaHelperStuff -{ - void formatLuaStackContext( std::string &stackContext ); - std::string formatLuaErrorSysInfo( const std::string &error ); - std::string formatLuaErrorNlWarn( const std::string &error ); -} - - -// *************************************************************************** -/** Helper class to see if a stack is restored at its initial size (or with n return results). - * Check that the stack size remains unchanged when the object goes out of scope - */ -class CLuaStackChecker -{ -public: - CLuaStackChecker(CLuaState *state, int numWantedResults = 0); - ~CLuaStackChecker(); - /** Increment exception context counter - * When an exception is thrown, lua stack checker do any assert bu will - * rather restore the lua stack at its original size, and will - * let the exception a chance to propagate - */ - static void incrementExceptionContextCounter(); - static void decrementExceptionContextCounter(); - -private: - CLuaState *_State; - int _FinalWantedSize; - static uint _ExceptionContextCounter; - -}; - -// ************************************************************************** -/** Helper class to restore the lua stack to the desired size when this object goes out of scope - */ -class CLuaStackRestorer -{ -public: - CLuaStackRestorer(CLuaState *state, int finalSize); - ~CLuaStackRestorer(); -private: - int _FinalSize; - CLuaState *_State; -}; - -//////////////// -// EXCEPTIONS // -//////////////// - -class ELuaError : public NLMISC::Exception -{ -public: - ELuaError() { CLuaStackChecker::incrementExceptionContextCounter(); } - virtual ~ELuaError() throw() { CLuaStackChecker::decrementExceptionContextCounter(); } - ELuaError(const std::string &reason) : Exception(reason) { CLuaStackChecker::incrementExceptionContextCounter(); } - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("LUAError: %s", what());} -}; - -// A parse error occured -class ELuaParseError : public ELuaError -{ -public: - ELuaParseError() {} - ELuaParseError(const std::string &reason) : ELuaError(reason) {} - virtual ~ELuaParseError() throw() { } - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaParseError: %s", what());} -}; - -/** Exception thrown when something went wrong inside a wrapped function called by lua - */ -class ELuaWrappedFunctionException : public ELuaError -{ -public: - ELuaWrappedFunctionException(CLuaState *luaState); - ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason); - ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...); - virtual ~ELuaWrappedFunctionException() throw() { } - virtual const char *what() const throw() {return _Reason.c_str();} -protected: - void init(CLuaState *ls, const std::string &reason); -protected: - std::string _Reason; -}; - -// A execution error occured -class ELuaExecuteError : public ELuaError -{ -public: - ELuaExecuteError() {} - ELuaExecuteError(const std::string &reason) : ELuaError(reason) {} - virtual ~ELuaExecuteError() throw() { } - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaExecuteError: %s", what());} -}; - -// A bad cast occured when using lua_checkcast -class ELuaBadCast : public ELuaError -{ -public: - ELuaBadCast() {} - ELuaBadCast(const std::string &reason) : ELuaError(reason) {} - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaBadCast: %s", what());} -}; - -// Error when trying to indexate an object that is not a table -class ELuaNotATable : public ELuaError -{ -public: - ELuaNotATable() {} - ELuaNotATable(const std::string &reason) : ELuaError(reason) {} - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaNotATable: %s", what());} -}; - - -// *************************************************************************** -// a function to be used with a CLuaState instance -typedef int (* TLuaWrappedFunction) (CLuaState &ls); - - -// *************************************************************************** -/** C++ version of a lua state - */ -class CLuaState : public NLMISC::CRefCount -{ -public: - typedef NLMISC::CRefPtr TRefPtr; - - // Create a new environement - CLuaState(); - ~CLuaState(); - - - /// \name Registering - // @{ - // register a wrapped function - void registerFunc(const char *name, TLuaWrappedFunction function); - // @} - - - /// \name Script execution - // @{ - - /** Parse a script and push as a function in top of the LUA stack - * \throw ELuaParseError - * \param dbgSrc is a string for debug. Should be a filename (preceded with '@'), or a short script. - */ - void loadScript(const std::string &code, const std::string &dbgSrc); - - /** Execute a script from a string, possibly throwing an exception if there's a parse error - * \throw ELuaParseError, ELuaExecuteError - */ - void executeScript(const std::string &code, int numRet = 0); - - /** Execute a script from a string. If an errors occurs it is printed in the log - * \return true if script execution was successful - */ - bool executeScriptNoThrow(const std::string &code, int numRet = 0); - - /** Load a Script from a File (maybe in a BNP), and execute it - * \return false if file not found - * \throw ELuaParseError, ELuaExecuteError - */ - bool executeFile(const std::string &pathName); - - /** execute a very Small Script (a function call for instance) - * It is different from doString() in such there is a cache (where the key is the script itself) - * so that the second time this script is executed, there is no parsing - * Note: I experienced optim with about 10 times faster than a executeScript() on a simple "a= a+1;" script - * \throw ELuaParseError, ELuaExecuteError - */ - void executeSmallScript(const std::string &script); - - // @} - - - /// \name Stack Manipulation - // @{ - // stack manipulation (indices start at 1) - void setTop(int index); // set new size of stack - void clear() { setTop(0); } - int getTop(); - bool empty() { return getTop() == 0; } - void pushValue(int index); // copie nth element of stack to the top of the stack - void remove(int index); // remove nth element of stack - void insert(int index); // insert last element of the stack before the given position - void replace(int index); // replace nth element of the stack with the top of the stack - void pop(int numElem = 1); // remove n elements from the top of the stack - // test the type of an element in the stack - // return one of the following values : - // LUA_TNIL - // LUA_TNUMBER - // LUA_TBOOLEAN - // LUA_TSTRING - // LUA_TTABLE - // LUA_TFUNCTION - // LUA_TUSERDATA - // LUA_TTHREAD - // LUA_TLIGHTUSERDATA - int type(int index = -1); - const char *getTypename(int type); - bool isNil(int index = -1); - bool isBoolean(int index = -1); - bool isNumber(int index = -1); - bool isString(int index = -1); - bool isTable(int index = -1); - bool isFunction(int index = -1); - bool isCFunction(int index = -1); - bool isUserData(int index = -1); - bool isLightUserData(int index = -1); - // converting then getting a value from the stack - bool toBoolean(int index = -1); - lua_Number toNumber(int index = -1); - const char *toString(int index = -1); - void toString(int index, std::string &str); // convert to a std::string, with a NULL check. - size_t strlen(int index = -1); - lua_CFunction toCFunction(int index = -1); - void *toUserData(int index = -1); - const void *toPointer(int index = -1); - /** Helper functions : get value of the wanted type in the top table after conversion - * A default value is used if the stack entry is NULL. - * If conversion fails then an exception is thrown (with optional msg) - */ - bool getTableBooleanValue(const char *name, bool defaultValue= false); - double getTableNumberValue(const char *name, double defaultValue= 0); - const char *getTableStringValue(const char *name, const char *defaultValue= NULL); - // pushing value onto the stack - void push(bool value); - void push(lua_Number value); - void push(const char *str); - void push(const char *str, int length); - void push(const std::string &str); - void pushNil(); - void push(lua_CFunction f); - void push(TLuaWrappedFunction function); - void pushLightUserData(void *); // push a light user data (use newUserData to push a full userdata) - // metatables - bool getMetaTable(int index = -1); - bool setMetaTable(int index = -1); // set the metatable at top of stack to the object at 'index' (usually -2), then pop the metatable - // even if asignment failed - // comparison - bool equal(int index1, int index2); - bool rawEqual(int index1, int index2); - bool lessThan(int index1, int index2); - // concatenation of the n element at the top of the stack (using lua semantic) - void concat(int numElem); - // tables - void newTable(); // create a new table at top of the stack - void getTable(int index); // get value from a table at index 'index' (key is at top) - void rawGet(int index); - void setTable(int index); // set (key, value) from top of the stack into the given table - // both key and value are poped - void rawSet(int index); - bool next(int index); // table traversal - // UserData - void *newUserData(uint size); - // seting value by int index in a table - void rawSetI(int index, int n); - void rawGetI(int index, int n); - /** Calling functions (it's up to the caller to clear the results) - * The function should have been pushed on the stack - */ - void call(int nargs, int nresults); - int pcall(int nargs, int nresults, int errfunc = 0); - /** Helper : Execute a function by name. Lookup for the function is done in the table at the index 'funcTableIndex' - * the behaviour is the same than with call of pcall. - */ - int pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex = LUA_GLOBALSINDEX, int errfunc = 0); - - // push a C closure (pop n element from the stack and associate with the function) - void pushCClosure(lua_CFunction function, int n); - // @} - - - /// \name Misc - // @{ - /** Retrieve pointer to a CLuaState environment from its lua_State pointer, or NULL - * if there no such environment - */ - static CLuaState *fromStatePointer(lua_State *state); - // Get state pointer. The state should not be closed (this object has ownership) - lua_State *getStatePointer() const {return _State;} - // check that an index is valid when accessing the stack - // an assertion is raised if the index is not valid - void checkIndex(int index); - - // registering C function to use with a lua state pointer - void registerFunc(const char *name, lua_CFunction function); - - // Garbage collector - int getGCCount(); // get memory in use in KB - int getGCThreshold(); // get max memory in KB - void setGCThreshold(int kb); // set max memory in KB (no-op with ref-counted version) - - // handle garbage collector for ref-counted version of lua (no-op with standard version, in which case gc handling is automatic) - void handleGC(); - - /** For Debug: get the Stack context of execution (filename / line) - * \param stackLevel: get the context of execution of the given stackLevel. - * 0 for the current function - * 1 for the function that called 0 - * 2 .... - * NB: if called from a C function called from LUA, remember that stackLevel 0 is the current function. - * Hence if you want to know what LUA context called you, pass stackLevel=1! - * \param ret string cleared if any error, else filled with formated FileName / LineNumber - */ - void getStackContext(std::string &ret, uint stackLevel); - // @} - - // for debug : dump the current content of the stack (no recursion) - void dumpStack(); - static void dumpStack(lua_State *ls); - void getStackAsString(std::string &dest); - - -private: - lua_State *_State; - - #ifdef LUA_NEVRAX_VERSION - int _GCThreshold; // if refcounted gc is used, then garbage collector is handled manually - #endif - // Small Script Cache - uint _SmallScriptPool; - typedef std::map TSmallScriptCache; - TSmallScriptCache _SmallScriptCache; - static const char * _NELSmallScriptTableName; - -private: - // this object isn't intended to be copied - CLuaState(const CLuaState &/* other */):NLMISC::CRefCount() { nlassert(0); } - CLuaState &operator=(const CLuaState &/* other */) { nlassert(0); return *this; } - - void executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet = 0); - -}; - - -// Access to lua function -// one should not include lua.h directly because if a debugger is present, lua -// function pointer will be taken from a dynamic library. - - - -//============================================================================================= -// include implementation -#define RZ_INCLUDE_LUA_HELPER_INLINE - #include "lua_helper_inline.h" -#undef RZ_INCLUDE_LUA_HELPER_INLINE - - -#endif diff --git a/code/ryzom/client/src/interface_v3/lua_ihm.cpp b/code/ryzom/client/src/interface_v3/lua_ihm.cpp index ebb374bd9..61b1b4d2c 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm.cpp @@ -16,7 +16,8 @@ #include "stdpch.h" -#include "lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; #include diff --git a/code/ryzom/client/src/interface_v3/lua_ihm.h b/code/ryzom/client/src/interface_v3/lua_ihm.h index 12d8b5459..2826c1ac7 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm.h +++ b/code/ryzom/client/src/interface_v3/lua_ihm.h @@ -18,8 +18,8 @@ #define NL_LUA_IHM_H #include "nel/misc/types_nl.h" -#include "lua_helper.h" - +#include "nel/gui/lua_helper.h" +using namespace NLGUI; namespace NLMISC diff --git a/code/ryzom/client/src/interface_v3/lua_object.cpp b/code/ryzom/client/src/interface_v3/lua_object.cpp index eb5f76c4f..d2d4da1e1 100644 --- a/code/ryzom/client/src/interface_v3/lua_object.cpp +++ b/code/ryzom/client/src/interface_v3/lua_object.cpp @@ -17,7 +17,8 @@ #include "stdpch.h" #include "lua_object.h" #include "lua_ihm.h" -#include "lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; // #include "interface_manager.h" diff --git a/code/ryzom/client/src/interface_v3/lua_object.h b/code/ryzom/client/src/interface_v3/lua_object.h index e4cfee3d9..28d2e73b7 100644 --- a/code/ryzom/client/src/interface_v3/lua_object.h +++ b/code/ryzom/client/src/interface_v3/lua_object.h @@ -21,7 +21,8 @@ #include "nel/misc/smart_ptr.h" #include "nel/misc/rgba.h" // -#include "lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; diff --git a/code/ryzom/client/src/interface_v3/reflect.h b/code/ryzom/client/src/interface_v3/reflect.h index dfc4af5fa..5dbdbe554 100644 --- a/code/ryzom/client/src/interface_v3/reflect.h +++ b/code/ryzom/client/src/interface_v3/reflect.h @@ -26,7 +26,10 @@ #include class CReflectable; -class CLuaState; +namespace NLGUI +{ + class CLuaState; +} struct CClassInfo; /** A property of a reflectable object diff --git a/code/ryzom/client/src/r2/dmc/com_lua_module.cpp b/code/ryzom/client/src/r2/dmc/com_lua_module.cpp index 69223a2ae..2d15b18f6 100644 --- a/code/ryzom/client/src/r2/dmc/com_lua_module.cpp +++ b/code/ryzom/client/src/r2/dmc/com_lua_module.cpp @@ -48,7 +48,8 @@ #include -#include "../../interface_v3/lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; #include "../../interface_v3/lua_ihm.h" #include "../../entities.h" diff --git a/code/ryzom/client/src/r2/dmc/com_lua_module.h b/code/ryzom/client/src/r2/dmc/com_lua_module.h index 91c532fda..24bbfb9fd 100644 --- a/code/ryzom/client/src/r2/dmc/com_lua_module.h +++ b/code/ryzom/client/src/r2/dmc/com_lua_module.h @@ -22,7 +22,7 @@ extern "C" { - #include "../../interface_v3/lua_loadlib.h" + #include "nel/gui/lua_loadlib.h" } diff --git a/code/ryzom/client/src/r2/dmc/dmc.h b/code/ryzom/client/src/r2/dmc/dmc.h index 24d2893de..fa9235586 100644 --- a/code/ryzom/client/src/r2/dmc/dmc.h +++ b/code/ryzom/client/src/r2/dmc/dmc.h @@ -27,7 +27,7 @@ extern "C" { - #include "../../interface_v3/lua_loadlib.h" + #include "nel/gui/lua_loadlib.h" } diff --git a/code/ryzom/client/src/r2/editor.cpp b/code/ryzom/client/src/r2/editor.cpp index 859b89520..9daa5db70 100644 --- a/code/ryzom/client/src/r2/editor.cpp +++ b/code/ryzom/client/src/r2/editor.cpp @@ -46,7 +46,8 @@ #include "editor.h" // -#include "../interface_v3/lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; #include "../interface_v3/group_tree.h" #include "../interface_v3/interface_manager.h" #include "../contextual_cursor.h" diff --git a/code/ryzom/client/src/r2/instance.h b/code/ryzom/client/src/r2/instance.h index d10c37532..8825c6946 100644 --- a/code/ryzom/client/src/r2/instance.h +++ b/code/ryzom/client/src/r2/instance.h @@ -27,7 +27,10 @@ #include "lua_event_forwarder.h" class CEntityCL; +namespace NLGUI +{ class CLuaState; +} namespace R2 { diff --git a/code/ryzom/client/src/r2/lua_event_forwarder.h b/code/ryzom/client/src/r2/lua_event_forwarder.h index 4ad8139e1..bd16cd57c 100644 --- a/code/ryzom/client/src/r2/lua_event_forwarder.h +++ b/code/ryzom/client/src/r2/lua_event_forwarder.h @@ -17,7 +17,10 @@ #ifndef R2_LUA_EVENT_FORWARDER_H #define R2_LUA_EVENT_FORWARDER_H -class CLuaState; +namespace NLGUI +{ + class CLuaState; +} class CLuaString; namespace R2 @@ -53,7 +56,7 @@ public: const std::string &targetAttrName, sint32 targetAttrIndex); protected: // for derivers - virtual CLuaState *getLua() = 0; + virtual NLGUI::CLuaState *getLua() = 0; virtual void executeHandler(const CLuaString &eventName, int numArgs) = 0; }; diff --git a/code/ryzom/client/src/session_browser_impl.h b/code/ryzom/client/src/session_browser_impl.h index d22d6a1cf..cd56cb482 100644 --- a/code/ryzom/client/src/session_browser_impl.h +++ b/code/ryzom/client/src/session_browser_impl.h @@ -20,7 +20,8 @@ #include "session_browser.h" #include "game_share/ring_session_manager_itf.h" -#include "interface_v3/lua_helper.h" +#include "nel/gui/lua_helper.h" +using namespace NLGUI; #include "far_tp.h" class CSessionBrowserImpl : public CSessionBrowser,