diff options
author | Paul Gilbert | 2010-08-01 01:49:06 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-12 22:16:21 +0000 |
commit | 2d8e94e4ff71cefb9822732741bc7eb1a9116e07 (patch) | |
tree | 25d3e5c93e475ceb62f25869b25724270aef899c /engines/sword25/script | |
parent | ea29e41b86dd6efad5b044220505ded798b2503e (diff) | |
download | scummvm-rg350-2d8e94e4ff71cefb9822732741bc7eb1a9116e07.tar.gz scummvm-rg350-2d8e94e4ff71cefb9822732741bc7eb1a9116e07.tar.bz2 scummvm-rg350-2d8e94e4ff71cefb9822732741bc7eb1a9116e07.zip |
SWORD25: Converted Lua interface classes
svn-id: r53195
Diffstat (limited to 'engines/sword25/script')
-rw-r--r-- | engines/sword25/script/lua_extensions.cpp | 15 | ||||
-rw-r--r-- | engines/sword25/script/luabindhelper.cpp | 285 | ||||
-rw-r--r-- | engines/sword25/script/luabindhelper.h | 108 | ||||
-rw-r--r-- | engines/sword25/script/luacallback.cpp | 113 | ||||
-rw-r--r-- | engines/sword25/script/luacallback.h | 33 | ||||
-rw-r--r-- | engines/sword25/script/luascript.cpp | 328 | ||||
-rw-r--r-- | engines/sword25/script/luascript.h | 79 |
7 files changed, 471 insertions, 490 deletions
diff --git a/engines/sword25/script/lua_extensions.cpp b/engines/sword25/script/lua_extensions.cpp index 812db5592a..5fbc0ab3bd 100644 --- a/engines/sword25/script/lua_extensions.cpp +++ b/engines/sword25/script/lua_extensions.cpp @@ -41,8 +41,9 @@ // ----------------------------------------------------------------------------- -static int Warning(lua_State * L) -{ +namespace Sword25 { + +static int Warning(::lua_State *L) { #ifdef DEBUG int __startStackDepth = lua_gettop(L); #endif @@ -64,20 +65,20 @@ static int Warning(lua_State * L) // ----------------------------------------------------------------------------- -static const luaL_reg GLOBAL_FUNCTIONS[] = -{ +static const luaL_reg GLOBAL_FUNCTIONS[] = { "warning", Warning, 0, 0, }; // ----------------------------------------------------------------------------- -bool BS_LuaScriptEngine::RegisterStandardLibExtensions() -{ - lua_State * L = m_State; +bool BS_LuaScriptEngine::RegisterStandardLibExtensions() { + ::lua_State *L = m_State; BS_ASSERT(m_State); if (!BS_LuaBindhelper::AddFunctionsToLib(L, "", GLOBAL_FUNCTIONS)) return false; return true; } + +} // End of namespace Sword25 diff --git a/engines/sword25/script/luabindhelper.cpp b/engines/sword25/script/luabindhelper.cpp index 79c7f21efc..06e97ad2e2 100644 --- a/engines/sword25/script/luabindhelper.cpp +++ b/engines/sword25/script/luabindhelper.cpp @@ -39,97 +39,99 @@ #include "sword25/kernel/kernel.h" #include "sword25/script/luabindhelper.h" #include "sword25/script/luascript.h" -#include <sstream> #define BS_LOG_PREFIX "LUABINDHELPER" // ----------------------------------------------------------------------------- -namespace -{ +namespace { const char * METATABLES_TABLE_NAME = "__METATABLES"; const char * PERMANENTS_TABLE_NAME = "Permanents"; - bool RegisterPermanent(lua_State * L, const std::string & Name) - { - // Eine C-Funktion muss auf dem Stack liegen. + bool RegisterPermanent(::lua_State *L, const Common::String &Name) { + // A C function has to be on the stack if (!lua_iscfunction(L, -1)) return false; - // Sicherstellen, dass die Permanents-Tabelle oben auf dem Stack liegt. + // Make sure that the Permanents-Table is on top of the stack lua_getfield(L, LUA_REGISTRYINDEX, PERMANENTS_TABLE_NAME); - if (lua_isnil(L, -1)) - { - // Permanents-Tabelle existiert noch nicht, sie muss erstellt werden. + if (lua_isnil(L, -1)) { + // Permanents-Table does not yet exist, so it has to be created - // Nil vom Stack poppen. + // Pop nil from the stack lua_pop(L, 1); - // Permanents-Tabelle erstellen und eine zweite Referenz darauf auf den Stack legen. + // Create Permanents-Table and insert a second reference to it on the stack lua_newtable(L); lua_pushvalue(L, -1); - // Permanents-Tabelle in der Registry speichern. Die zweite Referenz verbleibt auf dem Stack um im Anschluss benutzt zu werden. + // Store the Permanents-Table in the registry. The second reference is left + // on the stack to be used in the connection lua_setfield(L, LUA_REGISTRYINDEX, PERMANENTS_TABLE_NAME); } - // C-Funktion mit dem Namen als Index in der Permanents-Tabelle ablegen. + // C function with the name of an index in the Permanents-Table lua_insert(L, -2); lua_setfield(L, -2, Name.c_str()); - // Permanents-Tabelle vom Stack nehmen. + // Remove the Permanents-Table from the stack lua_pop(L, 1); return true; } } +namespace Sword25 { + // ----------------------------------------------------------------------------- -bool BS_LuaBindhelper::AddFunctionsToLib(lua_State * L, const std::string & LibName, const luaL_reg * Functions) -{ +/** + * Registers a set of functions into a Lua library. + * @param L A pointer to the Lua VM + * @param LibName The name of the library. + * If this is an empty string, the functions will be added to the global namespace. + * @param Functions An array of function pointers along with their names. + * The array must be terminated with the enry (0, 0) + * @return Returns true if successful, otherwise false. + */ +bool BS_LuaBindhelper::AddFunctionsToLib(::lua_State *L, const Common::String &LibName, const luaL_reg *Functions) { #ifdef DEBUG int __startStackDepth = lua_gettop(L); #endif - // Wenn der Tabellenname leer ist, werden die Funktionen zum globalen Namensraum hinzugefügt. - if (LibName.size() == 0) - { - for (; Functions->name; ++Functions) - { + // If the table name is empty, the functions are to be added to the global namespace + if (LibName.size() == 0) { + for (; Functions->name; ++Functions) { lua_pushstring(L, Functions->name); lua_pushcclosure(L, Functions->func, 0); lua_settable(L, LUA_GLOBALSINDEX); - // Funktion als permanent registrieren, damit sie beim Persistieren ignoriert wird. + // Function is being permanently registed, so persistence can be ignored lua_pushstring(L, Functions->name); lua_gettable(L, LUA_GLOBALSINDEX); RegisterPermanent(L, Functions->name); } } - // Wenn der Tabellenname nicht leer ist, werden die Funktionen zu dieser Tabelle hinzugefügt. - else - { - // Sicherstellen, dass die Library-Table existiert. + // If the table name is not empty, the functions are added to the given table + else { + // Ensure that the library table exists if (!_CreateTable(L, LibName)) return false; - // Die einzelnen Funktionen in der Table registrieren. - for (; Functions->name; ++Functions) - { - // Funktion registrieren. + // Register each function into the table + for (; Functions->name; ++Functions) { + // Function registration lua_pushstring(L, Functions->name); lua_pushcclosure(L, Functions->func, 0); lua_settable(L, -3); - // Funktion als permanent registrieren, damit sie beim Persistieren ignoriert wird. + // Function is being permanently registed, so persistence can be ignored lua_pushstring(L, Functions->name); lua_gettable(L, -2); RegisterPermanent(L, LibName + "." + Functions->name); } - // Library-Table vom Lua-Stack nehmen. + // Remove the library table from the Lua stack lua_pop(L, 1); } - #ifdef DEBUG BS_ASSERT(__startStackDepth == lua_gettop(L)); @@ -140,37 +142,41 @@ bool BS_LuaBindhelper::AddFunctionsToLib(lua_State * L, const std::string & LibN // ----------------------------------------------------------------------------- -bool BS_LuaBindhelper::AddConstantsToLib(lua_State * L, const std::string & LibName, const lua_constant_reg * Constants) -{ +/** + * Adds a set of constants to the Lua library + * @param L A pointer to the Lua VM + * @param LibName The name of the library. + * If this is an empty string, the functions will be added to the global namespace. + * @param Constants An array of the constant values along with their names. + * The array must be terminated with the enry (0, 0) + * @return Returns true if successful, otherwise false. + */ +bool BS_LuaBindhelper::AddConstantsToLib(::lua_State *L, const Common::String &LibName, const lua_constant_reg *Constants) { #ifdef DEBUG int __startStackDepth = lua_gettop(L); #endif - // Wenn der Tabellenname leer ist, werden die Konstanten zum globalen Namensraum hinzugefügt. - if (LibName.size() == 0) - { - for (; Constants->Name; ++Constants) - { + // If the table is empty, the constants are added to the global namespace + if (LibName.size() == 0) { + for (; Constants->Name; ++Constants) { lua_pushstring(L, Constants->Name); lua_pushnumber(L, Constants->Value); lua_settable(L, LUA_GLOBALSINDEX); } } - // Wenn der Tabellenname nicht leer ist, werden die Konstanten zu dieser Tabelle hinzugefügt. - else - { - // Sicherstellen, dass die Library-Table existiert. + // If the table name is nto empty, the constants are added to that table + else { + // Ensure that the library table exists if (!_CreateTable(L, LibName)) return false; - // Die einzelnen Konstanten in der Table registrieren - for (; Constants->Name; ++Constants) - { + // Register each constant in the table + for (; Constants->Name; ++Constants) { lua_pushstring(L, Constants->Name); lua_pushnumber(L, Constants->Value); lua_settable(L, -3); } - // Library-Tabelle vom Lua-Stack nehmen + // Remove the library table from the Lua stack lua_pop(L, 1); } @@ -183,29 +189,36 @@ bool BS_LuaBindhelper::AddConstantsToLib(lua_State * L, const std::string & LibN // ----------------------------------------------------------------------------- -bool BS_LuaBindhelper::AddMethodsToClass(lua_State * L, const std::string & ClassName, const luaL_reg * Methods) -{ +/** + * Adds a set of methods to a Lua class + * @param L A pointer to the Lua VM + * @param ClassName The name of the class + * When the class name specified does not exist, it is created. + * @param Methods An array of function pointers along with their method names. + * The array must be terminated with the enry (0, 0) + * @return Returns true if successful, otherwise false. + */ +bool BS_LuaBindhelper::AddMethodsToClass(::lua_State *L, const Common::String &ClassName, const luaL_reg *Methods) { #ifdef DEBUG int __startStackDepth = lua_gettop(L); #endif - // Metatable auf den Lua-Stack laden + // Load the metatable onto the Lua stack if (!GetMetatable(L, ClassName)) return false; - // Die einzelnen Methoden in der Metatable registrieren - for (; Methods->name; ++Methods) - { + // Register each method in the Metatable + for (; Methods->name; ++Methods) { lua_pushstring(L, Methods->name); lua_pushcclosure(L, Methods->func, 0); lua_settable(L, -3); - // Funktion als permanent registrieren, damit sie beim Persistieren ignoriert wird. + // Function is being permanently registed, so persistence can be ignored lua_pushstring(L, Methods->name); lua_gettable(L, -2); RegisterPermanent(L, ClassName + "." + Methods->name); } - // Metatable vom Lua-Stack nehmen + // Remove the metatable from the stack lua_pop(L, 1); #ifdef DEBUG @@ -217,26 +230,33 @@ bool BS_LuaBindhelper::AddMethodsToClass(lua_State * L, const std::string & Clas // ----------------------------------------------------------------------------- -bool BS_LuaBindhelper::SetClassGCHandler(lua_State * L, const std::string & ClassName, lua_CFunction GCHandler) -{ +/** + * Sets the garbage collector callback method when items of a particular class are deleted + * @param L A pointer to the Lua VM + * @param ClassName The name of the class + * When the class name specified does not exist, it is created. + * @param GCHandler A function pointer + * @return Returns true if successful, otherwise false. + */ +bool BS_LuaBindhelper::SetClassGCHandler(::lua_State *L, const Common::String &ClassName, lua_CFunction GCHandler) { #ifdef DEBUG int __startStackDepth = lua_gettop(L); #endif - // Metatable auf den Lua-Stack laden + // Load the metatable onto the Lua stack if (!GetMetatable(L, ClassName)) return false; - // Den GC-Handler in die Metatable schreiben + // Add the GC handler to the Metatable lua_pushstring(L, "__gc"); lua_pushcclosure(L, GCHandler, 0); lua_settable(L, -3); - // Funktion als permanent registrieren, damit sie beim Persistieren ignoriert wird. + // Function is being permanently registed, so persistence can be ignored lua_pushstring(L, "__gc"); lua_gettable(L, -2); RegisterPermanent(L, ClassName + ".__gc"); - // Metatable vom Lua-Stack nehmen + // Remove the metatable from the stack lua_pop(L, 1); #ifdef DEBUG @@ -246,22 +266,21 @@ bool BS_LuaBindhelper::SetClassGCHandler(lua_State * L, const std::string & Clas return true; } +} // End of namespace Sword25 + // ----------------------------------------------------------------------------- -namespace -{ - void PushMetatableTable(lua_State * L) - { - // Tabelle mit den Metatabellen auf den Stack legen. +namespace { + void PushMetatableTable(::lua_State *L) { + // Push the Metatable table onto the stack lua_getglobal(L, METATABLES_TABLE_NAME); - // Wenn die Tabelle noch nicht existiert, muss sie erstellt werden. - if (lua_isnil(L, -1)) - { - // nil vom Stack poppen. + // If the table doesn't yet exist, it must be created + if (lua_isnil(L, -1)) { + // Pop nil from stack lua_pop(L, 1); - // Neue Tabelle erstellen, in die globale Table eintragen und eine Referenz auf dem Stack lassen. + // New table has been created, so add it to the global table and leave reference on stack lua_newtable(L); lua_pushvalue(L, -1); lua_setglobal(L, METATABLES_TABLE_NAME); @@ -269,36 +288,35 @@ namespace } } +namespace Sword25 { -bool BS_LuaBindhelper::GetMetatable(lua_State * L, const std::string & TableName) -{ - // Tabelle mit den Metatabellen auf den Stack legen. +bool BS_LuaBindhelper::GetMetatable(::lua_State *L, const Common::String &TableName) { + // Push the Metatable table onto the stack PushMetatableTable(L); // Versuchen, die gewünschte Metatabelle auf den Stack zu legen. Wenn sie noch nicht existiert, muss sie erstellt werden. lua_getfield(L, -1, TableName.c_str()); - if (lua_isnil(L, -1)) - { - // nil vom Stack poppen. + if (lua_isnil(L, -1)) { + // Pop nil from stack lua_pop(L, 1); - // Neue Tabelle erstellen. + // Create new table lua_newtable(L); - // Das __index Feld der Metatabele zeigt auf die Metatabelle selbst. + // Set the __index field in the table lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); - // Persistfeld auf true setzen. Dies sorgt dafür, dass Objekte mit dieser Metatabelle direkt gespeichert werden. + // Flag the table as persisted. This ensures that objects within this table get stored lua_pushbooleancpp(L, true); lua_setfield(L, -2, "__persist"); - // Metatabelle in die Tabelle für Metatabellen eintragen und eine Referenz auf dem Stack lassen. + // Set the table name and push it onto the stack lua_pushvalue(L, -1); lua_setfield(L, -3, TableName.c_str()); } - // Tabelle mit den Metatabellen vom Stack nehmen. + // Remove the Metatable table from the stack lua_remove(L, -2); return true; @@ -306,49 +324,41 @@ bool BS_LuaBindhelper::GetMetatable(lua_State * L, const std::string & TableName // ----------------------------------------------------------------------------- -bool BS_LuaBindhelper::_CreateTable(lua_State * L, const std::string & TableName) -{ - // Der Tabellenname wird an den Punkten auseinandergetrennt und jeweils die Untertabellen erstellt. - // Auf diese Weise können auch Tabellen mit Untertabellen erstellt werden (z.B. Foo.Bar). - std::string::size_type PartBegin = 0; - while (PartBegin <= TableName.size()) - { - std::string::size_type PartEnd; - PartEnd = TableName.find(".", PartBegin); - if (PartEnd == std::string::npos) PartEnd = TableName.size(); - std::string SubTableName = TableName.substr(PartBegin, PartEnd - PartBegin); - - // Tabellen mit einen leeren String als Namen sind nicht zulässig. +bool BS_LuaBindhelper::_CreateTable(::lua_State *L, const Common::String &TableName) { + const char *PartBegin = TableName.c_str(); + + while (PartBegin) { + const char *PartEnd = strchr(PartBegin, '.'); + if (!PartEnd) PartEnd = PartBegin + strlen(PartBegin); + Common::String SubTableName(PartBegin, PartEnd - PartBegin); + + // Tables with an empty string as the name are not allowed if (SubTableName.size() == 0) return false; - // Überprüfen, ob die Tabelle mit dem Namen bereits existiert. - // Beim ersten Durchgang wird im globalen Namensbereich gesucht, bei späteren Durchgängen in der entsprechenden Elterntabelle auf dem Stack. - if (PartBegin == 0) - { + // Verify that the table with the name already exists + // The first round will be searched in the global namespace, with later passages + // in the corresponding parent table in the stack + if (PartBegin == 0) { lua_pushstring(L, SubTableName.c_str()); lua_gettable(L, LUA_GLOBALSINDEX); - } - else - { + } else { lua_pushstring(L, SubTableName.c_str()); lua_gettable(L, -2); if (!lua_isnil(L, -1)) lua_remove(L, -2); } - // Wenn nicht, Table erstellen - if (lua_isnil(L, -1)) - { - // nil-Wert vom Stack holen + // If it doesn't exist, create table + if (lua_isnil(L, -1)) { + // Pop nil from stack lua_pop(L, 1); - // Neue Tabelle erstellen + // Create new table lua_newtable(L); lua_pushstring(L, SubTableName.c_str()); lua_pushvalue(L, -2); if (PartBegin == 0) lua_settable(L, LUA_GLOBALSINDEX); - else - { + else { lua_settable(L, -4); lua_remove(L, -2); } @@ -360,12 +370,11 @@ bool BS_LuaBindhelper::_CreateTable(lua_State * L, const std::string & TableName return true; } -namespace -{ - std::string GetLuaValueInfo(lua_State * L, int StackIndex) - { - switch (lua_type(L, StackIndex)) - { +} // End of namespace Sword25 + +namespace { + Common::String GetLuaValueInfo(::lua_State *L, int StackIndex) { + switch (lua_type(L, StackIndex)) { case LUA_TNUMBER: lua_pushstring(L, lua_tostring(L, StackIndex)); break; @@ -387,48 +396,48 @@ namespace break; } - std::string Result(lua_tostring(L, -1)); + Common::String Result(lua_tostring(L, -1)); lua_pop(L, 1); return Result; } } -std::string BS_LuaBindhelper::StackDump(lua_State *L) -{ - std::ostringstream oss; +namespace Sword25 { + +Common::String BS_LuaBindhelper::StackDump(::lua_State *L) { + Common::String oss; int i = lua_gettop(L); - oss << "------------------- Stack Dump -------------------\n"; + oss += "------------------- Stack Dump -------------------\n"; - while(i) - { - oss << i << ": " << GetLuaValueInfo(L, i) << "\n"; + while (i) { + oss += i + ": " + GetLuaValueInfo(L, i) + "\n"; i--; } - oss << "-------------- Stack Dump Finished ---------------\n"; + oss += "-------------- Stack Dump Finished ---------------\n"; - return oss.str(); + return oss; } -std::string BS_LuaBindhelper::TableDump(lua_State * L) -{ - std::ostringstream oss; +Common::String BS_LuaBindhelper::TableDump(::lua_State *L) { + Common::String oss; - oss << "------------------- Table Dump -------------------\n"; + oss += "------------------- Table Dump -------------------\n"; lua_pushnil(L); - while (lua_next(L, -2) != 0) - { - // Der Wert des aktuellen Elementes liegt oben auf dem Stack, darunter der Index. - oss << GetLuaValueInfo(L, -2) << " : " << GetLuaValueInfo(L, -1) << "\n"; + while (lua_next(L, -2) != 0) { + // Get the value of the current element on top of the stack, including the index + oss += GetLuaValueInfo(L, -2) + " : " + GetLuaValueInfo(L, -1) + "\n"; - // Wert vom Stack poppen. Der Index liegt dann oben für den nächsten Aufruf von lua_next(). + // Pop value from the stack. The index is then ready for the next call to lua_next() lua_pop(L, 1); } - oss << "-------------- Table Dump Finished ---------------\n"; + oss += "-------------- Table Dump Finished ---------------\n"; - return oss.str(); + return oss; } + +} // End of namespace Sword25 diff --git a/engines/sword25/script/luabindhelper.h b/engines/sword25/script/luabindhelper.h index 0891cb4938..ecc52fd417 100644 --- a/engines/sword25/script/luabindhelper.h +++ b/engines/sword25/script/luabindhelper.h @@ -37,86 +37,90 @@ #include "sword25/kernel/common.h" +namespace { + extern "C" { #include "sword25/util/lua/lua.h" #include "sword25/util/lua/lauxlib.h" } +} + +namespace Sword25 { + #define lua_pushbooleancpp(L, b) (lua_pushboolean(L, b ? 1 : 0)) #define lua_tobooleancpp(L, i) (lua_toboolean(L, i) == 0 ? false : true) -struct lua_constant_reg -{ +struct lua_constant_reg { const char * Name; lua_Number Value; }; -class BS_LuaBindhelper -{ +class BS_LuaBindhelper { public: /** - @brief Registriert eine Menge von Funktionen und fügt dieser einer Lua-Library hinzu. - @param L ein Pointer auf die Lua-VM in der die Funktionen registriert werden sollen - @param LibName der Name der Library.<br> - Wenn dies ein Leerer String ist, werden die Funktionen zum globalen Namensraum hinzugefügt. - @param Functions ein Array das die Funktionspointer mit ihren Namen enthält.<br> - Das Array muss mit dem Eintrag {0, 0} terminiert sein. - @return Gibt true bei Erfolg zurück, ansonsten false. - */ - static bool AddFunctionsToLib(lua_State * L, const Common::String & LibName, const luaL_reg * Functions); + * Registers a set of functions into a Lua library. + * @param L A pointer to the Lua VM + * @param LibName The name of the library. + * If this is an empty string, the functions will be added to the global namespace. + * @param Functions An array of function pointers along with their names. + * The array must be terminated with the enry (0, 0) + * @return Returns true if successful, otherwise false. + */ + static bool AddFunctionsToLib(::lua_State *L, const Common::String &LibName, const luaL_reg *Functions); /** - @brief Fügt eine Menge von Konstanten einer Lua-Library hinzu. - @param L ein Pointer auf die Lua-VM in der die Konstanten registriert werden sollen - @param LibName der Name der Library.<br> - Wenn dies ein Leerer String ist, werden die Konstanten zum globalen Namensraum hinzugefügt. - @param Constants ein Array das die Werte der Konstanten mit ihren Namen enthält.<br - Das Array muss mit dem Eintrag {0, 0} terminiert sein. - @return Gibt true bei Erfolg zurück, ansonsten false. - */ - static bool AddConstantsToLib(lua_State * L, const Common::String & LibName, const lua_constant_reg * Constants); + * Adds a set of constants to the Lua library + * @param L A pointer to the Lua VM + * @param LibName The name of the library. + * If this is an empty string, the functions will be added to the global namespace. + * @param Constants An array of the constant values along with their names. + * The array must be terminated with the enry (0, 0) + * @return Returns true if successful, otherwise false. + */ + static bool AddConstantsToLib(::lua_State * L, const Common::String & LibName, const lua_constant_reg * Constants); /** - @brief Fügt eine Menge von Methoden zu einer Lua-Klasse hinzu. - @param L ein Pointer auf die Lua-VM in der die Methoden registriert werden sollen - @param ClassName der Name der Metatable der Klasse.<br> - Wenn die Metatable noch nicht existiert, wird sie erstellt. - @param Methods ein Array das die Funktionspointer der Methoden mit ihren Namen enthält.<br> - Das Array muss mit dem Eintrag {0, 0} terminiert sein. - @return Gibt true bei Erfolg zurück, ansonsten false. - */ - static bool AddMethodsToClass(lua_State *L, const Common::String &ClassName, const luaL_reg *Methods); + * Adds a set of methods to a Lua class + * @param L A pointer to the Lua VM + * @param ClassName The name of the class + * When the class name specified does not exist, it is created. + * @param Methods An array of function pointers along with their method names. + * The array must be terminated with the enry (0, 0) + * @return Returns true if successful, otherwise false. + */ + static bool AddMethodsToClass(::lua_State *L, const Common::String &ClassName, const luaL_reg *Methods); /** - @brief Legt eine Funktion fest, die aufgerufen wird, wenn Exemplare einer bestimmten Lua-Klasse vom Garbage-Collecter gelöscht werden. - @param L ein Pointer auf die Lua-VM - @param ClassName der Name der Metatable der Klasse.<br> - Wenn die Metatable noch nicht existiert, wird sie erstellt. - @param GCHandler ein Funktionspointer auf die Funktion. - @return Gibt true bei Erfolg zurück, ansonsten false. - */ - static bool SetClassGCHandler(lua_State *L, const Common::String &ClassName, lua_CFunction GCHandler); + * Sets the garbage collector callback method when items of a particular class are deleted + * @param L A pointer to the Lua VM + * @param ClassName The name of the class + * When the class name specified does not exist, it is created. + * @param GCHandler A function pointer + * @return Returns true if successful, otherwise false. + */ + static bool SetClassGCHandler(::lua_State *L, const Common::String &ClassName, lua_CFunction GCHandler); /** - @brief Gibt einen String zurück, der einen Stackdump des Lua-Stacks enthält. - - @param L ein Pointer auf die Lua-VM. - */ - static Common::String StackDump(lua_State *L); + * Returns a string containing a stack dump of the Lua stack + * @param L A pointer to the Lua VM + */ + static Common::String StackDump(::lua_State *L); /** - @brief Gibt einen String zurück, den den Inhalt einer Tabelle beschreibt. + * Returns a string that describes the contents of a table + * @param L A pointer to the Lua VM + * @remark The table must be on the Lua stack to be read out. + */ + static Common::String TableDump(::lua_State *L); - @param L ein Pointer auf die Lua-VM. - @remark Auf dem Lua-Stack muss die Tabelle liegen, die ausgelesen werden soll. - */ - static Common::String TableDump(lua_State *L); - - static bool GetMetatable(lua_State *L, const Common::String &TableName); + static bool GetMetatable(::lua_State *L, const Common::String &TableName); private: - static bool _CreateTable(lua_State *L, const Common::String &TableName); + static bool _CreateTable(::lua_State *L, const Common::String &TableName); }; +} // End of namespace Sword25 + #endif diff --git a/engines/sword25/script/luacallback.cpp b/engines/sword25/script/luacallback.cpp index 88413f13f2..7fbbc1457a 100644 --- a/engines/sword25/script/luacallback.cpp +++ b/engines/sword25/script/luacallback.cpp @@ -39,93 +39,87 @@ #include "sword25/script/luacallback.h" #include "sword25/script/luabindhelper.h" +namespace { + extern "C" { #include "sword25/util/lua/lua.h" #include "sword25/util/lua/lauxlib.h" } -#define BS_LOG_PREFIX "LUA" +const char * CALLBACKTABLE_NAME = "__CALLBACKS"; + +} // ----------------------------------------------------------------------------- -namespace -{ - const char * CALLBACKTABLE_NAME = "__CALLBACKS"; -} +namespace Sword25 { + +#define BS_LOG_PREFIX "LUA" // ----------------------------------------------------------------------------- -BS_LuaCallback::BS_LuaCallback(lua_State * L) -{ - // Callbacktabelle erstellen. +BS_LuaCallback::BS_LuaCallback(::lua_State *L) { + // Create callback table lua_newtable(L); lua_setglobal(L, CALLBACKTABLE_NAME); } // ----------------------------------------------------------------------------- -BS_LuaCallback::~BS_LuaCallback() -{ +BS_LuaCallback::~BS_LuaCallback() { } // ----------------------------------------------------------------------------- -void BS_LuaCallback::RegisterCallbackFunction(lua_State * L, unsigned int ObjectHandle) -{ +void BS_LuaCallback::RegisterCallbackFunction(::lua_State *L, unsigned int ObjectHandle) { BS_ASSERT(lua_isfunction(L, -1)); EnsureObjectCallbackTableExists(L, ObjectHandle); - // Funktion in der Objekt-Callbacktabelle speichern. + // Store function in the callback object table store lua_pushvalue(L, -2); luaL_ref(L, -2); - // Funktion und Objekt-Callbacktabelle vom Stack poppen. + // Pop the function and object callback table from the stack lua_pop(L, 2); } // ----------------------------------------------------------------------------- -void BS_LuaCallback::UnregisterCallbackFunction(lua_State * L, unsigned int ObjectHandle) -{ +void BS_LuaCallback::UnregisterCallbackFunction(::lua_State *L, unsigned int ObjectHandle) { BS_ASSERT(lua_isfunction(L, -1)); EnsureObjectCallbackTableExists(L,ObjectHandle); - // Über alle Elemente der Objekt-Callbacktabelle iterieren und die Funktion daraus entfernen. + // Iterate over all elements of the object callback table and remove the function from it lua_pushnil(L); - while (lua_next(L, -2) != 0) - { - // Der Wert des aktuellen Elementes liegt oben auf dem Stack, darunter der Index. + while (lua_next(L, -2) != 0) { + // The value of the current element is the top of the stack, including the index - // Falls der Wert identisch mit dem Funktionsparameter ist, wird sie aus der Tabelle entfernt. - if (lua_equal(L, -1, -4)) - { + // If the value is identical to the function parameters, it is removed from the table + if (lua_equal(L, -1, -4)) { lua_pushvalue(L, -2); lua_pushnil(L); lua_settable(L, -5); - // Die Funktion wurde gefunden, die Iteration kann abgebrochen werden. + // The function was found, iteration can be stopped lua_pop(L, 2); break; - } - else - { - // Wert vom Stack poppen. Der Index liegt dann oben für den nächsten Aufruf von lua_next(). + } else { + // Pop value from the stack. The index is then ready for the next call to lua_next() lua_pop(L, 1); } } - // Funktion und Objekt-Callbacktabelle vom Stack poppen. + // Function and object table are popped from the stack lua_pop(L, 2); } // ----------------------------------------------------------------------------- -void BS_LuaCallback::RemoveAllObjectCallbacks(lua_State * L, unsigned int ObjectHandle) -{ +void BS_LuaCallback::RemoveAllObjectCallbacks(::lua_State *L, unsigned int ObjectHandle) { PushCallbackTable(L); - // Objekt-Callbacktabelle aus der Callbacktabelle entfernen. + // Remove the object callback from the callback table lua_pushnumber(L, ObjectHandle); lua_pushnil(L); lua_settable(L, -3); @@ -135,37 +129,34 @@ void BS_LuaCallback::RemoveAllObjectCallbacks(lua_State * L, unsigned int Object // ----------------------------------------------------------------------------- -void BS_LuaCallback::InvokeCallbackFunctions(lua_State * L, unsigned int ObjectHandle) -{ +void BS_LuaCallback::InvokeCallbackFunctions(::lua_State *L, unsigned int ObjectHandle) { EnsureObjectCallbackTableExists(L, ObjectHandle); - // Über die Tabelle iterieren und alle Callbacks ausführen. + // Iterate through the table and perform all the callbacks lua_pushnil(L); - while (lua_next(L, -2) != 0) - { - // Der Wert des aktuellen Elementes liegt oben auf dem Stack, darunter der Index. + while (lua_next(L, -2) != 0) { + // The value of the current element is at the top of the stack, including the index - // Falls der Wert eine Funktion ist, wird sie ausgeführt. + // If the value is a function, execute it if (lua_type(L, -1) == LUA_TFUNCTION) { - // Pre-Funktion aufrufen. - // Abgeleitete Klassen könnten in dieser Funktion Parameter auf den Stack schieben. - // Der Rückgabewert gibt die Anzahl der Parameter zurück. + // Pre-Function Call + // Derived classes can function in this parameter onto the stack. + // The return value indicates the number of parameters int ArgumentCount = PreFunctionInvokation(L); - // lua_pcall poppt die Funktion und die Parameter selber vom Stack. - if (lua_pcall(L, ArgumentCount, 0, 0) != 0) - { - // Ein Fehler ist aufgetreten. + // Lua_pcall the function and the parameters pop themselves from the stack + if (lua_pcall(L, ArgumentCount, 0, 0) != 0) { + // An error has occurred BS_LOG_ERRORLN("An error occured executing a callback function: %s", lua_tostring(L, -1)); - // Fehlernachricht vom Stack poppen. + // Pop error message from the stack lua_pop(L, 1); } } else { - // Wert vom Stack poppen. Der Index liegt dann oben für den nächsten Aufruf von lua_next(). + // Pop value from the stack. The index is then ready for the next call to lua_next() lua_pop(L, 1); } } @@ -173,46 +164,44 @@ void BS_LuaCallback::InvokeCallbackFunctions(lua_State * L, unsigned int ObjectH // ----------------------------------------------------------------------------- -void BS_LuaCallback::EnsureObjectCallbackTableExists(lua_State * L, unsigned int ObjectHandle) -{ +void BS_LuaCallback::EnsureObjectCallbackTableExists(::lua_State *L, unsigned int ObjectHandle) { PushObjectCallbackTable(L, ObjectHandle); - // Falls die Tabelle nil ist, muss sie zunächst erstellt werden. - if (lua_isnil(L, -1)) - { - // Nil vom Stack poppen. + // If the table is nil, it must first be created + if (lua_isnil(L, -1)) { + // Pop nil from stack lua_pop(L, 1); PushCallbackTable(L); - // Neue Tabelle unter dem Index ObjectHandle in der Callbacktabelle ablegen. + // Create the table, and put the ObjectHandle into it lua_newtable(L); lua_pushnumber(L, ObjectHandle); lua_pushvalue(L, -2); lua_settable(L, -4); - // Callbacktabelle vom Stack entfernen, Objekt-Callbacktabelle aber dort lassen. + // Pop the callback table from the stack lua_remove(L, -2); } } // ----------------------------------------------------------------------------- -void BS_LuaCallback::PushCallbackTable(lua_State * L) -{ +void BS_LuaCallback::PushCallbackTable(::lua_State *L) { lua_getglobal(L, CALLBACKTABLE_NAME); } // ----------------------------------------------------------------------------- -void BS_LuaCallback::PushObjectCallbackTable(lua_State * L, unsigned int ObjectHandle) -{ +void BS_LuaCallback::PushObjectCallbackTable(::lua_State *L, unsigned int ObjectHandle) { PushCallbackTable(L); - // Objekt-Callbacktabelle auf den Stack legen. + // Push Object Callback table onto the stack lua_pushnumber(L, ObjectHandle); lua_gettable(L, -2); - // Callbacktabelle vom Stack entfernen, Objekt-Callbacktabelle aber dort lassen. + // Pop the callback table from the stack lua_remove(L, -2); } + +} // End of namespace Sword25 diff --git a/engines/sword25/script/luacallback.h b/engines/sword25/script/luacallback.h index 96eeadca24..6a5b43be8a 100644 --- a/engines/sword25/script/luacallback.h +++ b/engines/sword25/script/luacallback.h @@ -42,38 +42,45 @@ #include "sword25/kernel/common.h" // ----------------------------------------------------------------------------- -// Forward Deklarationen +// Forward Declarations // ----------------------------------------------------------------------------- +namespace { + struct lua_State; +} + +namespace Sword25 { + // ----------------------------------------------------------------------------- -// Klassendeklaration +// Class definitions // ----------------------------------------------------------------------------- -class BS_LuaCallback -{ +class BS_LuaCallback { public: - BS_LuaCallback(lua_State * L); + BS_LuaCallback(::lua_State * L); virtual ~BS_LuaCallback(); // Funktion muss auf dem Lua-Stack liegen. - void RegisterCallbackFunction(lua_State * L, unsigned int ObjectHandle); + void RegisterCallbackFunction(::lua_State *L, unsigned int ObjectHandle); // Funktion muss auf dem Lua-Stack liegen. - void UnregisterCallbackFunction(lua_State * L, unsigned int ObjectHandle); + void UnregisterCallbackFunction(::lua_State *L, unsigned int ObjectHandle); - void RemoveAllObjectCallbacks(lua_State * L, unsigned int ObjectHandle); + void RemoveAllObjectCallbacks(::lua_State *L, unsigned int ObjectHandle); - void InvokeCallbackFunctions(lua_State * L, unsigned int ObjectHandle); + void InvokeCallbackFunctions(::lua_State *L, unsigned int ObjectHandle); protected: - virtual int PreFunctionInvokation(lua_State * L) { return 0; } + virtual int PreFunctionInvokation(::lua_State *L) { return 0; } private: - void EnsureObjectCallbackTableExists(lua_State * L,unsigned int ObjectHandle); - void PushCallbackTable(lua_State * L); - void PushObjectCallbackTable(lua_State * L, unsigned int ObjectHandle); + void EnsureObjectCallbackTableExists(::lua_State *L,unsigned int ObjectHandle); + void PushCallbackTable(::lua_State *L); + void PushObjectCallbackTable(::lua_State *L, unsigned int ObjectHandle); }; +} // End of namespace Sword25 + #endif diff --git a/engines/sword25/script/luascript.cpp b/engines/sword25/script/luascript.cpp index a497151776..22d2a28072 100644 --- a/engines/sword25/script/luascript.cpp +++ b/engines/sword25/script/luascript.cpp @@ -38,6 +38,8 @@ // Includes // ----------------------------------------------------------------------------- +//namespace { + extern "C" { #include "sword25/util/lua/lua.h" @@ -46,6 +48,8 @@ extern "C" #include "sword25/util/pluto/pluto.h" } +//} + #include "sword25/package/packagemanager.h" #include "sword25/script/luascript.h" #include "sword25/script/luabindhelper.h" @@ -53,41 +57,35 @@ extern "C" #include "sword25/kernel/outputpersistenceblock.h" #include "sword25/kernel/inputpersistenceblock.h" -#include "sword25/kernel/memlog_off.h" -#include <vector> -#include "sword25/kernel/memlog_on.h" +namespace Sword25 { using namespace std; // ----------------------------------------------------------------------------- -// Konstruktion / Destruktion +// Constructor / Destructor // ----------------------------------------------------------------------------- -BS_LuaScriptEngine::BS_LuaScriptEngine(BS_Kernel * KernelPtr) : +BS_LuaScriptEngine::BS_LuaScriptEngine(BS_Kernel *KernelPtr) : BS_ScriptEngine(KernelPtr), m_State(0), - m_PcallErrorhandlerRegistryIndex(0) -{ + m_PcallErrorhandlerRegistryIndex(0) { } // ----------------------------------------------------------------------------- -BS_LuaScriptEngine::~BS_LuaScriptEngine() -{ - // Lua deinitialisieren +BS_LuaScriptEngine::~BS_LuaScriptEngine() { + // Lua de-initialisation if (m_State) lua_close(m_State); } // ----------------------------------------------------------------------------- -BS_Service * BS_LuaScriptEngine_CreateObject(BS_Kernel * KernelPtr) { return new BS_LuaScriptEngine(KernelPtr); } +BS_Service *BS_LuaScriptEngine_CreateObject(BS_Kernel * KernelPtr) { return new BS_LuaScriptEngine(KernelPtr); } // ----------------------------------------------------------------------------- -namespace -{ - int PanicCB(lua_State * L) - { +namespace { + int PanicCB(::lua_State *L) { BS_LOG_ERRORLN("Lua panic. Error message: %s", lua_isnil(L, -1) ? "" : lua_tostring(L, -1)); return 0; } @@ -95,50 +93,46 @@ namespace // ----------------------------------------------------------------------------- -bool BS_LuaScriptEngine::Init() -{ - // Lua-State intialisieren und Standardbibliotheken initialisieren +bool BS_LuaScriptEngine::Init() { + // Lua-State initialisation, as well as standard libaries initialisation m_State = luaL_newstate(); - if (!m_State || ! RegisterStandardLibs() || !RegisterStandardLibExtensions()) - { + if (!m_State || ! RegisterStandardLibs() || !RegisterStandardLibExtensions()) { BS_LOG_ERRORLN("Lua could not be initialized."); return false; } - // Panic-Callbackfunktion registrieren. + // Register panic callback function lua_atpanic(m_State, PanicCB); - // Errorhandlerfunktion für lua_pcall-Aufrufe. - // Der untenstehende Code enthält eine lokale ErrorHandler-Funktion und gibt diese zurück. + // Error handler for lua_pcall calls + // The code below contains a local error handler function const char ErrorHandlerCode[] = "local function ErrorHandler(message) " " return message .. '\\n' .. debug.traceback('', 2) " "end " "return ErrorHandler"; - // Den Code compilieren. - if (luaL_loadbuffer(m_State, ErrorHandlerCode, strlen(ErrorHandlerCode), "PCALL ERRORHANDLER") != 0) - { - // Fehlernachricht ausgeben und Methode beenden. + // Compile the code + if (luaL_loadbuffer(m_State, ErrorHandlerCode, strlen(ErrorHandlerCode), "PCALL ERRORHANDLER") != 0) { + // An error occurred, so dislay the reason and exit BS_LOG_ERRORLN("Couldn't compile luaL_pcall errorhandler:\n%s", lua_tostring(m_State, -1)); lua_pop(m_State, 1); return false; } - // Den Code ausführen, dies legt die Errorhandler-Funktion oben auf den Stack. - if (lua_pcall(m_State, 0, 1, 0) != 0) - { - // Fehlernachricht ausgeben und Methode beenden. + // Running the code, the error handler function sets the top of the stack + if (lua_pcall(m_State, 0, 1, 0) != 0) { + // An error occurred, so dislay the reason and exit BS_LOG_ERRORLN("Couldn't prepare luaL_pcall errorhandler:\n%s", lua_tostring(m_State, -1)); lua_pop(m_State, 1); return false; } - // Die Errorhandler-Funktion in der Lua-Registry ablegen und den Index merken. + // Place the error handler function in the Lua registry, and remember the index m_PcallErrorhandlerRegistryIndex = luaL_ref(m_State, LUA_REGISTRYINDEX); - // Die Pluto Persistenz-Bibliothek initialisieren. + // Initialise the Pluto-Persistence library luaopen_pluto(m_State); lua_pop(m_State, 1); @@ -149,21 +143,19 @@ bool BS_LuaScriptEngine::Init() // ----------------------------------------------------------------------------- -bool BS_LuaScriptEngine::ExecuteFile(const std::string & FileName) -{ +bool BS_LuaScriptEngine::ExecuteFile(const Common::String &FileName) { #ifdef DEBUG int __startStackDepth = lua_gettop(m_State); #endif - // Pointer auf den Packagemanager holen - BS_PackageManager * pPackage = static_cast<BS_PackageManager *>(BS_Kernel::GetInstance()->GetService("package")); + // Get a pointer to the package manager + BS_PackageManager *pPackage = static_cast<BS_PackageManager *>(BS_Kernel::GetInstance()->GetService("package")); BS_ASSERT(pPackage); - // Datei einlesen + // File read unsigned int FileSize; - char * FileData = static_cast<char *>(pPackage->GetFile(FileName, &FileSize)); - if (!FileData) - { + char *FileData = static_cast<char *>(pPackage->GetFile(FileName, &FileSize)); + if (!FileData) { BS_LOG_ERRORLN("Couldn't read \"%s\".", FileName.c_str()); #ifdef DEBUG BS_ASSERT(__startStackDepth == lua_gettop(m_State)); @@ -171,10 +163,9 @@ bool BS_LuaScriptEngine::ExecuteFile(const std::string & FileName) return false; } - // Dateiinhalt ausführen - if (!ExecuteBuffer(FileData, FileSize, "@" + pPackage->GetAbsolutePath(FileName))) - { - // Dateipuffer freigeben + // Run the file content + if (!ExecuteBuffer(FileData, FileSize, "@" + pPackage->GetAbsolutePath(FileName))) { + // Release file buffer delete[] FileData; #ifdef DEBUG BS_ASSERT(__startStackDepth == lua_gettop(m_State)); @@ -182,7 +173,7 @@ bool BS_LuaScriptEngine::ExecuteFile(const std::string & FileName) return false; } - // Dateipuffer freigeben + // Release file buffer delete[] FileData; #ifdef DEBUG @@ -194,26 +185,22 @@ bool BS_LuaScriptEngine::ExecuteFile(const std::string & FileName) // ----------------------------------------------------------------------------- -bool BS_LuaScriptEngine::ExecuteString(const std::string & Code) -{ - return ExecuteBuffer(Code.c_str(), Code.length(), "???"); +bool BS_LuaScriptEngine::ExecuteString(const Common::String &Code) { + return ExecuteBuffer(Code.c_str(), Code.size(), "???"); } // ----------------------------------------------------------------------------- -namespace -{ - void RemoveForbiddenFunctions(lua_State * L) - { - static const char * FORBIDDEN_FUNCTIONS[] = - { +namespace { + + void RemoveForbiddenFunctions(::lua_State *L) { + static const char *FORBIDDEN_FUNCTIONS[] = { "dofile", 0 }; const char ** Iterator = FORBIDDEN_FUNCTIONS; - while (*Iterator) - { + while (*Iterator) { lua_pushnil(L); lua_setfield(L, LUA_GLOBALSINDEX, *Iterator); ++Iterator; @@ -221,8 +208,7 @@ namespace } } -bool BS_LuaScriptEngine::RegisterStandardLibs() -{ +bool BS_LuaScriptEngine::RegisterStandardLibs() { luaL_openlibs(m_State); RemoveForbiddenFunctions(m_State); return true; @@ -230,24 +216,21 @@ bool BS_LuaScriptEngine::RegisterStandardLibs() // ----------------------------------------------------------------------------- -bool BS_LuaScriptEngine::ExecuteBuffer(const char * Data, unsigned int Size, const std::string & Name) const -{ - // Puffer kompilieren - if (luaL_loadbuffer(m_State, Data, Size, Name.c_str()) != 0) - { +bool BS_LuaScriptEngine::ExecuteBuffer(const char *Data, unsigned int Size, const Common::String &Name) const { + // Compile buffer + if (luaL_loadbuffer(m_State, Data, Size, Name.c_str()) != 0) { BS_LOG_ERRORLN("Couldn't compile \"%s\":\n%s", Name.c_str(), lua_tostring(m_State, -1)); lua_pop(m_State, 1); return false; } - // Error-Handler Funktion hinter der auszuführenden Funktion auf den Stack legen. + // Error handling function to be executed after the function is put on the stack lua_rawgeti(m_State, LUA_REGISTRYINDEX, m_PcallErrorhandlerRegistryIndex); lua_insert(m_State, -2); - // Pufferinhalt ausführen - if (lua_pcall(m_State, 0, 0, -2) != 0) - { + // Run buffer contents + if (lua_pcall(m_State, 0, 0, -2) != 0) { BS_LOG_ERRORLN("An error occured while executing \"%s\":\n%s.", Name.c_str(), lua_tostring(m_State, -1)); @@ -256,7 +239,7 @@ bool BS_LuaScriptEngine::ExecuteBuffer(const char * Data, unsigned int Size, con return false; } - // Error-Handler Funktion vom Stack nehmen. + // Remove the error handler function from the stack lua_pop(m_State, 1); return true; @@ -264,12 +247,10 @@ bool BS_LuaScriptEngine::ExecuteBuffer(const char * Data, unsigned int Size, con // ----------------------------------------------------------------------------- -void BS_LuaScriptEngine::SetCommandLine(const vector<string> & CommandLineParameters) -{ +void BS_LuaScriptEngine::SetCommandLine(const Common::StringArray &CommandLineParameters) { lua_newtable(m_State); - for (size_t i = 0; i < CommandLineParameters.size(); ++i) - { + for (size_t i = 0; i < CommandLineParameters.size(); ++i) { lua_pushnumber(m_State, i + 1); lua_pushstring(m_State, CommandLineParameters[i].c_str()); lua_settable(m_State, -3); @@ -280,15 +261,13 @@ void BS_LuaScriptEngine::SetCommandLine(const vector<string> & CommandLineParame // ----------------------------------------------------------------------------- -namespace -{ - const char * PERMANENTS_TABLE_NAME = "Permanents"; +namespace { + const char *PERMANENTS_TABLE_NAME = "Permanents"; // ------------------------------------------------------------------------- - // Diese Array enthält die Namen der globalen Lua-Objekte, die nicht persistiert werden sollen. - const char * STANDARD_PERMANENTS[] = - { + // This array contains the name of global Lua objects that should not be persisted + const char *STANDARD_PERMANENTS[] = { "string", "xpcall", "package", @@ -340,93 +319,87 @@ namespace // ------------------------------------------------------------------------- - enum PERMANENT_TABLE_TYPE - { + enum PERMANENT_TABLE_TYPE { PTT_PERSIST, PTT_UNPERSIST }; // ------------------------------------------------------------------------- - bool PushPermanentsTable(lua_State * L, PERMANENT_TABLE_TYPE TableType) - { - // Permanents-Tabelle erstellen. + bool PushPermanentsTable(::lua_State *L, PERMANENT_TABLE_TYPE TableType) { + // Permanents-Table lua_newtable(L); - // Alle Standard-Permanents in die Tabelle einfügen. + // All standard permanents are inserted into this table unsigned int Index = 0; - while (STANDARD_PERMANENTS[Index]) - { - // Permanent auf den Stack legen, falls es nicht existiert, wird es einfach ignoriert. + while (STANDARD_PERMANENTS[Index]) { + // Permanents are placed onto the stack; if it does not exist, it is simply ignored lua_getglobal(L, STANDARD_PERMANENTS[Index]); - if (!lua_isnil(L, -1)) - { - // Namen des Elementes als einzigartigen Wert auf den Stack legen. + if (!lua_isnil(L, -1)) { + // Name of the element as a unique value on the stack lua_pushstring(L, STANDARD_PERMANENTS[Index]); - // Falls geladen wird, ist der Name der Index und das Objekt der Wert. - // In diesem Fall müssen also die Position von Name und Objekt auf dem Stack vertauscht werden. + // If it is loaded, then it can be used + // In this case, the position of name and object are reversed on the stack if (TableType == PTT_UNPERSIST) lua_insert(L, -2); - // Eintrag in der Tabelle vornehmen. + // Make an entry in the table lua_settable(L, -3); } - else - { - // nil von Stack poppen. + else { + // Pop nil value from stack lua_pop(L, 1); } ++Index; } - // Alle Registrierten C-Funktionen in die Tabelle einfügen. - // BS_LuaBindhelper legt in der Registry eine Tabelle an, in der alle registrierten C-Funktionen gespeichert werden. + // All registered C functions to be inserted into the table + // BS_LuaBindhelper places in the register a table in which all registered C functions + // are stored - // Tabelle mit den C-Permanents auf den Stack legen. + // Table is put on the stack lua_getfield(L, LUA_REGISTRYINDEX, PERMANENTS_TABLE_NAME); - if (!lua_isnil(L, -1)) - { - // Über alle Elemente der Tabelle iterieren. + if (!lua_isnil(L, -1)) { + // Iterate over all elements of the table lua_pushnil(L); - while (lua_next(L, -2) != 0) - { - // Wert und Index auf dem Stack duplizieren und in der Reihenfolge vertauschen. + while (lua_next(L, -2) != 0) { + // Value and index duplicated on the stack and changed in the sequence lua_pushvalue(L, -1); lua_pushvalue(L, -3); - // Falls geladen wird, ist der Name der Index und das Objekt der Wert. - // In diesem Fall müssen also die Position von Name und Objekt auf dem Stack vertauscht werden. + // If it is loaded, then it can be used + // In this case, the position of name and object are reversed on the stack if (TableType == PTT_UNPERSIST) lua_insert(L, -2); - // Eintrag in der Ergebnistabelle vornehmen. + // Make an entry in the results table lua_settable(L, -6); - // Wert vom Stack poppen. Der Index liegt dann oben für den nächsten Aufruf von lua_next(). + // Pop value from the stack. The index is then ready for the next call to lua_next() lua_pop(L, 1); } } - // Tabelle mit den C-Permanents vom Stack poppen. + // Pop the C-Permanents table from the stack lua_pop(L, 1); - // coroutine.yield muss extra in die Permanents-Tabelle eingetragen werden, da inaktive Coroutinen diese C-Funktion auf dem Stack liegen - // haben. + // coroutine.yield must be registered in the extra-Permanents table because they + // are inactive coroutine C functions on the stack - // Funktion coroutine.yield auf den Stack legen. + // Function coroutine.yield placed on the stack lua_getglobal(L, "coroutine"); lua_pushstring(L, "yield"); lua_gettable(L, -2); - // coroutine.yield mit eigenem eindeutigen Wert in der Permanents-Tabelle ablegen. + // Store coroutine.yield with it's own unique value in the Permanents table lua_pushstring(L, "coroutine.yield"); if (TableType == PTT_UNPERSIST) lua_insert(L, -2); lua_settable(L, -4); - // Tabelle coroutine vom Stack poppen. + // Coroutine table is popped from the stack lua_pop(L, 1); return true; @@ -435,33 +408,30 @@ namespace // ----------------------------------------------------------------------------- -namespace -{ - int Chunkwriter(lua_State *L, const void* p, size_t sz, void* ud) - { +namespace { + int Chunkwriter(::lua_State *L, const void *p, size_t sz, void *ud) { vector<unsigned char> & chunkData = *reinterpret_cast<vector<unsigned char> * >(ud); - const unsigned char * buffer = reinterpret_cast<const unsigned char *>(p); + const unsigned char *buffer = reinterpret_cast<const unsigned char *>(p); - while (sz--) chunkData.push_back(*buffer++); + while (sz--) chunkData.push_back(*buffer++) ; return 1; } } -bool BS_LuaScriptEngine::Persist(BS_OutputPersistenceBlock & Writer) -{ - // Den Lua-Stack leeren. pluto_persist() erwartet, dass der Stack bis aus seine Parameter leer ist. +bool BS_LuaScriptEngine::Persist(BS_OutputPersistenceBlock &Writer) { + // Empty the Lua stack. pluto_persist() xepects that the stack is empty except for its parameters lua_settop(m_State, 0); // Garbage Collection erzwingen. lua_gc(m_State, LUA_GCCOLLECT, 0); - // Permanents-Tabelle und die zu persistierende Tabelle auf den Stack legen. - // pluto_persist erwartet diese beiden Objekte auf dem Lua-Stack. + // Permanents-Table is set on the stack + // pluto_persist expects these two items on the Lua stack PushPermanentsTable(m_State, PTT_PERSIST); lua_getglobal(m_State, "_G"); - // Lua persistieren und die Daten in einem vector ablegen. + // Lua persists and stores the data in a vector vector<unsigned char> chunkData; pluto_persist(m_State, Chunkwriter, &chunkData); @@ -476,114 +446,104 @@ bool BS_LuaScriptEngine::Persist(BS_OutputPersistenceBlock & Writer) // ----------------------------------------------------------------------------- -namespace -{ +namespace { // ------------------------------------------------------------------------- - struct ChunkreaderData - { + struct ChunkreaderData { void * BufferPtr; size_t Size; bool BufferReturned; }; - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------ - const char * Chunkreader(lua_State *L, void *ud, size_t *sz) - { + const char *Chunkreader(::lua_State *L, void *ud, size_t *sz) { ChunkreaderData & cd = *reinterpret_cast<ChunkreaderData *>(ud); - if (!cd.BufferReturned) - { + if (!cd.BufferReturned) { cd.BufferReturned = true; *sz = cd.Size; return reinterpret_cast<const char *>(cd.BufferPtr); - } - else - { + } else { return 0; } } // ------------------------------------------------------------------------- - void ClearGlobalTable(lua_State * L, const char ** Exceptions) - { - // Über alle Elemente der globalen Tabelle iterieren. + void ClearGlobalTable(::lua_State *L, const char **Exceptions) { + // Iterate over all elements of the global table lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushnil(L); - while (lua_next(L, -2) != 0) - { - // Jetzt liegen der Wert und der Index des aktuellen Elementes auf dem Stack. - // Der Wert interessiert uns nicht, daher wird er vom Stack gepoppt. + while (lua_next(L, -2) != 0) { + // Now the value and the index of the current element is on the stack + // This value does not interest us, so it is popped from the stack lua_pop(L, 1); - // Feststellen, ob das Element auf nil gesetzt , also aus der globalen Tabelle entfernt werden soll. - // Hierfür wird geprüft, ob das Elementname ein String ist und in der Liste der Ausnahmen vorkommt. + // Determine whether the item is set to nil, so you want to remove from the global table. + // For this will determine whether the element name is a string and is present in + // the list of exceptions bool SetElementToNil = true; - if (lua_isstring(L, -1)) - { - const char * IndexString = lua_tostring(L, -1); + if (lua_isstring(L, -1)) { + const char *IndexString = lua_tostring(L, -1); const char ** ExceptionsWalker = Exceptions; - while (*ExceptionsWalker) - { + while (*ExceptionsWalker) { if (strcmp(IndexString, *ExceptionsWalker) == 0) SetElementToNil = false; ++ExceptionsWalker; } } - // Wenn der obige Test ergeben hat, dass das Element entfernt werden soll, wird es entfernt indem der Wert auf nil gesetzt wird. - if (SetElementToNil) - { + // If the above test showed that the item should be removed, it is removed by setting the value to nil. + if (SetElementToNil) { lua_pushvalue(L, -1); lua_pushnil(L); lua_settable(L, LUA_GLOBALSINDEX); } } - // Globale Tabelle vom Stack nehmen. + // Pop the Global table from the stack lua_pop(L, 1); - // Garbage-Collection vornehmen, damit die entfernten Elemente alle gelöscht werden. + // Perform garbage collection, so that all removed elements are deleted lua_gc(L, LUA_GCCOLLECT, 0); } } // ----------------------------------------------------------------------------- -bool BS_LuaScriptEngine::Unpersist(BS_InputPersistenceBlock & Reader) -{ - // Den Lua-Stack leeren. pluto_unpersist() erwartet, dass der Stack bis aus seine Parameter leer ist. +bool BS_LuaScriptEngine::Unpersist(BS_InputPersistenceBlock &Reader) { + // Empty the Lua stack. pluto_persist() xepects that the stack is empty except for its parameters lua_settop(m_State, 0); - // Permanents Tabelle auf den Stack legen. Dies passiert schon an dieser Stelle, da zum Erstellen der Tabelle alle Permanents zugreifbar sein - // müssen. Dies ist nur am Anfang dieser Funktion der Fall, im Folgenden wird die globale Tabelle geleert. + // Permanents table is placed on the stack. This has already happened at this point, because + // to create the table all permanents must be accessible. This is the case only for the + // beginning of the function, because the global table is emptied below PushPermanentsTable(m_State, PTT_UNPERSIST); - // Alle Elemente aus der globalen Tabelle mit Ausnhame von _G und __METATABLES entfernen. - // Danach wird eine Garbage Collection durchgeführt und somit alle von Lua verwalteten Objekte gelöscht. - // __METATABLES wird zunächst nicht entfernt, da die Metatables für die Finalizer der Objekte benötigt werden. - static const char * ClearExceptionsFirstPass[] = - { + // All items from global table of _G and __METATABLES are removed. + // After a garbage collection is performed, and thus all managed objects deleted + + // __METATABLES is not immediately removed becausen the Metatables are needed + // for the finalisers of objects. + static const char *ClearExceptionsFirstPass[] = { "_G", "__METATABLES", 0 }; ClearGlobalTable(m_State, ClearExceptionsFirstPass); - // Im zweiten Durchgang werden auch die Metatables entfernt. - static const char * ClearExceptionsSecondPass[] = - { + // In the second pass, the Metatables are removed + static const char *ClearExceptionsSecondPass[] = { "_G", 0 }; ClearGlobalTable(m_State, ClearExceptionsSecondPass); - // Persistierte Lua-Daten einlesen. + // Persisted Lua data vector<unsigned char> chunkData; Reader.Read(chunkData); - // Chunk-Reader initialisieren. Er wird von pluto_unpersist benutzt um die benötigten Daten einzulesen. + // Chunk-Reader initialisation. It is used with pluto_unpersist to restore read data ChunkreaderData cd; cd.BufferPtr = &chunkData[0]; cd.Size = chunkData.size(); @@ -591,32 +551,32 @@ bool BS_LuaScriptEngine::Unpersist(BS_InputPersistenceBlock & Reader) pluto_unpersist(m_State, Chunkreader, &cd); - // Permanents-Tabelle vom Stack nehmen. + // Permanents-Table is removed from stack lua_remove(m_State, -2); - // Die eingelesenen Elemente in die globale Tabelle eintragen. + // The read elements in the global table about lua_pushnil(m_State); - while (lua_next(m_State, -2) != 0) - { - // Die Referenz auf die globale Tabelle (_G) darf nicht überschrieben werden, sonst tickt Lua total aus. + while (lua_next(m_State, -2) != 0) { + // The referenec to the global table (_G) must not be overwritten, or ticks from Lua total bool IsGlobalReference = lua_isstring(m_State, -2) && strcmp(lua_tostring(m_State, -2), "_G") == 0; - if (!IsGlobalReference) - { + if (!IsGlobalReference) { lua_pushvalue(m_State, -2); lua_pushvalue(m_State, -2); lua_settable(m_State, LUA_GLOBALSINDEX); } - // Wert vom Stack poppen. Der Index liegt dann oben für den nächsten Aufruf von lua_next(). + // Pop value from the stack. The index is then ready for the next call to lua_next() lua_pop(m_State, 1); } - // Tabelle mit den geladenen Daten vom Stack poppen. + // The table with the loaded data is popped from the stack lua_pop(m_State, 1); - // Garbage Collection erzwingen. + // Force garbage collection lua_gc(m_State, LUA_GCCOLLECT, 0); return true; } + +} // End of namespace Sword25 diff --git a/engines/sword25/script/luascript.h b/engines/sword25/script/luascript.h index 214d728d07..4d216be413 100644 --- a/engines/sword25/script/luascript.h +++ b/engines/sword25/script/luascript.h @@ -39,6 +39,8 @@ // Includes // ----------------------------------------------------------------------------- +#include "common/str.h" +#include "common/str-array.h" #include "sword25/kernel/common.h" #include "sword25/script/script.h" @@ -46,72 +48,81 @@ // Forward declarations // ----------------------------------------------------------------------------- -class BS_Kernel; +namespace { + struct lua_State; +} + +namespace Sword25 { + +class BS_Kernel; + // ----------------------------------------------------------------------------- // Class declaration // ----------------------------------------------------------------------------- -class BS_LuaScriptEngine : public BS_ScriptEngine -{ +class BS_LuaScriptEngine : public BS_ScriptEngine { public: // ----------------------------------------------------------------------------- - // Konstruktion / Destruktion + // Constructor / Destructor // ----------------------------------------------------------------------------- - BS_LuaScriptEngine(BS_Kernel * KernelPtr); + BS_LuaScriptEngine(BS_Kernel *KernelPtr); virtual ~BS_LuaScriptEngine(); /** - @brief Initialisiert die Scriptengine. - @return Gibt true bei Erfolg zurück, ansonsten false. + * Initialises the scripting engine + * @return Returns true if successful, otherwise false. */ virtual bool Init(); /** - @brief Lädt eine Skriptdatei und führt diese aus. - @param FileName der Dateiname der Skriptdatei - @return Gibt true bei Erfolg zurück, ansonsten false. - */ - virtual bool ExecuteFile(const std::string & FileName); + * Loads a script file and executes it + * @param FileName The filename of the script + * @return Returns true if successful, otherwise false. + */ + virtual bool ExecuteFile(const Common::String &FileName); /** - @brief Führt einen String mit Skriptcode aus. - @param Code ein String der Skriptcode enthält. - @return Gibt true bei Erfolg zurück, ansonsten false. - */ - virtual bool ExecuteString(const std::string & Code); + * Execute a string of script code + * @param Code A string of script code + * @return Returns true if successful, otherwise false. + */ + virtual bool ExecuteString(const Common::String &Code); /** - @brief Gibt einen Pointer auf das Hauptobjekt der Skriptsprache zurück. - @remark Durch die Benutzung dieser Methode wird die Kapselung der Sprache aufgehoben. - */ - virtual void * GetScriptObject() { return m_State; } + * Returns a pointer to the main object of the scripting language + * @remark Using this method breaks the encapsulation of the language + */ + virtual void *GetScriptObject() { return m_State; } /** - @brief Macht die Kommandozeilen-Parameter für die Skriptumgebung zugänglich. - @param CommandLineParameters ein string vector der alle Kommandozeilenparameter enthält. - @remark Auf welche Weise die Kommandozeilen-Parameter durch Skripte zugegriffen werden können hängt von der jeweiligen Implementierung ab. - */ - virtual void SetCommandLine(const std::vector<std::string> & CommandLineParameters); + * Makes the command line parameters for the scripting environment available + * @param CommandLineParameters An array containing all the command line parameters + * @remark How the command line parameters will be used by scripts is + * dependant on the particular implementation. + */ + virtual void SetCommandLine(const Common::StringArray &CommandLineParameters); /** - @remark Der Lua-Stack wird durch diese Methode geleert. - */ - virtual bool Persist(BS_OutputPersistenceBlock & Writer); + * @remark The Lua stack is cleared by this method + */ + virtual bool Persist(BS_OutputPersistenceBlock &Writer); /** - @remark Der Lua-Stack wird durch diese Methode geleert. - */ - virtual bool Unpersist(BS_InputPersistenceBlock & Reader); + * @remark The Lua stack is cleared by this method + */ + virtual bool Unpersist(BS_InputPersistenceBlock &Reader); private: - lua_State * m_State; + ::lua_State *m_State; int m_PcallErrorhandlerRegistryIndex; bool RegisterStandardLibs(); bool RegisterStandardLibExtensions(); - bool ExecuteBuffer(const char * Data, unsigned int Size, const std::string & Name) const; + bool ExecuteBuffer(const char *Data, unsigned int Size, const Common::String &Name) const; }; +} // End of namespace Sword25 + #endif |