[Orxonox-commit 5602] r10264 - code/trunk/src/libraries/core

muemart at orxonox.net muemart at orxonox.net
Wed Feb 11 10:56:26 CET 2015


Author: muemart
Date: 2015-02-11 10:56:26 +0100 (Wed, 11 Feb 2015)
New Revision: 10264

Modified:
   code/trunk/src/libraries/core/Loader.cc
   code/trunk/src/libraries/core/LuaState.cc
   code/trunk/src/libraries/core/LuaState.h
Log:
Various fixes and improvements in the Loader (and LuaState)
- When there's lua code in the xml, the error message now says where exactly the error is coming from (file and line)
- When there's an error in the loader when reading xml, the full xml file gets dumped to the temporary directory for inspection
- Fix and simplify detection of lua tags
- Make sure the reported line in an xml parsing error is useful

Modified: code/trunk/src/libraries/core/Loader.cc
===================================================================
--- code/trunk/src/libraries/core/Loader.cc	2015-02-10 22:10:39 UTC (rev 10263)
+++ code/trunk/src/libraries/core/Loader.cc	2015-02-11 09:56:26 UTC (rev 10264)
@@ -31,6 +31,8 @@
 #include <sstream>
 #include <tinyxml/ticpp.h>
 #include <boost/scoped_ptr.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
 
 #include "util/Output.h"
 #include "util/Exception.h"
@@ -156,10 +158,16 @@
         Loader::currentMask_s = file->getMask() * mask;
 
         std::string xmlInput;
+
+        shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> lineTrace(new std::vector<std::vector<std::pair<std::string, size_t>>>());
+        lineTrace->reserve(1000); //arbitrary number
+
+
         if (file->getLuaSupport() && !bRemoveLuaTags)
         {
             // Use the LuaState to replace the XML tags (calls our function)
             scoped_ptr<LuaState> luaState(new LuaState());
+            luaState->setTraceMap(lineTrace);
             luaState->setIncludeParser(&Loader::replaceLuaTags);
             luaState->includeFile(file->getFilename());
             xmlInput = luaState->getOutput().str();
@@ -230,7 +238,27 @@
             orxout(user_error, context::loader) << "An XML-error occurred in Loader.cc while loading " << file->getFilename() << ':' << endl;
             orxout(user_error, context::loader) << ex.what() << endl;
             orxout(user_error, context::loader) << "Loading aborted." << endl;
-            return false;
+            if (lineTrace->size() > 0)
+            {
+                //Extract the line number from the exception
+                std::string tempstring(ex.what());
+                std::string::size_type pos = tempstring.find("\nLine: ");
+                if (pos != std::string::npos)
+                {
+                    std::istringstream istr(tempstring.substr(pos + 7));
+                    size_t line;
+                    istr >> line;
+                    if (line <= lineTrace->size())
+                    {
+                        std::vector<std::pair<std::string, size_t>> linesources = lineTrace->at(line - 1);
+                        orxout(user_error, context::loader) << "Line contains data from:" << endl;
+                        for (std::vector<std::pair<std::string, size_t>>::iterator it = linesources.begin(); it != linesources.end(); ++it)
+                        {
+                            orxout(user_error, context::loader) << it->first << " , Line " << it->second << endl;
+                        }                        
+                    }
+                }
+            }
         }
         catch (Exception& ex)
         {
@@ -238,7 +266,6 @@
             orxout(user_error, context::loader) << "A loading-error occurred in Loader.cc while loading " << file->getFilename() << ':' << endl;
             orxout(user_error, context::loader) << ex.what() << endl;
             orxout(user_error, context::loader) << "Loading aborted." << endl;
-            return false;
         }
         catch (...)
         {
@@ -246,8 +273,18 @@
             orxout(user_error, context::loader) << "An error occurred in Loader.cc while loading " << file->getFilename() << ':' << endl;
             orxout(user_error, context::loader) << Exception::handleMessage() << endl;
             orxout(user_error, context::loader) << "Loading aborted." << endl;
-            return false;
         }
+        //The Tardis' version of boost is too old...
+#if BOOST_VERSION >= 104600
+        boost::filesystem::path temppath = boost::filesystem::temp_directory_path() / "orxonoxml.xml";
+        //Need binary mode, because xmlInput already has \r\n for windows
+        boost::filesystem::ofstream outfile(temppath, std::ios_base::binary | std::ios_base::out);
+        outfile << xmlInput;
+        outfile.flush();
+        outfile.close();
+        orxout(user_error, context::loader) << "The complete xml file has been saved to " << temppath << endl;
+#endif
+        return false;
     }
 
     void Loader::unload(const XMLFile* file, const ClassTreeMask& mask)
