2012-03-09 16:08:05 +00:00
|
|
|
|
// * This file is part of the COLOBOT source code
|
|
|
|
|
// * 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-11 19:49:33 +00:00
|
|
|
|
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
#include "CBot.h"
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
CBotProgram::CBotProgram()
|
|
|
|
|
{
|
|
|
|
|
m_Prog = NULL;
|
|
|
|
|
m_pRun = NULL;
|
|
|
|
|
m_pClass = NULL;
|
|
|
|
|
m_pStack = NULL;
|
|
|
|
|
m_pInstance = NULL;
|
|
|
|
|
|
|
|
|
|
m_ErrorCode = 0;
|
|
|
|
|
m_Ident = 0;
|
|
|
|
|
m_bDebugDD = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotProgram::CBotProgram(CBotVar* pInstance)
|
|
|
|
|
{
|
|
|
|
|
m_Prog = NULL;
|
|
|
|
|
m_pRun = NULL;
|
|
|
|
|
m_pClass = NULL;
|
|
|
|
|
m_pStack = NULL;
|
|
|
|
|
m_pInstance = pInstance;
|
|
|
|
|
|
|
|
|
|
m_ErrorCode = 0;
|
|
|
|
|
m_Ident = 0;
|
|
|
|
|
m_bDebugDD = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotProgram::~CBotProgram()
|
|
|
|
|
{
|
|
|
|
|
// delete m_pClass;
|
|
|
|
|
m_pClass->Purge();
|
|
|
|
|
m_pClass = NULL;
|
|
|
|
|
|
|
|
|
|
CBotClass::FreeLock(this);
|
|
|
|
|
|
|
|
|
|
delete m_Prog;
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
m_pStack->Delete();
|
|
|
|
|
#else
|
|
|
|
|
delete m_pStack;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::Compile( const char* program, CBotStringArray& ListFonctions, void* pUser )
|
|
|
|
|
{
|
|
|
|
|
int error = 0;
|
|
|
|
|
Stop();
|
|
|
|
|
|
|
|
|
|
// delete m_pClass;
|
2012-03-09 16:08:05 +00:00
|
|
|
|
m_pClass->Purge(); // purge les anciennes d<>finitions des classes
|
|
|
|
|
// mais sans d<>truire l'object
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_pClass = NULL;
|
|
|
|
|
delete m_Prog; m_Prog= NULL;
|
|
|
|
|
|
|
|
|
|
ListFonctions.SetSize(0);
|
|
|
|
|
m_ErrorCode = 0;
|
|
|
|
|
|
|
|
|
|
if (m_pInstance != NULL && m_pInstance->m_pUserPtr != NULL)
|
|
|
|
|
pUser = m_pInstance->m_pUserPtr;
|
|
|
|
|
|
|
|
|
|
// transforme le programme en Tokens
|
|
|
|
|
CBotToken* pBaseToken = CBotToken::CompileTokens(program, error);
|
|
|
|
|
if ( pBaseToken == NULL ) return FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotCStack* pStack = new CBotCStack(NULL);
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken* p = pBaseToken->GivNext(); // saute le 1er token (s<>parateur)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
pStack->SetBotCall(this); // d<>fini les routines utilisables
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotCall::SetPUser(pUser);
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// fait une premi<6D>re passe rapide juste pour prendre les ent<6E>tes de routines et de classes
|
2012-03-08 18:32:05 +00:00
|
|
|
|
while ( pStack->IsOk() && p != NULL && p->GivType() != 0)
|
|
|
|
|
{
|
|
|
|
|
if ( IsOfType(p, ID_SEP) ) continue; // des point-virgules qui trainent
|
|
|
|
|
|
|
|
|
|
if ( p->GivType() == ID_CLASS ||
|
|
|
|
|
( p->GivType() == ID_PUBLIC && p->GivNext()->GivType() == ID_CLASS ))
|
|
|
|
|
{
|
|
|
|
|
CBotClass* nxt = CBotClass::Compile1(p, pStack);
|
|
|
|
|
if (m_pClass == NULL ) m_pClass = nxt;
|
|
|
|
|
else m_pClass->AddNext(nxt);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CBotFunction* next = CBotFunction::Compile1(p, pStack, NULL);
|
|
|
|
|
if (m_Prog == NULL ) m_Prog = next;
|
|
|
|
|
else m_Prog->AddNext(next);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( !pStack->IsOk() )
|
|
|
|
|
{
|
|
|
|
|
m_ErrorCode = pStack->GivError(m_ErrorStart, m_ErrorEnd);
|
|
|
|
|
delete m_Prog;
|
|
|
|
|
m_Prog = NULL;
|
|
|
|
|
delete pBaseToken;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CBotFunction* temp = NULL;
|
|
|
|
|
CBotFunction* next = m_Prog; // reprend la liste
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
p = pBaseToken->GivNext(); // revient au d<>but
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
while ( pStack->IsOk() && p != NULL && p->GivType() != 0 )
|
|
|
|
|
{
|
|
|
|
|
if ( IsOfType(p, ID_SEP) ) continue; // des point-virgules qui trainent
|
|
|
|
|
|
|
|
|
|
if ( p->GivType() == ID_CLASS ||
|
|
|
|
|
( p->GivType() == ID_PUBLIC && p->GivNext()->GivType() == ID_CLASS ))
|
|
|
|
|
{
|
|
|
|
|
m_bCompileClass = TRUE;
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotClass::Compile(p, pStack); // compl<70>te la d<>finition de la classe
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_bCompileClass = FALSE;
|
|
|
|
|
CBotFunction::Compile(p, pStack, next);
|
|
|
|
|
if (next->IsExtern()) ListFonctions.Add(next->GivName()/* + next->GivParams()*/);
|
|
|
|
|
next->m_pProg = this; // garde le pointeur au module
|
|
|
|
|
next = next->Next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// delete m_Prog; // la liste de la 1<>re passe
|
2012-03-08 18:32:05 +00:00
|
|
|
|
// m_Prog = temp; // la liste de la seconde passe
|
|
|
|
|
|
|
|
|
|
if ( !pStack->IsOk() )
|
|
|
|
|
{
|
|
|
|
|
m_ErrorCode = pStack->GivError(m_ErrorStart, m_ErrorEnd);
|
|
|
|
|
delete m_Prog;
|
|
|
|
|
m_Prog = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete pBaseToken;
|
|
|
|
|
delete pStack;
|
|
|
|
|
|
|
|
|
|
return (m_Prog != NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::Start(const char* name)
|
|
|
|
|
{
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
m_pStack->Delete();
|
|
|
|
|
#else
|
|
|
|
|
delete m_pStack;
|
|
|
|
|
#endif
|
|
|
|
|
m_pStack = NULL;
|
|
|
|
|
|
|
|
|
|
m_pRun = m_Prog;
|
|
|
|
|
while (m_pRun != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( m_pRun->GivName() == name ) break;
|
|
|
|
|
m_pRun = m_pRun->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_pRun == NULL )
|
|
|
|
|
{
|
|
|
|
|
m_ErrorCode = TX_NORUN;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
m_pStack = CBotStack::FirstStack();
|
|
|
|
|
#else
|
2012-03-09 16:08:05 +00:00
|
|
|
|
m_pStack = new CBotStack(NULL); // cr<63>e une pile d'ex<65>cution
|
2012-03-08 18:32:05 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
m_pStack->SetBotCall(this); // bases pour les routines
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
return TRUE; // on est pr<70>t pour un Run()
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::GetPosition(const char* name, int& start, int& stop, CBotGet modestart, CBotGet modestop)
|
|
|
|
|
{
|
|
|
|
|
CBotFunction* p = m_Prog;
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
if ( p->GivName() == name ) break;
|
|
|
|
|
p = p->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p == NULL ) return FALSE;
|
|
|
|
|
|
|
|
|
|
p->GetPosition(start, stop, modestart, modestop);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::Run(void* pUser, int timer)
|
|
|
|
|
{
|
|
|
|
|
BOOL ok;
|
|
|
|
|
|
|
|
|
|
if (m_pStack == NULL || m_pRun == NULL) goto error;
|
|
|
|
|
|
|
|
|
|
m_ErrorCode = 0;
|
|
|
|
|
if (m_pInstance != NULL && m_pInstance->m_pUserPtr != NULL)
|
|
|
|
|
pUser = m_pInstance->m_pUserPtr;
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
m_pStack->Reset(pUser); // vide l'<27>ventuelle erreur pr<70>c<EFBFBD>dente, et remet le timer
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( timer >= 0 ) m_pStack->SetTimer(timer);
|
|
|
|
|
|
|
|
|
|
m_pStack->SetBotCall(this); // bases pour les routines
|
|
|
|
|
|
|
|
|
|
#if STACKRUN
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// reprend l'ex<65>cution sur le haut de la pile
|
2012-03-08 18:32:05 +00:00
|
|
|
|
ok = m_pStack->Execute();
|
|
|
|
|
if ( ok )
|
|
|
|
|
{
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
CBotVar* ppVar[3];
|
|
|
|
|
ppVar[0] = CBotVar::Create("aa", CBotTypInt);
|
|
|
|
|
ppVar[1] = CBotVar::Create("bb", CBotTypInt);
|
|
|
|
|
ppVar[2] = NULL;
|
|
|
|
|
ok = m_pRun->Execute(ppVar, m_pStack, m_pInstance);
|
|
|
|
|
#else
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// revient sur l'ex<65>cution normale
|
2012-03-08 18:32:05 +00:00
|
|
|
|
ok = m_pRun->Execute(NULL, m_pStack, m_pInstance);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
ok = m_pRun->Execute(NULL, m_pStack, m_pInstance);
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// termin<69> sur une erreur ?
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if (!ok && !m_pStack->IsOk())
|
|
|
|
|
{
|
|
|
|
|
m_ErrorCode = m_pStack->GivError(m_ErrorStart, m_ErrorEnd);
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
m_pStack->Delete();
|
|
|
|
|
#else
|
|
|
|
|
delete m_pStack;
|
|
|
|
|
#endif
|
|
|
|
|
m_pStack = NULL;
|
2012-03-09 16:08:05 +00:00
|
|
|
|
return TRUE; // ex<65>cution termin<69>e !!
|
2012-03-08 18:32:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
if ( ok ) m_pRun = NULL; // plus de fonction en ex<65>cution
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return ok;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
m_ErrorCode = TX_NORUN;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotProgram::Stop()
|
|
|
|
|
{
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
m_pStack->Delete();
|
|
|
|
|
#else
|
|
|
|
|
delete m_pStack;
|
|
|
|
|
#endif
|
|
|
|
|
m_pStack = NULL;
|
|
|
|
|
m_pRun = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::GetRunPos(const char* &FunctionName, int &start, int &end)
|
|
|
|
|
{
|
|
|
|
|
FunctionName = NULL;
|
|
|
|
|
start = end = 0;
|
|
|
|
|
if (m_pStack == NULL) return FALSE;
|
|
|
|
|
|
|
|
|
|
m_pStack->GetRunPos(FunctionName, start, end);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotVar* CBotProgram::GivStackVars(const char* &FunctionName, int level)
|
|
|
|
|
{
|
|
|
|
|
FunctionName = NULL;
|
|
|
|
|
if (m_pStack == NULL) return NULL;
|
|
|
|
|
|
|
|
|
|
return m_pStack->GivStackVars(FunctionName, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CBotProgram::SetTimer(int n)
|
|
|
|
|
{
|
|
|
|
|
CBotStack::SetTimer( n );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CBotProgram::GivError()
|
|
|
|
|
{
|
|
|
|
|
return m_ErrorCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotProgram::SetIdent(long n)
|
|
|
|
|
{
|
|
|
|
|
m_Ident = n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long CBotProgram::GivIdent()
|
|
|
|
|
{
|
|
|
|
|
return m_Ident;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::GetError(int& code, int& start, int& end)
|
|
|
|
|
{
|
|
|
|
|
code = m_ErrorCode;
|
|
|
|
|
start = m_ErrorStart;
|
|
|
|
|
end = m_ErrorEnd;
|
|
|
|
|
return code > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::GetError(int& code, int& start, int& end, CBotProgram* &pProg)
|
|
|
|
|
{
|
|
|
|
|
code = m_ErrorCode;
|
|
|
|
|
start = m_ErrorStart;
|
|
|
|
|
end = m_ErrorEnd;
|
|
|
|
|
pProg = this;
|
|
|
|
|
return code > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotString CBotProgram::GivErrorText(int code)
|
|
|
|
|
{
|
|
|
|
|
CBotString TextError;
|
|
|
|
|
|
|
|
|
|
TextError.LoadString( code );
|
|
|
|
|
if (TextError.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
char buf[100];
|
2012-03-09 16:08:05 +00:00
|
|
|
|
sprintf(buf, "Exception num<75>ro %d.", code);
|
2012-03-08 18:32:05 +00:00
|
|
|
|
TextError = buf;
|
|
|
|
|
}
|
|
|
|
|
return TextError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotFunction* CBotProgram::GivFunctions()
|
|
|
|
|
{
|
|
|
|
|
return m_Prog;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::AddFunction(const char* name,
|
|
|
|
|
BOOL rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
|
|
|
|
|
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// m<>morise les pointeurs aux deux fonctions
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return CBotCall::AddFunction(name, rExec, rCompile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL WriteWord(FILE* pf, WORD w)
|
|
|
|
|
{
|
|
|
|
|
size_t lg;
|
|
|
|
|
|
|
|
|
|
lg = fwrite(&w, sizeof( WORD ), 1, pf );
|
|
|
|
|
|
|
|
|
|
return (lg == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL ReadWord(FILE* pf, WORD& w)
|
|
|
|
|
{
|
|
|
|
|
size_t lg;
|
|
|
|
|
|
|
|
|
|
lg = fread(&w, sizeof( WORD ), 1, pf );
|
|
|
|
|
|
|
|
|
|
return (lg == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WriteFloat(FILE* pf, float w)
|
|
|
|
|
{
|
|
|
|
|
size_t lg;
|
|
|
|
|
|
|
|
|
|
lg = fwrite(&w, sizeof( float ), 1, pf );
|
|
|
|
|
|
|
|
|
|
return (lg == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL ReadFloat(FILE* pf, float& w)
|
|
|
|
|
{
|
|
|
|
|
size_t lg;
|
|
|
|
|
|
|
|
|
|
lg = fread(&w, sizeof( float ), 1, pf );
|
|
|
|
|
|
|
|
|
|
return (lg == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WriteLong(FILE* pf, long w)
|
|
|
|
|
{
|
|
|
|
|
size_t lg;
|
|
|
|
|
|
|
|
|
|
lg = fwrite(&w, sizeof( long ), 1, pf );
|
|
|
|
|
|
|
|
|
|
return (lg == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL ReadLong(FILE* pf, long& w)
|
|
|
|
|
{
|
|
|
|
|
size_t lg;
|
|
|
|
|
|
|
|
|
|
lg = fread(&w, sizeof( long ), 1, pf );
|
|
|
|
|
|
|
|
|
|
return (lg == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WriteString(FILE* pf, CBotString s)
|
|
|
|
|
{
|
|
|
|
|
size_t lg1, lg2;
|
|
|
|
|
|
|
|
|
|
lg1 = s.GivLength();
|
|
|
|
|
if (!WriteWord(pf, lg1)) return FALSE;
|
|
|
|
|
|
|
|
|
|
lg2 = fwrite(s, 1, lg1, pf );
|
|
|
|
|
return (lg1 == lg2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL ReadString(FILE* pf, CBotString& s)
|
|
|
|
|
{
|
|
|
|
|
WORD w;
|
|
|
|
|
char buf[1000];
|
|
|
|
|
size_t lg1, lg2;
|
|
|
|
|
|
|
|
|
|
if (!ReadWord(pf, w)) return FALSE;
|
|
|
|
|
lg1 = w;
|
|
|
|
|
lg2 = fread(buf, 1, lg1, pf );
|
|
|
|
|
buf[lg2] = 0;
|
|
|
|
|
|
|
|
|
|
s = buf;
|
|
|
|
|
return (lg1 == lg2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WriteType(FILE* pf, CBotTypResult type)
|
|
|
|
|
{
|
|
|
|
|
int typ = type.GivType();
|
|
|
|
|
if ( typ == CBotTypIntrinsic ) typ = CBotTypClass;
|
|
|
|
|
if ( !WriteWord(pf, typ) ) return FALSE;
|
|
|
|
|
if ( typ == CBotTypClass )
|
|
|
|
|
{
|
|
|
|
|
CBotClass* p = type.GivClass();
|
|
|
|
|
if ( !WriteString(pf, p->GivName()) ) return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if ( type.Eq( CBotTypArrayBody ) ||
|
|
|
|
|
type.Eq( CBotTypArrayPointer ) )
|
|
|
|
|
{
|
|
|
|
|
if ( !WriteWord(pf, type.GivLimite()) ) return FALSE;
|
|
|
|
|
if ( !WriteType(pf, type.GivTypElem()) ) return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL ReadType(FILE* pf, CBotTypResult& type)
|
|
|
|
|
{
|
|
|
|
|
WORD w, ww;
|
|
|
|
|
if ( !ReadWord(pf, w) ) return FALSE;
|
|
|
|
|
type.SetType(w);
|
|
|
|
|
|
|
|
|
|
if ( type.Eq( CBotTypIntrinsic ) )
|
|
|
|
|
{
|
|
|
|
|
type = CBotTypResult( w, "point" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( type.Eq( CBotTypClass ) )
|
|
|
|
|
{
|
|
|
|
|
CBotString s;
|
|
|
|
|
if ( !ReadString(pf, s) ) return FALSE;
|
|
|
|
|
type = CBotTypResult( w, s );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( type.Eq( CBotTypArrayPointer ) ||
|
|
|
|
|
type.Eq( CBotTypArrayBody ) )
|
|
|
|
|
{
|
|
|
|
|
CBotTypResult r;
|
|
|
|
|
if ( !ReadWord(pf, ww) ) return FALSE;
|
|
|
|
|
if ( !ReadType(pf, r) ) return FALSE;
|
|
|
|
|
type = CBotTypResult( w, r );
|
|
|
|
|
type.SetLimite((short)ww);
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::DefineNum(const char* name, long val)
|
|
|
|
|
{
|
|
|
|
|
return CBotToken::DefineNum(name, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::SaveState(FILE* pf)
|
|
|
|
|
{
|
|
|
|
|
if (!WriteWord( pf, CBOTVERSION)) return FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( m_pStack != NULL )
|
|
|
|
|
{
|
|
|
|
|
if (!WriteWord( pf, 1)) return FALSE;
|
|
|
|
|
if (!WriteString( pf, m_pRun->GivName() )) return FALSE;
|
|
|
|
|
if (!m_pStack->SaveState(pf)) return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!WriteWord( pf, 0)) return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CBotProgram::RestoreState(FILE* pf)
|
|
|
|
|
{
|
|
|
|
|
WORD w;
|
|
|
|
|
CBotString s;
|
|
|
|
|
|
|
|
|
|
Stop();
|
|
|
|
|
|
|
|
|
|
if (!ReadWord( pf, w )) return FALSE;
|
|
|
|
|
if ( w != CBOTVERSION ) return FALSE;
|
|
|
|
|
|
|
|
|
|
if (!ReadWord( pf, w )) return FALSE;
|
|
|
|
|
if ( w == 0 ) return TRUE;
|
|
|
|
|
|
|
|
|
|
if (!ReadString( pf, s )) return FALSE;
|
|
|
|
|
Start(s); // point de reprise
|
|
|
|
|
|
|
|
|
|
#if STACKMEM
|
|
|
|
|
m_pStack->Delete();
|
|
|
|
|
#else
|
|
|
|
|
delete m_pStack;
|
|
|
|
|
#endif
|
|
|
|
|
m_pStack = NULL;
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// r<>cup<75>re la pile depuis l'enregistrement
|
|
|
|
|
// utilise un pointeur NULL (m_pStack) mais c'est ok comme <20>a
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if (!m_pStack->RestoreState(pf, m_pStack)) return FALSE;
|
|
|
|
|
m_pStack->SetBotCall(this); // bases pour les routines
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// r<>tabli certains <20>tats dans la pile selon la structure
|
2012-03-08 18:32:05 +00:00
|
|
|
|
m_pRun->RestoreState(NULL, m_pStack, m_pInstance);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CBotProgram::GivVersion()
|
|
|
|
|
{
|
|
|
|
|
return CBOTVERSION;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
CBotCall* CBotCall::m_ListCalls = NULL;
|
|
|
|
|
|
|
|
|
|
CBotCall::CBotCall(const char* name,
|
|
|
|
|
BOOL rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
|
|
|
|
|
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
|
|
|
|
|
{
|
|
|
|
|
m_name = name;
|
|
|
|
|
m_rExec = rExec;
|
|
|
|
|
m_rComp = rCompile;
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
m_nFuncIdent = CBotVar::NextUniqNum();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotCall::~CBotCall()
|
|
|
|
|
{
|
|
|
|
|
if (m_next) delete m_next;
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCall::Free()
|
|
|
|
|
{
|
|
|
|
|
delete CBotCall::m_ListCalls;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CBotCall::AddFunction(const char* name,
|
|
|
|
|
BOOL rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
|
|
|
|
|
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
|
|
|
|
|
{
|
|
|
|
|
CBotCall* p = m_ListCalls;
|
|
|
|
|
CBotCall* pp = NULL;
|
|
|
|
|
|
|
|
|
|
if ( p != NULL ) while ( p->m_next != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( p->GivName() == name )
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// lib<69>re une fonction qu'on red<65>fini
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( pp ) pp->m_next = p->m_next;
|
|
|
|
|
else m_ListCalls = p->m_next;
|
|
|
|
|
pp = p;
|
|
|
|
|
p = p->m_next;
|
2012-03-09 16:08:05 +00:00
|
|
|
|
pp->m_next = NULL; // ne pas d<>truire la suite de la liste
|
2012-03-08 18:32:05 +00:00
|
|
|
|
delete pp;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2012-03-09 16:08:05 +00:00
|
|
|
|
pp = p; // pointeur pr<70>c<EFBFBD>dent
|
2012-03-08 18:32:05 +00:00
|
|
|
|
p = p->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pp = new CBotCall(name, rExec, rCompile);
|
|
|
|
|
|
|
|
|
|
if (p) p->m_next = pp;
|
|
|
|
|
else m_ListCalls = pp;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// transforme le tableau de pointeurs aux variables
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// en une liste de variables cha<68>n<EFBFBD>es
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotVar* MakeListVars(CBotVar** ppVars, BOOL bSetVal=FALSE)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
CBotVar* pVar = NULL;
|
|
|
|
|
|
|
|
|
|
while( TRUE )
|
|
|
|
|
{
|
|
|
|
|
ppVars[i];
|
|
|
|
|
if ( ppVars[i] == NULL ) break;
|
|
|
|
|
|
|
|
|
|
CBotVar* pp = CBotVar::Create(ppVars[i]);
|
|
|
|
|
if (bSetVal) pp->Copy(ppVars[i]);
|
|
|
|
|
else
|
|
|
|
|
if ( ppVars[i]->GivType() == CBotTypPointer )
|
|
|
|
|
pp->SetClass( ppVars[i]->GivClass());
|
|
|
|
|
// copier le pointeur selon indirection
|
|
|
|
|
if (pVar == NULL) pVar = pp;
|
|
|
|
|
else pVar->AddNext(pp);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
return pVar;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// trouve un appel acceptable selon le nom de la proc<6F>dure
|
|
|
|
|
// et les param<61>tres donn<6E>s
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotTypResult CBotCall::CompileCall(CBotToken* &p, CBotVar** ppVar, CBotCStack* pStack, long& nIdent)
|
|
|
|
|
{
|
|
|
|
|
nIdent = 0;
|
|
|
|
|
CBotCall* pt = m_ListCalls;
|
|
|
|
|
CBotString name = p->GivString();
|
|
|
|
|
|
|
|
|
|
while ( pt != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pt->m_name == name )
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pVar = MakeListVars(ppVar);
|
|
|
|
|
CBotVar* pVar2 = pVar;
|
|
|
|
|
CBotTypResult r = pt->m_rComp(pVar2, m_pUser);
|
|
|
|
|
int ret = r.GivType();
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// si une classe est retourn<72>e, c'est en fait un pointeur
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( ret == CBotTypClass ) r.SetType( ret = CBotTypPointer );
|
|
|
|
|
|
|
|
|
|
if ( ret > 20 )
|
|
|
|
|
{
|
|
|
|
|
if (pVar2) pStack->SetError(ret, p /*pVar2->GivToken()*/ );
|
|
|
|
|
}
|
|
|
|
|
delete pVar;
|
|
|
|
|
nIdent = pt->m_nFuncIdent;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
pt = pt->m_next;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* CBotCall::m_pUser = NULL;
|
|
|
|
|
|
|
|
|
|
void CBotCall::SetPUser(void* pUser)
|
|
|
|
|
{
|
|
|
|
|
m_pUser = pUser;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CBotCall::CheckCall(const char* name)
|
|
|
|
|
{
|
|
|
|
|
CBotCall* p = m_ListCalls;
|
|
|
|
|
|
|
|
|
|
while ( p != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( name == p->GivName() ) return TRUE;
|
|
|
|
|
p = p->m_next;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotString CBotCall::GivName()
|
|
|
|
|
{
|
|
|
|
|
return m_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotCall* CBotCall::Next()
|
|
|
|
|
{
|
|
|
|
|
return m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int CBotCall::DoCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack, CBotTypResult& rettype)
|
|
|
|
|
{
|
|
|
|
|
CBotCall* pt = m_ListCalls;
|
|
|
|
|
|
|
|
|
|
if ( nIdent ) while ( pt != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pt->m_nFuncIdent == nIdent )
|
|
|
|
|
{
|
|
|
|
|
goto fund;
|
|
|
|
|
}
|
|
|
|
|
pt = pt->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pt = m_ListCalls;
|
|
|
|
|
|
|
|
|
|
if ( token != NULL )
|
|
|
|
|
{
|
|
|
|
|
CBotString name = token->GivString();
|
|
|
|
|
while ( pt != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pt->m_name == name )
|
|
|
|
|
{
|
|
|
|
|
nIdent = pt->m_nFuncIdent;
|
|
|
|
|
goto fund;
|
|
|
|
|
}
|
|
|
|
|
pt = pt->m_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
fund:
|
|
|
|
|
#if !STACKRUN
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// fait la liste des param<61>tres selon le contenu de la pile (pStackVar)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotVar* pVar = MakeListVars(ppVar, TRUE);
|
|
|
|
|
CBotVar* pVarToDelete = pVar;
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// cr<63>e une variable pour le r<>sultat
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotVar* pResult = rettype.Eq(0) ? NULL : CBotVar::Create("", rettype);
|
|
|
|
|
|
|
|
|
|
CBotVar* pRes = pResult;
|
|
|
|
|
int Exception = 0;
|
|
|
|
|
int res = pt->m_rExec(pVar, pResult, Exception, pStack->GivPUser());
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
if ( pResult != pRes ) delete pRes; // si r<>sultat diff<66>rent rendu
|
2012-03-08 18:32:05 +00:00
|
|
|
|
delete pVarToDelete;
|
|
|
|
|
|
|
|
|
|
if (res == FALSE)
|
|
|
|
|
{
|
|
|
|
|
if (Exception!=0)
|
|
|
|
|
{
|
|
|
|
|
pStack->SetError(Exception, token);
|
|
|
|
|
}
|
|
|
|
|
delete pResult;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
pStack->SetVar(pResult);
|
|
|
|
|
|
|
|
|
|
if ( rettype.GivType() > 0 && pResult == NULL )
|
|
|
|
|
{
|
|
|
|
|
pStack->SetError(TX_NORETVAL, token);
|
|
|
|
|
}
|
|
|
|
|
nIdent = pt->m_nFuncIdent;
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
CBotStack* pile = pStack->AddStackEOX(pt);
|
|
|
|
|
if ( pile == EOX ) return TRUE;
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// fait la liste des param<61>tres selon le contenu de la pile (pStackVar)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotVar* pVar = MakeListVars(ppVar, TRUE);
|
|
|
|
|
CBotVar* pVarToDelete = pVar;
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// cr<63>e une variable pour le r<>sultat
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotVar* pResult = rettype.Eq(0) ? NULL : CBotVar::Create("", rettype);
|
|
|
|
|
|
|
|
|
|
pile->SetVar( pVar );
|
|
|
|
|
|
|
|
|
|
CBotStack* pile2 = pile->AddStack();
|
|
|
|
|
pile2->SetVar( pResult );
|
|
|
|
|
|
|
|
|
|
pile->SetError(0, token); // pour la position en cas d'erreur + loin
|
|
|
|
|
return pt->Run( pStack );
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if STACKRUN
|
|
|
|
|
|
|
|
|
|
BOOL CBotCall::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotStack* pStack)
|
|
|
|
|
{
|
|
|
|
|
CBotCall* pt = m_ListCalls;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CBotString name = token->GivString();
|
|
|
|
|
while ( pt != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pt->m_name == name )
|
|
|
|
|
{
|
|
|
|
|
nIdent = pt->m_nFuncIdent;
|
|
|
|
|
|
|
|
|
|
CBotStack* pile = pStack->RestoreStackEOX(pt);
|
|
|
|
|
if ( pile == NULL ) return TRUE;
|
|
|
|
|
|
|
|
|
|
CBotStack* pile2 = pile->RestoreStack();
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
pt = pt->m_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL CBotCall::Run(CBotStack* pStack)
|
|
|
|
|
{
|
|
|
|
|
CBotStack* pile = pStack->AddStackEOX(this);
|
|
|
|
|
if ( pile == EOX ) return TRUE;
|
|
|
|
|
CBotVar* pVar = pile->GivVar();
|
|
|
|
|
|
|
|
|
|
CBotStack* pile2 = pile->AddStack();
|
|
|
|
|
CBotVar* pResult = pile2->GivVar();
|
|
|
|
|
CBotVar* pRes = pResult;
|
|
|
|
|
|
|
|
|
|
int Exception = 0;
|
|
|
|
|
int res = m_rExec(pVar, pResult, Exception, pStack->GivPUser());
|
|
|
|
|
|
|
|
|
|
if (res == FALSE)
|
|
|
|
|
{
|
|
|
|
|
if (Exception!=0)
|
|
|
|
|
{
|
|
|
|
|
pStack->SetError(Exception);
|
|
|
|
|
}
|
2012-03-09 16:08:05 +00:00
|
|
|
|
if ( pResult != pRes ) delete pResult; // si r<>sultat diff<66>rent rendu
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( pResult != NULL ) pStack->SetCopyVar( pResult );
|
2012-03-09 16:08:05 +00:00
|
|
|
|
if ( pResult != pRes ) delete pResult; // si r<>sultat diff<66>rent rendu
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
CBotCallMethode::CBotCallMethode(const char* name,
|
|
|
|
|
BOOL rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
|
|
|
|
|
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar))
|
|
|
|
|
{
|
|
|
|
|
m_name = name;
|
|
|
|
|
m_rExec = rExec;
|
|
|
|
|
m_rComp = rCompile;
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
m_nFuncIdent = CBotVar::NextUniqNum();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotCallMethode::~CBotCallMethode()
|
|
|
|
|
{
|
|
|
|
|
delete m_next;
|
|
|
|
|
m_next = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// trouve un appel acceptable selon le nom de la proc<6F>dure
|
|
|
|
|
// et les param<61>tres donn<6E>s
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotTypResult CBotCallMethode::CompileCall(const char* name, CBotVar* pThis,
|
|
|
|
|
CBotVar** ppVar, CBotCStack* pStack,
|
|
|
|
|
long& nIdent)
|
|
|
|
|
{
|
|
|
|
|
CBotCallMethode* pt = this;
|
|
|
|
|
nIdent = 0;
|
|
|
|
|
|
|
|
|
|
while ( pt != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pt->m_name == name )
|
|
|
|
|
{
|
|
|
|
|
CBotVar* pVar = MakeListVars(ppVar, TRUE);
|
|
|
|
|
CBotVar* pVar2 = pVar;
|
|
|
|
|
CBotTypResult r = pt->m_rComp(pThis, pVar2);
|
|
|
|
|
int ret = r.GivType();
|
|
|
|
|
if ( ret > 20 )
|
|
|
|
|
{
|
|
|
|
|
if (pVar2) pStack->SetError(ret, pVar2->GivToken());
|
|
|
|
|
}
|
|
|
|
|
delete pVar;
|
|
|
|
|
nIdent = pt->m_nFuncIdent;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
pt = pt->m_next;
|
|
|
|
|
}
|
|
|
|
|
return CBotTypResult(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotString CBotCallMethode::GivName()
|
|
|
|
|
{
|
|
|
|
|
return m_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotCallMethode* CBotCallMethode::Next()
|
|
|
|
|
{
|
|
|
|
|
return m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotCallMethode::AddNext(CBotCallMethode* pt)
|
|
|
|
|
{
|
|
|
|
|
CBotCallMethode* p = this;
|
|
|
|
|
while ( p->m_next != NULL ) p = p->m_next;
|
|
|
|
|
|
|
|
|
|
p->m_next = pt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int CBotCallMethode::DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotVar* &pResult, CBotStack* pStack, CBotToken* pToken)
|
|
|
|
|
{
|
|
|
|
|
CBotCallMethode* pt = this;
|
|
|
|
|
|
|
|
|
|
// recherche selon l'identificateur
|
|
|
|
|
|
|
|
|
|
if ( nIdent ) while ( pt != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pt->m_nFuncIdent == nIdent )
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// fait la liste des param<61>tres selon le contenu de la pile (pStackVar)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotVar* pVar = MakeListVars(ppVars, TRUE);
|
|
|
|
|
CBotVar* pVarToDelete = pVar;
|
|
|
|
|
|
|
|
|
|
// puis appelle la routine externe au module
|
|
|
|
|
|
|
|
|
|
int Exception = 0;
|
|
|
|
|
int res = pt->m_rExec(pThis, pVar, pResult, Exception);
|
|
|
|
|
pStack->SetVar(pResult);
|
|
|
|
|
|
|
|
|
|
if (res == FALSE)
|
|
|
|
|
{
|
|
|
|
|
if (Exception!=0)
|
|
|
|
|
{
|
|
|
|
|
// pStack->SetError(Exception, pVar->GivToken());
|
|
|
|
|
pStack->SetError(Exception, pToken);
|
|
|
|
|
}
|
|
|
|
|
delete pVarToDelete;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
delete pVarToDelete;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
pt = pt->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// recherche selon le nom
|
|
|
|
|
|
|
|
|
|
while ( pt != NULL )
|
|
|
|
|
{
|
|
|
|
|
if ( pt->m_name == name )
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// fait la liste des param<61>tres selon le contenu de la pile (pStackVar)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
|
|
|
|
CBotVar* pVar = MakeListVars(ppVars, TRUE);
|
|
|
|
|
CBotVar* pVarToDelete = pVar;
|
|
|
|
|
|
|
|
|
|
int Exception = 0;
|
|
|
|
|
int res = pt->m_rExec(pThis, pVar, pResult, Exception);
|
|
|
|
|
pStack->SetVar(pResult);
|
|
|
|
|
|
|
|
|
|
if (res == FALSE)
|
|
|
|
|
{
|
|
|
|
|
if (Exception!=0)
|
|
|
|
|
{
|
|
|
|
|
// pStack->SetError(Exception, pVar->GivToken());
|
|
|
|
|
pStack->SetError(Exception, pToken);
|
|
|
|
|
}
|
|
|
|
|
delete pVarToDelete;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
delete pVarToDelete;
|
|
|
|
|
nIdent = pt->m_nFuncIdent;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
pt = pt->m_next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL rSizeOf( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
|
|
|
|
|
{
|
|
|
|
|
if ( pVar == NULL ) return TX_LOWPARAM;
|
|
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
pVar = pVar->GivItemList();
|
|
|
|
|
|
|
|
|
|
while ( pVar != NULL )
|
|
|
|
|
{
|
|
|
|
|
i++;
|
|
|
|
|
pVar = pVar->GivNext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pResult->SetValInt(i);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotTypResult cSizeOf( CBotVar* &pVar, void* pUser )
|
|
|
|
|
{
|
|
|
|
|
if ( pVar == NULL ) return CBotTypResult( TX_LOWPARAM );
|
|
|
|
|
if ( pVar->GivType() != CBotTypArrayPointer )
|
|
|
|
|
return CBotTypResult( TX_BADPARAM );
|
|
|
|
|
return CBotTypResult( CBotTypInt );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotString CBotProgram::m_DebugVarStr = "";
|
|
|
|
|
|
|
|
|
|
BOOL rCBotDebug( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
|
|
|
|
|
{
|
|
|
|
|
pResult->SetValString( CBotProgram::m_DebugVarStr );
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CBotTypResult cCBotDebug( CBotVar* &pVar, void* pUser )
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// pas de param<61>tre
|
2012-03-08 18:32:05 +00:00
|
|
|
|
if ( pVar != NULL ) return CBotTypResult( TX_OVERPARAM );
|
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// la fonction retourne un r<>sultat "string"
|
2012-03-08 18:32:05 +00:00
|
|
|
|
return CBotTypResult( CBotTypString );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "StringFunctions.cpp"
|
|
|
|
|
|
|
|
|
|
void CBotProgram::Init()
|
|
|
|
|
{
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrOpenPar", 5000) ; // manque la parenth<74>se ouvrante
|
|
|
|
|
CBotToken::DefineNum( "CBotErrClosePar", 5001) ; // manque la parenth<74>se fermante
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNotBoolean", 5002) ; // l'expression doit <20>tre un boolean
|
|
|
|
|
CBotToken::DefineNum( "CBotErrUndefVar", 5003) ; // variable non d<>clar<61>e
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrBadLeft", 5004) ; // assignation impossible ( 5 = ... )
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNoTerminator", 5005) ;// point-virgule attendu
|
|
|
|
|
CBotToken::DefineNum( "CBotErrCaseOut", 5006) ; // case en dehors d'un switch
|
|
|
|
|
CBotToken::DefineNum( "CBotErrCloseBlock", 5008) ; // manque " } "
|
|
|
|
|
CBotToken::DefineNum( "CBotErrElseWhitoutIf", 5009) ;// else sans if correspondant
|
|
|
|
|
CBotToken::DefineNum( "CBotErrOpenBlock", 5010) ; // manque " { "
|
|
|
|
|
CBotToken::DefineNum( "CBotErrBadType1", 5011) ; // mauvais type pour l'assignation
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrRedefVar", 5012) ; // red<65>finition de la variable
|
|
|
|
|
CBotToken::DefineNum( "CBotErrBadType2", 5013) ; // 2 op<6F>randes de type incompatibles
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrUndefCall", 5014) ; // routine inconnue
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNoDoubleDots", 5015) ;// " : " attendu
|
|
|
|
|
CBotToken::DefineNum( "CBotErrBreakOutside", 5017) ;// break en dehors d'une boucle
|
|
|
|
|
CBotToken::DefineNum( "CBotErrUndefLabel", 5019) ; // label inconnu
|
|
|
|
|
CBotToken::DefineNum( "CBotErrLabel", 5018) ; // label ne peut se mettre ici
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNoCase", 5020) ; // manque " case "
|
|
|
|
|
CBotToken::DefineNum( "CBotErrBadNum", 5021) ; // nombre attendu
|
|
|
|
|
CBotToken::DefineNum( "CBotErrVoid", 5022) ; // " void " pas possible ici
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrNoType", 5023) ; // d<>claration de type attendue
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrNoVar", 5024) ; // nom de variable attendu
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNoFunc", 5025) ; // nom de fonction attendu
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrOverParam", 5026) ; // trop de param<61>tres
|
|
|
|
|
CBotToken::DefineNum( "CBotErrRedefFunc", 5027) ; // cette fonction existe d<>j<EFBFBD>
|
|
|
|
|
CBotToken::DefineNum( "CBotErrLowParam", 5028) ; // pas assez de param<61>tres
|
|
|
|
|
CBotToken::DefineNum( "CBotErrBadParam", 5029) ; // mauvais types de param<61>tres
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNbParam", 5030) ; // mauvais nombre de param<61>tres
|
|
|
|
|
CBotToken::DefineNum( "CBotErrUndefItem", 5031) ; // <20>l<EFBFBD>ment n'existe pas dans la classe
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrUndefClass", 5032) ; // variable n'est pas une classe
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrNoConstruct", 5033) ; // pas de constructeur appropri<72>
|
|
|
|
|
CBotToken::DefineNum( "CBotErrRedefClass", 5034) ; // classe existe d<>j<EFBFBD>
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrCloseIndex", 5035) ; // " ] " attendu
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrReserved", 5036) ; // mot r<>serv<72> (par un DefineNum)
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
// voici la liste des erreurs pouvant <20>tre retourn<72>es par le module
|
|
|
|
|
// pour l'ex<65>cution
|
2012-03-08 18:32:05 +00:00
|
|
|
|
|
2012-03-09 16:08:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrZeroDiv", 6000) ; // division par z<>ro
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNotInit", 6001) ; // variable non initialis<69>e
|
|
|
|
|
CBotToken::DefineNum( "CBotErrBadThrow", 6002) ; // throw d'une valeur n<>gative
|
|
|
|
|
CBotToken::DefineNum( "CBotErrNoRetVal", 6003) ; // fonction n'a pas retourn<72> de r<>sultat
|
2012-03-08 18:32:05 +00:00
|
|
|
|
CBotToken::DefineNum( "CBotErrNoRun", 6004) ; // Run() sans fonction active
|
|
|
|
|
CBotToken::DefineNum( "CBotErrUndefFunc", 6005) ; // appel d'une fonction qui n'existe plus
|
|
|
|
|
|
|
|
|
|
CBotProgram::AddFunction("sizeof", rSizeOf, cSizeOf );
|
|
|
|
|
|
|
|
|
|
InitStringFunctions();
|
|
|
|
|
|
|
|
|
|
// une fonction juste pour les debug divers
|
|
|
|
|
CBotProgram::AddFunction("CBOTDEBUGDD", rCBotDebug, cCBotDebug);
|
|
|
|
|
DeleteFile("CbotDebug.txt");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CBotProgram::Free()
|
|
|
|
|
{
|
|
|
|
|
CBotToken::Free() ;
|
|
|
|
|
CBotCall ::Free() ;
|
|
|
|
|
CBotClass::Free() ;
|
|
|
|
|
}
|
|
|
|
|
|