Index: code/trunk/src/libraries/core/LuaState.cc
===================================================================
--- code/trunk/src/libraries/core/LuaState.cc	(revision 6417)
+++ code/trunk/src/libraries/core/LuaState.cc	(revision 6746)
@@ -37,4 +37,7 @@
 
 #include "util/Debug.h"
+#include "util/Exception.h"
+#include "util/ScopeGuard.h"
+#include "IOConsole.h"
 #include "Resource.h"
 #include "ToluaBindCore.h"
@@ -54,4 +57,5 @@
         // Create new lua state and configure it
         luaState_ = lua_open();
+        Loki::ScopeGuard luaStateGuard = Loki::MakeGuard(&lua_close, luaState_);
 #if LUA_VERSION_NUM == 501
         luaL_openlibs(luaState_);
@@ -78,5 +82,8 @@
 
         // Parse init script
-        this->doFile("LuaStateInit.lua");
+        if (!this->doFile("LuaStateInit.lua"))
+            ThrowException(InitialisationFailed, "Running LuaStateInit.lua failed");
+
+        luaStateGuard.Dismiss();
     }
 
@@ -96,14 +103,17 @@
     }
 
-    void LuaState::includeFile(const std::string& filename)
+    bool LuaState::includeFile(const std::string& filename)
     {
         shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
         if (sourceInfo != NULL)
-            this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
-        else
-            COUT(2) << "LuaState: Cannot include file '" << filename << "'." << std::endl;
-    }
-
-    void LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
+            return this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
+        else
+        {
+            COUT(2) << "LuaState: Cannot include file '" << filename << "' (not found)." << std::endl;
+            return false;
+        }
+    }
+
+    bool LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
     {
         // Parse string with provided include parser (otherwise don't preparse at all)
@@ -114,17 +124,36 @@
             luaInput = code;
 
-        this->doString(luaInput, sourceFileInfo);
-    }
-
-    void LuaState::doFile(const std::string& filename)
+        if (sourceFileInfo != NULL)
+        {
+            // Also fill a map with the actual source code. This is just for the include* commands
+            // where the content of sourceFileInfo->filename doesn't match 'code'
+            this->sourceCodeMap_[sourceFileInfo->filename] = code;
+        }
+
+        bool returnValue = this->doString(luaInput, sourceFileInfo);
+
+        if (sourceFileInfo != NULL)
+        {
+            // Delete source code entry
+            if (sourceFileInfo != NULL)
+                this->sourceCodeMap_.erase(sourceFileInfo->filename);
+        }
+
+        return returnValue;
+    }
+
+    bool LuaState::doFile(const std::string& filename)
     {
         shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
         if (sourceInfo != NULL)
-            this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
-        else
-            COUT(2) << "LuaState: Cannot do file '" << filename << "'." << std::endl;
-    }
-
-    void LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
+            return this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
+        else
+        {
+            COUT(2) << "LuaState: Cannot do file '" << filename << "' (not found)." << std::endl;
+            return false;
+        }
+    }
+
+    bool LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
     {
         // Save the old source file info
@@ -134,31 +163,91 @@
             sourceFileInfo_ = sourceFileInfo;
 
-        int error = 0;
+        std::string chunkname;
+        if (sourceFileInfo != NULL)
+        {
+            // Provide lua_load with the filename for debug purposes
+            // The '@' is a Lua convention to identify the chunk name as filename
+            chunkname = '@' + sourceFileInfo->filename;
+        }
+        else
+        {
+            // Use the code string to identify the chunk
+            chunkname = code;
+        }
+
+        // Push custom error handler that uses the debugger
+        lua_getglobal(this->luaState_, "errorHandler");
+        int errorHandler = lua_gettop(luaState_);
+        if (lua_isnil(this->luaState_, -1))
+        {
+            lua_pop(this->luaState_, 1);
+            errorHandler = 0;
+        }
+
 #if LUA_VERSION_NUM != 501
         LoadS ls;
         ls.s = code.c_str();
         ls.size = code.size();
-        error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());
+        int error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, chunkname.c_str());
 #else
-        error = luaL_loadstring(luaState_, code.c_str());
+        int error = luaL_loadbuffer(luaState_, code.c_str(), code.size(), chunkname.c_str());
 #endif
 
-        // execute the chunk
+        switch (error)
+        {
+        case LUA_ERRSYNTAX: // Syntax error
+            COUT(1) << "Lua syntax error: " << lua_tostring(luaState_, -1) << std::endl;
+            break;
+        case LUA_ERRMEM:    // Memory allocation error
+            COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl;
+            break;
+        }
+
         if (error == 0)
-            error = lua_pcall(luaState_, 0, 1, 0);
+        {
+            // Execute the chunk in protected mode with an error handler function (stack index)
+            error = lua_pcall(luaState_, 0, 1, errorHandler);
+
+            switch (error)
+            {
+            case LUA_ERRRUN: // Runtime error
+                if (errorHandler)
+                {
+                    // Do nothing (we already display the error in the
+                    // 'errorHandler' Lua function in LuaStateInit.lua)
+                }
+                else
+                {
+                    std::string errorString = lua_tostring(this->luaState_, -1);
+                    if (errorString.find("Error propagation") == std::string::npos)
+                        COUT(1) << "Lua runtime error: " << errorString << std::endl;
+                }
+                break;
+            case LUA_ERRERR: // Error in the error handler
+                COUT(1) << "Lua error in error handler. No message available." << std::endl;
+                break;
+            case LUA_ERRMEM: // Memory allocation error
+                COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl;
+                break;
+            }
+        }
+
         if (error != 0)
         {
-            std::string origin;
-            if (sourceFileInfo != NULL)
-                origin = " originating from " + sourceFileInfo_->filename;
-            COUT(1) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl;
-            // return value is nil
-            lua_pushnil(luaState_);
-        }
-        // push return value because it will get lost since the return value of this function is void
+            lua_pop(luaState_, 1);  // Remove error message
+            lua_pushnil(luaState_); // Push a nil return value
+        }
+
+        if (errorHandler != 0)
+            lua_remove(luaState_, errorHandler); // Remove error handler from stack
+
+        // Set return value to a global variable because we cannot return a table in this function
+        // here. It would work for numbers, pointers and strings, but certainly not for Lua tables.
         lua_setglobal(luaState_, "LuaStateReturnValue");
 
         // Load the old info again
         sourceFileInfo_ = oldSourceFileInfo;
+
+        return (error == 0);
     }
 
@@ -180,4 +269,24 @@
         else
             return true;
+    }
+
+    //! Returns the content of a file
+    std::string LuaState::getSourceCode(const std::string& filename)
+    {
+        // Try the internal map first to get the actual Lua code
+        // and not just some pseudo Lua-XML code when using include* commands
+        std::map<std::string, std::string>::const_iterator it = this->sourceCodeMap_.find(filename);
+        if (it != this->sourceCodeMap_.end())
+            return it->second;
+        shared_ptr<ResourceInfo> info = Resource::getInfo(filename);
+        if (info == NULL)
+            return "";
+        else
+            return Resource::open(info)->getAsString();
+    }
+
+    bool LuaState::usingIOConsole() const
+    {
+        return IOConsole::exists();
     }
 
