Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Feb 11, 2015, 10:56:26 AM (10 years ago)
Author:
muemart
Message:

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
Location:
code/trunk/src/libraries/core
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • code/trunk/src/libraries/core/Loader.cc

    r9667 r10264  
    3232#include <tinyxml/ticpp.h>
    3333#include <boost/scoped_ptr.hpp>
     34#include <boost/filesystem.hpp>
     35#include <boost/filesystem/fstream.hpp>
    3436
    3537#include "util/Output.h"
     
    157159
    158160        std::string xmlInput;
     161
     162        shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> lineTrace(new std::vector<std::vector<std::pair<std::string, size_t>>>());
     163        lineTrace->reserve(1000); //arbitrary number
     164
     165
    159166        if (file->getLuaSupport() && !bRemoveLuaTags)
    160167        {
    161168            // Use the LuaState to replace the XML tags (calls our function)
    162169            scoped_ptr<LuaState> luaState(new LuaState());
     170            luaState->setTraceMap(lineTrace);
    163171            luaState->setIncludeParser(&Loader::replaceLuaTags);
    164172            luaState->includeFile(file->getFilename());
     
    231239            orxout(user_error, context::loader) << ex.what() << endl;
    232240            orxout(user_error, context::loader) << "Loading aborted." << endl;
    233             return false;
     241            if (lineTrace->size() > 0)
     242            {
     243                //Extract the line number from the exception
     244                std::string tempstring(ex.what());
     245                std::string::size_type pos = tempstring.find("\nLine: ");
     246                if (pos != std::string::npos)
     247                {
     248                    std::istringstream istr(tempstring.substr(pos + 7));
     249                    size_t line;
     250                    istr >> line;
     251                    if (line <= lineTrace->size())
     252                    {
     253                        std::vector<std::pair<std::string, size_t>> linesources = lineTrace->at(line - 1);
     254                        orxout(user_error, context::loader) << "Line contains data from:" << endl;
     255                        for (std::vector<std::pair<std::string, size_t>>::iterator it = linesources.begin(); it != linesources.end(); ++it)
     256                        {
     257                            orxout(user_error, context::loader) << it->first << " , Line " << it->second << endl;
     258                        }                       
     259                    }
     260                }
     261            }
    234262        }
    235263        catch (Exception& ex)
     
    239267            orxout(user_error, context::loader) << ex.what() << endl;
    240268            orxout(user_error, context::loader) << "Loading aborted." << endl;
    241             return false;
    242269        }
    243270        catch (...)
     
    247274            orxout(user_error, context::loader) << Exception::handleMessage() << endl;
    248275            orxout(user_error, context::loader) << "Loading aborted." << endl;
    249             return false;
    250         }
     276        }
     277        //The Tardis' version of boost is too old...
     278#if BOOST_VERSION >= 104600
     279        boost::filesystem::path temppath = boost::filesystem::temp_directory_path() / "orxonoxml.xml";
     280        //Need binary mode, because xmlInput already has \r\n for windows
     281        boost::filesystem::ofstream outfile(temppath, std::ios_base::binary | std::ios_base::out);
     282        outfile << xmlInput;
     283        outfile.flush();
     284        outfile.close();
     285        orxout(user_error, context::loader) << "The complete xml file has been saved to " << temppath << endl;
     286#endif
     287        return false;
    251288    }
    252289
     
    299336        {
    300337            std::map<size_t, bool>::iterator it = luaTags.begin();
    301             std::map<size_t, bool>::iterator it2 = it;
    302             bool bBetweenQuotes = false;
    303             size_t pos = 0;
    304             while ((pos = getNextQuote(text, pos)) != std::string::npos)
    305             {
    306                 while ((it != luaTags.end()) && (it->first < pos))
     338            while(it != luaTags.end())
     339            {
     340                if (isBetweenQuotes(text, it->first))
    307341                {
    308                     if (bBetweenQuotes)
    309                     {
    310                         it2++;
    311                         if (it->second && !(it2->second) && it2->first < pos)
    312                             it = ++it2;
    313                         else
    314                             luaTags.erase(it++);
    315                     }
    316                     else
    317                         ++it;
     342                    luaTags.erase(it++);
    318343                }
    319                 bBetweenQuotes = !bBetweenQuotes;
    320                 pos++;
     344                else
     345                {
     346                    ++it;
     347                }
    321348            }
    322349        }
     
    337364            if (!expectedValue)
    338365            {
    339                 orxout(internal_error, context::loader) << "Error in level file" << endl;
     366                orxout(internal_error, context::loader) << "Error parsing file: lua tags not matching" << endl;
    340367                // TODO: error handling
    341368                return false;
     
    425452                        equalSigns += '=';
    426453                    }
    427                     output << "print([" + equalSigns + '[' + temp + ']' + equalSigns +"])";
     454                    //A newline directly after square brackets is ignored. To make sure that the string is printed
     455                    //exactly as it is, including newlines at the beginning, insert a space after the brackets.
     456                    output << "print([" + equalSigns + "[ " + temp + ']' + equalSigns +"])";
    428457                    start = end + 5;
    429458                }
     
    471500            }
    472501            else
     502            {
     503                //Preserve the amount of lines, otherwise the linenumber from the xml parse error is useless
     504                std::string tempstring = text.substr(start, end - start);
     505                output << std::string(std::count(tempstring.begin(), tempstring.end(), '\n'), '\n');
    473506                start = end + 2;
     507            }
    474508
    475509            bLuaCode = !bLuaCode;
  • code/trunk/src/libraries/core/LuaState.cc

    r8858 r10264  
    233233    void LuaState::luaPrint(const std::string& str)
    234234    {
     235        if (lineTrace_)
     236        {
     237            //Get lua debug info of second level in stack (level 1 is function print in LuaStateInit.lua)
     238            lua_Debug ar;
     239            lua_getstack(luaState_, 2, &ar);
     240            lua_getinfo(luaState_, "nSl", &ar);
     241            int line = ar.currentline;
     242            std::string filename(ar.short_src);
     243
     244            //Add first line, which always exists
     245            //Note: due to newlines etc., it's possible that one line consists of parts of
     246            //      multiple, different files
     247            std::vector<std::vector<std::pair<std::string, size_t>>>::reverse_iterator it = lineTrace_->rbegin();
     248            std::pair<std::string, size_t> temppair = std::make_pair(filename, line);
     249            //Avoid duplicate entries. This could happen if there were lua blocks on the same line
     250            if (it->size() == 0 || std::find(it->begin(), it->end(), temppair) == it->end())
     251            {
     252                it->push_back(temppair);
     253            }
     254
     255            //Add the rest of the lines, if there are any. Empty or not doesn't matter
     256            size_t newlinecount = std::count(str.begin(), str.end(), '\n');
     257            //i newlines -> i+1 lines, first line already added
     258            for (size_t i = 1; i <= newlinecount; i++)
     259            {
     260                //Add the new line to the trace map
     261                lineTrace_->push_back(std::vector<std::pair<std::string, size_t>>());
     262                //Add the source of the line at the end
     263                lineTrace_->rbegin()->push_back(std::make_pair(filename, line + i));
     264            }
     265        }
     266
    235267        output_ << str;
    236268    }
  • code/trunk/src/libraries/core/LuaState.h

    r8858 r10264  
    9494        void clearOutput() { output_.clear(); } // tolua_export
    9595
     96        void setTraceMap(shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> map)
     97            { map->push_back(std::vector<std::pair<std::string, size_t>>()); lineTrace_ = map; }
     98
    9699        void setIncludeParser(std::string (*function)(const std::string&)) { includeParseFunction_ = function; }
    97100        lua_State* getInternalLuaState() { return luaState_; }
     
    113116    private:
    114117        shared_ptr<ResourceInfo> getFileInfo(const std::string& filename);
    115 
     118        shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> lineTrace_;
     119       
    116120        std::stringstream output_;
    117121        lua_State* luaState_;
Note: See TracChangeset for help on using the changeset viewer.