diff --git a/src/script/ScriptUtils.cpp b/src/script/ScriptUtils.cpp index 6cd551bff3..903e4b8896 100644 --- a/src/script/ScriptUtils.cpp +++ b/src/script/ScriptUtils.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "game/Entity.h" #include "graphics/data/Mesh.h" @@ -54,7 +55,22 @@ Context::Context(const EERIE_SCRIPT * script, size_t pos, Entity * sender, Entit , m_entity(entity) , m_message(msg) , m_parameters(std::move(parameters)) -{ } +{ + updateNewLinesList(); +} + +void Context::updateNewLinesList() { + size_t posNL = 0; + while(true) { + posNL = m_script->data.find('\n', posNL); + if(posNL == std::string::npos) { + break; + }else{ + m_vNewLineAt.push_back(posNL); + posNL++; + } + } +} std::string Context::getStringVar(std::string_view name) const { @@ -125,6 +141,72 @@ std::string Context::getCommand(bool skipNewlines) { return word; } +std::string Context::getPositionAndLineNumber(bool compact, size_t pos) const { + std::stringstream s; + + if(pos == static_cast(-1)) { + pos = m_pos; + } + + s << "(" << (compact ? "p=" : "Position ") << pos; + + size_t iLine, iColumn; + getLineColumn(iLine, iColumn, pos); + + s << (compact ? ",l=" : ", Line ") << iLine << (compact ? ",c=" : ", Column ") << iColumn << ")"; + return s.str(); +} + +void Context::getLineColumn(size_t & iLine, size_t & iColumn, size_t pos) const { + if(pos == static_cast(-1)) { + pos = m_pos; + } + + iLine = 0; + iColumn = 1; + for(size_t i = 0; i < m_vNewLineAt.size(); i++) { + if(pos > m_vNewLineAt[i]) { + iLine = i + 1; + iColumn = pos - m_vNewLineAt[i]; + iLine++; + iColumn--; + } else { + break; + } + } +} + +size_t Context::getGoSubCallFromPos(size_t indexFromLast) const { + if(m_stackIdCalledFromPos.size() == 0) { + return static_cast(-1); // means invalid + } + + if(indexFromLast >= m_stackIdCalledFromPos.size()) { + indexFromLast = m_stackIdCalledFromPos.size() - 1; + } + + return m_stackIdCalledFromPos[m_stackIdCalledFromPos.size() - indexFromLast - 1].first; +} + +std::string Context::getGoSubCallStack(std::string_view prepend, std::string_view append, std::string_view between) const { + std::stringstream ss; + + if(m_stackIdCalledFromPos.size() > 0) { + ss << prepend; + + size_t index = 0; + for(auto pair : m_stackIdCalledFromPos) { + if(index >= 1) ss << between; + ss << pair.second << getPositionAndLineNumber(true, m_stackIdCalledFromPos[index].first); + index++; + } + + ss << append; + } + + return ss.str(); +} + std::string Context::getWord() { std::string_view esdat = m_script->data; @@ -342,7 +424,7 @@ size_t Context::skipCommand() { bool Context::jumpToLabel(std::string_view target, bool substack) { if(substack) { - m_stack.push_back(m_pos); + m_stackIdCalledFromPos.push_back(std::make_pair(m_pos, std::string() += target)); } size_t targetpos = FindScriptPos(m_script, std::string(">>") += target); @@ -356,12 +438,13 @@ bool Context::jumpToLabel(std::string_view target, bool substack) { bool Context::returnToCaller() { - if(m_stack.empty()) { + if(m_stackIdCalledFromPos.empty()) { return false; } - m_pos = m_stack.back(); - m_stack.pop_back(); + m_pos = m_stackIdCalledFromPos.back().first; + m_stackIdCalledFromPos.pop_back(); + return true; } diff --git a/src/script/ScriptUtils.h b/src/script/ScriptUtils.h index 7c2d77aae8..32ed6c1c8d 100644 --- a/src/script/ScriptUtils.h +++ b/src/script/ScriptUtils.h @@ -89,7 +89,8 @@ class Context { Entity * m_entity; ScriptMessage m_message; ScriptParameters m_parameters; - std::vector m_stack; + std::vector> m_stackIdCalledFromPos; + std::vector m_vNewLineAt; public: @@ -104,6 +105,7 @@ class Context { std::string getCommand(bool skipNewlines = true); void skipWhitespace(bool skipNewlines = false, bool warnNewlines = false); + void updateNewLinesList(); Entity * getSender() const { return m_sender; } Entity * getEntity() const { return m_entity; } @@ -130,7 +132,11 @@ class Context { const EERIE_SCRIPT * getScript() const { return m_script; } size_t getPosition() const { return m_pos; } + void getLineColumn(size_t & iLine, size_t & iColumn, size_t pos = static_cast(-1)) const; + std::string getPositionAndLineNumber(bool compact = false, size_t pos = static_cast(-1)) const; + size_t getGoSubCallFromPos(size_t indexFromLast) const; + std::string getGoSubCallStack(std::string_view prepend, std::string_view append, std::string_view between = " -> ") const; }; @@ -181,7 +187,7 @@ bool isBlockEndSuprressed(const Context & context, std::string_view command); size_t initSuppressions(); -#define ScriptContextPrefix(context) '[' << ((context).getEntity() ? (((context).getScript() == &(context).getEntity()->script) ? (context).getEntity()->className() : (context).getEntity()->idString()) : "unknown") << ':' << (context).getPosition() << "] " +#define ScriptContextPrefix(context) '[' << ((context).getEntity() ? (((context).getScript() == &(context).getEntity()->script) ? (context).getEntity()->className() : (context).getEntity()->idString()) : "unknown") << ':' << (context).getPositionAndLineNumber() << (context).getGoSubCallStack(" (CallStack:", ")") << "] " #define ScriptPrefix ScriptContextPrefix(context) << getName() << #define DebugScript(args) LogDebug(ScriptPrefix args) #define ScriptInfo(args) LogInfo << ScriptPrefix args diff --git a/src/script/ScriptedInterface.cpp b/src/script/ScriptedInterface.cpp index 60349c261a..084e1b0118 100644 --- a/src/script/ScriptedInterface.cpp +++ b/src/script/ScriptedInterface.cpp @@ -202,6 +202,30 @@ std::ostream & operator<<(std::ostream & os, const PrintLocalVariables & data) { return os; } +static std::string getEventAndStackInfo(Context & context) { + std::stringstream s; + + if(context.getMessage() < SM_MAXCMD) { + s << " at Event " << ScriptEvent::name(context.getMessage()); + } + + if(context.getSender()) { + s << " sent from " << context.getSender()->idString(); + } + + if(context.getParameters().size() > 0) { + s << " with parameters ("; + for(std::string s2 : context.getParameters()) { + s << s2 << " "; + } + s << ")"; + } + + s << context.getGoSubCallStack(" at GoSub callStack ", ", " + context.getPositionAndLineNumber()); + + return s.str(); +} + class ShowLocalsCommand : public Command { public: @@ -212,8 +236,8 @@ class ShowLocalsCommand : public Command { DebugScript(""); - LogInfo << "Local variables for " << context.getEntity()->idString() << ":\n" - << PrintLocalVariables(context.getEntity()); + LogInfo << "Local variables for " << context.getEntity()->idString() << getEventAndStackInfo(context) << ":\n" + << PrintLocalVariables(context.getEntity()); return Success; } @@ -230,8 +254,8 @@ class ShowVarsCommand : public Command { DebugScript(""); - LogInfo << "Local variables for " << context.getEntity()->idString() << ":\n" - << PrintLocalVariables(context.getEntity()); + LogInfo << "Local variables for " << context.getEntity()->idString() << getEventAndStackInfo(context) << ":\n" + << PrintLocalVariables(context.getEntity()); LogInfo << "Global variables:\n" << PrintGlobalVariables(); return Success;