[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