2014-10-14 13:11:37 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the Colobot: Gold Edition source code
|
2015-08-22 14:40:02 +00:00
|
|
|
* Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
|
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
2014-10-14 13:11:37 +00:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
* See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see http://gnu.org/licenses
|
|
|
|
*/
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotStack.h"
|
2015-12-24 10:57:34 +00:00
|
|
|
#include "CBotExternalCall.h"
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotInstr/CBotFunction.h"
|
2015-11-15 17:31:57 +00:00
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotVar/CBotVarPointer.h"
|
|
|
|
#include "CBot/CBotVar/CBotVarClass.h"
|
2015-11-15 18:11:57 +00:00
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotFileUtils.h"
|
2015-12-20 15:19:10 +00:00
|
|
|
#include "CBot/CBotUtils.h"
|
2015-11-22 16:36:01 +00:00
|
|
|
|
2013-11-25 19:03:06 +00:00
|
|
|
#include <cassert>
|
2012-08-08 00:01:06 +00:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
2015-12-26 13:19:24 +00:00
|
|
|
namespace CBot
|
|
|
|
{
|
|
|
|
|
2012-08-08 00:01:06 +00:00
|
|
|
#define ITIMER 100
|
|
|
|
|
|
|
|
int CBotStack::m_initimer = ITIMER;
|
|
|
|
int CBotStack::m_timer = 0;
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotVar* CBotStack::m_retvar = nullptr;
|
2015-12-21 20:35:20 +00:00
|
|
|
CBotError CBotStack::m_error = CBotNoErr;
|
2012-08-08 00:01:06 +00:00
|
|
|
int CBotStack::m_start = 0;
|
|
|
|
int CBotStack::m_end = 0;
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string CBotStack::m_labelBreak="";
|
2015-08-16 10:43:42 +00:00
|
|
|
void* CBotStack::m_pUser = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 13:39:38 +00:00
|
|
|
CBotStack* CBotStack::AllocateStack()
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotStack* p;
|
|
|
|
|
|
|
|
long size = sizeof(CBotStack);
|
|
|
|
size *= (MAXSTACK+10);
|
|
|
|
|
|
|
|
// request a slice of memory for the stack
|
2012-08-12 23:26:36 +00:00
|
|
|
p = static_cast<CBotStack*>(malloc(size));
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
// completely empty
|
|
|
|
memset(p, 0, size);
|
|
|
|
|
2015-12-25 21:03:23 +00:00
|
|
|
p-> m_bBlock = BlockVisibilityType::BLOCK;
|
2012-08-08 00:01:06 +00:00
|
|
|
m_timer = m_initimer; // sets the timer at the beginning
|
|
|
|
|
|
|
|
CBotStack* pp = p;
|
|
|
|
pp += MAXSTACK;
|
|
|
|
int i;
|
|
|
|
for ( i = 0 ; i< 10 ; i++ )
|
|
|
|
{
|
|
|
|
pp->m_bOver = true;
|
|
|
|
pp ++;
|
|
|
|
}
|
|
|
|
|
2015-12-21 20:35:20 +00:00
|
|
|
m_error = CBotNoErr; // avoids deadlocks because m_error is static
|
2012-08-08 00:01:06 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
void CBotStack::Delete()
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( this == nullptr || this == EOX ) return;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
m_next->Delete();
|
|
|
|
m_next2->Delete();
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_prev != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
if ( m_prev->m_next == this )
|
2015-08-16 10:43:42 +00:00
|
|
|
m_prev->m_next = nullptr; // removes chain
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
if ( m_prev->m_next2 == this )
|
2015-08-16 10:43:42 +00:00
|
|
|
m_prev->m_next2 = nullptr; // removes chain
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
delete m_var;
|
|
|
|
delete m_listVar;
|
|
|
|
|
|
|
|
CBotStack* p = m_prev;
|
|
|
|
bool bOver = m_bOver;
|
|
|
|
|
|
|
|
// clears the freed block
|
|
|
|
memset(this, 0, sizeof(CBotStack));
|
|
|
|
m_bOver = bOver;
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( p == nullptr )
|
2012-08-08 00:01:06 +00:00
|
|
|
free( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
// routine improved
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 21:03:23 +00:00
|
|
|
CBotStack* CBotStack::AddStack(CBotInstr* instr, BlockVisibilityType bBlock)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_next != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
return m_next; // included in an existing stack
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
p ++;
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p->m_prev != nullptr );
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
m_next = p; // chain an element
|
|
|
|
p->m_bBlock = bBlock;
|
|
|
|
p->m_instr = instr;
|
|
|
|
p->m_prog = m_prog;
|
|
|
|
p->m_step = 0;
|
|
|
|
p->m_prev = this;
|
|
|
|
p->m_state = 0;
|
2015-08-16 10:43:42 +00:00
|
|
|
p->m_call = nullptr;
|
2015-12-25 19:47:30 +00:00
|
|
|
p->m_bFunc = IsFunction::NO;
|
2012-08-08 00:01:06 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 21:03:23 +00:00
|
|
|
CBotStack* CBotStack::AddStackEOX(CBotExternalCall* instr, BlockVisibilityType bBlock)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_next != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
if ( m_next == EOX )
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
m_next = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
return EOX;
|
|
|
|
}
|
|
|
|
return m_next; // included in an existing stack
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotStack* p = AddStack(nullptr, bBlock);
|
2012-08-08 00:01:06 +00:00
|
|
|
p->m_call = instr;
|
2015-12-25 19:47:30 +00:00
|
|
|
p->m_bFunc = IsFunction::EXTERNAL_CALL; // special
|
2012-08-08 00:01:06 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 21:03:23 +00:00
|
|
|
CBotStack* CBotStack::AddStack2(BlockVisibilityType bBlock)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_next2 != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
m_next2->m_prog = m_prog; // special avoids RestoreStack2
|
|
|
|
return m_next2; // included in an existing stack
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
p ++;
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p->m_prev != nullptr );
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
m_next2 = p; // chain an element
|
|
|
|
p->m_prev = this;
|
|
|
|
p->m_bBlock = bBlock;
|
|
|
|
p->m_prog = m_prog;
|
|
|
|
p->m_step = 0;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 21:03:23 +00:00
|
|
|
CBotStack::BlockVisibilityType CBotStack::GetBlock()
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
return m_bBlock;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::Return(CBotStack* pfils)
|
|
|
|
{
|
|
|
|
if ( pfils == this ) return true; // special
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_var != nullptr) delete m_var; // value replaced?
|
2012-08-08 00:01:06 +00:00
|
|
|
m_var = pfils->m_var; // result transmitted
|
2015-08-16 10:43:42 +00:00
|
|
|
pfils->m_var = nullptr; // not to destroy the variable
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
m_next->Delete();m_next = nullptr; // releases the stack above
|
|
|
|
m_next2->Delete();m_next2 = nullptr; // also the second stack (catch)
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-12-25 19:47:30 +00:00
|
|
|
return IsOk(); // interrupted if error
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::ReturnKeep(CBotStack* pfils)
|
|
|
|
{
|
|
|
|
if ( pfils == this ) return true; // special
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_var != nullptr) delete m_var; // value replaced?
|
2012-08-08 00:01:06 +00:00
|
|
|
m_var = pfils->m_var; // result transmitted
|
2015-08-16 10:43:42 +00:00
|
|
|
pfils->m_var = nullptr; // not to destroy the variable
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-12-25 19:47:30 +00:00
|
|
|
return IsOk(); // interrupted if error
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::StackOver()
|
|
|
|
{
|
|
|
|
if (!m_bOver) return false;
|
2015-12-20 18:01:03 +00:00
|
|
|
m_error = CBotErrStackOver;
|
2012-08-08 00:01:06 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 13:39:38 +00:00
|
|
|
void CBotStack::Reset()
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-12-24 13:39:38 +00:00
|
|
|
m_timer = m_initimer; // resets the timer
|
2015-12-21 20:35:20 +00:00
|
|
|
m_error = CBotNoErr;
|
2012-08-08 00:01:06 +00:00
|
|
|
// m_start = 0;
|
|
|
|
// m_end = 0;
|
2015-12-20 15:19:10 +00:00
|
|
|
m_labelBreak.clear();
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
CBotStack* CBotStack::RestoreStack(CBotInstr* instr)
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_next != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
m_next->m_instr = instr; // reset (if recovery after )
|
|
|
|
m_next->m_prog = m_prog;
|
|
|
|
return m_next; // included in an existing stack
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
return nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 10:57:34 +00:00
|
|
|
CBotStack* CBotStack::RestoreStackEOX(CBotExternalCall* instr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotStack* p = RestoreStack();
|
|
|
|
p->m_call = instr;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
// routine for execution step by step
|
|
|
|
bool CBotStack::IfStep()
|
|
|
|
{
|
|
|
|
if ( m_initimer > 0 || m_step++ > 0 ) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
bool CBotStack::BreakReturn(CBotStack* pfils, const std::string& name)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
if ( m_error>=0 ) return false; // normal output
|
|
|
|
if ( m_error==-3 ) return false; // normal output (return current)
|
|
|
|
|
2015-12-20 15:19:10 +00:00
|
|
|
if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name))
|
2012-08-08 00:01:06 +00:00
|
|
|
return false; // it's not for me
|
|
|
|
|
2015-12-21 20:35:20 +00:00
|
|
|
m_error = CBotNoErr;
|
2015-12-20 15:19:10 +00:00
|
|
|
m_labelBreak.clear();
|
2012-08-08 00:01:06 +00:00
|
|
|
return Return(pfils);
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
bool CBotStack::IfContinue(int state, const std::string& name)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
if ( m_error != -2 ) return false;
|
|
|
|
|
2015-12-20 15:19:10 +00:00
|
|
|
if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name))
|
2012-08-08 00:01:06 +00:00
|
|
|
return false; // it's not for me
|
|
|
|
|
|
|
|
m_state = state; // where again?
|
2015-12-21 20:35:20 +00:00
|
|
|
m_error = CBotNoErr;
|
2015-12-20 15:19:10 +00:00
|
|
|
m_labelBreak.clear();
|
2012-08-08 00:01:06 +00:00
|
|
|
if ( m_next != EOX ) m_next->Delete(); // purge above stack
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
void CBotStack::SetBreak(int val, const std::string& name)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-12-21 20:35:20 +00:00
|
|
|
m_error = static_cast<CBotError>(-val); // reacts as an Exception
|
2012-08-08 00:01:06 +00:00
|
|
|
m_labelBreak = name;
|
|
|
|
if (val == 3) // for a return
|
|
|
|
{
|
|
|
|
m_retvar = m_var;
|
2015-08-16 10:43:42 +00:00
|
|
|
m_var = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// gives on the stack value calculated by the last CBotReturn
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-11 18:59:35 +00:00
|
|
|
bool CBotStack::GetRetVar(bool bRet)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
if (m_error == -3)
|
|
|
|
{
|
|
|
|
if ( m_var ) delete m_var;
|
|
|
|
m_var = m_retvar;
|
2015-08-16 10:43:42 +00:00
|
|
|
m_retvar = nullptr;
|
2015-12-21 20:35:20 +00:00
|
|
|
m_error = CBotNoErr;
|
2012-08-08 00:01:06 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return bRet; // interrupted by something other than return
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 13:39:38 +00:00
|
|
|
CBotVar* CBotStack::FindVar(CBotToken*& pToken, bool bUpdate)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotStack* p = this;
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string name = pToken->GetString();
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while (p != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotVar* pp = p->m_listVar;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( pp != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
if (pp->GetName() == name)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2013-05-26 15:47:54 +00:00
|
|
|
if ( bUpdate )
|
2015-12-24 13:39:38 +00:00
|
|
|
pp->Maj(m_pUser);
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
return pp;
|
|
|
|
}
|
|
|
|
pp = pp->m_next;
|
|
|
|
}
|
|
|
|
p = p->m_prev;
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
return nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotVar* CBotStack::FindVar(const std::string& name)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotStack* p = this;
|
2015-08-16 10:43:42 +00:00
|
|
|
while (p != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotVar* pp = p->m_listVar;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( pp != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
if (pp->GetName() == name)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
return pp;
|
|
|
|
}
|
|
|
|
pp = pp->m_next;
|
|
|
|
}
|
|
|
|
p = p->m_prev;
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
return nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 13:39:38 +00:00
|
|
|
CBotVar* CBotStack::FindVar(long ident, bool bUpdate)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotStack* p = this;
|
2015-08-16 10:43:42 +00:00
|
|
|
while (p != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotVar* pp = p->m_listVar;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( pp != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
if (pp->GetUniqNum() == ident)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2013-05-26 15:47:54 +00:00
|
|
|
if ( bUpdate )
|
2015-12-24 13:39:38 +00:00
|
|
|
pp->Maj(m_pUser);
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
return pp;
|
|
|
|
}
|
|
|
|
pp = pp->m_next;
|
|
|
|
}
|
|
|
|
p = p->m_prev;
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
return nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 13:39:38 +00:00
|
|
|
CBotVar* CBotStack::FindVar(CBotToken& pToken, bool bUpdate)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-08-16 22:43:32 +00:00
|
|
|
CBotToken* pt = &pToken;
|
2015-12-24 13:39:38 +00:00
|
|
|
return FindVar(pt, bUpdate);
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 18:48:31 +00:00
|
|
|
CBotVar* CBotStack::CopyVar(CBotToken& pToken, bool bUpdate)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-12-25 18:48:31 +00:00
|
|
|
CBotVar* pVar = FindVar(pToken, bUpdate);
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pVar == nullptr) return nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
CBotVar* pCopy = CBotVar::Create(pVar);
|
|
|
|
pCopy->Copy(pVar);
|
|
|
|
return pCopy;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::SetState(int n, int limite)
|
|
|
|
{
|
|
|
|
m_state = n;
|
|
|
|
|
|
|
|
m_timer--; // decrement the operations \TODO decrement the operations
|
|
|
|
return ( m_timer > limite ); // interrupted if timer pass
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::IncState(int limite)
|
|
|
|
{
|
|
|
|
m_state++;
|
|
|
|
|
|
|
|
m_timer--; // decrement the operations \TODO decompte les operations
|
|
|
|
return ( m_timer > limite ); // interrupted if timer pass
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-21 20:35:20 +00:00
|
|
|
void CBotStack::SetError(CBotError n, CBotToken* token)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-12-25 21:03:23 +00:00
|
|
|
if (n != CBotNoErr && m_error != CBotNoErr) return; // does not change existing error
|
2012-08-08 00:01:06 +00:00
|
|
|
m_error = n;
|
2015-08-16 10:43:42 +00:00
|
|
|
if (token != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
m_start = token->GetStart();
|
|
|
|
m_end = token->GetEnd();
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-21 20:35:20 +00:00
|
|
|
void CBotStack::ResetError(CBotError n, int start, int end)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
m_error = n;
|
|
|
|
m_start = start;
|
|
|
|
m_end = end;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
void CBotStack::SetPosError(CBotToken* token)
|
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
m_start = token->GetStart();
|
|
|
|
m_end = token->GetEnd();
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
void CBotStack::SetTimer(int n)
|
|
|
|
{
|
|
|
|
m_initimer = n;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::Execute()
|
|
|
|
{
|
2015-12-24 10:57:34 +00:00
|
|
|
CBotExternalCall* instr = nullptr; // the most highest instruction
|
2012-08-08 00:01:06 +00:00
|
|
|
CBotStack* pile;
|
|
|
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while (p != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( p->m_next2 != nullptr ) break;
|
|
|
|
if ( p->m_call != nullptr )
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
instr = p->m_call;
|
|
|
|
pile = p->m_prev ;
|
|
|
|
}
|
|
|
|
p = p->m_next;
|
|
|
|
}
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( instr == nullptr ) return true; // normal execution request
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-12-24 11:57:37 +00:00
|
|
|
if (!instr->Run(nullptr, pile)) return false; // \TODO exécution à partir de là
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
pile->m_next->Delete();
|
|
|
|
|
|
|
|
pile->m_next = EOX; // special for recovery
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// puts on the stack pointer to a variable
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
void CBotStack::SetVar( CBotVar* var )
|
|
|
|
{
|
|
|
|
if (m_var) delete m_var; // replacement of a variable
|
|
|
|
m_var = var;
|
|
|
|
}
|
|
|
|
|
|
|
|
// puts on the stack a copy of a variable
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
void CBotStack::SetCopyVar( CBotVar* var )
|
|
|
|
{
|
|
|
|
if (m_var) delete m_var; // replacement of a variable
|
|
|
|
|
2015-12-25 18:16:54 +00:00
|
|
|
m_var = CBotVar::Create("", var->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC));
|
2012-08-08 00:01:06 +00:00
|
|
|
m_var->Copy( var );
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotVar* CBotStack::GetVar()
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
return m_var;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-11 18:59:35 +00:00
|
|
|
long CBotStack::GetVal()
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_var == nullptr) return 0;
|
2012-08-11 18:59:35 +00:00
|
|
|
return m_var->GetValInt();
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
void CBotStack::AddVar(CBotVar* pVar)
|
|
|
|
{
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
|
|
|
// returns to the father element
|
2015-12-25 21:03:23 +00:00
|
|
|
while (p != nullptr && p->m_bBlock == BlockVisibilityType::INSTRUCTION) p = p->m_prev;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( p == nullptr ) return;
|
2013-05-26 15:47:54 +00:00
|
|
|
|
2015-12-25 18:48:31 +00:00
|
|
|
// p->m_bDontDelete = bDontDelete;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
CBotVar** pp = &p->m_listVar;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( *pp != nullptr ) pp = &(*pp)->m_next;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
*pp = pVar; // added after
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 13:39:38 +00:00
|
|
|
void CBotStack::SetProgram(CBotProgram* p)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
m_prog = p;
|
2015-12-25 19:47:30 +00:00
|
|
|
m_bFunc = IsFunction::TRUE;
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 19:47:30 +00:00
|
|
|
CBotProgram* CBotStack::GetProgram(bool bFirst)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
if ( ! bFirst ) return m_prog;
|
|
|
|
CBotStack* p = this;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p->m_prev != nullptr ) p = p->m_prev;
|
2012-08-08 00:01:06 +00:00
|
|
|
return p->m_prog;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 13:39:38 +00:00
|
|
|
void* CBotStack::GetUserPtr()
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
return m_pUser;
|
|
|
|
}
|
|
|
|
|
2015-12-24 13:39:38 +00:00
|
|
|
void CBotStack::SetUserPtr(void* user)
|
|
|
|
{
|
|
|
|
m_pUser = user;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 21:03:23 +00:00
|
|
|
bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, const CBotTypResult& rettype)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotTypResult res;
|
|
|
|
|
|
|
|
// first looks by the identifier
|
|
|
|
|
2015-12-24 11:57:37 +00:00
|
|
|
res = m_prog->GetExternalCalls()->DoCall(nullptr, nullptr, ppVar, this, rettype);
|
2012-08-11 18:59:35 +00:00
|
|
|
if (res.GetType() >= 0) return res.GetType();
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-12-23 19:39:56 +00:00
|
|
|
res = m_prog->GetFunctions()->DoCall(nIdent, "", ppVar, this, token );
|
2012-08-11 18:59:35 +00:00
|
|
|
if (res.GetType() >= 0) return res.GetType();
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
// if not found (recompile?) seeks by name
|
|
|
|
|
|
|
|
nIdent = 0;
|
2015-12-24 11:57:37 +00:00
|
|
|
res = m_prog->GetExternalCalls()->DoCall(token, nullptr, ppVar, this, rettype);
|
2012-08-11 18:59:35 +00:00
|
|
|
if (res.GetType() >= 0) return res.GetType();
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
res = m_prog->GetFunctions()->DoCall(nIdent, token->GetString(), ppVar, this, token );
|
|
|
|
if (res.GetType() >= 0) return res.GetType();
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-12-20 18:01:03 +00:00
|
|
|
SetError(CBotErrUndefFunc, token);
|
2012-08-08 00:01:06 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
void CBotStack::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar)
|
|
|
|
{
|
2015-12-24 11:36:09 +00:00
|
|
|
if (m_next == nullptr) return;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-12-24 11:57:37 +00:00
|
|
|
if (m_prog->GetExternalCalls()->RestoreCall(token, nullptr, ppVar, this))
|
2015-12-24 11:36:09 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
m_prog->GetFunctions()->RestoreCall(nIdent, token->GetString(), ppVar, this);
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool SaveVar(FILE* pf, CBotVar* pVar)
|
|
|
|
{
|
|
|
|
while ( true )
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pVar == nullptr )
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
return WriteWord(pf, 0); // is a terminator
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !pVar->Save0State(pf)) return false; // common header
|
|
|
|
if ( !pVar->Save1State(pf) ) return false; // saves as the child class
|
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
pVar = pVar->GetNext();
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 21:03:23 +00:00
|
|
|
void CBotStack::GetRunPos(std::string& functionName, int& start, int& end)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotProgram* prog = m_prog; // Current program
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotInstr* funct = nullptr; // function found
|
|
|
|
CBotInstr* instr = nullptr; // the highest intruction
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while (p->m_next != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( p->m_instr != nullptr ) instr = p->m_instr;
|
2015-12-25 19:47:30 +00:00
|
|
|
if ( p->m_bFunc == IsFunction::TRUE && p->m_instr != nullptr ) funct = p->m_instr;
|
2013-05-26 15:47:54 +00:00
|
|
|
if ( p->m_next->m_prog != prog ) break ;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
if (p->m_next2 && p->m_next2->m_state != 0) p = p->m_next2 ;
|
|
|
|
else p = p->m_next;
|
|
|
|
}
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( p->m_instr != nullptr ) instr = p->m_instr;
|
2015-12-25 19:47:30 +00:00
|
|
|
if ( p->m_bFunc == IsFunction::TRUE && p->m_instr != nullptr ) funct = p->m_instr;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( funct == nullptr ) return;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotToken* t = funct->GetToken();
|
2015-12-25 21:03:23 +00:00
|
|
|
functionName = t->GetString();
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
// if ( p->m_instr != nullptr ) instr = p->m_instr;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
t = instr->GetToken();
|
|
|
|
start = t->GetStart();
|
2014-10-07 20:28:32 +00:00
|
|
|
end = t->GetEnd();
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 21:03:23 +00:00
|
|
|
CBotVar* CBotStack::GetStackVars(std::string& functionName, int level)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
CBotProgram* prog = m_prog; // current program
|
2015-12-25 21:03:23 +00:00
|
|
|
functionName = "";
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
// back the stack in the current module
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while (p->m_next != nullptr)
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2013-05-26 15:47:54 +00:00
|
|
|
if ( p->m_next->m_prog != prog ) break ;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
if (p->m_next2 && p->m_next2->m_state != 0) p = p->m_next2 ;
|
|
|
|
else p = p->m_next;
|
|
|
|
}
|
2014-10-19 13:27:00 +00:00
|
|
|
// Now p is the highest element on the stack
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
// descends upon the elements of block
|
2015-12-25 21:03:23 +00:00
|
|
|
while ( p != nullptr && p->m_bBlock == BlockVisibilityType::INSTRUCTION) p = p->m_prev;
|
2014-10-19 13:27:00 +00:00
|
|
|
// Now p is on the beggining of the top block (with local variables)
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p != nullptr && level++ < 0 )
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
p = p->m_prev;
|
2015-12-25 21:03:23 +00:00
|
|
|
while ( p != nullptr && p->m_bBlock == BlockVisibilityType::INSTRUCTION) p = p->m_prev;
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
2014-10-19 13:27:00 +00:00
|
|
|
// Now p is on the block "level"
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( p == nullptr ) return nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
// search the name of the current function
|
|
|
|
CBotStack* pp = p;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( pp != nullptr )
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
2015-12-25 19:47:30 +00:00
|
|
|
if ( pp->m_bFunc == IsFunction::TRUE) break;
|
2012-08-08 00:01:06 +00:00
|
|
|
pp = pp->m_prev;
|
|
|
|
}
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pp == nullptr || pp->m_instr == nullptr ) return nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotToken* t = pp->m_instr->GetToken();
|
2015-12-25 21:03:23 +00:00
|
|
|
functionName = t->GetString();
|
2013-05-26 15:47:54 +00:00
|
|
|
|
2012-08-08 00:01:06 +00:00
|
|
|
return p->m_listVar;
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::SaveState(FILE* pf)
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( this == nullptr ) // end of the tree?
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
return WriteWord(pf, 0); // is a terminator
|
|
|
|
}
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( m_next2 != nullptr )
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
if (!WriteWord(pf, 2)) return false; // a mark of pursuit
|
|
|
|
if (!m_next2->SaveState(pf)) return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!WriteWord(pf, 1)) return false; // a mark of pursuit
|
|
|
|
}
|
2015-12-19 20:20:41 +00:00
|
|
|
if (!WriteWord(pf, static_cast<unsigned short>(m_bBlock))) return false; // is a local block
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!WriteWord(pf, m_state)) return false; // in what state?
|
|
|
|
if (!WriteWord(pf, 0)) return false; // by compatibility m_bDontDelete
|
|
|
|
if (!WriteWord(pf, m_step)) return false; // in what state?
|
2013-05-26 15:47:54 +00:00
|
|
|
|
|
|
|
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!SaveVar(pf, m_var)) return false; // current result
|
|
|
|
if (!SaveVar(pf, m_listVar)) return false; // local variables
|
|
|
|
|
|
|
|
return m_next->SaveState(pf); // saves the following
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotStack::RestoreState(FILE* pf, CBotStack* &pStack)
|
|
|
|
{
|
|
|
|
unsigned short w;
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
pStack = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!ReadWord(pf, w)) return false;
|
|
|
|
if ( w == 0 ) return true;
|
|
|
|
|
2015-12-24 13:39:38 +00:00
|
|
|
if ( this == nullptr ) pStack = AllocateStack();
|
2012-08-08 00:01:06 +00:00
|
|
|
else pStack = AddStack();
|
|
|
|
|
|
|
|
if ( w == 2 )
|
|
|
|
{
|
|
|
|
if (!pStack->RestoreState(pf, pStack->m_next2)) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ReadWord(pf, w)) return false; // is a local block
|
2015-12-25 21:03:23 +00:00
|
|
|
pStack->m_bBlock = static_cast<BlockVisibilityType>(w);
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
if (!ReadWord(pf, w)) return false; // in what state ?
|
2012-08-12 23:26:36 +00:00
|
|
|
pStack->SetState(static_cast<short>(w)); // in a good state
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
if (!ReadWord(pf, w)) return false; // dont delete?
|
|
|
|
// uses more
|
|
|
|
|
|
|
|
if (!ReadWord(pf, w)) return false; // step by step
|
|
|
|
pStack->m_step = w;
|
|
|
|
|
|
|
|
if (!CBotVar::RestoreState(pf, pStack->m_var)) return false; // temp variable
|
|
|
|
if (!CBotVar::RestoreState(pf, pStack->m_listVar)) return false;// local variables
|
|
|
|
|
|
|
|
return pStack->RestoreState(pf, pStack->m_next);
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotVar::Save0State(FILE* pf)
|
2013-05-26 15:47:54 +00:00
|
|
|
{
|
2015-12-21 22:07:40 +00:00
|
|
|
if (!WriteWord(pf, 100+static_cast<int>(m_mPrivate)))return false; // private variable?
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!WriteWord(pf, m_bStatic))return false; // static variable?
|
2012-08-11 18:59:35 +00:00
|
|
|
if (!WriteWord(pf, m_type.GetType()))return false; // saves the type (always non-zero)
|
2015-07-04 21:36:11 +00:00
|
|
|
if (!WriteWord(pf, static_cast<unsigned short>(m_binit))) return false; // variable defined?
|
2012-08-11 18:59:35 +00:00
|
|
|
return WriteString(pf, m_token->GetString()); // and variable name
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-04 21:36:11 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
bool ParseInitType(int rawInitType, CBotVar::InitType* initType)
|
|
|
|
{
|
|
|
|
switch (rawInitType)
|
|
|
|
{
|
|
|
|
case static_cast<int>(CBotVar::InitType::UNDEF):
|
|
|
|
*initType = CBotVar::InitType::UNDEF;
|
|
|
|
break;
|
|
|
|
case static_cast<int>(CBotVar::InitType::DEF):
|
|
|
|
*initType = CBotVar::InitType::DEF;
|
|
|
|
break;
|
|
|
|
case static_cast<int>(CBotVar::InitType::IS_POINTER):
|
|
|
|
*initType = CBotVar::InitType::IS_POINTER;
|
|
|
|
break;
|
|
|
|
case static_cast<int>(CBotVar::InitType::IS_NAN):
|
|
|
|
*initType = CBotVar::InitType::IS_NAN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*initType = CBotVar::InitType::UNDEF;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-14 11:56:16 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-08 00:01:06 +00:00
|
|
|
bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
|
|
|
|
{
|
|
|
|
unsigned short w, wi, prv, st;
|
|
|
|
float ww;
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string name, s;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
delete pVar;
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
pVar = nullptr;
|
|
|
|
CBotVar* pNew = nullptr;
|
|
|
|
CBotVar* pPrev = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
while ( true ) // retrieves a list
|
|
|
|
{
|
|
|
|
if (!ReadWord(pf, w)) return false; // private or type?
|
|
|
|
if ( w == 0 ) return true;
|
|
|
|
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string defnum;
|
2012-08-08 00:01:06 +00:00
|
|
|
if ( w == 200 )
|
|
|
|
{
|
|
|
|
if (!ReadString(pf, defnum)) return false; // number with identifier
|
|
|
|
if (!ReadWord(pf, w)) return false; // type
|
|
|
|
}
|
|
|
|
|
|
|
|
prv = 100; st = 0;
|
|
|
|
if ( w >= 100 )
|
|
|
|
{
|
|
|
|
prv = w;
|
|
|
|
if (!ReadWord(pf, st)) return false; // static
|
|
|
|
if (!ReadWord(pf, w)) return false; // type
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( w == CBotTypClass ) w = CBotTypIntrinsic; // necessarily intrinsic
|
|
|
|
|
2015-07-04 21:36:11 +00:00
|
|
|
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
|
|
|
|
if (!ReadWord(pf, wi) || !ParseInitType(wi, &initType)) return false; // init ?
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!ReadString(pf, name)) return false; // variable name
|
|
|
|
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotToken token(name, std::string());
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
switch (w)
|
|
|
|
{
|
|
|
|
case CBotTypInt:
|
|
|
|
case CBotTypBoolean:
|
2015-12-23 16:50:10 +00:00
|
|
|
pNew = CBotVar::Create(token, w); // creates a variable
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!ReadWord(pf, w)) return false;
|
2012-08-12 23:26:36 +00:00
|
|
|
pNew->SetValInt(static_cast<short>(w), defnum);
|
2012-08-08 00:01:06 +00:00
|
|
|
break;
|
|
|
|
case CBotTypFloat:
|
2015-12-23 16:50:10 +00:00
|
|
|
pNew = CBotVar::Create(token, w); // creates a variable
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!ReadFloat(pf, ww)) return false;
|
|
|
|
pNew->SetValFloat(ww);
|
|
|
|
break;
|
|
|
|
case CBotTypString:
|
2015-12-23 16:50:10 +00:00
|
|
|
pNew = CBotVar::Create(token, w); // creates a variable
|
2012-08-08 00:01:06 +00:00
|
|
|
if (!ReadString(pf, s)) return false;
|
|
|
|
pNew->SetValString(s);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// returns an intrinsic object or element of an array
|
|
|
|
case CBotTypIntrinsic:
|
|
|
|
case CBotTypArrayBody:
|
|
|
|
{
|
|
|
|
CBotTypResult r;
|
|
|
|
long id;
|
|
|
|
if (!ReadType(pf, r)) return false; // complete type
|
|
|
|
if (!ReadLong(pf, id) ) return false;
|
|
|
|
|
|
|
|
// if (!ReadString(pf, s)) return false;
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotVar* p = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
if ( id ) p = CBotVarClass::Find(id) ;
|
|
|
|
|
2015-12-23 16:50:10 +00:00
|
|
|
pNew = new CBotVarClass(token, r); // directly creates an instance
|
2012-08-08 00:01:06 +00:00
|
|
|
// attention cptuse = 0
|
2012-08-12 23:26:36 +00:00
|
|
|
if ( !RestoreState(pf, (static_cast<CBotVarClass*>(pNew))->m_pVar)) return false;
|
2012-08-08 00:01:06 +00:00
|
|
|
pNew->SetIdent(id);
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( p != nullptr )
|
2012-08-08 00:01:06 +00:00
|
|
|
{
|
|
|
|
delete pNew;
|
2013-05-26 15:47:54 +00:00
|
|
|
pNew = p; // resume known element
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CBotTypPointer:
|
|
|
|
case CBotTypNullPointer:
|
|
|
|
if (!ReadString(pf, s)) return false;
|
|
|
|
{
|
2015-12-23 16:50:10 +00:00
|
|
|
pNew = CBotVar::Create(token, CBotTypResult(w, s));// creates a variable
|
2015-08-16 10:43:42 +00:00
|
|
|
// CBotVarClass* p = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
long id;
|
|
|
|
ReadLong(pf, id);
|
|
|
|
// if ( id ) p = CBotVarClass::Find(id); // found the instance (made by RestoreInstance)
|
|
|
|
|
|
|
|
// returns a copy of the original instance
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotVar* pInstance = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
if ( !CBotVar::RestoreState( pf, pInstance ) ) return false;
|
2012-08-12 23:26:36 +00:00
|
|
|
(static_cast<CBotVarPointer*>(pNew))->SetPointer( pInstance ); // and point over
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
// if ( p != nullptr ) (static_cast<CBotVarPointer*>(pNew))->SetPointer( p ); // rather this one
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CBotTypArrayPointer:
|
|
|
|
{
|
|
|
|
CBotTypResult r;
|
|
|
|
if (!ReadType(pf, r)) return false;
|
|
|
|
|
2015-12-23 16:50:10 +00:00
|
|
|
pNew = CBotVar::Create(token, r); // creates a variable
|
2012-08-08 00:01:06 +00:00
|
|
|
|
|
|
|
// returns a copy of the original instance
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotVar* pInstance = nullptr;
|
2012-08-08 00:01:06 +00:00
|
|
|
if ( !CBotVar::RestoreState( pf, pInstance ) ) return false;
|
2012-08-12 23:26:36 +00:00
|
|
|
(static_cast<CBotVarPointer*>(pNew))->SetPointer( pInstance ); // and point over
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2013-11-25 19:03:06 +00:00
|
|
|
assert(0);
|
2012-08-08 00:01:06 +00:00
|
|
|
}
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pPrev != nullptr ) pPrev->m_next = pNew;
|
|
|
|
if ( pVar == nullptr ) pVar = pNew;
|
2012-08-08 00:01:06 +00:00
|
|
|
|
2015-07-04 21:36:11 +00:00
|
|
|
pNew->m_binit = initType; // pNew->SetInit(wi);
|
2012-08-08 00:01:06 +00:00
|
|
|
pNew->SetStatic(st);
|
2015-12-21 22:07:40 +00:00
|
|
|
pNew->SetPrivate(static_cast<ProtectionLevel>(prv-100));
|
2012-08-08 00:01:06 +00:00
|
|
|
pPrev = pNew;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2015-12-26 13:19:24 +00:00
|
|
|
|
|
|
|
} // namespace CBot
|