@@ -298,26 +335,16 @@
         // erase all tags from the map that are between two quotes
         {
             std::map<size_t, bool>::iterator it = luaTags.begin();
-            std::map<size_t, bool>::iterator it2 = it;
-            bool bBetweenQuotes = false;
-            size_t pos = 0;
-            while ((pos = getNextQuote(text, pos)) != std::string::npos)
+            while(it != luaTags.end())
             {
-                while ((it != luaTags.end()) && (it->first < pos))
+                if (isBetweenQuotes(text, it->first))
                 {
-                    if (bBetweenQuotes)
-                    {
-                        it2++;
-                        if (it->second && !(it2->second) && it2->first < pos)
-                            it = ++it2;
-                        else
-                            luaTags.erase(it++);
-                    }
-                    else
-                        ++it;
+                    luaTags.erase(it++);
                 }
-                bBetweenQuotes = !bBetweenQuotes;
-                pos++;
+                else
+                {
+                    ++it;
+                }
             }
         }
 
@@ -336,7 +363,7 @@
             }
             if (!expectedValue)
             {
-                orxout(internal_error, context::loader) << "Error in level file" << endl;
+                orxout(internal_error, context::loader) << "Error parsing file: lua tags not matching" << endl;
                 // TODO: error handling
                 return false;
             }
@@ -424,7 +451,9 @@
                     {
                         equalSigns += '=';
                     }
-                    output << "print([" + equalSigns + '[' + temp + ']' + equalSigns +"])";
+                    //A newline directly after square brackets is ignored. To make sure that the string is printed
+                    //exactly as it is, including newlines at the beginning, insert a space after the brackets.
+                    output << "print([" + equalSigns + "[ " + temp + ']' + equalSigns +"])";
                     start = end + 5;
                 }
                 else
@@ -470,7 +499,12 @@
                 start = end + 5;
             }
             else
+            {
+                //Preserve the amount of lines, otherwise the linenumber from the xml parse error is useless
+                std::string tempstring = text.substr(start, end - start);
+                output << std::string(std::count(tempstring.begin(), tempstring.end(), '\n'), '\n');
                 start = end + 2;
+            }
 
             bLuaCode = !bLuaCode;
         }

Modified: code/trunk/src/libraries/core/LuaState.cc
===================================================================
--- code/trunk/src/libraries/core/LuaState.cc	2015-02-10 22:10:39 UTC (rev 10263)
+++ code/trunk/src/libraries/core/LuaState.cc	2015-02-11 09:56:26 UTC (rev 10264)
@@ -232,6 +232,38 @@
 
     void LuaState::luaPrint(const std::string& str)
     {
+        if (lineTrace_)
+        {
+            //Get lua debug info of second level in stack (level 1 is function print in LuaStateInit.lua)
+            lua_Debug ar;
+            lua_getstack(luaState_, 2, &ar);
+            lua_getinfo(luaState_, "nSl", &ar);
+            int line = ar.currentline;
+            std::string filename(ar.short_src);
+
+            //Add first line, which always exists
+            //Note: due to newlines etc., it's possible that one line consists of parts of
+            //      multiple, different files
+            std::vector<std::vector<std::pair<std::string, size_t>>>::reverse_iterator it = lineTrace_->rbegin();
+            std::pair<std::string, size_t> temppair = std::make_pair(filename, line);
+            //Avoid duplicate entries. This could happen if there were lua blocks on the same line
+            if (it->size() == 0 || std::find(it->begin(), it->end(), temppair) == it->end())
+            {
+                it->push_back(temppair);
+            }
+
+            //Add the rest of the lines, if there are any. Empty or not doesn't matter
+            size_t newlinecount = std::count(str.begin(), str.end(), '\n');
+            //i newlines -> i+1 lines, first line already added
+            for (size_t i = 1; i <= newlinecount; i++)
+            {
+                //Add the new line to the trace map
+                lineTrace_->push_back(std::vector<std::pair<std::string, size_t>>());
+                //Add the source of the line at the end
+                lineTrace_->rbegin()->push_back(std::make_pair(filename, line + i));
+            }
+        }
+
         output_ << str;
     }
 

Modified: code/trunk/src/libraries/core/LuaState.h
===================================================================
--- code/trunk/src/libraries/core/LuaState.h	2015-02-10 22:10:39 UTC (rev 10263)
+++ code/trunk/src/libraries/core/LuaState.h	2015-02-11 09:56:26 UTC (rev 10264)
@@ -93,6 +93,9 @@
         const std::stringstream& getOutput() const { return output_; }
         void clearOutput() { output_.clear(); } // tolua_export
 
+        void setTraceMap(shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> map)
+            { map->push_back(std::vector<std::pair<std::string, size_t>>()); lineTrace_ = map; }
+
         void setIncludeParser(std::string (*function)(const std::string&)) { includeParseFunction_ = function; }
         lua_State* getInternalLuaState() { return luaState_; }
 
@@ -112,7 +115,8 @@
 
     private:
         shared_ptr<ResourceInfo> getFileInfo(const std::string& filename);
-
+        shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> lineTrace_;
+        
         std::stringstream output_;
         lua_State* luaState_;
         bool bIsRunning_;




More information about the Orxonox-commit mailing list