2012-03-19 11:44:39 +00:00
|
|
|
|
// * This file is part of the COLOBOT source code
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
|
|
|
|
|
// *
|
|
|
|
|
// * 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
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// * along with this program. If not, see http://www.gnu.org/licenses/.//////////////////////////////////////////////////////////////////////
|
2012-07-10 20:58:52 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \file CBotStack.cpp
|
|
|
|
|
* \brief Management of the stack
|
|
|
|
|
*/
|
|
|
|
|
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#include "CBot.h"
|
2012-07-04 20:14:28 +00:00
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <cstring>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define ITIMER 100
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// gestion de la pile d'ex<65>cution
|
2012-03-08 18:32:05 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
int CBotStack::m_initimer = ITIMER;
|
|
|
|
|
int CBotStack::m_timer = 0;
|
|
|
|
|
CBotVar* CBotStack::m_retvar = NULL;
|
|
|
|
|
int CBotStack::m_error = 0;
|
|
|
|
|
int CBotStack::m_start = 0;
|
|
|
|
|
int CBotStack::m_end = 0;
|
|
|
|
|
CBotString CBotStack::m_labelBreak="";
|
|
|
|
|
void* CBotStack::m_pUser = NULL;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
|
|
|
|
|
CBotStack* CBotStack::FirstStack()
|
|
|
|
|
{
|
|
|
|
|
CBotStack* p;
|
|
|
|
|
|
|
|
|
|
long size = sizeof(CBotStack);
|
|
|
|
|
size *= (MAXSTACK+10);
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// demande une tranche m<>moire pour la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p = (CBotStack*)malloc(size);
|
|
|
|
|
|
|
|
|
|
// la vide totalement
|
|
|
|
|
memset(p, 0, size);
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
p-> m_bBlock = true;
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_timer = m_initimer; // met le timer au d<>but
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotStack* pp = p;
|
|
|
|
|
pp += MAXSTACK;
|
2012-04-14 22:50:13 +00:00
|
|
|
|
int i;
|
|
|
|
|
for ( i = 0 ; i< 10 ; i++ )
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
pp->m_bOver = true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pp ++;
|
|
|
|
|
}
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
int n = 1;
|
|
|
|
|
pp = p;
|
|
|
|
|
for ( i = 0 ; i< MAXSTACK+10 ; i++ )
|
|
|
|
|
{
|
|
|
|
|
pp->m_index = n++;
|
|
|
|
|
pp ++;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_error = 0; // <20>vite des blocages car m_error est static
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotStack::CBotStack(CBotStack* ppapa)
|
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
// constructor must exist or the destructor is never called!
|
|
|
|
|
ASM_TRAP();
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotStack::~CBotStack()
|
|
|
|
|
{
|
2012-04-14 22:50:13 +00:00
|
|
|
|
ASM_TRAP(); // utiliser Delete() <20> la place
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotStack::Delete()
|
|
|
|
|
{
|
|
|
|
|
if ( this == NULL || this == EOX ) return;
|
|
|
|
|
|
|
|
|
|
m_next->Delete();
|
|
|
|
|
m_next2->Delete();
|
|
|
|
|
|
|
|
|
|
if (m_prev != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( m_prev->m_next == this )
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_prev->m_next = NULL; // enl<6E>ve de la cha<68>ne
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
if ( m_prev->m_next2 == this )
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_prev->m_next2 = NULL; // enl<6E>ve de la cha<68>ne
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete m_var;
|
|
|
|
|
delete m_listVar;
|
|
|
|
|
|
|
|
|
|
CBotStack* p = m_prev;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool bOver = m_bOver;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
int n = m_index;
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// efface le bloc lib<69>r<EFBFBD>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
memset(this, 0, sizeof(CBotStack));
|
|
|
|
|
m_bOver = bOver;
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
m_index = n;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( p == NULL )
|
|
|
|
|
free( this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// routine optimis<69>e
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotStack* CBotStack::AddStack(CBotInstr* instr, bool bBlock)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_next != NULL)
|
|
|
|
|
{
|
|
|
|
|
return m_next; // reprise dans une pile existante
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
int n = 0;
|
|
|
|
|
#endif
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
p ++;
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
n ++;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
while ( p->m_prev != NULL );
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next = p; // cha<68>ne l'<27>l<EFBFBD>ment
|
2012-03-08 18:32:05 +00:00
|
|
|
|
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;
|
|
|
|
|
p->m_call = NULL;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
p->m_bFunc = false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotStack* CBotStack::AddStackEOX(CBotCall* instr, bool bBlock)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_next != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( m_next == EOX )
|
|
|
|
|
{
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
return EOX;
|
|
|
|
|
}
|
|
|
|
|
return m_next; // reprise dans une pile existante
|
|
|
|
|
}
|
|
|
|
|
CBotStack* p = AddStack(NULL, bBlock);
|
|
|
|
|
p->m_call = instr;
|
2012-03-19 11:44:39 +00:00
|
|
|
|
p->m_bFunc = 2; // sp<73>cial
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotStack* CBotStack::AddStack2(bool bBlock)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_next2 != NULL)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next2->m_prog = m_prog; // sp<73>cial <20>vite un RestoreStack2
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return m_next2; // reprise dans une pile existante
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
p ++;
|
|
|
|
|
}
|
|
|
|
|
while ( p->m_prev != NULL );
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next2 = p; // cha<68>ne l'<27>l<EFBFBD>ment
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p->m_prev = this;
|
|
|
|
|
p->m_bBlock = bBlock;
|
|
|
|
|
p->m_prog = m_prog;
|
|
|
|
|
p->m_step = 0;
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::GivBlock()
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
return m_bBlock;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::Return(CBotStack* pfils)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( pfils == this ) return true; // sp<73>cial
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (m_var != NULL) delete m_var; // valeur remplac<61>e ?
|
|
|
|
|
m_var = pfils->m_var; // r<>sultat transmis
|
|
|
|
|
pfils->m_var = NULL; // ne pas d<>truire la variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next->Delete();m_next = NULL; // lib<69>re la pile au dessus
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_next2->Delete();m_next2 = NULL; // aussi la seconde pile (catch)
|
|
|
|
|
|
|
|
|
|
return (m_error == 0); // interrompu si erreur
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::ReturnKeep(CBotStack* pfils)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( pfils == this ) return true; // sp<73>cial
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (m_var != NULL) delete m_var; // valeur remplac<61>e ?
|
|
|
|
|
m_var = pfils->m_var; // r<>sultat transmis
|
|
|
|
|
pfils->m_var = NULL; // ne pas d<>truire la variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
return (m_error == 0); // interrompu si erreur
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::StackOver()
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!m_bOver) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_error = TX_STACKOVER;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
CBotStack::CBotStack(CBotStack* ppapa)
|
|
|
|
|
{
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
m_next2 = NULL;
|
|
|
|
|
m_prev = ppapa;
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
m_bBlock = (ppapa == NULL) ? true : false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
m_state = 0;
|
|
|
|
|
m_step = 1;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (ppapa == NULL) m_timer = m_initimer; // met le timer au d<>but
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
m_listVar = NULL;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
m_bDontDelete = false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
m_var = NULL;
|
|
|
|
|
m_prog = NULL;
|
|
|
|
|
m_instr = NULL;
|
|
|
|
|
m_call = NULL;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
m_bFunc = false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// destructeur
|
|
|
|
|
CBotStack::~CBotStack()
|
|
|
|
|
{
|
|
|
|
|
if ( m_next != EOX) delete m_next;
|
|
|
|
|
delete m_next2;
|
|
|
|
|
if (m_prev != NULL && m_prev->m_next == this )
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_prev->m_next = NULL; // enl<6E>ve de la cha<68>ne
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
delete m_var;
|
|
|
|
|
if ( !m_bDontDelete ) delete m_listVar;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// routine <20> optimiser
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotStack* CBotStack::AddStack(CBotInstr* instr, bool bBlock)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_next != NULL)
|
|
|
|
|
{
|
|
|
|
|
return m_next; // reprise dans une pile existante
|
|
|
|
|
}
|
|
|
|
|
CBotStack* p = new CBotStack(this);
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next = p; // cha<68>ne l'<27>l<EFBFBD>ment
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p->m_bBlock = bBlock;
|
|
|
|
|
p->m_instr = instr;
|
|
|
|
|
p->m_prog = m_prog;
|
|
|
|
|
p->m_step = 0;
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotStack* CBotStack::AddStackEOX(CBotCall* instr, bool bBlock)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_next != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( m_next == EOX )
|
|
|
|
|
{
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
return EOX;
|
|
|
|
|
}
|
|
|
|
|
return m_next; // reprise dans une pile existante
|
|
|
|
|
}
|
|
|
|
|
CBotStack* p = new CBotStack(this);
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next = p; // cha<68>ne l'<27>l<EFBFBD>ment
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p->m_bBlock = bBlock;
|
|
|
|
|
p->m_call = instr;
|
|
|
|
|
p->m_prog = m_prog;
|
|
|
|
|
p->m_step = 0;
|
2012-03-19 11:44:39 +00:00
|
|
|
|
p->m_bFunc = 2; // sp<73>cial
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotStack* CBotStack::AddStack2(bool bBlock)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_next2 != NULL)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next2->m_prog = m_prog; // sp<73>cial <20>vite un RestoreStack2
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return m_next2; // reprise dans une pile existante
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotStack* p = new CBotStack(this);
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next2 = p; // cha<68>ne l'<27>l<EFBFBD>ment
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p->m_bBlock = bBlock;
|
|
|
|
|
p->m_prog = m_prog;
|
|
|
|
|
p->m_step = 0;
|
|
|
|
|
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::Return(CBotStack* pfils)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( pfils == this ) return true; // sp<73>cial
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (m_var != NULL) delete m_var; // valeur remplac<61>e ?
|
|
|
|
|
m_var = pfils->m_var; // r<>sultat transmis
|
|
|
|
|
pfils->m_var = NULL; // ne pas d<>truite la variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if ( m_next != EOX ) delete m_next; // lib<69>re la pile au dessus
|
2012-03-08 18:32:05 +00:00
|
|
|
|
delete m_next2;m_next2 = NULL; // aussi la seconde pile (catch)
|
|
|
|
|
|
|
|
|
|
return (m_error == 0); // interrompu si erreur
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::StackOver()
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return false; // pas de test de d<>bordement dans cette version
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void CBotStack::Reset(void* pUser)
|
|
|
|
|
{
|
|
|
|
|
m_timer = m_initimer; // remet le timer
|
|
|
|
|
m_error = 0;
|
|
|
|
|
// m_start = 0;
|
|
|
|
|
// m_end = 0;
|
|
|
|
|
m_labelBreak.Empty();
|
|
|
|
|
m_pUser = pUser;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotStack* CBotStack::RestoreStack(CBotInstr* instr)
|
|
|
|
|
{
|
|
|
|
|
if (m_next != NULL)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next->m_instr = instr; // r<>init (si reprise apr<70>s restitution)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_next->m_prog = m_prog;
|
|
|
|
|
return m_next; // reprise dans une pile existante
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotStack* CBotStack::RestoreStackEOX(CBotCall* instr)
|
|
|
|
|
{
|
|
|
|
|
CBotStack* p = RestoreStack();
|
|
|
|
|
p->m_call = instr;
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// routine pour l'ex<65>cution pas <20> pas
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::IfStep()
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( m_initimer > 0 || m_step++ > 0 ) return false;
|
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::BreakReturn(CBotStack* pfils, const char* name)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( m_error>=0 ) return false; // sortie normale
|
|
|
|
|
if ( m_error==-3 ) return false; // sortie normale (return en cours)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
if (!m_labelBreak.IsEmpty() && (name[0] == 0 || m_labelBreak != name))
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return false; // c'est pas pour moi
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
m_error = 0;
|
|
|
|
|
m_labelBreak.Empty();
|
|
|
|
|
return Return(pfils);
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::IfContinue(int state, const char* name)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( m_error != -2 ) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
if (!m_labelBreak.IsEmpty() && (name == NULL || m_labelBreak != name))
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return false; // c'est pas pour moi
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_state = state; // o<> reprendre ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_error = 0;
|
|
|
|
|
m_labelBreak.Empty();
|
|
|
|
|
if ( m_next != EOX ) m_next->Delete(); // purge la pile au dessus
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotStack::SetBreak(int val, const char* name)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_error = -val; // r<>agit comme une Exception
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_labelBreak = name;
|
|
|
|
|
if (val == 3) // pour un return
|
|
|
|
|
{
|
|
|
|
|
m_retvar = m_var;
|
|
|
|
|
m_var = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// remet sur la pile la valeur calcul<75>e par le dernier CBotReturn
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::GivRetVar(bool bRet)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_error == -3)
|
|
|
|
|
{
|
|
|
|
|
if ( m_var ) delete m_var;
|
|
|
|
|
m_var = m_retvar;
|
|
|
|
|
m_retvar = NULL;
|
|
|
|
|
m_error = 0;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
return bRet; // interrompu par autre chose que return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CBotStack::GivError(int& start, int& end)
|
|
|
|
|
{
|
|
|
|
|
start = m_start;
|
|
|
|
|
end = m_end;
|
|
|
|
|
return m_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type d'instruction sur la pile
|
|
|
|
|
int CBotStack::GivType(int mode)
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL) return -1;
|
|
|
|
|
return m_var->GivType(mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// type d'instruction sur la pile
|
|
|
|
|
CBotTypResult CBotStack::GivTypResult(int mode)
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL) return -1;
|
|
|
|
|
return m_var->GivTypResult(mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// type d'instruction sur la pile
|
|
|
|
|
void CBotStack::SetType(CBotTypResult& type)
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL) return;
|
|
|
|
|
m_var->SetType( type );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// trouve une variable par son token
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// ce peut <20>tre une variable compos<6F>e avec un point
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotVar* CBotStack::FindVar(CBotToken* &pToken, bool bUpdate, bool bModif)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
CBotString name = pToken->GivString();
|
|
|
|
|
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pp = p->m_listVar;
|
|
|
|
|
while ( pp != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (pp->GivName() == name)
|
|
|
|
|
{
|
|
|
|
|
if ( bUpdate )
|
2012-07-04 20:14:28 +00:00
|
|
|
|
pp->Maj(m_pUser, false);
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
return pp;
|
|
|
|
|
}
|
|
|
|
|
pp = pp->m_next;
|
|
|
|
|
}
|
|
|
|
|
p = p->m_prev;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotStack::FindVar(const char* name)
|
|
|
|
|
{
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pp = p->m_listVar;
|
|
|
|
|
while ( pp != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (pp->GivName() == name)
|
|
|
|
|
{
|
|
|
|
|
return pp;
|
|
|
|
|
}
|
|
|
|
|
pp = pp->m_next;
|
|
|
|
|
}
|
|
|
|
|
p = p->m_prev;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// retrouve une variable sur la pile selon son num<75>ro d'identification
|
2012-03-08 18:32:05 +00:00
|
|
|
|
// ce qui va plus vite que de comparer les noms.
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotVar* CBotStack::FindVar(long ident, bool bUpdate, bool bModif)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pp = p->m_listVar;
|
|
|
|
|
while ( pp != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (pp->GivUniqNum() == ident)
|
|
|
|
|
{
|
|
|
|
|
if ( bUpdate )
|
2012-07-04 20:14:28 +00:00
|
|
|
|
pp->Maj(m_pUser, false);
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
return pp;
|
|
|
|
|
}
|
|
|
|
|
pp = pp->m_next;
|
|
|
|
|
}
|
|
|
|
|
p = p->m_prev;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotVar* CBotStack::FindVar(CBotToken& Token, bool bUpdate, bool bModif)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotToken* pt = &Token;
|
|
|
|
|
return FindVar(pt, bUpdate, bModif);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotVar* CBotStack::CopyVar(CBotToken& Token, bool bUpdate)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotVar* pVar = FindVar( Token, bUpdate );
|
|
|
|
|
|
|
|
|
|
if ( pVar == NULL) return NULL;
|
|
|
|
|
|
|
|
|
|
CBotVar* pCopy = CBotVar::Create(pVar);
|
|
|
|
|
pCopy->Copy(pVar);
|
|
|
|
|
return pCopy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::SetState(int n, int limite)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_state = n;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_timer--; // d<>compte les op<6F>rations
|
|
|
|
|
return ( m_timer > limite ); // interrompu si timer pass<73>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::IncState(int limite)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
m_state++;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_timer--; // d<>compte les op<6F>rations
|
|
|
|
|
return ( m_timer > limite ); // interrompu si timer pass<73>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CBotStack::SetError(int n, CBotToken* token)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if ( n!= 0 && m_error != 0) return; // ne change pas une erreur d<>j<EFBFBD> existante
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_error = n;
|
|
|
|
|
if (token != NULL)
|
|
|
|
|
{
|
|
|
|
|
m_start = token->GivStart();
|
|
|
|
|
m_end = token->GivEnd();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotStack::ResetError(int n, int start, int end)
|
|
|
|
|
{
|
|
|
|
|
m_error = n;
|
|
|
|
|
m_start = start;
|
|
|
|
|
m_end = end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotStack::SetPosError(CBotToken* token)
|
|
|
|
|
{
|
|
|
|
|
m_start = token->GivStart();
|
|
|
|
|
m_end = token->GivEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotStack::SetTimer(int n)
|
|
|
|
|
{
|
|
|
|
|
m_initimer = n;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::Execute()
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
CBotCall* instr = NULL; // instruction la plus <20>lev<65>e
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotStack* pile;
|
|
|
|
|
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( p->m_next2 != NULL ) break;
|
|
|
|
|
if ( p->m_call != NULL )
|
|
|
|
|
{
|
|
|
|
|
instr = p->m_call;
|
|
|
|
|
pile = p->m_prev ;
|
|
|
|
|
}
|
|
|
|
|
p = p->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( instr == NULL ) return true; // ex<65>cution normale demand<6E>e
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!instr->Run(pile)) return false; // ex<65>cution <20> partir de l<>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
pile->m_next->Delete();
|
|
|
|
|
#else
|
|
|
|
|
delete pile->m_next;
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pile->m_next = EOX; // sp<73>cial pour reprise
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// met sur le stack le pointeur <20> une variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
void CBotStack::SetVar( CBotVar* var )
|
|
|
|
|
{
|
|
|
|
|
if (m_var) delete m_var; // remplacement d'une variable
|
|
|
|
|
m_var = var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// met sur le stack une copie d'une variable
|
|
|
|
|
void CBotStack::SetCopyVar( CBotVar* var )
|
|
|
|
|
{
|
|
|
|
|
if (m_var) delete m_var; // remplacement d'une variable
|
|
|
|
|
|
|
|
|
|
m_var = CBotVar::Create("", var->GivTypResult(2));
|
|
|
|
|
m_var->Copy( var );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotStack::GivVar()
|
|
|
|
|
{
|
|
|
|
|
return m_var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotStack::GivPtVar()
|
|
|
|
|
{
|
|
|
|
|
CBotVar* p = m_var;
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_var = NULL; // ne sera pas d<>truit donc
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotStack::GivCopyVar()
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL) return NULL;
|
|
|
|
|
CBotVar* v = CBotVar::Create("", m_var->GivType());
|
|
|
|
|
v->Copy( m_var );
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long CBotStack::GivVal()
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL) return 0;
|
|
|
|
|
return m_var->GivValInt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CBotStack::AddVar(CBotVar* pVar)
|
|
|
|
|
{
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// revient sur l'<27>lement p<>re
|
2012-03-08 18:32:05 +00:00
|
|
|
|
while (p != NULL && p->m_bBlock == 0) p = p->m_prev;
|
|
|
|
|
|
|
|
|
|
if ( p == NULL ) return;
|
|
|
|
|
|
|
|
|
|
/// p->m_bDontDelete = bDontDelete;
|
|
|
|
|
|
|
|
|
|
CBotVar** pp = &p->m_listVar;
|
|
|
|
|
while ( *pp != NULL ) pp = &(*pp)->m_next;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
*pp = pVar; // ajoute <20> la suite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2012-04-14 22:50:13 +00:00
|
|
|
|
if ( pVar->GivUniqNum() == 0 ) ASM_TRAP();
|
2012-03-08 18:32:05 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*void CBotStack::RestoreVar(CBotVar* pVar)
|
|
|
|
|
{
|
|
|
|
|
if ( !m_bDontDelete ) __asm int 3;
|
|
|
|
|
delete m_listVar;
|
|
|
|
|
m_listVar = pVar; // remplace directement
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
void CBotStack::SetBotCall(CBotProgram* p)
|
|
|
|
|
{
|
|
|
|
|
m_prog = p;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
m_bFunc = true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotProgram* CBotStack::GivBotCall(bool bFirst)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( ! bFirst ) return m_prog;
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
while ( p->m_prev != NULL ) p = p->m_prev;
|
|
|
|
|
return p->m_prog;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* CBotStack::GivPUser()
|
|
|
|
|
{
|
|
|
|
|
return m_pUser;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotTypResult& rettype)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotTypResult res;
|
|
|
|
|
|
|
|
|
|
// cherche d'abord selon l'identificateur
|
|
|
|
|
|
|
|
|
|
res = CBotCall::DoCall(nIdent, NULL, ppVar, this, rettype );
|
|
|
|
|
if (res.GivType() >= 0) return res.GivType();
|
|
|
|
|
|
|
|
|
|
res = m_prog->GivFunctions()->DoCall(nIdent, NULL, ppVar, this, token );
|
|
|
|
|
if (res.GivType() >= 0) return res.GivType();
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// si pas trouv<75> (recompil<69> ?) cherche selon le nom
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
nIdent = 0;
|
|
|
|
|
res = CBotCall::DoCall(nIdent, token, ppVar, this, rettype );
|
|
|
|
|
if (res.GivType() >= 0) return res.GivType();
|
|
|
|
|
|
|
|
|
|
res = m_prog->GivFunctions()->DoCall(nIdent, token->GivString(), ppVar, this, token );
|
|
|
|
|
if (res.GivType() >= 0) return res.GivType();
|
|
|
|
|
|
|
|
|
|
SetError(TX_NOCALL, token);
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotStack::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar)
|
|
|
|
|
{
|
|
|
|
|
if ( m_next == NULL ) return;
|
|
|
|
|
|
|
|
|
|
if ( !CBotCall::RestoreCall(nIdent, token, ppVar, this) )
|
|
|
|
|
m_prog->GivFunctions()->RestoreCall(nIdent, token->GivString(), ppVar, this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool SaveVar(FILE* pf, CBotVar* pVar)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
while ( true )
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( pVar == NULL )
|
|
|
|
|
{
|
|
|
|
|
return WriteWord(pf, 0); // met un terminateur
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( !pVar->Save0State(pf)) return false; // ent<6E>te commune
|
|
|
|
|
if ( !pVar->Save1State(pf) ) return false; // sauve selon la classe fille
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
pVar = pVar->GivNext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotStack::GetRunPos(const char* &FunctionName, int &start, int &end)
|
|
|
|
|
{
|
|
|
|
|
CBotProgram* prog = m_prog; // programme courrant
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
CBotInstr* funct = NULL; // fonction trouv<75>e
|
|
|
|
|
CBotInstr* instr = NULL; // instruction la plus <20>lev<65>e
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
|
|
|
|
|
while (p->m_next != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( p->m_instr != NULL ) instr = p->m_instr;
|
|
|
|
|
if ( p->m_bFunc == 1 ) funct = p->m_instr;
|
|
|
|
|
if ( p->m_next->m_prog != prog ) break ;
|
|
|
|
|
|
|
|
|
|
if (p->m_next2 && p->m_next2->m_state != 0) p = p->m_next2 ;
|
|
|
|
|
else p = p->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p->m_instr != NULL ) instr = p->m_instr;
|
|
|
|
|
if ( p->m_bFunc == 1 ) funct = p->m_instr;
|
|
|
|
|
|
|
|
|
|
if ( funct == NULL ) return;
|
|
|
|
|
|
|
|
|
|
CBotToken* t = funct->GivToken();
|
|
|
|
|
FunctionName = t->GivString();
|
|
|
|
|
|
|
|
|
|
// if ( p->m_instr != NULL ) instr = p->m_instr;
|
|
|
|
|
|
|
|
|
|
t = instr->GivToken();
|
|
|
|
|
start = t->GivStart();
|
|
|
|
|
end = t->GivEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotStack::GivStackVars(const char* &FunctionName, int level)
|
|
|
|
|
{
|
|
|
|
|
CBotProgram* prog = m_prog; // programme courrant
|
|
|
|
|
FunctionName = NULL;
|
|
|
|
|
|
|
|
|
|
// remonte la pile dans le module courant
|
|
|
|
|
CBotStack* p = this;
|
|
|
|
|
|
|
|
|
|
while (p->m_next != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( p->m_next->m_prog != prog ) break ;
|
|
|
|
|
|
|
|
|
|
if (p->m_next2 && p->m_next2->m_state != 0) p = p->m_next2 ;
|
|
|
|
|
else p = p->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// descend sur les <20>l<EFBFBD>ments de block
|
2012-03-08 18:32:05 +00:00
|
|
|
|
while ( p != NULL && !p->m_bBlock ) p = p->m_prev;
|
|
|
|
|
|
|
|
|
|
while ( p != NULL && level++ < 0 )
|
|
|
|
|
{
|
|
|
|
|
p = p->m_prev;
|
|
|
|
|
while ( p != NULL && !p->m_bBlock ) p = p->m_prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p == NULL ) return NULL;
|
|
|
|
|
|
|
|
|
|
// recherche le nom de la fonction courante
|
|
|
|
|
CBotStack* pp = p;
|
|
|
|
|
while ( pp != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pp->m_bFunc == 1 ) break;
|
|
|
|
|
pp = pp->m_prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( pp == NULL || pp->m_instr == NULL ) return NULL;
|
|
|
|
|
|
|
|
|
|
CBotToken* t = pp->m_instr->GivToken();
|
|
|
|
|
FunctionName = t->GivString();
|
|
|
|
|
|
|
|
|
|
return p->m_listVar;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::SaveState(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( this == NULL ) // fin de l'arbre ?
|
|
|
|
|
{
|
|
|
|
|
return WriteWord(pf, 0); // met un terminateur
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_next2 != NULL )
|
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!WriteWord(pf, 2)) return false; // une marque de poursuite
|
|
|
|
|
if (!m_next2->SaveState(pf)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!WriteWord(pf, 1)) return false; // une marque de poursuite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!WriteWord(pf, m_bBlock)) return false; // est-ce un bloc local
|
|
|
|
|
if (!WriteWord(pf, m_state)) return false; // dans quel <20>tat
|
|
|
|
|
if (!WriteWord(pf, 0)) return false; // par compatibilit<69> m_bDontDelete
|
|
|
|
|
if (!WriteWord(pf, m_step)) return false; // dans quel <20>tat
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!SaveVar(pf, m_var)) return false; // le r<>sultat courant
|
|
|
|
|
if (!SaveVar(pf, m_listVar)) return false; // les variables locales
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
return m_next->SaveState(pf); // enregistre la suite
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotStack::RestoreState(FILE* pf, CBotStack* &pStack)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
unsigned short w;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
pStack = NULL;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, w)) return false;
|
|
|
|
|
if ( w == 0 ) return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
if ( this == NULL ) pStack = FirstStack();
|
|
|
|
|
else pStack = AddStack();
|
|
|
|
|
#else
|
|
|
|
|
pStack = new CBotStack(this);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( w == 2 )
|
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!pStack->RestoreState(pf, pStack->m_next2)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, w)) return false; // est-ce un bloc local
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pStack->m_bBlock = w;
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, w)) return false; // dans quel <20>tat j'<27>re ?
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pStack->SetState((short)w); // dans le bon <20>tat
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, w)) return false; // dont delete ?
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// plus utilis<69>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, w)) return false; // pas <20> pas
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pStack->m_step = w;
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!CBotVar::RestoreState(pf, pStack->m_var)) return false; // la variable temp
|
|
|
|
|
if (!CBotVar::RestoreState(pf, pStack->m_listVar)) return false;// les variables locales
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
return pStack->RestoreState(pf, pStack->m_next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVar::Save0State(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!WriteWord(pf, 100+m_mPrivate))return false; // variable priv<69>e ?
|
|
|
|
|
if (!WriteWord(pf, m_bStatic))return false; // variable static ?
|
|
|
|
|
if (!WriteWord(pf, m_type.GivType()))return false; // enregiste le type (toujours non nul)
|
|
|
|
|
if (!WriteWord(pf, m_binit))return false; // variable d<>finie ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return WriteString(pf, m_token->GivString()); // et le nom de la variable
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVarInt::Save0State(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if ( !m_defnum.IsEmpty() )
|
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if(!WriteWord(pf, 200 )) return false; // marqueur sp<73>cial
|
|
|
|
|
if(!WriteString(pf, m_defnum)) return false; // nom de la valeur
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CBotVar::Save0State(pf);
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVarInt::Save1State(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
return WriteWord(pf, m_val); // la valeur de la variable
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVarBoolean::Save1State(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
return WriteWord(pf, m_val); // la valeur de la variable
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVarFloat::Save1State(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
return WriteFloat(pf, m_val); // la valeur de la variable
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVarString::Save1State(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
return WriteString(pf, m_val); // la valeur de la variable
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVarClass::Save1State(FILE* pf)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( !WriteType(pf, m_type) ) return false;
|
|
|
|
|
if ( !WriteLong(pf, m_ItemIdent) ) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
return SaveVar(pf, m_pVar); // contenu de l'objet
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
unsigned short w, wi, prv, st;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
float ww;
|
|
|
|
|
CBotString name, s;
|
|
|
|
|
|
|
|
|
|
delete pVar;
|
|
|
|
|
|
|
|
|
|
pVar = NULL;
|
|
|
|
|
CBotVar* pNew = NULL;
|
|
|
|
|
CBotVar* pPrev = NULL;
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
while ( true ) // recup<75>re toute une liste
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, w)) return false; // priv<69> ou type ?
|
|
|
|
|
if ( w == 0 ) return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotString defnum;
|
|
|
|
|
if ( w == 200 )
|
|
|
|
|
{
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadString(pf, defnum)) return false; // nombre avec un identifiant
|
|
|
|
|
if (!ReadWord(pf, w)) return false; // type
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prv = 100; st = 0;
|
|
|
|
|
if ( w >= 100 )
|
|
|
|
|
{
|
|
|
|
|
prv = w;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, st)) return false; // statique
|
|
|
|
|
if (!ReadWord(pf, w)) return false; // type
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if ( w == CBotTypClass ) w = CBotTypIntrinsic; // forc<72>ment intrins<6E>que
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, wi)) return false; // init ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadString(pf, name)) return false; // nom de la variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotToken token(name, CBotString());
|
|
|
|
|
|
|
|
|
|
switch (w)
|
|
|
|
|
{
|
|
|
|
|
case CBotTypInt:
|
|
|
|
|
case CBotTypBoolean:
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pNew = CBotVar::Create(&token, w); // cr<63>e une variable
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadWord(pf, w)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pNew->SetValInt((short)w, defnum);
|
|
|
|
|
break;
|
|
|
|
|
case CBotTypFloat:
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pNew = CBotVar::Create(&token, w); // cr<63>e une variable
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadFloat(pf, ww)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pNew->SetValFloat(ww);
|
|
|
|
|
break;
|
|
|
|
|
case CBotTypString:
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pNew = CBotVar::Create(&token, w); // cr<63>e une variable
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadString(pf, s)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pNew->SetValString(s);
|
|
|
|
|
break;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// restitue un objet intrinsic ou un <20>l<EFBFBD>ment d'un array
|
2012-03-08 18:32:05 +00:00
|
|
|
|
case CBotTypIntrinsic:
|
|
|
|
|
case CBotTypArrayBody:
|
|
|
|
|
{
|
|
|
|
|
CBotTypResult r;
|
|
|
|
|
long id;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadType(pf, r)) return false; // type complet
|
|
|
|
|
if (!ReadLong(pf, id) ) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
// if (!ReadString(pf, s)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotVar* p = NULL;
|
|
|
|
|
if ( id ) p = CBotVarClass::Find(id) ;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pNew = new CBotVarClass(&token, r); // cr<63>e directement une instance
|
2012-03-08 18:32:05 +00:00
|
|
|
|
// attention cptuse = 0
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( !RestoreState(pf, ((CBotVarClass*)pNew)->m_pVar)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pNew->SetIdent(id);
|
|
|
|
|
|
|
|
|
|
if ( p != NULL )
|
|
|
|
|
{
|
|
|
|
|
delete pNew;
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pNew = p; // reprend l'<27>l<EFBFBD>ment connu
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CBotTypPointer:
|
|
|
|
|
case CBotTypNullPointer:
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadString(pf, s)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pNew = CBotVar::Create(&token, CBotTypResult(w, s));// cr<63>e une variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotVarClass* p = NULL;
|
|
|
|
|
long id;
|
|
|
|
|
ReadLong(pf, id);
|
|
|
|
|
// if ( id ) p = CBotVarClass::Find(id); // retrouve l'instance ( fait par RestoreInstance )
|
|
|
|
|
|
|
|
|
|
// restitue une copie de l'instance d'origine
|
|
|
|
|
CBotVar* pInstance = NULL;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( !CBotVar::RestoreState( pf, pInstance ) ) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
((CBotVarPointer*)pNew)->SetPointer( pInstance ); // et pointe dessus
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// if ( p != NULL ) ((CBotVarPointer*)pNew)->SetPointer( p ); // plut<75>t celui-ci !
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CBotTypArrayPointer:
|
|
|
|
|
{
|
|
|
|
|
CBotTypResult r;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (!ReadType(pf, r)) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
pNew = CBotVar::Create(&token, r); // cr<63>e une variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
// restitue une copie de l'instance d'origine
|
|
|
|
|
CBotVar* pInstance = NULL;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( !CBotVar::RestoreState( pf, pInstance ) ) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
((CBotVarPointer*)pNew)->SetPointer( pInstance ); // et pointe dessus
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2012-04-14 22:50:13 +00:00
|
|
|
|
ASM_TRAP();
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( pPrev != NULL ) pPrev->m_next = pNew;
|
|
|
|
|
if ( pVar == NULL ) pVar = pNew;
|
|
|
|
|
|
|
|
|
|
pNew->m_binit = wi; // pNew->SetInit(wi);
|
|
|
|
|
pNew->SetStatic(st);
|
|
|
|
|
pNew->SetPrivate(prv-100);
|
|
|
|
|
pPrev = pNew;
|
|
|
|
|
}
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// gestion de la pile <20> la compilation
|
2012-03-08 18:32:05 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
CBotProgram* CBotCStack::m_prog = NULL; // init la variable statique
|
|
|
|
|
int CBotCStack::m_error = 0;
|
|
|
|
|
int CBotCStack::m_end = 0;
|
|
|
|
|
CBotTypResult CBotCStack::m_retTyp = CBotTypResult(0);
|
|
|
|
|
//CBotToken* CBotCStack::m_retClass= NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotCStack::CBotCStack(CBotCStack* ppapa)
|
|
|
|
|
{
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
m_prev = ppapa;
|
|
|
|
|
|
|
|
|
|
if (ppapa == NULL)
|
|
|
|
|
{
|
|
|
|
|
m_error = 0;
|
|
|
|
|
m_start = 0;
|
|
|
|
|
m_end = 0;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
m_bBlock = true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_start = ppapa->m_start;
|
2012-07-04 20:14:28 +00:00
|
|
|
|
m_bBlock = false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_listVar = NULL;
|
|
|
|
|
m_var = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// destructeur
|
|
|
|
|
CBotCStack::~CBotCStack()
|
|
|
|
|
{
|
|
|
|
|
if (m_next != NULL) delete m_next;
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (m_prev != NULL) m_prev->m_next = NULL; // enl<6E>ve de la cha<68>ne
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
delete m_var;
|
|
|
|
|
delete m_listVar;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// utilis<69> uniquement <20> la compilation
|
2012-07-04 20:14:28 +00:00
|
|
|
|
CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_next != NULL) return m_next; // reprise dans une pile existante
|
|
|
|
|
|
|
|
|
|
CBotCStack* p = new CBotCStack(this);
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_next = p; // cha<68>ne l'<27>l<EFBFBD>ment
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p->m_bBlock = bBlock;
|
|
|
|
|
|
|
|
|
|
if (pToken != NULL) p->SetStartError(pToken->GivStart());
|
|
|
|
|
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
|
|
|
|
|
{
|
|
|
|
|
if ( pfils == this ) return inst;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (m_var != NULL) delete m_var; // valeur remplac<61>e ?
|
|
|
|
|
m_var = pfils->m_var; // r<>sultat transmis
|
|
|
|
|
pfils->m_var = NULL; // ne pas d<>truire la variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
if (m_error)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_start = pfils->m_start; // r<>cup<75>re la position de l'erreur
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_end = pfils->m_end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete pfils;
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (m_var != NULL) delete m_var; // valeur remplac<61>e ?
|
|
|
|
|
m_var = pfils->m_var; // r<>sultat transmis
|
|
|
|
|
pfils->m_var = NULL; // ne pas d<>truire la variable
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
if (m_error)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
m_start = pfils->m_start; // r<>cup<75>re la position de l'erreur
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_end = pfils->m_end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete pfils;
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CBotCStack::GivError(int& start, int& end)
|
|
|
|
|
{
|
|
|
|
|
start = m_start;
|
|
|
|
|
end = m_end;
|
|
|
|
|
return m_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CBotCStack::GivError()
|
|
|
|
|
{
|
|
|
|
|
return m_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// type d'instruction sur la pile
|
|
|
|
|
CBotTypResult CBotCStack::GivTypResult(int mode)
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL)
|
|
|
|
|
return CBotTypResult(99);
|
|
|
|
|
return m_var->GivTypResult(mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// type d'instruction sur la pile
|
|
|
|
|
int CBotCStack::GivType(int mode)
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL)
|
|
|
|
|
return 99;
|
|
|
|
|
return m_var->GivType(mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pointeur sur la pile est de quelle classe ?
|
|
|
|
|
CBotClass* CBotCStack::GivClass()
|
|
|
|
|
{
|
|
|
|
|
if ( m_var == NULL )
|
|
|
|
|
return NULL;
|
|
|
|
|
if ( m_var->GivType(1) != CBotTypPointer ) return NULL;
|
|
|
|
|
|
|
|
|
|
return m_var->GivClass();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// type d'instruction sur la pile
|
|
|
|
|
void CBotCStack::SetType(CBotTypResult& type)
|
|
|
|
|
{
|
|
|
|
|
if (m_var == NULL) return;
|
|
|
|
|
m_var->SetType( type );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cherche une variable sur la pile
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// le token peut <20>tre une suite de TokenTypVar (objet d'une classe)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
// ou un pointeur dans le source
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotCStack::FindVar(CBotToken* &pToken)
|
|
|
|
|
{
|
|
|
|
|
CBotCStack* p = this;
|
|
|
|
|
CBotString name = pToken->GivString();
|
|
|
|
|
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pp = p->m_listVar;
|
|
|
|
|
while ( pp != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (name == pp->GivName())
|
|
|
|
|
{
|
|
|
|
|
return pp;
|
|
|
|
|
}
|
|
|
|
|
pp = pp->m_next;
|
|
|
|
|
}
|
|
|
|
|
p = p->m_prev;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotCStack::FindVar(CBotToken& Token)
|
|
|
|
|
{
|
|
|
|
|
CBotToken* pt = &Token;
|
|
|
|
|
return FindVar(pt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotCStack::CopyVar(CBotToken& Token)
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pVar = FindVar( Token );
|
|
|
|
|
|
|
|
|
|
if ( pVar == NULL) return NULL;
|
|
|
|
|
|
|
|
|
|
CBotVar* pCopy = CBotVar::Create( "", pVar->GivType() );
|
|
|
|
|
pCopy->Copy(pVar);
|
|
|
|
|
return pCopy;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotCStack::IsOk()
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
return (m_error == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CBotCStack::SetStartError( int pos )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if ( m_error != 0) return; // ne change pas une erreur d<>j<EFBFBD> existante
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_start = pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCStack::SetError(int n, int pos)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if ( n!= 0 && m_error != 0) return; // ne change pas une erreur d<>j<EFBFBD> existante
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_error = n;
|
|
|
|
|
m_end = pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCStack::SetError(int n, CBotToken* p)
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
if (m_error) return; // ne change pas une erreur d<>j<EFBFBD> existante
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_error = n;
|
|
|
|
|
m_start = p->GivStart();
|
|
|
|
|
m_end = p->GivEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCStack::ResetError(int n, int start, int end)
|
|
|
|
|
{
|
|
|
|
|
m_error = n;
|
|
|
|
|
m_start = start;
|
|
|
|
|
m_end = end;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotCStack::NextToken(CBotToken* &p)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotToken* pp = p;
|
|
|
|
|
|
|
|
|
|
p = p->GivNext();
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if (p!=NULL) return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
SetError(TX_ENDOF, pp->GivEnd());
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCStack::SetBotCall(CBotProgram* p)
|
|
|
|
|
{
|
|
|
|
|
m_prog = p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotProgram* CBotCStack::GivBotCall()
|
|
|
|
|
{
|
|
|
|
|
return m_prog;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCStack::SetRetType(CBotTypResult& type)
|
|
|
|
|
{
|
|
|
|
|
m_retTyp = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotTypResult CBotCStack::GivRetType()
|
|
|
|
|
{
|
|
|
|
|
return m_retTyp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCStack::SetVar( CBotVar* var )
|
|
|
|
|
{
|
|
|
|
|
if (m_var) delete m_var; // remplacement d'une variable
|
|
|
|
|
m_var = var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// met sur le stack une copie d'une variable
|
|
|
|
|
void CBotCStack::SetCopyVar( CBotVar* var )
|
|
|
|
|
{
|
|
|
|
|
if (m_var) delete m_var; // remplacement d'une variable
|
|
|
|
|
|
|
|
|
|
if ( var == NULL ) return;
|
|
|
|
|
m_var = CBotVar::Create("", var->GivTypResult(2));
|
|
|
|
|
m_var->Copy( var );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotCStack::GivVar()
|
|
|
|
|
{
|
|
|
|
|
return m_var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCStack::AddVar(CBotVar* pVar)
|
|
|
|
|
{
|
|
|
|
|
CBotCStack* p = this;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// revient sur l'<27>lement p<>re
|
2012-03-08 18:32:05 +00:00
|
|
|
|
while (p != NULL && p->m_bBlock == 0) p = p->m_prev;
|
|
|
|
|
|
|
|
|
|
if ( p == NULL ) return;
|
|
|
|
|
|
|
|
|
|
CBotVar** pp = &p->m_listVar;
|
|
|
|
|
while ( *pp != NULL ) pp = &(*pp)->m_next;
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
*pp = pVar; // ajoute <20> la suite
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2012-04-14 22:50:13 +00:00
|
|
|
|
if ( pVar->GivUniqNum() == 0 ) ASM_TRAP();
|
2012-03-08 18:32:05 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// test si une variable est d<>j<EFBFBD> d<>finie localement
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotCStack* p = this;
|
|
|
|
|
CBotString name = pToken->GivString();
|
|
|
|
|
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pp = p->m_listVar;
|
|
|
|
|
while ( pp != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (name == pp->GivName())
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
pp = pp->m_next;
|
|
|
|
|
}
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( p->m_bBlock ) return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p = p->m_prev;
|
|
|
|
|
}
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nIdent)
|
|
|
|
|
{
|
|
|
|
|
nIdent = 0;
|
|
|
|
|
CBotTypResult val(-1);
|
|
|
|
|
|
|
|
|
|
val = CBotCall::CompileCall(p, ppVars, this, nIdent);
|
|
|
|
|
if (val.GivType() < 0)
|
|
|
|
|
{
|
|
|
|
|
val = m_prog->GivFunctions()->CompileCall(p->GivString(), ppVars, nIdent);
|
|
|
|
|
if ( val.GivType() < 0 )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// pVar = NULL; // l'erreur n'est pas sur un param<61>tre en particulier
|
2012-03-08 18:32:05 +00:00
|
|
|
|
SetError( -val.GivType(), p );
|
|
|
|
|
val.SetType(-val.GivType());
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// test si un nom de proc<6F>dure est d<>j<EFBFBD> d<>fini quelque part
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
{
|
|
|
|
|
CBotString name = pToken->GivString();
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
if ( CBotCall::CheckCall(name) ) return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotFunction* pp = m_prog->GivFunctions();
|
|
|
|
|
while ( pp != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pToken->GivString() == pp->GivName() )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// les param<61>tres sont-ils exactement les m<>mes ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( pp->CheckParam( pParam ) )
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
pp = pp->Next();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pp = CBotFunction::m_listPublic;
|
|
|
|
|
while ( pp != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pToken->GivString() == pp->GivName() )
|
|
|
|
|
{
|
2012-03-19 11:44:39 +00:00
|
|
|
|
// les param<61>tres sont-ils exactement les m<>mes ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( pp->CheckParam( pParam ) )
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return true;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
pp = pp->m_nextpublic;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 20:14:28 +00:00
|
|
|
|
return false;
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|