2014-10-14 13:11:37 +00:00
/*
* This file is part of the Colobot : Gold Edition source code
2015-08-22 14:40:02 +00:00
* Copyright ( C ) 2001 - 2015 , Daniel Roux , EPSITEC SA & TerranovaTeam
* http : //epsitec.ch; http://colobot.info; http://github.com/colobot
2014-10-14 13:11:37 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see http : //gnu.org/licenses
*/
2012-08-02 22:50:25 +00:00
//////////////////////////////////////////////////////////////////////
// database management of CBoT program
# include "CBot.h"
# include <stdio.h>
CBotProgram : : CBotProgram ( )
{
2015-08-16 10:43:42 +00:00
m_Prog = nullptr ;
m_pRun = nullptr ;
m_pClass = nullptr ;
m_pStack = nullptr ;
m_pInstance = nullptr ;
2012-08-08 20:35:17 +00:00
m_ErrorCode = 0 ;
m_Ident = 0 ;
2012-08-02 22:50:25 +00:00
}
CBotProgram : : CBotProgram ( CBotVar * pInstance )
{
2015-08-16 10:43:42 +00:00
m_Prog = nullptr ;
m_pRun = nullptr ;
m_pClass = nullptr ;
m_pStack = nullptr ;
2012-08-08 20:35:17 +00:00
m_pInstance = pInstance ;
m_ErrorCode = 0 ;
m_Ident = 0 ;
2012-08-02 22:50:25 +00:00
}
CBotProgram : : ~ CBotProgram ( )
{
2012-08-08 20:35:17 +00:00
// delete m_pClass;
m_pClass - > Purge ( ) ;
2015-08-16 10:43:42 +00:00
m_pClass = nullptr ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
CBotClass : : FreeLock ( this ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
delete m_Prog ;
# if STACKMEM
m_pStack - > Delete ( ) ;
2012-08-02 22:50:25 +00:00
# else
2012-08-08 20:35:17 +00:00
delete m_pStack ;
2012-08-02 22:50:25 +00:00
# endif
}
bool CBotProgram : : Compile ( const char * program , CBotStringArray & ListFonctions , void * pUser )
{
2012-08-08 20:35:17 +00:00
int error = 0 ;
Stop ( ) ;
// delete m_pClass;
m_pClass - > Purge ( ) ; // purge the old definitions of classes
// but without destroying the object
2015-08-16 10:43:42 +00:00
m_pClass = nullptr ;
delete m_Prog ; m_Prog = nullptr ;
2012-08-08 20:35:17 +00:00
ListFonctions . SetSize ( 0 ) ;
m_ErrorCode = 0 ;
// transforms the program in Tokens
CBotToken * pBaseToken = CBotToken : : CompileTokens ( program , error ) ;
2015-08-16 10:43:42 +00:00
if ( pBaseToken = = nullptr ) return false ;
2012-08-08 20:35:17 +00:00
2015-08-16 10:43:42 +00:00
CBotCStack * pStack = new CBotCStack ( nullptr ) ;
2012-08-11 18:59:35 +00:00
CBotToken * p = pBaseToken - > GetNext ( ) ; // skips the first token (separator)
2012-08-08 20:35:17 +00:00
pStack - > SetBotCall ( this ) ; // defined used routines
CBotCall : : SetPUser ( pUser ) ;
// first made a quick pass just to take the headers of routines and classes
2015-08-16 10:43:42 +00:00
while ( pStack - > IsOk ( ) & & p ! = nullptr & & p - > GetType ( ) ! = 0 )
2012-08-08 20:35:17 +00:00
{
if ( IsOfType ( p , ID_SEP ) ) continue ; // semicolons lurking
2013-05-26 15:47:54 +00:00
if ( p - > GetType ( ) = = ID_CLASS | |
2012-08-11 18:59:35 +00:00
( p - > GetType ( ) = = ID_PUBLIC & & p - > GetNext ( ) - > GetType ( ) = = ID_CLASS ) )
2012-08-08 20:35:17 +00:00
{
CBotClass * nxt = CBotClass : : Compile1 ( p , pStack ) ;
2015-08-16 10:43:42 +00:00
if ( m_pClass = = nullptr ) m_pClass = nxt ;
2012-08-08 20:35:17 +00:00
else m_pClass - > AddNext ( nxt ) ;
}
else
{
2015-08-16 10:43:42 +00:00
CBotFunction * next = CBotFunction : : Compile1 ( p , pStack , nullptr ) ;
if ( m_Prog = = nullptr ) m_Prog = next ;
2012-08-08 20:35:17 +00:00
else m_Prog - > AddNext ( next ) ;
}
}
if ( ! pStack - > IsOk ( ) )
{
2013-05-26 15:47:54 +00:00
m_ErrorCode = pStack - > GetError ( m_ErrorStart , m_ErrorEnd ) ;
2012-08-08 20:35:17 +00:00
delete m_Prog ;
2015-08-16 10:43:42 +00:00
m_Prog = nullptr ;
2012-08-08 20:35:17 +00:00
delete pBaseToken ;
return false ;
}
2015-08-16 10:43:42 +00:00
// CBotFunction* temp = nullptr;
2012-08-08 20:35:17 +00:00
CBotFunction * next = m_Prog ; // rewind the list
2012-08-11 18:59:35 +00:00
p = pBaseToken - > GetNext ( ) ; // returns to the beginning
2012-08-08 20:35:17 +00:00
2015-08-16 10:43:42 +00:00
while ( pStack - > IsOk ( ) & & p ! = nullptr & & p - > GetType ( ) ! = 0 )
2012-08-08 20:35:17 +00:00
{
if ( IsOfType ( p , ID_SEP ) ) continue ; // semicolons lurking
2013-05-26 15:47:54 +00:00
if ( p - > GetType ( ) = = ID_CLASS | |
2012-08-11 18:59:35 +00:00
( p - > GetType ( ) = = ID_PUBLIC & & p - > GetNext ( ) - > GetType ( ) = = ID_CLASS ) )
2012-08-08 20:35:17 +00:00
{
m_bCompileClass = true ;
CBotClass : : Compile ( p , pStack ) ; // completes the definition of the class
}
else
{
m_bCompileClass = false ;
CBotFunction : : Compile ( p , pStack , next ) ;
2012-08-11 18:59:35 +00:00
if ( next - > IsExtern ( ) ) ListFonctions . Add ( next - > GetName ( ) /* + next->GetParams()*/ ) ;
2012-08-08 20:35:17 +00:00
next - > m_pProg = this ; // keeps pointers to the module
next = next - > Next ( ) ;
}
}
// delete m_Prog; // the list of first pass
// m_Prog = temp; // list of the second pass
if ( ! pStack - > IsOk ( ) )
{
2013-05-26 15:47:54 +00:00
m_ErrorCode = pStack - > GetError ( m_ErrorStart , m_ErrorEnd ) ;
2012-08-08 20:35:17 +00:00
delete m_Prog ;
2015-08-16 10:43:42 +00:00
m_Prog = nullptr ;
2012-08-08 20:35:17 +00:00
}
delete pBaseToken ;
delete pStack ;
2015-08-16 10:43:42 +00:00
return ( m_Prog ! = nullptr ) ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : Start ( const char * name )
{
2012-08-08 20:35:17 +00:00
# if STACKMEM
m_pStack - > Delete ( ) ;
2012-08-02 22:50:25 +00:00
# else
2012-08-08 20:35:17 +00:00
delete m_pStack ;
2012-08-02 22:50:25 +00:00
# endif
2015-08-16 10:43:42 +00:00
m_pStack = nullptr ;
2012-08-08 20:35:17 +00:00
m_pRun = m_Prog ;
2015-08-16 10:43:42 +00:00
while ( m_pRun ! = nullptr )
2012-08-08 20:35:17 +00:00
{
2012-08-11 18:59:35 +00:00
if ( m_pRun - > GetName ( ) = = name ) break ;
2012-08-08 20:35:17 +00:00
m_pRun = m_pRun - > m_next ;
}
2015-08-16 10:43:42 +00:00
if ( m_pRun = = nullptr )
2012-08-08 20:35:17 +00:00
{
m_ErrorCode = TX_NORUN ;
return false ;
}
# if STACKMEM
m_pStack = CBotStack : : FirstStack ( ) ;
2012-08-02 22:50:25 +00:00
# else
2015-08-16 10:43:42 +00:00
m_pStack = new CBotStack ( nullptr ) ; // creates an execution stack
2012-08-02 22:50:25 +00:00
# endif
2012-08-08 20:35:17 +00:00
m_pStack - > SetBotCall ( this ) ; // bases for routines
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
return true ; // we are ready for Run ()
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : GetPosition ( const char * name , int & start , int & stop , CBotGet modestart , CBotGet modestop )
{
2012-08-08 20:35:17 +00:00
CBotFunction * p = m_Prog ;
2015-08-16 10:43:42 +00:00
while ( p ! = nullptr )
2012-08-08 20:35:17 +00:00
{
2012-08-11 18:59:35 +00:00
if ( p - > GetName ( ) = = name ) break ;
2012-08-08 20:35:17 +00:00
p = p - > m_next ;
}
2012-08-02 22:50:25 +00:00
2015-08-16 10:43:42 +00:00
if ( p = = nullptr ) return false ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
p - > GetPosition ( start , stop , modestart , modestop ) ;
return true ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : Run ( void * pUser , int timer )
{
2012-08-08 20:35:17 +00:00
bool ok ;
2015-08-16 10:43:42 +00:00
if ( m_pStack = = nullptr | | m_pRun = = nullptr ) goto error ;
2012-08-08 20:35:17 +00:00
m_ErrorCode = 0 ;
m_pStack - > Reset ( pUser ) ; // empty the possible previous error, and resets the timer
if ( timer > = 0 ) m_pStack - > SetTimer ( timer ) ;
m_pStack - > SetBotCall ( this ) ; // bases for routines
# if STACKRUN
// resumes execution on the top of the stack
ok = m_pStack - > Execute ( ) ;
2013-05-26 15:47:54 +00:00
if ( ok )
2012-08-08 20:35:17 +00:00
{
# ifdef _DEBUG
CBotVar * ppVar [ 3 ] ;
ppVar [ 0 ] = CBotVar : : Create ( " aa " , CBotTypInt ) ;
ppVar [ 1 ] = CBotVar : : Create ( " bb " , CBotTypInt ) ;
2015-08-16 10:43:42 +00:00
ppVar [ 2 ] = nullptr ;
2012-08-08 20:35:17 +00:00
ok = m_pRun - > Execute ( ppVar , m_pStack , m_pInstance ) ;
2012-08-02 22:50:25 +00:00
# else
2012-08-08 20:35:17 +00:00
// returns to normal execution
2015-08-16 10:43:42 +00:00
ok = m_pRun - > Execute ( nullptr , m_pStack , m_pInstance ) ;
2012-08-02 22:50:25 +00:00
# endif
2012-08-08 20:35:17 +00:00
}
2012-08-02 22:50:25 +00:00
# else
2015-08-16 10:43:42 +00:00
ok = m_pRun - > Execute ( nullptr , m_pStack , m_pInstance ) ;
2012-08-02 22:50:25 +00:00
# endif
2012-08-08 20:35:17 +00:00
// completed on a mistake?
if ( ! ok & & ! m_pStack - > IsOk ( ) )
{
2012-08-11 18:59:35 +00:00
m_ErrorCode = m_pStack - > GetError ( m_ErrorStart , m_ErrorEnd ) ;
2012-08-08 20:35:17 +00:00
# if STACKMEM
m_pStack - > Delete ( ) ;
2012-08-02 22:50:25 +00:00
# else
2012-08-08 20:35:17 +00:00
delete m_pStack ;
2012-08-02 22:50:25 +00:00
# endif
2015-08-16 10:43:42 +00:00
m_pStack = nullptr ;
2012-08-08 20:35:17 +00:00
return true ; // execution is finished!
}
2012-08-02 22:50:25 +00:00
2015-08-16 10:43:42 +00:00
if ( ok ) m_pRun = nullptr ; // more function in execution
2012-08-08 20:35:17 +00:00
return ok ;
2012-08-02 22:50:25 +00:00
error :
2012-08-08 20:35:17 +00:00
m_ErrorCode = TX_NORUN ;
return true ;
2012-08-02 22:50:25 +00:00
}
void CBotProgram : : Stop ( )
{
2012-08-08 20:35:17 +00:00
# if STACKMEM
m_pStack - > Delete ( ) ;
2012-08-02 22:50:25 +00:00
# else
2012-08-08 20:35:17 +00:00
delete m_pStack ;
2012-08-02 22:50:25 +00:00
# endif
2015-08-16 10:43:42 +00:00
m_pStack = nullptr ;
m_pRun = nullptr ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : GetRunPos ( const char * & FunctionName , int & start , int & end )
{
2015-08-16 10:43:42 +00:00
FunctionName = nullptr ;
2012-08-08 20:35:17 +00:00
start = end = 0 ;
2015-08-16 10:43:42 +00:00
if ( m_pStack = = nullptr ) return false ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
m_pStack - > GetRunPos ( FunctionName , start , end ) ;
return true ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
CBotVar * CBotProgram : : GetStackVars ( const char * & FunctionName , int level )
2012-08-02 22:50:25 +00:00
{
2015-08-16 10:43:42 +00:00
FunctionName = nullptr ;
if ( m_pStack = = nullptr ) return nullptr ;
2012-08-02 22:50:25 +00:00
2012-08-11 18:59:35 +00:00
return m_pStack - > GetStackVars ( FunctionName , level ) ;
2012-08-02 22:50:25 +00:00
}
void CBotProgram : : SetTimer ( int n )
{
2012-08-08 20:35:17 +00:00
CBotStack : : SetTimer ( n ) ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
int CBotProgram : : GetError ( )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
return m_ErrorCode ;
2012-08-02 22:50:25 +00:00
}
void CBotProgram : : SetIdent ( long n )
{
2012-08-08 20:35:17 +00:00
m_Ident = n ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
long CBotProgram : : GetIdent ( )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
return m_Ident ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : GetError ( int & code , int & start , int & end )
{
2012-08-08 20:35:17 +00:00
code = m_ErrorCode ;
start = m_ErrorStart ;
end = m_ErrorEnd ;
return code > 0 ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : GetError ( int & code , int & start , int & end , CBotProgram * & pProg )
{
2012-08-08 20:35:17 +00:00
code = m_ErrorCode ;
start = m_ErrorStart ;
end = m_ErrorEnd ;
pProg = this ;
return code > 0 ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
CBotString CBotProgram : : GetErrorText ( int code )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
CBotString TextError ;
TextError . LoadString ( code ) ;
if ( TextError . IsEmpty ( ) )
{
char buf [ 100 ] ;
sprintf ( buf , " Exception numéro %d. " , code ) ;
TextError = buf ;
}
return TextError ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
CBotFunction * CBotProgram : : GetFunctions ( )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
return m_Prog ;
2012-08-02 22:50:25 +00:00
}
2013-05-26 15:47:54 +00:00
bool CBotProgram : : AddFunction ( const char * name ,
bool rExec ( CBotVar * pVar , CBotVar * pResult , int & Exception , void * pUser ) ,
2012-08-08 20:35:17 +00:00
CBotTypResult rCompile ( CBotVar * & pVar , void * pUser ) )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
// stores pointers to the two functions
return CBotCall : : AddFunction ( name , rExec , rCompile ) ;
2012-08-02 22:50:25 +00:00
}
bool WriteWord ( FILE * pf , unsigned short w )
{
2012-08-08 20:35:17 +00:00
size_t lg ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
lg = fwrite ( & w , sizeof ( unsigned short ) , 1 , pf ) ;
2012-08-02 22:50:25 +00:00
2013-05-26 15:47:54 +00:00
return ( lg = = 1 ) ;
2012-08-02 22:50:25 +00:00
}
bool ReadWord ( FILE * pf , unsigned short & w )
{
2012-08-08 20:35:17 +00:00
size_t lg ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
lg = fread ( & w , sizeof ( unsigned short ) , 1 , pf ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
return ( lg = = 1 ) ;
2012-08-02 22:50:25 +00:00
}
bool WriteFloat ( FILE * pf , float w )
{
2012-08-08 20:35:17 +00:00
size_t lg ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
lg = fwrite ( & w , sizeof ( float ) , 1 , pf ) ;
2012-08-02 22:50:25 +00:00
2013-05-26 15:47:54 +00:00
return ( lg = = 1 ) ;
2012-08-02 22:50:25 +00:00
}
bool ReadFloat ( FILE * pf , float & w )
{
2012-08-08 20:35:17 +00:00
size_t lg ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
lg = fread ( & w , sizeof ( float ) , 1 , pf ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
return ( lg = = 1 ) ;
2012-08-02 22:50:25 +00:00
}
bool WriteLong ( FILE * pf , long w )
{
2012-08-08 20:35:17 +00:00
size_t lg ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
lg = fwrite ( & w , sizeof ( long ) , 1 , pf ) ;
2012-08-02 22:50:25 +00:00
2013-05-26 15:47:54 +00:00
return ( lg = = 1 ) ;
2012-08-02 22:50:25 +00:00
}
bool ReadLong ( FILE * pf , long & w )
{
2012-08-08 20:35:17 +00:00
size_t lg ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
lg = fread ( & w , sizeof ( long ) , 1 , pf ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
return ( lg = = 1 ) ;
2012-08-02 22:50:25 +00:00
}
bool WriteString ( FILE * pf , CBotString s )
{
2012-08-08 20:35:17 +00:00
size_t lg1 , lg2 ;
2012-08-02 22:50:25 +00:00
2012-08-11 18:59:35 +00:00
lg1 = s . GetLength ( ) ;
2012-08-08 20:35:17 +00:00
if ( ! WriteWord ( pf , lg1 ) ) return false ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
lg2 = fwrite ( s , 1 , lg1 , pf ) ;
2013-05-26 15:47:54 +00:00
return ( lg1 = = lg2 ) ;
2012-08-02 22:50:25 +00:00
}
bool ReadString ( FILE * pf , CBotString & s )
{
2012-08-08 20:35:17 +00:00
unsigned short w ;
char buf [ 1000 ] ;
size_t lg1 , lg2 ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
if ( ! ReadWord ( pf , w ) ) return false ;
lg1 = w ;
lg2 = fread ( buf , 1 , lg1 , pf ) ;
buf [ lg2 ] = 0 ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
s = buf ;
return ( lg1 = = lg2 ) ;
2012-08-02 22:50:25 +00:00
}
bool WriteType ( FILE * pf , CBotTypResult type )
{
2012-08-11 18:59:35 +00:00
int typ = type . GetType ( ) ;
2012-08-08 20:35:17 +00:00
if ( typ = = CBotTypIntrinsic ) typ = CBotTypClass ;
if ( ! WriteWord ( pf , typ ) ) return false ;
if ( typ = = CBotTypClass )
{
2012-08-11 18:59:35 +00:00
CBotClass * p = type . GetClass ( ) ;
if ( ! WriteString ( pf , p - > GetName ( ) ) ) return false ;
2012-08-08 20:35:17 +00:00
}
if ( type . Eq ( CBotTypArrayBody ) | |
type . Eq ( CBotTypArrayPointer ) )
{
2012-08-11 18:59:35 +00:00
if ( ! WriteWord ( pf , type . GetLimite ( ) ) ) return false ;
if ( ! WriteType ( pf , type . GetTypElem ( ) ) ) return false ;
2012-08-08 20:35:17 +00:00
}
return true ;
2012-08-02 22:50:25 +00:00
}
bool ReadType ( FILE * pf , CBotTypResult & type )
{
2012-08-08 20:35:17 +00:00
unsigned short 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 ) ;
2012-08-12 23:26:36 +00:00
type . SetLimite ( static_cast < short > ( ww ) ) ;
2012-08-08 20:35:17 +00:00
}
return true ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : DefineNum ( const char * name , long val )
{
2012-08-08 20:35:17 +00:00
return CBotToken : : DefineNum ( name , val ) ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : SaveState ( FILE * pf )
{
2012-08-08 20:35:17 +00:00
if ( ! WriteWord ( pf , CBOTVERSION ) ) return false ;
2015-08-16 10:43:42 +00:00
if ( m_pStack ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( ! WriteWord ( pf , 1 ) ) return false ;
2012-08-11 18:59:35 +00:00
if ( ! WriteString ( pf , m_pRun - > GetName ( ) ) ) return false ;
2012-08-08 20:35:17 +00:00
if ( ! m_pStack - > SaveState ( pf ) ) return false ;
}
2013-05-26 15:47:54 +00:00
else
2012-08-08 20:35:17 +00:00
{
if ( ! WriteWord ( pf , 0 ) ) return false ;
}
return true ;
2012-08-02 22:50:25 +00:00
}
bool CBotProgram : : RestoreState ( FILE * pf )
{
2012-08-08 20:35:17 +00:00
unsigned short w ;
CBotString s ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
Stop ( ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
if ( ! ReadWord ( pf , w ) ) return false ;
if ( w ! = CBOTVERSION ) return false ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
if ( ! ReadWord ( pf , w ) ) return false ;
if ( w = = 0 ) return true ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
if ( ! ReadString ( pf , s ) ) return false ;
Start ( s ) ; // point de reprise
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
# if STACKMEM
m_pStack - > Delete ( ) ;
2012-08-02 22:50:25 +00:00
# else
2012-08-08 20:35:17 +00:00
delete m_pStack ;
2012-08-02 22:50:25 +00:00
# endif
2015-08-16 10:43:42 +00:00
m_pStack = nullptr ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
// retrieves the stack from the memory
2015-08-16 10:43:42 +00:00
// uses a nullptr pointer (m_pStack) but it's ok like that
2012-08-08 20:35:17 +00:00
if ( ! m_pStack - > RestoreState ( pf , m_pStack ) ) return false ;
m_pStack - > SetBotCall ( this ) ; // bases for routines
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
// restored some states in the stack according to the structure
2015-08-16 10:43:42 +00:00
m_pRun - > RestoreState ( nullptr , m_pStack , m_pInstance ) ;
2012-08-08 20:35:17 +00:00
return true ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
int CBotProgram : : GetVersion ( )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
return CBOTVERSION ;
2012-08-02 22:50:25 +00:00
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
2015-08-16 10:43:42 +00:00
CBotCall * CBotCall : : m_ListCalls = nullptr ;
2013-05-26 15:47:54 +00:00
CBotCall : : CBotCall ( const char * name ,
bool rExec ( CBotVar * pVar , CBotVar * pResult , int & Exception , void * pUser ) ,
2012-08-08 20:35:17 +00:00
CBotTypResult rCompile ( CBotVar * & pVar , void * pUser ) )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
m_name = name ;
m_rExec = rExec ;
m_rComp = rCompile ;
2015-08-16 10:43:42 +00:00
m_next = nullptr ;
2012-08-08 20:35:17 +00:00
m_nFuncIdent = CBotVar : : NextUniqNum ( ) ;
2012-08-02 22:50:25 +00:00
}
CBotCall : : ~ CBotCall ( )
{
2012-08-08 20:35:17 +00:00
if ( m_next ) delete m_next ;
2015-08-16 10:43:42 +00:00
m_next = nullptr ;
2012-08-02 22:50:25 +00:00
}
void CBotCall : : Free ( )
{
2012-08-08 20:35:17 +00:00
delete CBotCall : : m_ListCalls ;
2012-08-02 22:50:25 +00:00
}
2013-05-26 15:47:54 +00:00
bool CBotCall : : AddFunction ( const char * name ,
bool rExec ( CBotVar * pVar , CBotVar * pResult , int & Exception , void * pUser ) ,
2012-08-08 20:35:17 +00:00
CBotTypResult rCompile ( CBotVar * & pVar , void * pUser ) )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
CBotCall * p = m_ListCalls ;
2015-08-16 10:43:42 +00:00
CBotCall * pp = nullptr ;
2012-08-08 20:35:17 +00:00
2015-08-16 10:43:42 +00:00
if ( p ! = nullptr ) while ( p - > m_next ! = nullptr )
2012-08-08 20:35:17 +00:00
{
2012-08-11 18:59:35 +00:00
if ( p - > GetName ( ) = = name )
2012-08-08 20:35:17 +00:00
{
// frees redefined function
if ( pp ) pp - > m_next = p - > m_next ;
else m_ListCalls = p - > m_next ;
pp = p ;
p = p - > m_next ;
2015-08-16 10:43:42 +00:00
pp - > m_next = nullptr ; // not to destroy the following list
2012-08-08 20:35:17 +00:00
delete pp ;
continue ;
}
pp = p ; // previous pointer
p = p - > m_next ;
}
pp = new CBotCall ( name , rExec , rCompile ) ;
2013-05-26 15:47:54 +00:00
2012-08-08 20:35:17 +00:00
if ( p ) p - > m_next = pp ;
else m_ListCalls = pp ;
return true ;
2012-08-02 22:50:25 +00:00
}
// transforms the array of pointers to variables
// in a chained list of variables
CBotVar * MakeListVars ( CBotVar * * ppVars , bool bSetVal = false )
{
2012-08-08 20:35:17 +00:00
int i = 0 ;
2015-08-16 10:43:42 +00:00
CBotVar * pVar = nullptr ;
2012-08-08 20:35:17 +00:00
while ( true )
{
2012-08-12 23:26:36 +00:00
// ppVars[i];
2015-08-16 10:43:42 +00:00
if ( ppVars [ i ] = = nullptr ) break ;
2012-08-08 20:35:17 +00:00
CBotVar * pp = CBotVar : : Create ( ppVars [ i ] ) ;
if ( bSetVal ) pp - > Copy ( ppVars [ i ] ) ;
else
2012-08-11 18:59:35 +00:00
if ( ppVars [ i ] - > GetType ( ) = = CBotTypPointer )
pp - > SetClass ( ppVars [ i ] - > GetClass ( ) ) ;
2012-08-02 22:50:25 +00:00
// copy the pointer according to indirections
2015-08-16 10:43:42 +00:00
if ( pVar = = nullptr ) pVar = pp ;
2012-08-08 20:35:17 +00:00
else pVar - > AddNext ( pp ) ;
i + + ;
}
return pVar ;
2012-08-02 22:50:25 +00:00
}
// is acceptable by a call procedure name
// and given parameters
CBotTypResult CBotCall : : CompileCall ( CBotToken * & p , CBotVar * * ppVar , CBotCStack * pStack , long & nIdent )
{
2012-08-08 20:35:17 +00:00
nIdent = 0 ;
CBotCall * pt = m_ListCalls ;
2012-08-11 18:59:35 +00:00
CBotString name = p - > GetString ( ) ;
2012-08-08 20:35:17 +00:00
2015-08-16 10:43:42 +00:00
while ( pt ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( pt - > m_name = = name )
{
CBotVar * pVar = MakeListVars ( ppVar ) ;
CBotVar * pVar2 = pVar ;
CBotTypResult r = pt - > m_rComp ( pVar2 , m_pUser ) ;
2012-08-11 18:59:35 +00:00
int ret = r . GetType ( ) ;
2013-05-26 15:47:54 +00:00
2012-08-08 20:35:17 +00:00
// if a class is returned, it is actually a pointer
if ( ret = = CBotTypClass ) r . SetType ( ret = CBotTypPointer ) ;
if ( ret > 20 )
{
2012-08-11 18:59:35 +00:00
if ( pVar2 ) pStack - > SetError ( ret , p /*pVar2->GetToken()*/ ) ;
2012-08-08 20:35:17 +00:00
}
delete pVar ;
nIdent = pt - > m_nFuncIdent ;
return r ;
}
pt = pt - > m_next ;
}
return - 1 ;
2012-08-02 22:50:25 +00:00
}
2015-08-16 10:43:42 +00:00
void * CBotCall : : m_pUser = nullptr ;
2012-08-02 22:50:25 +00:00
void CBotCall : : SetPUser ( void * pUser )
{
2012-08-08 20:35:17 +00:00
m_pUser = pUser ;
2012-08-02 22:50:25 +00:00
}
bool CBotCall : : CheckCall ( const char * name )
{
2012-08-08 20:35:17 +00:00
CBotCall * p = m_ListCalls ;
2015-08-16 10:43:42 +00:00
while ( p ! = nullptr )
2012-08-08 20:35:17 +00:00
{
2012-08-11 18:59:35 +00:00
if ( name = = p - > GetName ( ) ) return true ;
2012-08-08 20:35:17 +00:00
p = p - > m_next ;
}
return false ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
CBotString CBotCall : : GetName ( )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
return m_name ;
2012-08-02 22:50:25 +00:00
}
CBotCall * CBotCall : : Next ( )
{
2012-08-08 20:35:17 +00:00
return m_next ;
2012-08-02 22:50:25 +00:00
}
int CBotCall : : DoCall ( long & nIdent , CBotToken * token , CBotVar * * ppVar , CBotStack * pStack , CBotTypResult & rettype )
{
2012-08-08 20:35:17 +00:00
CBotCall * pt = m_ListCalls ;
2015-08-16 10:43:42 +00:00
if ( nIdent ) while ( pt ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( pt - > m_nFuncIdent = = nIdent )
{
goto fund ;
}
pt = pt - > m_next ;
}
pt = m_ListCalls ;
2015-08-16 10:43:42 +00:00
if ( token ! = nullptr )
2012-08-08 20:35:17 +00:00
{
2012-08-11 18:59:35 +00:00
CBotString name = token - > GetString ( ) ;
2015-08-16 10:43:42 +00:00
while ( pt ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( pt - > m_name = = name )
{
nIdent = pt - > m_nFuncIdent ;
goto fund ;
}
pt = pt - > m_next ;
}
}
return - 1 ;
2012-08-02 22:50:25 +00:00
fund :
# if !STACKRUN
2012-08-08 20:35:17 +00:00
// lists the parameters depending on the contents of the stack (pStackVar)
CBotVar * pVar = MakeListVars ( ppVar , true ) ;
CBotVar * pVarToDelete = pVar ;
// creates a variable to the result
2015-08-16 10:43:42 +00:00
CBotVar * pResult = rettype . Eq ( 0 ) ? nullptr : CBotVar : : Create ( " " , rettype ) ;
2012-08-08 20:35:17 +00:00
CBotVar * pRes = pResult ;
int Exception = 0 ;
2012-08-11 18:59:35 +00:00
int res = pt - > m_rExec ( pVar , pResult , Exception , pStack - > GetPUser ( ) ) ;
2012-08-08 20:35:17 +00:00
if ( pResult ! = pRes ) delete pRes ; // different result if made
delete pVarToDelete ;
if ( res = = false )
{
if ( Exception ! = 0 )
{
pStack - > SetError ( Exception , token ) ;
}
delete pResult ;
return false ;
}
pStack - > SetVar ( pResult ) ;
2015-08-16 10:43:42 +00:00
if ( rettype . GetType ( ) > 0 & & pResult = = nullptr )
2012-08-08 20:35:17 +00:00
{
pStack - > SetError ( TX_NORETVAL , token ) ;
}
nIdent = pt - > m_nFuncIdent ;
return true ;
2012-08-02 22:50:25 +00:00
# else
2012-08-08 20:35:17 +00:00
CBotStack * pile = pStack - > AddStackEOX ( pt ) ;
if ( pile = = EOX ) return true ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
// lists the parameters depending on the contents of the stack (pStackVar)
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
CBotVar * pVar = MakeListVars ( ppVar , true ) ;
2012-08-12 23:26:36 +00:00
// CBotVar* pVarToDelete = pVar;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
// creates a variable to the result
2015-08-16 10:43:42 +00:00
CBotVar * pResult = rettype . Eq ( 0 ) ? nullptr : CBotVar : : Create ( " " , rettype ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
pile - > SetVar ( pVar ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
CBotStack * pile2 = pile - > AddStack ( ) ;
pile2 - > SetVar ( pResult ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
pile - > SetError ( 0 , token ) ; // for the position on error + away
return pt - > Run ( pStack ) ;
2012-08-02 22:50:25 +00:00
# endif
}
2012-08-08 20:35:17 +00:00
# if STACKRUN
2012-08-02 22:50:25 +00:00
bool CBotCall : : RestoreCall ( long & nIdent , CBotToken * token , CBotVar * * ppVar , CBotStack * pStack )
{
2012-08-08 20:35:17 +00:00
CBotCall * pt = m_ListCalls ;
{
2012-08-11 18:59:35 +00:00
CBotString name = token - > GetString ( ) ;
2015-08-16 10:43:42 +00:00
while ( pt ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( pt - > m_name = = name )
{
nIdent = pt - > m_nFuncIdent ;
CBotStack * pile = pStack - > RestoreStackEOX ( pt ) ;
2015-08-16 10:43:42 +00:00
if ( pile = = nullptr ) return true ;
2012-08-08 20:35:17 +00:00
2012-08-12 23:26:36 +00:00
// CBotStack* pile2 = pile->RestoreStack();
pile - > RestoreStack ( ) ;
2012-08-08 20:35:17 +00:00
return true ;
}
pt = pt - > m_next ;
}
}
return false ;
2012-08-02 22:50:25 +00:00
}
bool CBotCall : : Run ( CBotStack * pStack )
{
2012-08-08 20:35:17 +00:00
CBotStack * pile = pStack - > AddStackEOX ( this ) ;
if ( pile = = EOX ) return true ;
2012-08-11 18:59:35 +00:00
CBotVar * pVar = pile - > GetVar ( ) ;
2012-08-08 20:35:17 +00:00
CBotStack * pile2 = pile - > AddStack ( ) ;
2012-08-11 18:59:35 +00:00
CBotVar * pResult = pile2 - > GetVar ( ) ;
2012-08-08 20:35:17 +00:00
CBotVar * pRes = pResult ;
int Exception = 0 ;
2012-08-11 18:59:35 +00:00
int res = m_rExec ( pVar , pResult , Exception , pStack - > GetPUser ( ) ) ;
2012-08-08 20:35:17 +00:00
if ( res = = false )
{
if ( Exception ! = 0 )
{
pStack - > SetError ( Exception ) ;
}
if ( pResult ! = pRes ) delete pResult ; // different result if made
return false ;
}
2015-08-16 10:43:42 +00:00
if ( pResult ! = nullptr ) pStack - > SetCopyVar ( pResult ) ;
2012-08-08 20:35:17 +00:00
if ( pResult ! = pRes ) delete pResult ; // different result if made
return true ;
2012-08-02 22:50:25 +00:00
}
# endif
///////////////////////////////////////////////////////////////////////////////////////
2013-05-26 15:47:54 +00:00
CBotCallMethode : : CBotCallMethode ( const char * name ,
2015-07-13 16:40:13 +00:00
bool rExec ( CBotVar * pThis , CBotVar * pVar , CBotVar * pResult , int & Exception , void * user ) ,
2012-08-08 20:35:17 +00:00
CBotTypResult rCompile ( CBotVar * pThis , CBotVar * & pVar ) )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
m_name = name ;
m_rExec = rExec ;
m_rComp = rCompile ;
2015-08-16 10:43:42 +00:00
m_next = nullptr ;
2012-08-08 20:35:17 +00:00
m_nFuncIdent = CBotVar : : NextUniqNum ( ) ;
2012-08-02 22:50:25 +00:00
}
CBotCallMethode : : ~ CBotCallMethode ( )
{
2012-08-08 20:35:17 +00:00
delete m_next ;
2015-08-16 10:43:42 +00:00
m_next = nullptr ;
2012-08-02 22:50:25 +00:00
}
// is acceptable by a call procedure name
// and given parameters
2013-05-26 15:47:54 +00:00
CBotTypResult CBotCallMethode : : CompileCall ( const char * name , CBotVar * pThis ,
2012-08-08 20:35:17 +00:00
CBotVar * * ppVar , CBotCStack * pStack ,
long & nIdent )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
CBotCallMethode * pt = this ;
nIdent = 0 ;
2015-08-16 10:43:42 +00:00
while ( pt ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( pt - > m_name = = name )
{
CBotVar * pVar = MakeListVars ( ppVar , true ) ;
CBotVar * pVar2 = pVar ;
CBotTypResult r = pt - > m_rComp ( pThis , pVar2 ) ;
2012-08-11 18:59:35 +00:00
int ret = r . GetType ( ) ;
2012-08-08 20:35:17 +00:00
if ( ret > 20 )
{
2012-08-11 18:59:35 +00:00
if ( pVar2 ) pStack - > SetError ( ret , pVar2 - > GetToken ( ) ) ;
2012-08-08 20:35:17 +00:00
}
delete pVar ;
nIdent = pt - > m_nFuncIdent ;
return r ;
}
pt = pt - > m_next ;
}
return CBotTypResult ( - 1 ) ;
2012-08-02 22:50:25 +00:00
}
2012-08-11 18:59:35 +00:00
CBotString CBotCallMethode : : GetName ( )
2012-08-02 22:50:25 +00:00
{
2012-08-08 20:35:17 +00:00
return m_name ;
2012-08-02 22:50:25 +00:00
}
CBotCallMethode * CBotCallMethode : : Next ( )
{
2012-08-08 20:35:17 +00:00
return m_next ;
2012-08-02 22:50:25 +00:00
}
void CBotCallMethode : : AddNext ( CBotCallMethode * pt )
{
2012-08-08 20:35:17 +00:00
CBotCallMethode * p = this ;
2015-08-16 10:43:42 +00:00
while ( p - > m_next ! = nullptr ) p = p - > m_next ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
p - > m_next = pt ;
2012-08-02 22:50:25 +00:00
}
int CBotCallMethode : : DoCall ( long & nIdent , const char * name , CBotVar * pThis , CBotVar * * ppVars , CBotVar * & pResult , CBotStack * pStack , CBotToken * pToken )
{
2012-08-08 20:35:17 +00:00
CBotCallMethode * pt = this ;
// search by the identifier
2015-08-16 10:43:42 +00:00
if ( nIdent ) while ( pt ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( pt - > m_nFuncIdent = = nIdent )
{
// lists the parameters depending on the contents of the stack (pStackVar)
CBotVar * pVar = MakeListVars ( ppVars , true ) ;
CBotVar * pVarToDelete = pVar ;
// then calls the routine external to the module
int Exception = 0 ;
2015-07-13 16:40:13 +00:00
int res = pt - > m_rExec ( pThis , pVar , pResult , Exception , pStack - > GetPUser ( ) ) ;
2012-08-08 20:35:17 +00:00
pStack - > SetVar ( pResult ) ;
if ( res = = false )
{
if ( Exception ! = 0 )
{
2012-08-11 18:59:35 +00:00
// pStack->SetError(Exception, pVar->GetToken());
2012-08-08 20:35:17 +00:00
pStack - > SetError ( Exception , pToken ) ;
}
delete pVarToDelete ;
return false ;
}
delete pVarToDelete ;
return true ;
}
pt = pt - > m_next ;
}
// search by name
2015-08-16 10:43:42 +00:00
while ( pt ! = nullptr )
2012-08-08 20:35:17 +00:00
{
if ( pt - > m_name = = name )
{
// lists the parameters depending on the contents of the stack (pStackVar)
CBotVar * pVar = MakeListVars ( ppVars , true ) ;
CBotVar * pVarToDelete = pVar ;
int Exception = 0 ;
2015-07-13 16:40:13 +00:00
int res = pt - > m_rExec ( pThis , pVar , pResult , Exception , pStack - > GetPUser ( ) ) ;
2012-08-08 20:35:17 +00:00
pStack - > SetVar ( pResult ) ;
if ( res = = false )
{
if ( Exception ! = 0 )
{
2012-08-11 18:59:35 +00:00
// pStack->SetError(Exception, pVar->GetToken());
2012-08-08 20:35:17 +00:00
pStack - > SetError ( Exception , pToken ) ;
}
delete pVarToDelete ;
return false ;
}
delete pVarToDelete ;
nIdent = pt - > m_nFuncIdent ;
return true ;
}
pt = pt - > m_next ;
}
return - 1 ;
2012-08-02 22:50:25 +00:00
}
bool rSizeOf ( CBotVar * pVar , CBotVar * pResult , int & ex , void * pUser )
{
2015-08-16 10:43:42 +00:00
if ( pVar = = nullptr ) return TX_LOWPARAM ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
int i = 0 ;
2012-08-11 18:59:35 +00:00
pVar = pVar - > GetItemList ( ) ;
2012-08-02 22:50:25 +00:00
2015-08-16 10:43:42 +00:00
while ( pVar ! = nullptr )
2012-08-08 20:35:17 +00:00
{
2013-05-26 15:47:54 +00:00
i + + ;
2012-08-11 18:59:35 +00:00
pVar = pVar - > GetNext ( ) ;
2012-08-08 20:35:17 +00:00
}
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
pResult - > SetValInt ( i ) ;
return true ;
2012-08-02 22:50:25 +00:00
}
CBotTypResult cSizeOf ( CBotVar * & pVar , void * pUser )
{
2015-08-16 10:43:42 +00:00
if ( pVar = = nullptr ) return CBotTypResult ( TX_LOWPARAM ) ;
2012-08-11 18:59:35 +00:00
if ( pVar - > GetType ( ) ! = CBotTypArrayPointer )
2012-08-08 20:35:17 +00:00
return CBotTypResult ( TX_BADPARAM ) ;
return CBotTypResult ( CBotTypInt ) ;
2012-08-02 22:50:25 +00:00
}
2015-11-21 13:52:56 +00:00
// TODO: Refactor this - including .cpp files is bad
2012-08-02 22:50:25 +00:00
# include "StringFunctions.cpp"
void CBotProgram : : Init ( )
{
2015-11-21 16:26:56 +00:00
CBotToken : : DefineNum ( " CBotErrZeroDiv " , TX_DIVZERO ) ; // division by zero
CBotToken : : DefineNum ( " CBotErrNotInit " , TX_NOTINIT ) ; // uninitialized variable
CBotToken : : DefineNum ( " CBotErrBadThrow " , TX_BADTHROW ) ; // throw a negative value
//CBotToken::DefineNum("CBotErrNoRetVal", 6003); // function did not return results // TODO: Not used. I'm pretty sure not returning a value crashes the game :P
CBotToken : : DefineNum ( " CBotErrNoRun " , TX_NORUN ) ; // active Run () without a function // TODO: Is this actually a runtime error?
CBotToken : : DefineNum ( " CBotErrUndefFunc " , TX_NOCALL ) ; // Calling a function that no longer exists
CBotToken : : DefineNum ( " CBotErrUndefClass " , TX_NOCLASS ) ; // Class no longer exists
CBotToken : : DefineNum ( " CBotErrNullPointer " , TX_NULLPT ) ; // Attempted to use a null pointer
CBotToken : : DefineNum ( " CBotErrNan " , TX_OPNAN ) ; // Can't do operations on nan
CBotToken : : DefineNum ( " CBotErrOutOfBounds " , TX_OUTARRAY ) ; // Attempted access out of bounds of an array
CBotToken : : DefineNum ( " CBotErrStackOverflow " , TX_STACKOVER ) ; // Stack overflow
CBotToken : : DefineNum ( " CBotErrDeletedObject " , TX_DELETEDPT ) ; // Attempted to use deleted object
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
CBotProgram : : AddFunction ( " sizeof " , rSizeOf , cSizeOf ) ;
2012-08-02 22:50:25 +00:00
2012-08-08 20:35:17 +00:00
InitStringFunctions ( ) ;
2012-08-02 22:50:25 +00:00
}
void CBotProgram : : Free ( )
{
2013-05-26 15:47:54 +00:00
CBotToken : : Free ( ) ;
2012-08-08 20:35:17 +00:00
CBotCall : : Free ( ) ;
CBotClass : : Free ( ) ;
2012-08-02 22:50:25 +00:00
}