diff --git a/src/CBot/CBotProgram.cpp b/src/CBot/CBotProgram.cpp index c55bf06f..4a09eef2 100644 --- a/src/CBot/CBotProgram.cpp +++ b/src/CBot/CBotProgram.cpp @@ -243,13 +243,6 @@ CBotVar* CBotProgram::GetStackVars(std::string& functionName, int level) return m_stack->GetStackVars(functionName, level); } -//////////////////////////////////////////////////////////////////////////////// -void CBotProgram::SetTimer(int n) -{ - CBotStack::SetTimer( n ); -} - -//////////////////////////////////////////////////////////////////////////////// CBotError CBotProgram::GetError() { return m_error; diff --git a/src/CBot/CBotProgram.h b/src/CBot/CBotProgram.h index 1ac41450..41ef6b8b 100644 --- a/src/CBot/CBotProgram.h +++ b/src/CBot/CBotProgram.h @@ -202,14 +202,6 @@ public: */ void Stop(); - /** - * \brief Sets the number of steps (parts of instructions) to execute in Run() before suspending the program execution - * \param n new timer value - * - * FIXME: Seems to be currently kind of broken (see issue #410) - */ - static void SetTimer(int n); - /** * \brief Add a function that can be called from CBot * diff --git a/src/CBot/CBotStack.cpp b/src/CBot/CBotStack.cpp index 25e895d7..7de0670b 100644 --- a/src/CBot/CBotStack.cpp +++ b/src/CBot/CBotStack.cpp @@ -39,16 +39,24 @@ namespace CBot const int DEFAULT_TIMER = 100; -int CBotStack::m_initimer = DEFAULT_TIMER; -int CBotStack::m_timer = 0; -CBotVar* CBotStack::m_retvar = nullptr; -CBotError CBotStack::m_error = CBotNoErr; -int CBotStack::m_start = 0; -int CBotStack::m_end = 0; -std::string CBotStack::m_labelBreak=""; -void* CBotStack::m_pUser = nullptr; +struct CBotStack::Data +{ + int initimer = DEFAULT_TIMER; + int timer = 0; + + CBotError error = CBotNoErr; + int errStart = 0; + int errEnd = 0; + + std::string labelBreak = ""; + + CBotProgram* baseProg = nullptr; + CBotStack* topStack = nullptr; + void* pUser = nullptr; + + std::unique_ptr retvar; +}; -//////////////////////////////////////////////////////////////////////////////// CBotStack* CBotStack::AllocateStack() { CBotStack* p; @@ -73,7 +81,8 @@ CBotStack* CBotStack::AllocateStack() pp ++; } - m_error = CBotNoErr; // avoids deadlocks because m_error is static + p->m_data = new CBotStack::Data; + p->m_data->topStack = p; return p; } @@ -97,6 +106,7 @@ void CBotStack::Delete() CBotStack* p = m_prev; bool bOver = m_bOver; + if ( m_prev == nullptr ) delete m_data; // clears the freed block memset(this, 0, sizeof(CBotStack)); @@ -123,6 +133,7 @@ CBotStack* CBotStack::AddStack(CBotInstr* instr, BlockVisibilityType bBlock) while ( p->m_prev != nullptr ); m_next = p; // chain an element + p->m_data = m_data; p->m_block = bBlock; p->m_instr = instr; p->m_prog = m_prog; @@ -166,6 +177,7 @@ CBotStack* CBotStack::AddStack2(BlockVisibilityType bBlock) while ( p->m_prev != nullptr ); m_next2 = p; // chain an element + p->m_data = m_data; p->m_prev = this; p->m_block = bBlock; p->m_prog = m_prog; @@ -220,18 +232,32 @@ bool CBotStack::ReturnKeep(CBotStack* pfils) bool CBotStack::StackOver() { if (!m_bOver) return false; - m_error = CBotErrStackOver; + m_data->error = CBotErrStackOver; return true; } -//////////////////////////////////////////////////////////////////////////////// +CBotError CBotStack::GetError(int& start, int& end) +{ + start = m_data->errStart; + end = m_data->errEnd; + return m_data->error; +} + +CBotError CBotStack::GetError() +{ + return m_data->error; +} + +bool CBotStack::IsOk() +{ + return m_data->error == CBotNoErr; +} + void CBotStack::Reset() { - m_timer = m_initimer; // resets the timer - m_error = CBotNoErr; -// m_start = 0; -// m_end = 0; - m_labelBreak.clear(); + m_data->timer = m_data->initimer; // resets the timer + m_data->error = CBotNoErr; + m_data->labelBreak.clear(); } //////////////////////////////////////////////////////////////////////////////// @@ -258,35 +284,35 @@ CBotStack* CBotStack::RestoreStackEOX(CBotExternalCall* instr) // routine for execution step by step bool CBotStack::IfStep() { - if ( m_initimer > 0 || m_step++ > 0 ) return false; + if (m_data->initimer > 0 || m_step++ > 0) return false; return true; } //////////////////////////////////////////////////////////////////////////////// bool CBotStack::BreakReturn(CBotStack* pfils, const std::string& name) { - if ( m_error>=0 ) return false; // normal output - if ( m_error==CBotError(-3) ) return false; // normal output (return current) + if (m_data->error >= CBotNoErr) return false; // normal output + if (m_data->error == CBotError(-3)) return false; // normal output (return current) - if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name)) + if (!m_data->labelBreak.empty() && (name.empty() || m_data->labelBreak != name)) return false; // it's not for me - m_error = CBotNoErr; - m_labelBreak.clear(); + m_data->error = CBotNoErr; + m_data->labelBreak.clear(); return Return(pfils); } //////////////////////////////////////////////////////////////////////////////// bool CBotStack::IfContinue(int state, const std::string& name) { - if ( m_error != CBotError(-2) ) return false; + if (m_data->error != CBotError(-2)) return false; - if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name)) + if (!m_data->labelBreak.empty() && (name.empty() || m_data->labelBreak != name)) return false; // it's not for me m_state = state; // where again? - m_error = CBotNoErr; - m_labelBreak.clear(); + m_data->error = CBotNoErr; + m_data->labelBreak.clear(); if (m_next != nullptr) m_next->Delete(); // purge above stack return true; } @@ -294,11 +320,11 @@ bool CBotStack::IfContinue(int state, const std::string& name) //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetBreak(int val, const std::string& name) { - m_error = static_cast(-val); // reacts as an Exception - m_labelBreak = name; + m_data->error = static_cast(-val); // reacts as an Exception + m_data->labelBreak = name; if (val == 3) // for a return { - m_retvar = m_var; + m_data->retvar.reset(m_var); m_var = nullptr; } } @@ -307,12 +333,11 @@ void CBotStack::SetBreak(int val, const std::string& name) //////////////////////////////////////////////////////////////////////////////// bool CBotStack::GetRetVar(bool bRet) { - if (m_error == CBotError(-3)) + if (m_data->error == CBotError(-3)) { if ( m_var ) delete m_var; - m_var = m_retvar; - m_retvar = nullptr; - m_error = CBotNoErr; + m_var = m_data->retvar.release(); + m_data->error = CBotNoErr; return true; } return bRet; // interrupted by something other than return @@ -322,7 +347,7 @@ bool CBotStack::GetRetVar(bool bRet) CBotVar* CBotStack::FindVar(CBotToken*& pToken, bool bUpdate) { CBotStack* p = this; - std::string name = pToken->GetString(); + const auto& name = pToken->GetString(); while (p != nullptr) { @@ -332,7 +357,7 @@ CBotVar* CBotStack::FindVar(CBotToken*& pToken, bool bUpdate) if (pp->GetName() == name) { if ( bUpdate ) - pp->Update(m_pUser); + pp->Update(m_data->pUser); return pp; } @@ -375,7 +400,7 @@ CBotVar* CBotStack::FindVar(long ident, bool bUpdate) if (pp->GetUniqNum() == ident) { if ( bUpdate ) - pp->Update(m_pUser); + pp->Update(m_data->pUser); return pp; } @@ -410,8 +435,8 @@ bool CBotStack::SetState(int n, int limite) { m_state = n; - m_timer--; // decrement the timer - return ( m_timer > limite ); // interrupted if timer pass + m_data->timer--; // decrement the timer + return (m_data->timer > limite); // interrupted if timer pass } //////////////////////////////////////////////////////////////////////////////// @@ -419,46 +444,46 @@ bool CBotStack::IncState(int limite) { m_state++; - m_timer--; // decrement the timer - return ( m_timer > limite ); // interrupted if timer pass + m_data->timer--; // decrement the timer + return (m_data->timer > limite); // interrupted if timer pass } //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetError(CBotError n, CBotToken* token) { - if (n != CBotNoErr && m_error != CBotNoErr) return; // does not change existing error - m_error = n; + if (n != CBotNoErr && m_data->error != CBotNoErr) return; // does not change existing error + m_data->error = n; if (token != nullptr) { - m_start = token->GetStart(); - m_end = token->GetEnd(); + m_data->errStart = token->GetStart(); + m_data->errEnd = token->GetEnd(); } } //////////////////////////////////////////////////////////////////////////////// void CBotStack::ResetError(CBotError n, int start, int end) { - m_error = n; - m_start = start; - m_end = end; + m_data->error = n; + m_data->errStart = start; + m_data->errEnd = end; } //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetPosError(CBotToken* token) { - m_start = token->GetStart(); - m_end = token->GetEnd(); + m_data->errStart = token->GetStart(); + m_data->errEnd = token->GetEnd(); } //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetTimer(int n) { - m_initimer = n; + m_data->initimer = n; } int CBotStack::GetTimer() { - return m_initimer; + return m_data->initimer; } //////////////////////////////////////////////////////////////////////////////// @@ -542,26 +567,25 @@ void CBotStack::SetProgram(CBotProgram* p) { m_prog = p; m_func = IsFunction::YES; + if (this == m_data->topStack) m_data->baseProg = p; } //////////////////////////////////////////////////////////////////////////////// CBotProgram* CBotStack::GetProgram(bool bFirst) { if ( ! bFirst ) return m_prog; - CBotStack* p = this; - while ( p->m_prev != nullptr ) p = p->m_prev; - return p->m_prog; + return m_data->baseProg; } //////////////////////////////////////////////////////////////////////////////// void* CBotStack::GetUserPtr() { - return m_pUser; + return m_data->pUser; } void CBotStack::SetUserPtr(void* user) { - m_pUser = user; + m_data->pUser = user; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CBot/CBotStack.h b/src/CBot/CBotStack.h index 20e8118d..64a81124 100644 --- a/src/CBot/CBotStack.h +++ b/src/CBot/CBotStack.h @@ -82,9 +82,6 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** \name Error management - * - * BE CAREFUL - errors are stored in static variables! - * \todo Refactor that */ //@{ @@ -94,24 +91,21 @@ public: * \param[out] end Ending position in code of the error * \return Error number */ - CBotError GetError(int& start, int& end) { start = m_start; end = m_end; return m_error; } + CBotError GetError(int& start, int& end); /** * \brief Get last error * \return Error number * \see GetError(int&, int&) for error position in code */ - CBotError GetError() { return m_error; } + CBotError GetError(); /** * \brief Check if there was an error * \return false if an error occurred * \see GetError() */ - bool IsOk() - { - return m_error == CBotNoErr; - } + bool IsOk(); /** * \brief Set execution error unless it's already set unless you are trying to reset it @@ -357,7 +351,7 @@ public: /** * \todo Document * - * Copies the result value from static m_retvar (m_var at a moment of SetBreak(3)) to this stack result + * Copies the result value from m_data->retvar (m_var at a moment of SetBreak(3)) to this stack result */ bool GetRetVar(bool bRet); @@ -446,11 +440,11 @@ public: * * \todo Full documentation of the timer */ - static void SetTimer(int n); + void SetTimer(int n); /** * \brief Get the current configured maximum number of "timer ticks" (parts of instructions) to execute */ - static int GetTimer(); + int GetTimer(); /** * \brief Get current position in the program @@ -476,10 +470,10 @@ private: int m_state; int m_step; - static CBotError m_error; - static int m_start; - static int m_end; - static CBotVar* m_retvar; // result of a return + + struct Data; + + CBotStack::Data* m_data; CBotVar* m_var; // result of the operations CBotVar* m_listVar; // variables declared at this level @@ -489,11 +483,6 @@ private: //! CBotProgram instance the execution is in in this stack level CBotProgram* m_prog; - static int m_initimer; - static int m_timer; - static std::string m_labelBreak; - static void* m_pUser; - //! The corresponding instruction CBotInstr* m_instr; //! If this stack level holds a function call diff --git a/src/CBot/CBotVar/CBotVarClass.cpp b/src/CBot/CBotVar/CBotVarClass.cpp index 0e14e077..3ee19874 100644 --- a/src/CBot/CBotVar/CBotVarClass.cpp +++ b/src/CBot/CBotVar/CBotVarClass.cpp @@ -380,14 +380,7 @@ void CBotVarClass::DecrementUse() { m_CptUse++; // does not return to the destructor - // m_error is static in the stack - // saves the value for return - CBotError err; - int start, end; - CBotStack* pile = nullptr; - err = pile->GetError(start,end); // stack == nullptr it does not bother! - - pile = CBotStack::AllocateStack(); // clears the error + CBotStack* pile = CBotStack::AllocateStack(); CBotVar* ppVars[1]; ppVars[0] = nullptr; @@ -401,8 +394,6 @@ void CBotVarClass::DecrementUse() while ( pile->IsOk() && !m_pClass->ExecuteMethode(ident, pThis, ppVars, CBotTypResult(CBotTypVoid), pile, &token)) ; // waits for the end - pile->ResetError(err, start,end); - pile->Delete(); delete pThis; m_CptUse--; diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index ad1a3839..f35c7a2f 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -3411,7 +3411,6 @@ private: void CScriptFunctions::Init() { - CBotProgram::SetTimer(100); CBotProgram::Init(); for (int i = 0; i < OBJECT_MAX; i++)